pax_global_header00006660000000000000000000000064131712454010014510gustar00rootroot0000000000000052 comment=4c9a75148de96144d29ceb890a59e06e0359fc7c liquid-dsp-1.3.1/000077500000000000000000000000001317124540100135655ustar00rootroot00000000000000liquid-dsp-1.3.1/HISTORY000066400000000000000000000166021317124540100146560ustar00rootroot00000000000000 ## Major improvements for v1.3.0 ## * New MIT/X11 license (https://opensource.org/licenses/MIT) * agc (automatic gain control) - major code scrub, improved reliability, simplified interface - block-level operation * buffer - new cbuffer objects for dynamic-sized circular buffering * channel - new module to define certain channel emulation objects - new functionality includes carrier frequency/phase offsets, (time-varying) multi-path, shadowing, and additive noise * dotprod - adding method to compute x^T * x of a vector (sum of squares) * equalization - improved interface for LMS and RLS equalizers - simplified methods to support blind operation * fec (forward error correctino) - interleaver and packetizer moved from the framing to the fec module - packetizer now includes data whitening * fft (fast Fourier transform) - general speed improvements for one-dimensional FFTs - completely reimplemented spgram (spectral periodogram) objects to include both complex and real-values amples with simpler interface - reimplemented asgram (ASCII spectral periodogram) objects * filter - additional prototype create methods, block execution - added new fftfilt family of objects to realize linear filter with fast Fourier transforms - interp family renamed to firinterp, new iirinterp family - decim family renamed to firdecim, new iirdecim family - add linear interpolation for arbitrary resamp output - new multi-stage half-band resampler family - symsync: improved stability, added rate adjustment to help pull in sample rate offsets - added autotests for validating performance of both the resamp and msresamp objects * framing - added `framedatastats` object for counting statistics across different framing objects (e.g. number of total bytes received) - adding generic callback function definition for all framing structures - qpacketmodem: new object to easily combine modulating and encoding; buffer of data in, modulated and encoded samples out - qpilotgen/qpilotsync: new objects to add and synchronize pilot symbols to modulated symbols to recover carrier frequency/phase, and gain - framing objects: frame64, flexframe now use qpacketmodem, qpilotgen, and qpilotsync objects for unified interface and vastly improved performance - flexframe: vastly simplified interface - qdetector: new family for pre-demodulator synchronizion and detection - moved interleaver and packetizer objects to `fec` module - symstream: new family for generating random stream of modulated samples - msource: new family for generating multiple signals for a single source, including tones, noise, modulated symbols - symtrack: new family for tracking a stream of symbols and recovering signal level, timing, carrier frequency/phase without pilots * math - new windowing methods (e.g. 7-term Blackman-harris window) * matrix - adding smatrix family of objects (sparse matrices) - improving linear solver methods (roughly doubled speed) * modem - re-organizing internal linear modem code (no interface change) - freqmod/freqdem: new interface, block-level execution for analog FM - cpfskmod/cpfskdem: new family for generic non-linear continuous-phase frequency-shift modulation (e.g. minimum-shift keying) - fskmod/fskdem: new family for non-coherent frequency-shift keying modulation, often with many samples per symbol (e.g. 256-FSK) * multicarrier - adding OFDM framing option for window tapering - simplfying OFDM framing for generating preamble symbols (all generated OFDM symbols are the same length) - adding run-time option for debugging ofdmframesync - adding method for initializing subcarriers with frequency range * nco (numerically-controlled oscillator) - general performance improvements, adding block-level execution * optim - gradsearch (gradient search) uses internal linesearch for significant speed increase and better reliability - gradsearch interface greatly simplified * utility - build no longer auto-generates tables at compile time (helps with cross compilation) * vector - new module to simplify basic vector operations * miscellany - documentation moved from core repository to website - global header file (`liquid.h`) include more structured source - consistent naming of reset() methods for most objects ## Major improvements for v1.2.0 ## * dotprod - leveraging SIMD extensions for vector operations (SSE2, SSE3) * fft - completely re-structured internal transform strategy including Cooley-Tukey mixed-radix algorithm, Rader algorithm for FFTs of prime length, and specific codelets for small-size transforms. * math - new modular arithmetic methods (prime factor, totient, etc.) * modem - new API creates linear modem objects with one argument, e.g. LIQUID_MODEM_QAM16 - new type definitions for analog modems ## Major improvements for v1.1.0 ## * build - simplifying build environment by explicitly defining object dependencies (no longer auto-generated; much faster now) * documentation - new tutorials (ofdmflexframe) - sections on new objects/methods (msresamp, gmsk filter design, soft-decision demodulation) - adding useful figures (polyfit-lagrange, symsync) - adding BER performance plots for new FEC schemes - adding BER performance plots for sqam32 and sqam128 * agc - fixing scaling issues - improving computation speed - simplifying interface with a single, unified design model * equalization - adding support for decision-directed equalizers * fec - adding soft decoding (when available) for forward error-correction schemes; generally improves performance by about 2 dB Eb/N0 - adding half-rate Golay(24,12) code - adding SEC-DED codes: (22,16), (39,32), (72,64) * filter - firdes: adding Nyquist prototyping design method - firdes: adding new GMSK receive filter design method - interp: porting to efficient polyphase filterbank implementation, adding prototype create() method - adding multi-stage resampler for efficient decimation and interpolation * framing - adding ofdmflexframe family of objects capable of defining which subcarriers are nulls/pilots/data, and easily loading data into frames. Very similar to 'flexframe' in usage. - supporting soft packet decoding (interleaving, etc.) - adding gmskframe generator and synchronizer object; simple, reliable * matrix - adding Cholesky factorization A = R^T * R (for positive definite matrices) - adding conjugate gradient solver (for positive definite matrices) * modem - adding simple on/off keying (OOK) type - adding 256-APSK type (6,18,32,36,46,54,64) - adding 'square' (cross) 32-, 128-QAM types - adding 'optimal' 64-, 128-, and 256-QAM constellations - improved speed of most schemes' modulate/demodulate implementations - adding soft-decision (log-likelihood ratio) demodulation - adding GMSK modulation/demodulation with improved filter design * multicarrier - ofdmframe: improving synchronization and reliability in interference environments, enabling squelch, improving equalization * optim - simplified interface to gradient search liquid-dsp-1.3.1/LICENSE000066400000000000000000000020531317124540100145720ustar00rootroot00000000000000Copyright (c) 2007 - 2016 Joseph Gaeddert Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. liquid-dsp-1.3.1/README.md000066400000000000000000000147651317124540100150610ustar00rootroot00000000000000 liquid-dsp ========== Software-Defined Radio Digital Signal Processing Library liquid-dsp is a free and open-source digital signal processing (DSP) library designed specifically for software-defined radios on embedded platforms. The aim is to provide a lightweight DSP library that does not rely on a myriad of external dependencies or proprietary and otherwise cumbersome frameworks. All signal processing elements are designed to be flexible, scalable, and dynamic, including filters, filter design, oscillators, modems, synchronizers, and complex mathematical operations. For more information, please refer to the documentation: * online HTML version: [http://liquidsdr.org/doc](http://liquidsdr.org/doc) * pre-compiled `.pdf` version: [liquid.pdf](http://liquidsdr.org/downloads/liquid.pdf) (4.4 MB). Installation and Dependencies ----------------------------- liquid-dsp only relies on `libc` and `libm` (standard C and math) libraries to run; however liquid will take advantage of other packages (such as [FFTW](http://www.fftw.org)) if they are available. ### Getting the source code ### There are two primary ways of obtaining the source code: 1. Clone the entire [repository](http://github.com/jgaeddert/liquid-dsp) (recommended) $ git clone git://github.com/jgaeddert/liquid-dsp.git 2. or download the [tarball](http://liquidsdr.org/downloads/liquid-dsp-1.2.0.tar.gz) (2.6 MB), validate the checksum, and unpack $ wget http://liquidsdr.org/downloads/liquid-dsp-1.2.0.tar.gz $ wget http://liquidsdr.org/downloads/liquid-dsp.md5 $ md5sum --check liquid-dsp.md5 $ tar -xf liquid-dsp-1.2.0.tar.gz ### Installation ### Once you have obtained a copy of the source code, you can now build the DSP library (NOTE: if you chose to clone the repository, you will need to also run the additional `./bootstrap.sh` script before configuring): $ ./bootstrap.sh # <- only if you cloned the Git repo $ ./configure $ make $ sudo make install If you are installing on Linux for the first time, you will also need to rebind your dynamic libraries with `sudo ldconfig` to make the shared object available. If you decide that you want to remove the installed DSP library, simply run $ sudo make uninstall ### Run all test scripts ### Source code validation is a critical step in any software library, particulary for verifying the portability of code to different processors and platforms. Packaged with liquid-dsp are a number of automatic test scripts to validate the correctness of the source code. The test scripts are located under each module's `tests/` directory and take the form of a C source file. liquid includes a framework for compiling, linking, and running the tests, and can be invoked with the make target `check`, viz. $ make check ### Examples ### Nearly all signal processing elements have a corresponding example in the `examples/` directory. Most example scripts generate an output `.m` file for plotting with [GNU octave](http://www.gnu.org/software/octave/) All examples are built as stand-alone programs and can be compiled with the make target `examples`: $ make examples Sometimes, however, it is useful to build one example individually. This can be accomplished by directly targeting its binary (e.g. `make examples/modem_example`). The example then can be run at the command line, viz. `./examples/modem_example`. ### Benchmarking tool ### Packaged with liquid are benchmarks to determine the speed each signal processing element can run on your machine. Initially the tool provides an estimate of the processor's clock frequency and will then estimate the number of trials so that each benchmark will take between 50 and 500 ms to run. You can build and run the benchmark program with the following command: $ make bench Available Modules ----------------- * _agc_: automatic gain control, received signal strength * _audio_: source audio encoders/decoders: cvsd, filterbanks * _buffer_: internal buffering, circular/static, ports (threaded) * _channel_: additive noise, multi-path fading, carrier phase/frequency offsets, timing phase/rate offsets * _dotprod_: inner dot products (real, complex), vector sum of squares * _equalization_: adaptive equalizers: least mean-squares, recursive least squares, semi-blind * _fec_: basic forward error correction codes including several Hamming codes, single error correction/double error detection, Golay block code, as well as several checksums and cyclic redundancy checks, interleaving, soft decoding * _fft_: fast Fourier transforms (arbitrary length), discrete sin/cos transforms * _filter_: finite/infinite impulse response, polyphase, hilbert, interpolation, decimation, filter design, resampling, symbol timing recovery * _framing_: flexible framing structures for amazingly easy packet software radio; dynamically adjust modulation and coding on the fly with single- and multi-carrier framing structures * _math_: transcendental functions not in the C standard library (gamma, besseli, etc.), polynomial operations (curve-fitting, root-finding, etc.) * _matrix_: basic math, LU/QR/Cholesky factorization, inversion, Gauss elimination, Gram-Schmidt decomposition, linear solver, sparse matrix representation * _modem_: modulate, demodulate, PSK, differential PSK, QAM, optimal QAM, as well as analog and non-linear digital modulations GMSK) * _multichannel_: filterbank channelizers, OFDM * _nco_: numerically-controlled oscillator: mixing, frequency synthesis, phase-locked loops * _optim_: (non-linear optimization) Newton-Raphson, evoluationary algorithms, gradient descent, line search * _quantization_: analog/digital converters, compression/expansion * _random_: (random number generators) uniform, exponential, gamma, Nakagami-m, Gauss, Rice-K, Weibull * _sequence_: linear feedback shift registers, complementary codes, maximal-length sequences * _utility_: useful miscellany, mostly bit manipulation (shifting, packing, and unpacking of arrays) * _vector_: generic vector operations ### License ### liquid projects are released under the X11/MIT license. Short version: this code is copyrighted to me (Joseph D. Gaeddert), I give you permission to do wantever you want with it except remove my name from the credits. See the LICENSE file or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT) for specific terms. liquid-dsp-1.3.1/TROUBLESHOOTING000066400000000000000000000066661317124540100160150ustar00rootroot00000000000000========================================================================= Troubleshooting ========================================================================= Here is a list of common problems and potential solutions. ========================================================================= Q1 When I try to compile I get an error like "internal compiler error: in gimplify_expr, at gimplify.c:7153" A1(a) This is a bug with gcc v4.5.1 and v4.5.2 dealing with complex data type, e.g. "float complex" (see: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47150). The best option is to update your compiler to a more recent version, revert to an older version, or apply a patch. A1(b) Alternatively, if you are observing this error with ellip.c you can probably comment out the offending lines; however this will render the elliptic filter generator in liquid-dsp useless. This is probably the fastest solution if you aren't concerned with generating elliptic filters. ========================================================================= Q2 When compiling I get linker errors: /liquid-dsp/src/fec/src/fec_conv.c:210: undefined reference to `create_viterbi27' /liquid-dsp/src/fec/src/fec_conv.c:210: undefined reference to `init_viterbi27' /liquid-dsp/src/fec/src/fec_conv.c:210: undefined reference to `update_viterbi27_blk' ... NOTE Issue should be resolved after version 1.2.0 (commit 2f6ed1c9d39f4) A2 This is because the linker cannot find the libfec library. The 'configure' script checks to make sure that the fec library is available before compiling. If found the additional forward error-correction codecs (e.g. convolutional) will be built and used. If the headers and library are not found, then the liquid-dsp build environment will ignore these. However if, for example, the fec headers are found but the libfec is not, the build script it will try to build the additional forward error- correction codecs without linking to the proper libraries. This is a bug with the current version of liquid-dsp. The quick fix is to run "./configure" and then edit "config.h" to ignore the fec headers. Open "config.h" and change the line (approx. 13) from #define HAVE_FEC_H 1 to /* #undef HAVE_FEC_H */ This will disable building the additional FEC codecs (such as convolutional) but will still build the internal codes (such as the Hamming codes). Now run "make" as normal. ========================================================================= Q3 When I try compiling on OS 10.9 I get the following error when trying to run "./configure": configure: error: Need standard c library! or configure: error: Could not use standard c library! A3 This is likely a result of using Apple's default build of gcc (LLVM version 5.0) which by default uses extremely strict checking for compiling. Because the script generated by configure is pretty sloppy, LLVM coughs when trying to build it. The simple fix is to update the repository and specify a different compiler by setting your environment variable CC, viz $ export CC="/usr/local/bin/gcc-4.8" I know this is a work-around; I'm working on a permanent fix. liquid-dsp-1.3.1/autotest/000077500000000000000000000000001317124540100154355ustar00rootroot00000000000000liquid-dsp-1.3.1/autotest/autotest.c000066400000000000000000000342271317124540100174610ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // autotest.c // // This file is used in conjunction with autotest_include.h (generated with // autotest_gen.py) to produce an executable for automatically testing the // various signal processing algorithms in liquid. // default include headers #include #include #include #include #include "autotest/autotest.h" void usage() { // help printf("Usage: xautotest [OPTION]\n"); printf("Execute autotest scripts for liquid-dsp library.\n"); printf(" -h display this help and exit\n"); printf(" -t run specific test\n"); printf(" -p run specific package\n"); printf(" -r run all tests, random order\n"); printf(" -L lists all scripts\n"); printf(" -l lists all packages\n"); printf(" -x stop on fail\n"); printf(" -s run all tests matching search string\n"); printf(" -v verbose\n"); printf(" -q quiet\n"); printf(" -o output file (json)\n"); } // define autotest function pointer typedef void(autotest_function_t) (void); // define autotest_t typedef struct { unsigned int id; // test identification autotest_function_t * api; // test function, e.g. autotest_modem() const char* name; // test name long unsigned int num_checks; // number of checks that were run for this test long unsigned int num_passed; // number of checks that passed long unsigned int num_failed; // number of checks that failed long unsigned int num_warnings; // number of warnings float percent_passed; // percent of checks that passed int executed; // was the test executed? int pass; // did the test pass? (i.e. no failures) } autotest_t; // define package_t typedef struct { unsigned int id; // package identification unsigned int index; // index of first autotest unsigned int num_scripts; // number of tests in package const char* name; // package name int executed; // were any tests executed? } package_t; // include auto-generated autotest header // // defines the following symbols: // #define AUTOSCRIPT_VERSION // #define NUM_AUTOSCRIPTS // autotest_t scripts[NUM_AUTOSCRIPTS] // #define NUM_PACKAGES // struct package_t packages[NUM_PACKAGES] #include "../autotest_include.h" // // helper functions: // // execute a specific test void execute_autotest(autotest_t * _test, int _verbose); // execute a specific package void execute_package(package_t * _p, int _verbose); // execute a specific package if string matches void execute_package_search(package_t * _p, char * _str, int _verbose); // print all autotest results void print_autotest_results(autotest_t * _test); // print the results of a particular package void print_package_results(package_t * _p); // print all unstable tests (those which failed or gave warnings) void print_unstable_tests(void); // print list of tests void print_test_list(void); // print list of packages void print_package_list(void); // print basic autotest results to stdout int export_results(char * _filename); // main function int main(int argc, char *argv[]) { // options enum {RUN_ALL, // run all tests RUN_ALL_RANDOM, // run all tests (random order) RUN_SINGLE_TEST, // run just a single test RUN_SINGLE_PACKAGE, // run just a single package RUN_SEARCH } mode = RUN_ALL; // set defaults unsigned int autotest_id = 0; unsigned int package_id = 0; int verbose = 1; int stop_on_fail = 0; int rseed = 0; char search_string[128] = ""; char filename[256] = ""; unsigned int i; // get input options int d; while((d = getopt(argc,argv,"ht:p:rLlxs:vqo:")) != EOF){ switch (d) { case 'h': usage(); return 0; case 't': autotest_id = atoi(optarg); mode = RUN_SINGLE_TEST; break; case 'p': package_id = atoi(optarg); mode = RUN_SINGLE_PACKAGE; break; case 'r': mode = RUN_ALL_RANDOM; break; case 'L': // list packages, scripts and exit print_test_list(); return 0; case 'l': // list only packages and exit print_package_list(); return 0; case 'x': stop_on_fail = 1; break; case 's': mode = RUN_SEARCH; strncpy(search_string, optarg, 128); search_string[127] = '\0'; break; case 'v': verbose = 1; liquid_autotest_verbose = 1; break; case 'q': verbose = 0; liquid_autotest_verbose = 0; break; case 'o': strncpy(filename,optarg,255); filename[255] = '\0'; break; default: return 1; } } // validate results if (autotest_id >= NUM_AUTOSCRIPTS) { printf("error, cannot run autotest %u; index exceeded\n", autotest_id); return -1; } else if (package_id >= NUM_PACKAGES) { printf("error, cannot run package %u; index exceeded\n", package_id); return -1; } unsigned int n=0; switch (mode) { case RUN_ALL: for (i=0; i 0) break; } for (i=0; i= NUM_AUTOSCRIPTS) i %= NUM_AUTOSCRIPTS; } printf("executing test %4u (%4u / %4u)\n", i, n+1, NUM_AUTOSCRIPTS); execute_autotest( &scripts[i], verbose ); n++; if (stop_on_fail && liquid_autotest_num_failed > 0) break; } for (i=0; iapi(); _test->num_passed = liquid_autotest_num_passed - autotest_num_passed_init; _test->num_failed = liquid_autotest_num_failed - autotest_num_failed_init; _test->num_warnings = liquid_autotest_num_warnings - autotest_num_warnings_init; _test->num_checks = _test->num_passed + _test->num_failed; _test->pass = (_test->num_failed==0) ? 1 : 0; if (_test->num_checks > 0) _test->percent_passed = 100.0f * (float) (_test->num_passed) / (float) (_test->num_checks); else _test->percent_passed = 0.0f; _test->executed = 1; //if (_verbose) // print_autotest_results(_test); } // execute a specific package // _p : pointer to package object // _verbose : verbose output flag void execute_package(package_t * _p, int _verbose) { if (_verbose) printf("%u: %s\n", _p->id, _p->name); unsigned int i; for (i=0; i<_p->num_scripts; i++) { execute_autotest( &scripts[ i + _p->index ], _verbose ); } _p->executed = 1; } // execute a specific package if string matches void execute_package_search(package_t * _p, char * _str, int _verbose) { // see if search string matches autotest name if (strstr(_p->name, _str) != NULL) { // run the package execute_package(_p, _verbose); } else { unsigned int i; unsigned int i0 = _p->index; unsigned int i1 = _p->num_scripts + i0; for (i=i0; iexecuted = 1; } } } } // print results of a particular test void print_autotest_results(autotest_t * _test) { if (!_test->executed) printf(" %3u : IGNORED ", _test->id); else if (_test->pass) printf(" %3u : PASS ", _test->id); else printf(" %3u : <> ", _test->id); printf("passed %4lu / %4lu checks (%5.1f%%) : %s\n", _test->num_passed, _test->num_checks, _test->percent_passed, _test->name); } // print results of a particular package void print_package_results(package_t * _p) { unsigned int i; printf("%u: %s:\n", _p->id, _p->name); for (i=_p->index; i<(_p->index+_p->num_scripts); i++) { //if ( scripts[i].executed ) // only print scripts that were executed print_autotest_results( &scripts[i] ); } printf("\n"); } // print all unstable tests (those which failed or gave warnings) void print_unstable_tests(void) { if (liquid_autotest_num_failed == 0 && liquid_autotest_num_warnings == 0) { return; } printf("==================================\n"); printf(" UNSTABLE TESTS:\n"); unsigned int t; for (t=0; t> %s\n", scripts[t].id, scripts[t].name); } if (scripts[t].num_warnings > 0) { printf(" %3u : %4lu warnings %s\n", scripts[t].id, scripts[t].num_warnings, scripts[t].name); } } } } void print_test_list(void) { unsigned int i; unsigned int j; for (i=0; i #include #include // total number of checks invoked extern unsigned long int liquid_autotest_num_checks; // total number of checks which passed extern unsigned long int liquid_autotest_num_passed; // total number of checks which failed extern unsigned long int liquid_autotest_num_failed; // total number of warnings extern unsigned long int liquid_autotest_num_warnings; // verbosity flag extern int liquid_autotest_verbose; // fail test // increment liquid_autotest_num_checks // increment liquid_autotest_num_failed void liquid_autotest_failed(); // pass test // increment liquid_autotest_num_checks // increment liquid_autotest_num_passed void liquid_autotest_passed(); // fail test, given expression // _file : filename (string) // _line : line number of test // _exprL : left side of expression (string) // _valueL : left side of expression (value) // _qualifier : expression qualifier // _exprR : right side of expression (string) // _valueR : right side of expression (value) void liquid_autotest_failed_expr(const char * _file, unsigned int _line, const char * _exprL, double _valueL, const char * _qualifier, const char * _exprR, double _valueR); // fail test with message // _file : filename (string) // _line : line number of test // _message : message string void liquid_autotest_failed_msg(const char * _file, unsigned int _line, const char * _message); // print basic autotest results to stdout void autotest_print_results(void); // export results to .json file int autotest_export_results(char * _filename); // print warning to stderr // increment liquid_autotest_num_warnings // _file : filename (string) // _line : line number of test // _message : message string void liquid_autotest_warn(const char * _file, unsigned int _line, const char * _message); // contend that data in two arrays are identical // _x : input array [size: _n x 1] // _y : input array [size: _n x 1] // _n : input array size int liquid_autotest_same_data(unsigned char * _x, unsigned char * _y, unsigned int _n); // print array to standard out // _x : input array [size: _n x 1] // _n : input array size void liquid_autotest_print_array(unsigned char * _x, unsigned int _n); // CONTEND_EQUALITY #define TEST_EQUALITY(F,L,EX,X,EY,Y) \ { \ if ((X)!=(Y)) \ { \ liquid_autotest_failed_expr(F,L,EX,X,"==",EY,Y); \ } else { \ liquid_autotest_passed(); \ } \ } #define CONTEND_EQUALITY_FL(F,L,X,Y) TEST_EQUALITY(F,L,#X,(X),#Y,(Y)) #define CONTEND_EQUALITY(X,Y) CONTEND_EQUALITY_FL(__FILE__,__LINE__,X,Y) // CONTEND_INEQUALITY #define TEST_INEQUALITY(F,L,EX,X,EY,Y) \ { \ if ((X)==(Y)) \ { \ liquid_autotest_failed_expr(F,L,EX,X,"!=",EY,Y); \ } else { \ liquid_autotest_passed(); \ } \ } #define CONTEND_INEQUALITY_FL(F,L,X,Y) TEST_INEQUALITY(F,L,#X,(X),#Y,(Y)) #define CONTEND_INEQUALITY(X,Y) CONTEND_INEQUALITY_FL(__FILE__,__LINE__,X,Y) // CONTEND_GREATER_THAN #define TEST_GREATER_THAN(F,L,EX,X,EY,Y) \ { \ if ((X)<=(Y)) \ { \ liquid_autotest_failed_expr(F,L,EX,X,">",EY,Y); \ } else { \ liquid_autotest_passed(); \ } \ } #define CONTEND_GREATER_THAN_FL(F,L,X,Y) TEST_GREATER_THAN(F,L,#X,(X),#Y,(Y)) #define CONTEND_GREATER_THAN(X,Y) CONTEND_GREATER_THAN_FL(__FILE__,__LINE__,X,Y) // CONTEND_LESS_THAN #define TEST_LESS_THAN(F,L,EX,X,EY,Y) \ { \ if ((X)>=(Y)) \ { \ liquid_autotest_failed_expr(F,L,EX,X,">",EY,Y); \ } else { \ liquid_autotest_passed(); \ } \ } #define CONTEND_LESS_THAN_FL(F,L,X,Y) TEST_LESS_THAN(F,L,#X,(X),#Y,(Y)) #define CONTEND_LESS_THAN(X,Y) CONTEND_LESS_THAN_FL(__FILE__,__LINE__,X,Y) // CONTEND_DELTA #define TEST_DELTA(F,L,EX,X,EY,Y,ED,D) \ { \ if (fabs((X)-(Y))>(D)) \ { \ liquid_autotest_failed_expr(F,L,"abs(" #X "-" #Y ")", \ fabs(X-Y),"<",ED,D); \ } else { \ liquid_autotest_passed(); \ } \ } #define CONTEND_DELTA_FL(F,L,X,Y,D) TEST_DELTA(F,L,#X,(X),#Y,(Y),#D,(D)) #define CONTEND_DELTA(X,Y,D) CONTEND_DELTA_FL(__FILE__,__LINE__,X,Y,D) // CONTEND_EXPRESSION #define TEST_EXPRESSION(F,L,EX,X) \ { \ if (!X) \ { \ liquid_autotest_failed_expr(F,L,#X,(X),"is","1",1); \ } else { \ liquid_autotest_passed(); \ } \ } #define CONTEND_EXPRESSION_FL(F,L,X) TEST_EXPRESSION(F,L,#X,(X)) #define CONTEND_EXPRESSION(X) CONTEND_EXPRESSION_FL(__FILE__,__LINE__,X) // CONTEND_SAME_DATA #define TEST_SAME_DATA(F,L,EX,X,EY,Y,EN,N) \ { \ if (!liquid_autotest_same_data((uint8_t*)(X),(uint8_t*)(Y),(N))) \ { \ liquid_autotest_failed_msg(F,L,EX "[] != " EY "[] for " EN " bytes"); \ if (liquid_autotest_verbose) \ { \ liquid_autotest_print_array((uint8_t*)(X),N); \ liquid_autotest_print_array((uint8_t*)(Y),N); \ } \ } else { \ liquid_autotest_passed(); \ } \ } #define CONTEND_SAME_DATA_FL(F,L,X,Y,N) TEST_SAME_DATA(F,L,#X,(X),#Y,(Y),#N,(N)) #define CONTEND_SAME_DATA(X,Y,N) CONTEND_SAME_DATA_FL(__FILE__,__LINE__,X,Y,N) // AUTOTEST WARN #define AUTOTEST_WARN_FL(F,L,MSG) liquid_autotest_warn(F,L,#MSG) #define AUTOTEST_WARN(MSG) AUTOTEST_WARN_FL(__FILE__,__LINE__,MSG) // AUTOTEST PASS #define AUTOTEST_PASS_FL(F,L) liquid_autotest_passed() #define AUTOTEST_PASS() AUTOTEST_PASS_FL(__FILE__,__LINE__) // AUTOTEST FAIL #define AUTOTEST_FAIL_FL(F,L,MSG) liquid_autotest_failed_msg(F,L,MSG) #define AUTOTEST_FAIL(MSG) AUTOTEST_FAIL_FL(__FILE__,__LINE__,MSG) #endif // __LIQUID_AUTOTEST_H__ liquid-dsp-1.3.1/autotest/autotestlib.c000066400000000000000000000131241317124540100201410ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotestlib.c // // default include headers #include #include #include "autotest/autotest.h" // total number of checks invoked unsigned long int liquid_autotest_num_checks=0; // total number of checks which passed unsigned long int liquid_autotest_num_passed=0; // total number of checks which failed unsigned long int liquid_autotest_num_failed=0; // total number of warnings unsigned long int liquid_autotest_num_warnings=0; // verbosity flag int liquid_autotest_verbose = 1; // fail test // increment liquid_autotest_num_checks // increment liquid_autotest_num_failed void liquid_autotest_failed() { liquid_autotest_num_checks++; liquid_autotest_num_failed++; } // pass test // increment liquid_autotest_num_checks // increment liquid_autotest_num_passed void liquid_autotest_passed() { liquid_autotest_num_checks++; liquid_autotest_num_passed++; } // fail test, given expression // _file : filename (string) // _line : line number of test // _exprL : left side of expression (string) // _valueL : left side of expression (value) // _qualifier : expression qualifier // _exprR : right side of expression (string) // _valueR : right side of expression (value) void liquid_autotest_failed_expr(const char * _file, unsigned int _line, const char * _exprL, double _valueL, const char * _qualifier, const char * _exprR, double _valueR) { if (liquid_autotest_verbose) { printf(" TEST FAILED: %s line %u : expected %s (%0.2E) %s %s (%0.2E)\n", _file, _line, _exprL, _valueL, _qualifier, _exprR, _valueR); } liquid_autotest_failed(); } // _file : filename (string) // _line : line number of test // _message : message string void liquid_autotest_failed_msg(const char * _file, unsigned int _line, const char * _message) { if (liquid_autotest_verbose) printf(" TEST FAILED: %s line %u : %s\n", _file, _line, _message); liquid_autotest_failed(); } // print basic autotest results to stdout void autotest_print_results(void) { if (liquid_autotest_num_warnings > 0) { printf("==================================\n"); printf(" WARNINGS : %-lu\n", liquid_autotest_num_warnings); } printf("==================================\n"); if (liquid_autotest_num_checks==0) { printf(" NO CHECKS RUN\n"); } else if (liquid_autotest_num_failed==0) { printf(" PASSED ALL %lu CHECKS\n", liquid_autotest_num_passed); } else { // compute and print percentage of failed tests double percent_failed = (double) liquid_autotest_num_failed / (double) liquid_autotest_num_checks; printf(" FAILED %lu / %lu CHECKS (%7.2f%%)\n", liquid_autotest_num_failed, liquid_autotest_num_checks, 100.0*percent_failed); } printf("==================================\n"); } // print warning to stderr // increment liquid_autotest_num_warnings // _file : filename (string) // _line : line number of test // _message : message string void liquid_autotest_warn(const char * _file, unsigned int _line, const char * _message) { if (liquid_autotest_verbose) fprintf(stderr," WARNING: %s line %u : %s\n", _file, _line, _message); liquid_autotest_num_warnings++; } // contend that data in two arrays are identical // _x : input array [size: _n x 1] // _y : input array [size: _n x 1] // _n : input array size int liquid_autotest_same_data(unsigned char * _x, unsigned char * _y, unsigned int _n) { unsigned int i; for (i=0; i<_n; i++) { if (_x[i] != _y[i]) return 0; } return 1; } // print array to standard out // _x : input array [size: _n x 1] // _n : input array size void liquid_autotest_print_array(unsigned char * _x, unsigned int _n) { unsigned int i; printf(" {"); for (i=0; i<_n; i++) { printf("%.2x, ", (unsigned int)(_x[i])); if ( ((i+1)%16 == 0) && (i != (_n-1)) ) printf("\n "); } printf("}\n"); } liquid-dsp-1.3.1/autotest/null_autotest.c000066400000000000000000000023121317124540100205010ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest.h" void autotest_null() { // pass unconditionally AUTOTEST_PASS(); } liquid-dsp-1.3.1/bench/000077500000000000000000000000001317124540100146445ustar00rootroot00000000000000liquid-dsp-1.3.1/bench/bench.c000066400000000000000000000400711317124540100160710ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // bench.c // // This file is used in conjunction with benchinclude.h (generated with // benchmarkgen.py) to produce an executable for benchmarking the various // signal processing algorithms in liquid. // // default include headers #include #include #include #include #include #include // define benchmark function pointer typedef void(benchmark_function_t) ( struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations); // define benchmark_t typedef struct { unsigned int id; benchmark_function_t * api; const char* name; unsigned int name_len; unsigned int num_trials; float extime; float rate; float cycles_per_trial; } benchmark_t; // define package_t typedef struct { unsigned int id; // package identification unsigned int index; // index of first benchmark unsigned int num_scripts; // number of tests in package const char* name; // package name } package_t; // include auto-generated benchmark header // // defines the following symbols: // #define AUTOSCRIPT_VERSION // #define NUM_AUTOSCRIPTS // benchmark_t scripts[NUM_AUTOSCRIPTS] // #define NUM_PACKAGES // package_t packages[NUM_PACKAGES] #include "benchmark_include.h" // helper functions: void estimate_cpu_clock(void); void set_num_trials_from_cpu_speed(void); void execute_benchmark(benchmark_t* _benchmark, int _verbose); void execute_package(package_t* _package, int _verbose); char convert_units(float * _s); void print_benchmark_results(benchmark_t* _benchmark); void print_package_results(package_t* _package); double calculate_execution_time(struct rusage, struct rusage); unsigned long int num_base_trials = 1<<12; float cpu_clock = 1.0f; // cpu clock speed (Hz) float runtime=0.100f; // minimum run time (s) FILE * fid; // output file id void output_benchmark_to_file(FILE * _fid, benchmark_t * _benchmark); void usage() { // help printf("Usage: benchmark [OPTION]\n"); printf("Execute benchmark scripts for liquid-dsp library.\n"); printf(" -h,-u display this help and exit\n"); printf(" -v verbose\n"); printf(" -q quiet\n"); printf(" -e estimate cpu clock frequency and exit\n"); printf(" -c set cpu clock frequency (Hz)\n"); printf(" -n[COUNT] set number of base trials\n"); printf(" -p[ID] run specific package\n"); printf(" -b[ID] run specific benchmark\n"); printf(" -t[SECONDS] set minimum execution time (s)\n"); printf(" -l list available packages\n"); printf(" -L list all available scripts\n"); printf(" -s[STRING] run all packages/benchmarks matching search string\n"); printf(" -o[FILENAME] export output\n"); } // main function int main(int argc, char *argv[]) { // initialize timing variables unsigned int i, j; // options enum {RUN_ALL, RUN_SINGLE_BENCH, RUN_SINGLE_PACKAGE, RUN_SEARCH, } mode = RUN_ALL; unsigned int benchmark_id = 0; unsigned int package_id = 0; int verbose = 1; int autoscale = 1; int cpu_clock_detect = 1; int output_to_file = 0; char filename[128]; char search_string[128]; // get input options int d; while((d = getopt(argc,argv,"uhvqec:n:b:p:t:lLs:o:")) != EOF){ switch (d) { case 'u': case 'h': usage(); return 0; case 'v': verbose = 1; break; case 'q': verbose = 0; break; case 'e': estimate_cpu_clock(); return 0; case 'c': cpu_clock = atof(optarg); if (cpu_clock < 0) { printf("error: cpu clock speed is negative (%f)\n", cpu_clock); return -1; } cpu_clock_detect = 0; break; case 'n': num_base_trials = atoi(optarg); autoscale = 0; break; case 'b': benchmark_id = atoi(optarg); if (benchmark_id >= NUM_AUTOSCRIPTS) { printf("error, cannot run benchmark %u; index exceeded\n", benchmark_id); return -1; } else { mode = RUN_SINGLE_BENCH; } break; case 'p': package_id = atoi(optarg); if (package_id >= NUM_PACKAGES) { printf("error, cannot run package %u; index exceeded\n", package_id); return -1; } else { mode = RUN_SINGLE_PACKAGE; } break; case 't': runtime = atof(optarg); if (runtime < 1e-3f) runtime = 1e-3f; else if (runtime > 10.f) runtime = 10.0f; printf("minimum runtime: %d ms\n", (int) roundf(runtime*1e3)); break; case 'l': // list only packages and exit for (i=0; i 0) output_benchmark_to_file(fid, &scripts[i]); } fclose(fid); printf("results written to %s\n", filename); } return 0; } // run basic benchmark to estimate CPU clock frequency void estimate_cpu_clock(void) { printf(" estimating cpu clock frequency...\n"); unsigned long int i, n = 1<<4; struct rusage start, finish; double extime; // run trials until execution time threshold is exceeded do { // trials n <<= 1; // NOTE: Smart compilers will realize that this loop doesn't really do // anything, so they won't actually compute anything. We need to // actually do something interesting here to trick the compiler // into actually crunching these numbers, and then later display // the results, even if they're meaningless unsigned int k = 366001; // large prime number unsigned int g = 184903; // another large prime number unsigned int s = 1; getrusage(RUSAGE_SELF, &start); for (i=0; iapi(&start, &finish, &num_trials); _benchmark->extime = calculate_execution_time(start, finish); // check exit criteria if (_benchmark->extime >= runtime) { break; } else if (num_attempts == 30) { fprintf(stderr,"warning: benchmark could not execute over minimum run time\n"); break; } else { // increase number of trials n *= 2; } } while (1); _benchmark->num_trials = num_trials; _benchmark->rate = (float)(_benchmark->num_trials) / _benchmark->extime; _benchmark->cycles_per_trial = cpu_clock / (_benchmark->rate); if (_verbose) print_benchmark_results(_benchmark); } void execute_package(package_t* _package, int _verbose) { if (_verbose) printf("%u: %s\n", _package->id, _package->name); unsigned int i; for (i=0; i<_package->num_scripts; i++) { execute_benchmark( &scripts[ i + _package->index ], _verbose ); } } // convert raw value into metric units, // example: "0.01397s" -> "13.97 ms" char convert_units(float * _v) { char unit; if (*_v < 1e-9) { (*_v) *= 1e12; unit = 'p';} else if (*_v < 1e-6){ (*_v) *= 1e9; unit = 'n';} else if (*_v < 1e-3){ (*_v) *= 1e6; unit = 'u';} else if (*_v < 1e+0){ (*_v) *= 1e3; unit = 'm';} else if (*_v < 1e3) { (*_v) *= 1e+0; unit = ' ';} else if (*_v < 1e6) { (*_v) *= 1e-3; unit = 'k';} else if (*_v < 1e9) { (*_v) *= 1e-6; unit = 'M';} else if (*_v < 1e12){ (*_v) *= 1e-9; unit = 'G';} else { (*_v) *= 1e-12; unit = 'T';} return unit; } void print_benchmark_results(benchmark_t* _b) { // format trials (iterations) float trials_format = (float)(_b->num_trials); char trials_units = convert_units(&trials_format); // format time (seconds) float extime_format = _b->extime; char extime_units = convert_units(&extime_format); // format rate (trials/second) float rate_format = _b->rate; char rate_units = convert_units(&rate_format); // format processor efficiency (cycles/trial) float cycles_format = _b->cycles_per_trial; char cycles_units = convert_units(&cycles_format); printf(" %-3u: %-30s: %6.2f %c trials / %6.2f %cs (%6.2f %c t/s, %6.2f %c c/t)\n", _b->id, _b->name, trials_format, trials_units, extime_format, extime_units, rate_format, rate_units, cycles_format, cycles_units); } void print_package_results(package_t* _package) { unsigned int i; printf("%u: %s:\n", _package->id, _package->name); for (i=_package->index; i<(_package->index+_package->num_scripts); i++) print_benchmark_results( &scripts[i] ); printf("\n"); } double calculate_execution_time(struct rusage _start, struct rusage _finish) { return _finish.ru_utime.tv_sec - _start.ru_utime.tv_sec + 1e-6*(_finish.ru_utime.tv_usec - _start.ru_utime.tv_usec) + _finish.ru_stime.tv_sec - _start.ru_stime.tv_sec + 1e-6*(_finish.ru_stime.tv_usec - _start.ru_stime.tv_usec); } void output_benchmark_to_file(FILE * _fid, benchmark_t * _benchmark) { fprintf(_fid," %-5u %-30s %12u %12.4e %12.4e %12.4e\n", _benchmark->id, _benchmark->name, _benchmark->num_trials, _benchmark->extime, _benchmark->rate, _benchmark->cycles_per_trial); } liquid-dsp-1.3.1/bench/example_benchmark.h000066400000000000000000000035251317124540100204670ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Example of a benchmark header // #include #include // strings parsed by benchmarkgen.py const char * mybench_opts[3] = { "opt1a opt1b", "opt2a opt2b opt2c", "opt3a opt3b opt3c" }; void benchmark_mybench( struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) // unsigned int argc, // char *argv[]) { // DSP initiazation goes here unsigned int i; float x, y, theta; getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { // DSP execution goes here x = cosf(M_PI/2.0f); y = sinf(M_PI/2.0f); theta = atan2(y,x); } getrusage(RUSAGE_SELF, _finish); // DSP cleanup goes here } liquid-dsp-1.3.1/bench/fftbench.c000066400000000000000000000434621317124540100166000ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fftbench.c : benchmark fft algorithms // // default include headers #include #include #include #include #include #include #include #include #include "liquid.h" void usage() { // help printf("Usage: benchmark [OPTION]\n"); printf("Execute benchmark scripts for liquid-dsp library.\n"); printf(" -h display this help and exit\n"); printf(" -v/q verbose/quiet\n"); printf(" -t[SECONDS] set minimum execution time (s)\n"); printf(" -o[FILENAME] export output\n"); printf(" -n[NFFT_MIN] minimum FFT size (benchmark single FFT)\n"); printf(" -N[NFFT_MAX] maximum FFT size\n"); printf(" -m[MODE] mode: all, radix2, composite, prime, fftwbench, single\n"); printf(" -l[library] library: float, fftw\n"); } // benchmark structure struct benchmark_s { // fft options unsigned int nfft; // FFT size int direction; // FFT direction int flags; // FFT flags/method // benchmark results unsigned int num_trials; // number of trials float extime; // execution time // derived values float time_per_trial; // execution time per trial float flops; // computation bandwidth }; typedef enum { LIB_FLOAT=0, LIB_FFTW, } library_t; // simulation structure struct fftbench_s { enum {RUN_ALL=0, RUN_RADIX2, RUN_COMPOSITE, RUN_PRIME, RUN_FFTWBENCH, RUN_SINGLE, } mode; // library version library_t library; int verbose; float runtime; // minimum run time (s) // min/max sizes for other modes unsigned int nfft_min; // minimum FFT size (also, size for RUN_SINGLE mode) unsigned int nfft_max; // maximum FFT size // output file char filename[128]; // output filename FILE * fid; // output file pointer int output_to_file; // output file write flag }; // helper functions: char convert_units(float * _s); double calculate_execution_time(struct rusage, struct rusage); // run all benchmarks void fftbench_execute(struct fftbench_s * _fftbench); // execute single benchmark void execute_benchmark_fft(struct benchmark_s * _benchmark, float _runtime, library_t _library); // main benchmark script (floating-point precision) void benchmark_fft(struct rusage * _start, struct rusage * _finish, struct benchmark_s * _benchmark); // main benchmark script (FFTW) void benchmark_fftw(struct rusage * _start, struct rusage * _finish, struct benchmark_s * _benchmark); void benchmark_print_to_file(FILE * _fid, struct benchmark_s * _benchmark); void benchmark_print(struct benchmark_s * _benchmark); // main function int main(int argc, char *argv[]) { // options struct fftbench_s fftbench; fftbench.mode = RUN_RADIX2; fftbench.library = LIB_FLOAT; fftbench.verbose = 1; fftbench.runtime = 0.1f; fftbench.nfft_min = 2; fftbench.nfft_max = 1024; fftbench.filename[0]= '\0'; fftbench.fid = NULL; fftbench.output_to_file = 0; // get input options int d; while((d = getopt(argc,argv,"hvqn:N:t:o:m:l:")) != EOF){ switch (d) { case 'h': usage(); return 0; case 'v': fftbench.verbose = 1; break; case 'q': fftbench.verbose = 0; break; case 'n': fftbench.nfft_min = atoi(optarg); break; case 'N': fftbench.nfft_max = atoi(optarg); break; case 't': fftbench.runtime = atof(optarg); if (fftbench.runtime < 1e-3f) fftbench.runtime = 1e-3f; else if (fftbench.runtime > 10.f) fftbench.runtime = 10.0f; printf("minimum runtime: %d ms\n", (int) roundf(fftbench.runtime*1e3)); break; case 'o': fftbench.output_to_file = 1; strcpy(fftbench.filename, optarg); break; case 'm': if (strcmp(optarg,"all")==0) fftbench.mode = RUN_ALL; else if (strcmp(optarg,"radix2")==0) fftbench.mode = RUN_RADIX2; else if (strcmp(optarg,"composite")==0) fftbench.mode = RUN_COMPOSITE; else if (strcmp(optarg,"prime")==0) fftbench.mode = RUN_PRIME; else if (strcmp(optarg,"fftwbench")==0) fftbench.mode = RUN_FFTWBENCH; else if (strcmp(optarg,"single")==0) fftbench.mode = RUN_SINGLE; else { fprintf(stderr,"error: %s, unknown mode '%s'\n", argv[0], optarg); exit(1); } break; case 'l': if (strcmp(optarg,"float")==0) fftbench.library = LIB_FLOAT; else if (strcmp(optarg,"fftw")==0) fftbench.library = LIB_FFTW; else { fprintf(stderr,"error: %s, unknown library option '%s'\n", argv[0], optarg); exit(1); } break; default: usage(); return 0; } } // run empty loop; a bug was found that sometimes the first package run // resulted in a longer execution time than what the benchmark really // reflected. This loop prevents that from happening. unsigned int i; for (i=0; i<1e6; i++) { // do nothing } // open output file (if applicable) if (fftbench.output_to_file) { fftbench.fid = fopen(fftbench.filename,"w"); if (!fftbench.fid) { fprintf(stderr,"error: %s, could not open file '%s' for writing\n", argv[0], fftbench.filename); exit(1); } FILE * fid = fftbench.fid; // print header fprintf(fid,"# %s : auto-generated file\n", fftbench.filename); fprintf(fid,"#\n"); fprintf(fid,"# invoked as:\n"); fprintf(fid,"# "); for (i=0; i "13.97 ms" char convert_units(float * _v) { char unit; if (*_v < 1e-9) { (*_v) *= 1e12; unit = 'p';} else if (*_v < 1e-6){ (*_v) *= 1e9; unit = 'n';} else if (*_v < 1e-3){ (*_v) *= 1e6; unit = 'u';} else if (*_v < 1e+0){ (*_v) *= 1e3; unit = 'm';} else if (*_v < 1e3) { (*_v) *= 1e+0; unit = ' ';} else if (*_v < 1e6) { (*_v) *= 1e-3; unit = 'k';} else if (*_v < 1e9) { (*_v) *= 1e-6; unit = 'M';} else if (*_v < 1e12){ (*_v) *= 1e-9; unit = 'G';} else { (*_v) *= 1e-12; unit = 'T';} return unit; } double calculate_execution_time(struct rusage _start, struct rusage _finish) { return _finish.ru_utime.tv_sec - _start.ru_utime.tv_sec + 1e-6*(_finish.ru_utime.tv_usec - _start.ru_utime.tv_usec) + _finish.ru_stime.tv_sec - _start.ru_stime.tv_sec + 1e-6*(_finish.ru_stime.tv_usec - _start.ru_stime.tv_usec); } // run all benchmarks void fftbench_execute(struct fftbench_s * _fftbench) { // validate input if (_fftbench->nfft_min > _fftbench->nfft_max && _fftbench->mode != RUN_SINGLE) { fprintf(stderr,"execute_benchmarks_composite(), nfft_min cannot be greater than nfft_max\n"); exit(1); } else if (_fftbench->runtime <= 0.0f) { fprintf(stderr,"execute_benchmarks_composite(), runtime must be greater than zero\n"); exit(1); } // create benchmark structure struct benchmark_s benchmark; if (_fftbench->mode == RUN_SINGLE) { // run single benchmark and exit // initialize benchmark structure benchmark.nfft = _fftbench->nfft_min; benchmark.direction = LIQUID_FFT_FORWARD; benchmark.num_trials = 1; benchmark.flags = 0; benchmark.extime = 0.0f; benchmark.flops = 0.0f; // run the benchmark execute_benchmark_fft(&benchmark, _fftbench->runtime, _fftbench->library); benchmark_print(&benchmark); return; } else if (_fftbench->mode == RUN_FFTWBENCH) { printf("running composite FFTs from FFTW benchmark\n"); unsigned int nfftw[18] = {6,9,12,15,18,24,36,80,108,210,504, 1000,1960,4725,10368,27000,75600,165375}; unsigned int i; for (i=0; i<18; i++) { // initialize benchmark structure benchmark.nfft = nfftw[i]; benchmark.direction = LIQUID_FFT_FORWARD; benchmark.num_trials = 1; benchmark.flags = 0; // run the benchmark execute_benchmark_fft(&benchmark, _fftbench->runtime, _fftbench->library); benchmark_print(&benchmark); if (_fftbench->output_to_file) benchmark_print_to_file(_fftbench->fid, &benchmark); } return; } else if (_fftbench->mode == RUN_RADIX2) { printf("running all power-of-two FFTs from %u to %u:\n", _fftbench->nfft_min, _fftbench->nfft_max); unsigned int nfft = 1 << liquid_nextpow2(_fftbench->nfft_min); while ( nfft <= _fftbench->nfft_max) { // initialize benchmark structure benchmark.nfft = nfft; benchmark.direction = LIQUID_FFT_FORWARD; benchmark.num_trials = 1; benchmark.flags = 0; // run the benchmark execute_benchmark_fft(&benchmark, _fftbench->runtime, _fftbench->library); benchmark_print(&benchmark); if (_fftbench->output_to_file) benchmark_print_to_file(_fftbench->fid, &benchmark); nfft *= 2; }; return; } printf("running "); switch (_fftbench->mode) { case RUN_ALL: printf("all"); break; case RUN_COMPOSITE: printf("all composite"); break; case RUN_PRIME: printf("all prime"); break; case RUN_SINGLE: default:; } printf(" FFTs from %u to %u:\n", _fftbench->nfft_min, _fftbench->nfft_max); unsigned int nfft; for (nfft=_fftbench->nfft_min; nfft<=_fftbench->nfft_max; nfft++) { int isprime = liquid_is_prime(nfft); int isradix2 = (1 << liquid_nextpow2(nfft))==nfft ? 1 : 0; // check run mode if (_fftbench->mode == RUN_COMPOSITE && (isprime || isradix2)) continue; if (_fftbench->mode == RUN_PRIME && !isprime) continue; // run the transform benchmark.nfft = nfft; benchmark.direction = LIQUID_FFT_FORWARD; benchmark.num_trials = 1; benchmark.flags = 0; benchmark.extime = 0.0f; benchmark.flops = 0.0f; execute_benchmark_fft(&benchmark, _fftbench->runtime, _fftbench->library); if (_fftbench->verbose) benchmark_print(&benchmark); if (_fftbench->output_to_file) benchmark_print_to_file(_fftbench->fid, &benchmark); } } // execute single benchmark void execute_benchmark_fft(struct benchmark_s * _benchmark, float _runtime, library_t _library) { unsigned long int n = _benchmark->num_trials; struct rusage start, finish; unsigned int num_attempts = 0; do { // increment number of attempts num_attempts++; // set number of trials and run benchmark _benchmark->num_trials = n; // run appropriate library switch (_library) { case LIB_FLOAT: benchmark_fft(&start, &finish, _benchmark); break; case LIB_FFTW: benchmark_fftw(&start, &finish, _benchmark); break; default: fprintf(stderr,"error: execute_benchmark_fft(), invalid library\n"); exit(1); } // calculate execution time _benchmark->extime = calculate_execution_time(start, finish); // check exit criteria if (_benchmark->extime >= _runtime) { break; } else if (num_attempts == 30) { fprintf(stderr,"warning: benchmark could not execute over minimum run time\n"); break; } else { // increase number of trials n *= 2; } } while (1); // compute time per trial _benchmark->time_per_trial = _benchmark->extime / (float)_benchmark->num_trials; // computational bandwidth (see: http://www.fftw.org/speed/) _benchmark->flops = 5.0f * _benchmark->nfft * log2f(_benchmark->nfft) / _benchmark->time_per_trial; } // main benchmark script void benchmark_fft(struct rusage * _start, struct rusage * _finish, struct benchmark_s * _benchmark) { // initialize arrays, plan float complex * x = (float complex *) malloc((_benchmark->nfft)*sizeof(float complex)); float complex * y = (float complex *) malloc((_benchmark->nfft)*sizeof(float complex)); fftplan q = fft_create_plan(_benchmark->nfft, x, y, _benchmark->direction, _benchmark->flags); unsigned long int i; // initialize input with random values for (i=0; i<_benchmark->nfft; i++) x[i] = randnf() + randnf()*_Complex_I; // scale number of iterations to keep execution time // relatively linear unsigned int num_iterations = _benchmark->num_trials; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; inum_trials = num_iterations * 4; fft_destroy_plan(q); free(x); free(y); } // main benchmark script (FFTW) void benchmark_fftw(struct rusage * _start, struct rusage * _finish, struct benchmark_s * _benchmark) { // initialize arrays, plan float complex * x = (float complex *) malloc((_benchmark->nfft)*sizeof(float complex)); float complex * y = (float complex *) malloc((_benchmark->nfft)*sizeof(float complex)); fftwf_plan q = fftwf_plan_dft_1d(_benchmark->nfft, x, y, //_benchmark->direction, FFTW_FORWARD, FFTW_ESTIMATE); unsigned long int i; // initialize input with random values for (i=0; i<_benchmark->nfft; i++) x[i] = randnf() + randnf()*_Complex_I; // scale number of iterations to keep execution time // relatively linear unsigned int num_iterations = _benchmark->num_trials; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; inum_trials = num_iterations * 4; fftwf_destroy_plan(q); free(x); free(y); } void benchmark_print_to_file(FILE * _fid, struct benchmark_s * _benchmark) { fprintf(_fid," %12u %12u %12.4e %12.6f %12.3f\n", _benchmark->nfft, _benchmark->num_trials, _benchmark->extime, _benchmark->time_per_trial * 1e6f, _benchmark->flops * 1e-6f); } void benchmark_print(struct benchmark_s * _benchmark) { // format time/trial float time_format = _benchmark->time_per_trial; char time_units = convert_units(&time_format); printf(" %12u: %12u trials / %10.3f ms (%10.3f %cs/t) > %10.3f M flops\n", _benchmark->nfft, _benchmark->num_trials, _benchmark->extime * 1e3f, time_format, time_units, _benchmark->flops * 1e-6f); } liquid-dsp-1.3.1/bench/main.c000066400000000000000000000031231317124540100157330ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // bench/main.c // // Benchmark generator script #include #include #include #include "benchmarkgen.h" int main(int argc, char*argv[]) { // create benchmarkgen object benchmarkgen q = benchmarkgen_create(); // parse files int i; for (i=1; i // null benchmark void benchmark_null(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { unsigned long int i; *_num_iterations *= 100; getrusage(RUSAGE_SELF, _start); unsigned int x = 0; for (i=0; i<*_num_iterations; i++) { // perform mindless task x <<= 1; x |= 1; x &= 0xff; x ^= 0xff; } getrusage(RUSAGE_SELF, _finish); } liquid-dsp-1.3.1/bootstrap.sh000077500000000000000000000024751317124540100161510ustar00rootroot00000000000000#!/bin/sh # Copyright (c) 2007 - 2016 Joseph Gaeddert # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # # bootstrap.sh # # This is the bootstrapping script to auto-generate a configure # script for checking build environments, etc. # rm -f config.cache aclocal.m4 aclocal autoconf autoheader #automake --foreign --add-missing liquid-dsp-1.3.1/configure.ac000066400000000000000000000236441317124540100160640ustar00rootroot00000000000000# Copyright (c) 2007 - 2017 Joseph Gaeddert # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # # liquid-dsp library configure # Process with autoconf to generate configure script # AC_INIT([liquid-dsp],[1.2.0],[support@liquidsdr.org]) AC_CONFIG_SRCDIR([src/libliquid.c]) AC_CONFIG_MACRO_DIR([scripts]) # permit auxiliary scripts directory (e.g. config.sub, config.guess, install-sh) AC_CONFIG_AUX_DIR(scripts/) # Specify 'C' language AC_LANG(C) # uncomment the following line to reset "CFLAGS" variable; it defaults to '-g -O2' #: ${CFLAGS=""} # Autoheader AH_TEMPLATE([LIQUID_FFTOVERRIDE], [Force internal FFT even if libfftw is available]) AH_TEMPLATE([LIQUID_SIMDOVERRIDE], [Force overriding of SIMD (use portable C code)]) AC_CONFIG_HEADER(config.h) AH_TOP([ #ifndef __LIQUID_CONFIG_H__ #define __LIQUID_CONFIG_H__ ]) AH_BOTTOM([ #endif // __LIQUID_CONFIG_H__ ]) # Configure options AC_ARG_ENABLE(debug-messages, AS_HELP_STRING([--enable-debug-messages],[enable verbose debug messages (-DDEBUG)]), [DEBUG_MSG_OPTION="-DDEBUG"], [DEBUG_MSG_OPTION=""] ) AC_ARG_ENABLE(simdoverride, AS_HELP_STRING([--enable-simdoverride],[use portable C code for dotprod, etc. even if SIMD extensions are available]), [AC_DEFINE(LIQUID_SIMDOVERRIDE)], [], ) AC_ARG_ENABLE(fftoverride, AS_HELP_STRING([--enable-fftoverride],[use internal fft even if libfftw is available]), [AC_DEFINE(LIQUID_FFTOVERRIDE)], [], ) # Check for necessary programs AC_PROG_CC AC_PROG_SED AC_PROG_GREP AC_PROG_INSTALL AC_PROG_RANLIB AN_MAKEVAR([AR], [AC_PROG_AR]) AN_PROGRAM([ar], [AC_PROG_AR]) AC_DEFUN([AC_PROG_AR], [AC_CHECK_TOOL(AR, ar, :)]) AC_PROG_AR # Check for necessary libraries, library functions AC_FUNC_ERROR_AT_LINE AC_FUNC_MALLOC AC_FUNC_REALLOC # AC_CHECK_LIB (library, function, [action-if-found], [action-if-not-found], [other-libraries]) AC_CHECK_LIB([c],[main], [],[AC_MSG_ERROR(Could not use standard C library)], []) AC_CHECK_LIB([m],[main], [],[AC_MSG_ERROR(Could not use standard math library)],[]) # AC_CHECK_FUNC(function, [action-if-found], [action-if-not-found]) AC_CHECK_FUNC([malloc], [],[AC_MSG_ERROR(Could not use malloc())]) AC_CHECK_FUNC([realloc], [],[AC_MSG_ERROR(Could not use realloc())],) AC_CHECK_FUNC([free], [],[AC_MSG_ERROR(Could not use free())],) AC_CHECK_FUNC([memset], [],[AC_MSG_ERROR(Could not use memset())],) AC_CHECK_FUNC([memmove], [],[AC_MSG_ERROR(Could not use memove())],) AC_CHECK_FUNC([sinf], [],[AC_MSG_ERROR(Could not use sinf())],) AC_CHECK_FUNC([cosf], [],[AC_MSG_ERROR(Could not use cosf())],) AC_CHECK_FUNC([expf], [],[AC_MSG_ERROR(Could not use expf())],) AC_CHECK_FUNC([cargf], [],[AC_MSG_ERROR(Could not use cargf())],) AC_CHECK_FUNC([cexpf], [],[AC_MSG_ERROR(Could not use cexpf())],) AC_CHECK_FUNC([crealf], [],[AC_MSG_ERROR(Could not use crealf())],) AC_CHECK_FUNC([cimagf], [],[AC_MSG_ERROR(Could not use cimagf())],) AC_CHECK_FUNC([sqrtf], [],[AC_MSG_ERROR(Could not use sqrtf())],) # Check for necessary header files AC_CHECK_HEADERS([stdio.h stdlib.h complex.h string.h getopt.h sys/resource.h float.h inttypes.h limits.h stdlib.h string.h unistd.h]) if test -z "$HAVE_stdio.h" then AC_MSG_ERROR([Need stdio.h!]) fi # Check for optional header files, libraries, programs AC_CHECK_HEADERS(fec.h fftw3.h) AC_CHECK_LIB([fftw3f], [fftwf_plan_dft_1d], [], [AC_MSG_WARN(fftw3 library useful but not required)], []) AC_CHECK_LIB([fec], [create_viterbi27], [], [AC_MSG_WARN(fec library useful but not required)], []) # Checks for typedefs, structures, and compiler characteristics. AC_C_INLINE AC_TYPE_SIZE_T AC_TYPE_UINT32_T AC_TYPE_UINT8_T # Check size of certain variables AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(unsigned int) # AX_GCC_ARCHFLAG([PORTABLE?], [ACTION-SUCCESS], [ACTION-FAILURE]) # Try to guess the "native" architecture of the target to use with gcc's # -march or -mtune flags. Default success action adds $ax_cv_gcc_archflag to # $CFLAGS (sets to "unknown" on failure). #AX_GCC_ARCHFLAG([no],[],[]) # get canonical target architecture AC_CANONICAL_TARGET # override SIMD if test "${enable_simdoverride+set}" = set; then # portable C version MLIBS_DOTPROD="src/dotprod/src/dotprod_cccf.o \ src/dotprod/src/dotprod_crcf.o \ src/dotprod/src/dotprod_rrrf.o \ src/dotprod/src/sumsq.o" ARCH_OPTION="" else # Check canonical system case $target_cpu in i386|i486|i586|i686|x86|x86_64) # check for MMX/SSE/AVX CPU extensions and intrinsics headers # MMX : mmintrin.h # SSE : xmmintrin.h # SSE2 : emmintrin.h # SSE3 : pmmintrin.h # SSSE3 : tmmintrin.h # SSE4.1/2: smmintrin.h # AVX : immintrin.h AX_EXT if [ test "$ax_cv_have_sse41_ext" = yes && test "$ac_cv_header_smmintrin_h" = yes ]; then # SSE4.1/2 extensions MLIBS_DOTPROD="src/dotprod/src/dotprod_cccf.mmx.o \ src/dotprod/src/dotprod_crcf.mmx.o \ src/dotprod/src/dotprod_rrrf.mmx.o \ src/dotprod/src/sumsq.mmx.o" ARCH_OPTION='-msse4.1' elif [ test "$ax_cv_have_sse3_ext" = yes && test "$ac_cv_header_pmmintrin_h" = yes ]; then # SSE3 extensions MLIBS_DOTPROD="src/dotprod/src/dotprod_cccf.mmx.o \ src/dotprod/src/dotprod_crcf.mmx.o \ src/dotprod/src/dotprod_rrrf.mmx.o \ src/dotprod/src/sumsq.mmx.o" ARCH_OPTION='-msse3' elif [ test "$ax_cv_have_sse2_ext" = yes && test "$ac_cv_header_emmintrin_h" = yes ]; then # SSE2 extensions MLIBS_DOTPROD="src/dotprod/src/dotprod_cccf.mmx.o \ src/dotprod/src/dotprod_crcf.mmx.o \ src/dotprod/src/dotprod_rrrf.mmx.o \ src/dotprod/src/sumsq.mmx.o" ARCH_OPTION='-msse2' else # portable C version MLIBS_DOTPROD="src/dotprod/src/dotprod_cccf.o \ src/dotprod/src/dotprod_crcf.o \ src/dotprod/src/dotprod_rrrf.o \ src/dotprod/src/sumsq.o" fi;; powerpc*) MLIBS_DOTPROD="src/dotprod/src/dotprod_cccf.o \ src/dotprod/src/dotprod_rrrf.av.o \ src/dotprod/src/dotprod_crcf.av.o \ src/dotprod/src/sumsq.o" ARCH_OPTION="-fno-common -faltivec";; armv1*|armv2*|armv3*|armv4*|armv5*|armv6*) # assume neon instructions are NOT available MLIBS_DOTPROD="src/dotprod/src/dotprod_cccf.o \ src/dotprod/src/dotprod_crcf.o \ src/dotprod/src/dotprod_rrrf.o \ src/dotprod/src/sumsq.o" ARCH_OPTION="-ffast-math";; armv7*|armv8*) # assume neon instructions are available # TODO: check for Neon availability # ARM architecture : use neon extensions MLIBS_DOTPROD="src/dotprod/src/dotprod_cccf.neon.o \ src/dotprod/src/dotprod_crcf.neon.o \ src/dotprod/src/dotprod_rrrf.neon.o \ src/dotprod/src/sumsq.o" # TODO: check these flags #ARCH_OPTION="-ffast-math -mcpu=cortex-a8 -mfloat-abi=softfp -mfpu=neon";; ARCH_OPTION="-ffast-math -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4";; *) # unknown architecture : use portable C version MLIBS_DOTPROD="src/dotprod/src/dotprod_cccf.o \ src/dotprod/src/dotprod_crcf.o \ src/dotprod/src/dotprod_rrrf.o \ src/dotprod/src/sumsq.o" ARCH_OPTION="";; esac fi # for now all vector operations are portable C versions MLIBS_VECTOR="src/vector/src/vectorf_add.port.o \ src/vector/src/vectorf_norm.port.o \ src/vector/src/vectorf_mul.port.o \ src/vector/src/vectorf_trig.port.o \ src/vector/src/vectorcf_add.port.o \ src/vector/src/vectorcf_norm.port.o \ src/vector/src/vectorcf_mul.port.o \ src/vector/src/vectorcf_trig.port.o" case $target_os in darwin*) SH_LIB=libliquid.dylib REBIND="" ;; *) SH_LIB=libliquid.so REBIND=ldconfig ;; esac # # autoconf variable substitutions # AC_SUBST(LIBS) # shared libraries (-lc, -lm, etc.) AC_SUBST(MLIBS_DOTPROD) # AC_SUBST(MLIBS_VECTOR) # AC_SUBST(SH_LIB) # output shared library target AC_SUBST(REBIND) # rebinding tool (e.g. ldconfig) AC_SUBST(ARCH_OPTION) # compiler architecture option AC_SUBST(DEBUG_MSG_OPTION) # debug messages option (.e.g -DDEBUG) AC_SUBST(CLIB) # C library linkage (e.g. '-lc') AC_CONFIG_FILES([makefile]) AC_OUTPUT liquid-dsp-1.3.1/examples/000077500000000000000000000000001317124540100154035ustar00rootroot00000000000000liquid-dsp-1.3.1/examples/README.md000066400000000000000000000634111317124540100166670ustar00rootroot00000000000000 liquid-dsp examples =================== This directory contains all the examples for interfacing the liquid modules. * `agc_crcf_example.c`: Automatic gain control example demonstrating its transient response. * `agc_crcf_qpsk_example.c`: Automatic gain control test for data signals with fluctuating signal levels. QPSK modulation introduces periodic random zero-crossings which gives instantaneous amplitude levels near zero. This example tests the response of the AGC to these types of signals. * `ampmodem_example.c`: Tests simple modulation/demodulation of the ampmodem (analog amplitude modulator/demodulator) with noise, carrier phase, and carrier frequency offsets. * `asgramcf_example.c`: ASCII spectrogram example for complex inputs. This example demonstrates the functionality of the ASCII spectrogram. A sweeping complex sinusoid is generated and the resulting spectral periodogram is printed to the screen. * `asgramf_example.c`: ASCII spectrogram example for real-valued input. This example demonstrates the functionality of the ASCII spectrogram for real-valued input siganls. A cosine signal with time-varying frequency is generated and the resulting spectral periodogram is printed to the screen. Because the time signal has no complex component, its spectrum is symmetric. * `autocorr_cccf_example.c`: This example demonstrates the autocorr (auto-correlation) object functionality. A random time-domain sequence is generated which exhibits time-domain repetitions (auto-correlation properties), for example: abcdabcdabcd....abcd. The sequence is pushed through the autocorr object, and the results are written to an output file. The command-line arguments allow the user to experiment with the sequence length, number of sequence repetitions, and properties of the auto-correlator, as well as signal-to- noise ratio. * `bpacketsync_example.c`: * `bpresync_example.c`: This example demonstrates the binary pre-demodulator synchronizer. A random binary sequence is generated, modulated with BPSK, and then interpolated. The resulting sequence is used to generate a bpresync object which in turn is used to detect a signal in the presence of carrier frequency and timing offsets and additive white Gauss noise. * `bsequence_example.c`: This example demonstrates the interface to the bsequence (binary sequence) object. The bsequence object acts like a buffer of bits which are stored and manipulated efficiently in memory. * `bufferf_example.c`: * `cgsolve_example.c`: Solve linear system of equations `Ax = b` using the conjugate- gradient method where A is a symmetric positive-definite matrix. Compare speed to matrixf_linsolve() for same system. * `chromosome_example.c`: * `compand_cf_example.c`: * `compand_example.c`: This example demonstrates the interface to the compand function (compression, expansion). The compander is typically used with the quantizer to increase the dynamic range of the converter, particularly for low-level signals. The transfer function is computed (emperically) and printed to the screen. * `complementary_codes_example.c`: This example demonstrates how to generate complementary binary codes in liquid. A pair of codes is generated using the bsequence interface, their auto-correlations are computed, and the result is summed and printed to the screen. The results are also printed to an output file, which plots the sequences and their auto-correlations. SEE ALSO: `bsequence_example.c` `msequence_example.c` * `cpfskmodem_example.c`: * `conversion_example.c`: This example demonstrates conversion from complex baseband to a real-valued signal, and then down-conversion back to complex baseband while removing the negative image. STEP 1: A signal is generated at complex baseband consisting of narrow-band filtered noise and an offset tone (to show asymmetry in the transmit spectrum). STEP 2: The signal is mixed up to a carrier 'fc' (relative to the sampling frequency) and the real-component of the result is retained. This is the DAC output. The spectrum of this signal has two images: one at +fc, the other at -fc. STEP 3: The DAC output is mixed back down to complex baseband and the lower image is (mostly) filtered off. Reminants of the lower frequency component are still visible due to the wide-band and low-order filter on the receiver. The received complex baseband signal also has a reduction in power by 2 because half the signal's energy (the negative image) is filtered off. * `crc_example.c`: Cyclic redundancy check (CRC) example. This example demonstrates how a CRC can be used to validate data received through un-reliable means (e.g. a noisy channel). A CRC is, in essence, a strong algebraic error detection code that computes a key on a block of data using base-2 polynomials. Also available is a checksum for data validation. SEE ALSO: `fec_example.c` * `cvsd_example.c`: Continuously-variable slope delta example, sinusoidal input. This example demonstrates the CVSD audio encoder interface, and its response to a sinusoidal input. The output distortion ratio is computed, and the time-domain results are written to a file. * `dotprod_cccf_example.c`: This example demonstrates the interface to the complex floating-point dot product object (dotprod_cccf). * `dotprod_rrrf_example.c`: This example demonstrates the interface to the floating-point dot product object (dotprod_rrrf). * `eqlms_cccf_blind_example.c`: This example tests the least mean-squares (LMS) equalizer (EQ) on a signal with an unknown modulation and carrier frequency offset. That is, the equalization is done completely blind of the modulation scheme or its underlying data set. The error estimate assumes a constant modulus linear modulation scheme. This works surprisingly well even more amplitude-modulated signals, e.g. 'qam16'. * `eqlms_cccf_block_example.c`: This example tests the least mean-squares (LMS) equalizer (EQ) on a signal with an unknown modulation and carrier frequency offset. Equalization is performed blind on a block of samples and the reulting constellation is output to a file for plotting. * `eqlms_cccf_decisiondirected_example.c`: Tests least mean-squares (LMS) equalizer (EQ) on a signal with a known linear modulation scheme, but unknown data. The equalizer is updated using decision-directed demodulator output samples. * `eqlms_cccf_example.c`: * `eqrls_cccf_example.c`: * `fct_example.c`: * `fec_example.c`: This example demonstrates the interface for forward error-correction (FEC) codes. A buffer of data bytes is encoded and corrupted with several errors. The decoder then attempts to recover the original data set. The user may select the FEC scheme from the command-line interface. SEE ALSO: `crc_example.c` `checksum_example.c` `packetizer_example.c` * `fec_soft_example.c`: This example demonstrates the interface for forward error-correction (FEC) codes with soft-decision decoding. A buffer of data bytes is encoded before the data are corrupted with at least one error and noise. The decoder then attempts to recover the original data set from the soft input bits. The user may select the FEC scheme from the command-line interface. SEE ALSO: `fec_example.c` `packetizer_soft_example.c` * `fft_example.c`: This example demonstrates the interface to the fast discrete Fourier transform (FFT). SEE ALSO: `mdct_example.c` `fct_example.c` * `fftfilt_crcf_example.c` Complex FFT-based finite impulse response filter example. This example demonstrates the functionality of firfilt by designing a low-order prototype and using it to filter a noisy signal. The filter coefficients are real, but the input and output arrays are complex. The filter order and cutoff frequency are specified at the beginning, and the result is compared to the regular corresponding firfilt_crcf output. SEE ALSO: `firfilt_crcf_example.c` * `firdecim_crcf_example.c`: This example demonstrates the interface to the firdecim (finite impulse response decimator) family of objects. Data symbols are generated and then interpolated according to a finite impulse response square-root Nyquist filter. The resulting sequence is then decimated with the same filter, matched to the interpolator. SEE ALSO: `firinterp_crcf_example.c` * `firdes_kaiser_example.c`: This example demonstrates finite impulse response filter design using a Kaiser window. SEE ALSO: `firdespm_example.c` * `firdespm_example.c`: This example demonstrates finite impulse response filter design using the Parks-McClellan algorithm. SEE ALSO: `firdes_kaiser_example.c` * `firfarrow_rrrf_sine_example.c`: * `firfilt_rrrf_example.c`: * `firfilt_cccf_example.c`: This example demonstrates the finite impulse response (FIR) filter with complex coefficients as a cross-correlator between transmitted and received sequences. * `firfilt_crcf_example.c`: Complex finite impulse response filter example. Demonstrates the functionality of firfilt by designing a low-order prototype and using it to filter a noisy signal. The filter coefficients are real, but the input and output arrays are complex. The filter order and cutoff frequency are specified at the beginning. * `firhilb_decim_example.c`: Hilbert transform: 2:1 real-to-complex decimator. This example demonstrates the functionality of firhilb (finite impulse response Hilbert transform) decimator which converts a real time series into a complex one with half the number of samples. The input is a real-valued sinusoid of N samples. The output is a complex-valued sinusoid of N/2 samples. SEE ALSO: `firhilb_interp_example.c` * `firhilb_example.c`: * `firhilb_interp_example.c`: Hilbert transform: 1:2 complex-to-real interpolator. This example demonstrates the functionality of firhilb (finite impulse response Hilbert transform) interpolator which converts a complex time series into a real one with twice the number of samples. The input is a complex-valued sinusoid of N samples. The output is a real-valued sinusoid of 2*N samples. SEE ALSO: `firhilb_decim_example.c` * `firpfbch2_crcf_example.c`: Example of the finite impulse response (FIR) polyphase filterbank (PFB) channelizer with an output rate of 2 Fs / M as an (almost) perfect reconstructive system. * `firinterp_crcf_example.c`: This example demonstrates the interp object (interpolator) interface. Data symbols are generated and then interpolated according to a finite impulse response Nyquist filter. * `firpfbch_crcf_analysis_example.c`: Example of the analysis channelizer filterbank. The input signal is comprised of several signals spanning different frequency bands. The channelizer downconverts each to baseband (maximally decimated), and the resulting spectrum of each is plotted. * `firpfbch_crcf_example.c`: Finite impulse response (FIR) polyphase filter bank (PFB) channelizer example. This example demonstrates the functionality of the polyphase filter bank channelizer and how its output is mathematically equivalent to a series of parallel down-converters (mixers/decimators). Both the synthesis and analysis filter banks are presented. * `firpfbch_crcf_synthesis_example.c`: Example of the synthesis channelizer filterbank. Random symbols are generated and loaded into the bins of the channelizer and the time-domain signal is synthesized. Subcarriers around the band edges are disabled as well as those near 0.25 to demonstrate the synthesizer's ability to efficiently notch the spectrum. The results are printed to a file for plotting. * `flexframesync_example.c`: This example demonstrates the basic interface to the flexframegen and flexframesync objects used to completely encapsulate raw data bytes into frame samples (nearly) ready for over-the-air transmission. A 14-byte header and variable length payload are encoded into baseband symbols using the flexframegen object. The resulting symbols are interpolated using a root-Nyquist filter and the resulting samples are then fed into the flexframesync object which attempts to decode the frame. Whenever frame is found and properly decoded, its callback function is invoked. * `flexframesync_reconfig_example.c`: Demonstrates the reconfigurability of the flexframegen and flexframesync objects. * `framesync64_example.c`: This example demonstrates the interfaces to the framegen64 and framesync64 objects used to completely encapsulate data for over-the-air transmission. A 24-byte header and 64-byte payload are encoded, modulated, and interpolated using the framegen64 object. The resulting complex baseband samples are corrupted with noise and moderate carrier frequency and phase offsets before the framesync64 object attempts to decode the frame. The resulting data are compared to the original to validate correctness. SEE ALSO: `flexframesync_example.c` * `freqmodem_example.c`: * `fskmodem_example.c`: This example demostrates the M-ary frequency-shift keying (MFSK) modem in liquid. A message signal is modulated and the resulting signal is recovered using a demodulator object. * `gasearch_example.c`: * `gasearch_knapsack_example.c`: * `gmskmodem_example.c`: * `gradsearch_example.c`: * `gradsearch_datafit_example.c`: Fit 3-parameter curve to sampled data set in the minimum mean-squared error sense. * `iirdes_analog_example.c`: Tests infinite impulse reponse (IIR) analog filter design. While this example seems purely academic as IIR filters used in liquid are all digital, it is important to realize that they are all derived from their analog counterparts. This example serves to check the response of the analog filters to ensure they are correct. The results of design are written to a file. SEE ALSO: `iirdes_example.c` `iirfilt_crcf_example.c` * `iirdes_example.c`: Tests infinite impulse reponse (IIR) digital filter design. SEE ALSO: `iirdes_analog_example.c` `iirfilt_crcf_example.c` * `iirdes_pll_example.c`: This example demonstrates 2nd-order IIR phase-locked loop filter design with a practical simulation. SEE ALSO: `nco_pll_example.c` `nco_pll_modem_example.c` * `iirfilt_cccf_example.c`: Complex infinite impulse response filter example. Demonstrates the functionality of iirfilt with complex coefficients by designing a filter with specified parameters and then filters noise. * `iirfilt_crcf_example.c`: Complex infinite impulse response filter example. Demonstrates the functionality of iirfilt by designing a low-order prototype (e.g. Butterworth) and using it to filter a noisy signal. The filter coefficients are real, but the input and output arrays are complex. The filter order and cutoff frequency are specified at the beginning. * `iirinterp_crcf_example.c`: This example demonstrates the iirinterp object (IIR interpolator) interface. * `interleaver_example.c`: This example demonstrates the functionality of the liquid interleaver object. Interleavers serve to distribute grouped bit errors evenly throughout a block of data. This aids certain forward error-correction codes in correcting bit errors. In this example, data bits are interleaved and de-interleaved; the resulting sequence is validated to match the original. SEE ALSO: `packetizer_example.c` * `interleaver_scatterplot_example.c`: * `interleaver_soft_example.c`: * `kbd_window_example.c`: * `lpc_example.c`: This example demonstrates linear prediction in liquid. An input signal is generated which exhibits a strong temporal correlation. The linear predictor generates an approximating all-pole filter which minimizes the squared error between the prediction and the actual output. * `matched_filter_example.c`: * `math_lngamma_example.c`: Demonstrates accuracy of lngamma function. * `mdct_example.c`: * `modem_arb_example.c`: This example demonstrates the functionality of the arbitrary modem, a digital modulator/demodulator object with signal constellation points chosen arbitrarily. A simple bit-error rate simulation is then run to test the performance of the modem. The results are written to a file. SEE ALSO: `modem_example.c` * `modem_example.c`: This example demonstates the digital modulator/demodulator (modem) object. Data symbols are modulated into complex samples which are then demodulated without noise or phase offsets. The user may select the modulation scheme via the command-line interface. SEE ALSO: `modem_arb_example.c` * `modem_soft_example.c`: This example demonstates soft demodulation of linear modulation schemes. * `modular_arithmetic_example.c`: This example demonstates some modular arithmetic functions. * `msequence_example.c`: This example demonstrates the auto-correlation properties of a maximal-length sequence (m-sequence). An m-sequence of a certain length is used to generate two binary sequences (buffers) which are then cross-correlated. The resulting correlation produces -1 for all values except at index zero, where the sequences align. SEE ALSO: `bsequence_example.c` * `msourcecf_example.c`: This example demonstrates generating multiple signal sources simultaneously for testing using the msource (multi-source) family of objects. * `msresamp_crcf_example.c`: Demonstration of the multi-stage arbitrary resampler. * `msresamp2_crcf_example.c`: Demonstration of the multi-stage half-band resampler. * `nco_example.c`: This example demonstrates the most basic functionality of the numerically-controlled oscillator (NCO) object. SEE ALSO: `nco_pll_example.c` `nco_pll_modem_example.c` * `nco_pll_example.c`: This example demonstrates how the use the nco/pll object (numerically-controlled oscillator with phase-locked loop) interface for tracking to a complex sinusoid. The loop bandwidth, phase offset, and other parameter can be specified via the command-line interface. SEE ALSO: `nco_example.c` `nco_pll_modem_example.c` * `nco_pll_modem_example.c`: This example demonstrates how the nco/pll object (numerically-controlled oscillator with phase-locked loop) can be used for carrier frequency recovery in digital modems. The modem type, SNR, and other parameters are specified via the command-line interface. SEE ALSO: `nco_example.c` `nco_pll_example.c` * `nyquist_filter_example.c`: * `ofdmflexframesync_example.c`: * `ofdmframegen_example.c`: * `ofdmframesync_example.c`: * `packetizer_example.c`: Demonstrates the functionality of the packetizer object. Data are encoded using two forward error-correction schemes (an inner and outer code) before data errors are introduced. The decoder then tries to recover the original data message. SEE ALSO: `fec_example.c` `crc_example.c` * `packetizer_soft_example.c`: This example demonstrates the functionality of the packetizer object for soft-decision decoding. Data are encoded using two forward error- correction schemes (an inner and outer code) before noise and data errors are added. The decoder then tries to recover the original data message. Only the outer code uses soft-decision decoding. SEE ALSO: `fec_soft_example.c` `packetizer_example.c` * `pll_example.c`: Demonstrates a basic phase-locked loop to track the phase of a complex sinusoid. * `poly_findroots_example.c`: * `polyfit_example.c`: Test polynomial fit to sample data. SEE ALSO: `polyfit_lagrange_example.c` * `polyfit_lagrange_example.c`: Test exact polynomial fit to sample data using Lagrange interpolating polynomials. SEE ALSO: `polyfit_example.c` * `qdetector_cccf_example.c`: This example demonstrates the functionality of the qdetector object to detect an arbitrary signal in time in the presence of noise, carrier frequency/phase offsets, and fractional-sample timing offsets. * `qpacketmodem_example.c`: This example demonstrates the basic packet modem encoder/decoder operation. A packet of data is encoded and modulated into symbols, channel noise is added, and the resulting packet is demodulated and decoded. * `qnsearch_example.c`: * `quantize_example.c`: * `random_histogram_example.c`: This example tests the random number generators for different distributions. * `repack_bytes_example.c`: This example demonstrates the repack_bytes() interface by packing a sequence of three 3-bit symbols into five 2-bit symbols. The results are printed to the screen. Because the total number of bits in the input is 9 and not evenly divisible by 2, the last of the 5 output symbols has a zero explicitly padded to the end. * `resamp2_cccf_example.c` This example demonstrates the halfband resampler cenetered at the quarter sample rate to split the signal into positive and negative frequency bands. Two distinct narrow-band signals are generated; one at a positive frequency and one at a negative frequency. The resamp2 object is run as a filter to separate the two about the zero- frequency center point. * `resamp2_crcf_example.c`: This example demonstrates the halfband resampler running as both an interpolator and a decimator. A narrow-band signal is first interpolated by a factor of 2, and then decimated. The resulting RMS error between the final signal and original is computed and printed to the screen. * `resamp2_crcf_decim_example.c`: Halfband decimator. This example demonstrates the interface to the decimating halfband resampler. A low-frequency input sinusoid is generated and fed into the decimator two samples at a time, producing one output at each iteration. The results are written to an output file. SEE ALSO: `resamp2_crcf_interp_example.c` `decim_rrrf_example.c` * `resamp2_crcf_filter_example.c`: Halfband (two-channel) filterbank example. This example demonstrates the analyzer/synthesizer execute() methods for the resamp2_xxxt family of objects. NOTE: The filterbank is not a perfect reconstruction filter; a significant amount of distortion occurs in the transition band of the half-band filters. * `resamp2_crcf_interp_example.c`: Halfband interpolator. This example demonstrates the interface to the interpolating halfband resampler. A low-frequency input sinusoid is generated and fed into the interpolator one sample at a time, producing two outputs at each iteration. The results are written to an output file. SEE ALSO: `resamp2_crcf_decim_example.c` `interp_crcf_example.c` * `resamp_crcf_example.c`: * `scramble_example.c`: Data-scrambling example. Physical layer synchronization of received waveforms relies on independent and identically distributed underlying data symbols. If the message sequence, however, is '00000....' and the modulation scheme is BPSK, the synchronizer probably won't be able to recover the symbol timing. It is imperative to increase the entropy of the data for this to happen. The data scrambler routine attempts to 'whiten' the data sequence with a bit mask in order to achieve maximum entropy. This example demonstrates the interface. * `smatrix_example.c`: * `spgramcf_example.c`: Spectral periodogram example with complex inputs. * `spgramf_example.c`: Spectral periodogram example with real inputs. * `symsync_crcf_example.c`: This example demonstrates the basic principles of the symbol timing recovery family of objects, specifically symsync_crcf. A set of random QPSK symbols are generated and interpolated with a timing offset. The resulting signal is run through the symsync_crcf object which applies a matched filter and recovers timing producing a clean constellation. * `symsync_crcf_full_example.c`: This example extends that of `symsync_crcf_example.c` by including options for simulating a timing rate offset in addition to just a timing phase error. The resulting output file shows not just the constellation but the time domain sequence as well as the timing phase estimate over time. * `symsync_crcf_kaiser_example.c`: This is a simplified example of the symync family of objects to show how symbol timing can be recovered after the matched filter output. * `symtrack_cccf_example.c`: This example demonstrates how to recover data symbols using the symtrack object. A stream of modulated and interpolated symbols are generated using the symstream object. The resulting samples are passed through a channel to add various impairments. The symtrack object recovers timing, carrier, and other information imparted by the channel and returns data symbols ready for demodulation. * `wdelayf_example.c`: * `windowf_example.c`: This example demonstrates the functionality of a window buffer (also known as a circular or ring buffer) of floating-point values. Values are written to and read from the buffer using several different methods. SEE ALSO: `bufferf_example.c` `wdelayf_example.c` liquid-dsp-1.3.1/examples/agc_crcf_example.c000066400000000000000000000073611317124540100210200ustar00rootroot00000000000000// // agc_crcf_example.c // // Automatic gain control example demonstrating its transient // response. // #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "agc_crcf_example.m" // print usage/help message void usage() { printf("agc_example [options]\n"); printf(" h : print usage\n"); printf(" n : number of samples, n >=100, default: 2000\n"); printf(" b : AGC bandwidth, b >= 0, default: 0.01\n"); } int main(int argc, char*argv[]) { // options float bt = 0.01f; // agc loop bandwidth float gamma = 0.001f; // initial signal level unsigned int num_samples = 2000; // number of samples int dopt; while((dopt = getopt(argc,argv,"hn:N:s:b:")) != EOF){ switch (dopt) { case 'h': usage(); return 0; case 'n': num_samples = atoi(optarg); break; case 'b': bt = atof(optarg); break; default: exit(1); } } // validate input if (bt < 0.0f) { fprintf(stderr,"error: %s, bandwidth must be positive\n", argv[0]); exit(1); } else if (num_samples == 0) { fprintf(stderr,"error: %s, number of samples must be greater than zero\n", argv[0]); exit(1); } unsigned int i; // create objects agc_crcf q = agc_crcf_create(); agc_crcf_set_bandwidth(q, bt); float complex x[num_samples]; // input float complex y[num_samples]; // output float rssi[num_samples]; // received signal strength // print info printf("automatic gain control // loop bandwidth: %4.2e\n",bt); // generate signal for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "agc_crcf_qpsk_example.m" int main(int argc, char*argv[]) { // options float noise_floor= -40.0f; // noise floor [dB] float SNRdB = 20.0f; // signal-to-noise ratio [dB] float bt = 0.05f; // loop bandwidth unsigned int num_symbols= 100; // number of iterations unsigned int d = 5; // print every d iterations unsigned int k = 2; // interpolation factor (samples/symbol) unsigned int m = 3; // filter delay (symbols) float beta = 0.3f; // filter excess bandwidth factor float dt = 0.0f; // filter fractional sample delay // derived values unsigned int num_samples=num_symbols*k; float gamma = powf(10.0f, (SNRdB+noise_floor)/20.0f); // channel gain float nstd = powf(10.0f, noise_floor / 20.0f); // arrays float complex x[num_samples]; float complex y[num_samples]; float rssi[num_samples]; // create objects modem mod = modem_create(LIQUID_MODEM_QPSK); firinterp_crcf interp = firinterp_crcf_create_prototype(LIQUID_FIRFILT_RRC,k,m,beta,dt); agc_crcf p = agc_crcf_create(); agc_crcf_set_bandwidth(p, bt); unsigned int i; // print info printf("automatic gain control // loop bandwidth: %4.2e\n",bt); unsigned int sym; float complex s; for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "agc_crcf_squelch_example.m" // print usage/help message void usage() { printf("agc_crcf_squelch_example [options]\n"); printf(" -h : print usage\n"); printf(" -b : AGC bandwidth, b >= 0, default: 0.25\n"); } int main(int argc, char*argv[]) { // options float bt = 0.25f; // agc loop bandwidth int dopt; while((dopt = getopt(argc,argv,"hn:N:s:b:")) != EOF){ switch (dopt) { case 'h': usage(); return 0; case 'b': bt = atof(optarg); break; default: exit(1); } } // validate input if (bt < 0.0f) { fprintf(stderr,"error: %s, bandwidth must be positive\n", argv[0]); exit(1); } unsigned int i; // create agc object, set loop bandwidth, and initialize parameters agc_crcf q = agc_crcf_create(); agc_crcf_set_bandwidth(q, bt); agc_crcf_set_signal_level(q,1e-3f); // initial guess at starting signal level // initialize squelch functionality agc_crcf_squelch_enable(q); // enable squelch agc_crcf_squelch_set_threshold(q, -50); // threshold for detection [dB] agc_crcf_squelch_set_timeout (q, 100); // timeout for hysteresis // initialize arrays unsigned int num_samples = 2000; // total number of samples to run float complex x [num_samples]; // input float complex y [num_samples]; // output float rssi[num_samples]; // received signal strength int mode[num_samples]; // squelch mode // print info printf("automatic gain control // loop bandwidth: %4.2e\n",bt); // generate signal, applying tapering window appropriately for (i=0; i #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "agc_rrrf_example.m" // print usage/help message void usage() { printf("agc_example [options]\n"); printf(" h : print usage\n"); printf(" n : number of samples, n >=100, default: 2000\n"); printf(" b : AGC bandwidth, b >= 0, default: 0.01\n"); } int main(int argc, char*argv[]) { // options float bt = 0.01f; // agc loop bandwidth float gamma = 0.001f; // initial signal level unsigned int num_samples = 2000; // number of samples int dopt; while((dopt = getopt(argc,argv,"hn:N:s:b:")) != EOF){ switch (dopt) { case 'h': usage(); return 0; case 'n': num_samples = atoi(optarg); break; case 'b': bt = atof(optarg); break; default: exit(1); } } // validate input if (bt < 0.0f) { fprintf(stderr,"error: %s, bandwidth must be positive\n", argv[0]); exit(1); } else if (num_samples == 0) { fprintf(stderr,"error: %s, number of samples must be greater than zero\n", argv[0]); exit(1); } unsigned int i; // create objects agc_rrrf q = agc_rrrf_create(); agc_rrrf_set_bandwidth(q, bt); float x[num_samples]; // input float y[num_samples]; // output float rssi[num_samples]; // received signal strength // print info printf("automatic gain control // loop bandwidth: %4.2e\n",bt); // generate signal for (i=0; i #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "ampmodem_example.m" // print usage/help message void usage() { printf("ampmodem_example [options]\n"); printf(" u/h : print usage\n"); printf(" f : frequency offset, default: 0.02\n"); printf(" p : phase offset, default: -pi/4\n"); printf(" n : number of samples, default: 256\n"); printf(" S : SNR [dB], default: 20\n"); printf(" t : AM type (dsb/usb/lsb), default: dsb\n"); printf(" s : suppress the carrier, default: off\n"); } int main(int argc, char*argv[]) { // options float mod_index = 0.1f; // modulation index (bandwidth) float fc = 0.0f; // AM carrier float cfo = 0.02f; // carrier frequency offset float cpo = -M_PI / 4.0f; // carrier phase offset unsigned int num_samples = 256; // number of samples float SNRdB = 30.0f; // signal-to-noise ratio [dB] liquid_ampmodem_type type = LIQUID_AMPMODEM_USB; int suppressed_carrier = 0; int dopt; while ((dopt = getopt(argc,argv,"uhf:p:n:S:t:s")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'f': cfo = atof(optarg); break; case 'p': cpo = atof(optarg); break; case 'n': num_samples = atoi(optarg); break; case 'S': SNRdB = atof(optarg); break; case 't': if (strcmp(optarg,"dsb")==0) { type = LIQUID_AMPMODEM_DSB; } else if (strcmp(optarg,"usb")==0) { type = LIQUID_AMPMODEM_USB; } else if (strcmp(optarg,"lsb")==0) { type = LIQUID_AMPMODEM_LSB; } else { fprintf(stderr,"error: %s, invalid AM type: %s\n", argv[0], optarg); return 1; } break; case 's': suppressed_carrier = 1; break; default: usage(); return 1; } } // create mod/demod objects ampmodem mod = ampmodem_create(mod_index, fc, type, suppressed_carrier); ampmodem demod = ampmodem_create(mod_index, fc, type, suppressed_carrier); ampmodem_print(mod); unsigned int i; float x[num_samples]; float complex y[num_samples]; float z[num_samples]; // generate 'audio' signal unsigned int h_len = 21; float h[h_len]; liquid_firdes_kaiser(h_len, 0.03f, -40.0f, 0.0f, h); firfilt_rrrf faudio = firfilt_rrrf_create(h,h_len); for (i=0; i // usleep #include #include #include #include "liquid.h" int main() { // options unsigned int nfft = 64; // transform size unsigned int num_frames = 200; // total number of frames unsigned int msdelay = 50; // delay between transforms [ms] float noise_floor = -40.0f; // noise floor // initialize objects asgramcf q = asgramcf_create(nfft); asgramcf_set_scale(q, noise_floor+15.0f, 5.0f); unsigned int i; unsigned int n; float theta = 0.0f; // current instantaneous phase float dtheta = 0.0f; // current instantaneous frequency float phi = 0.0f; // phase of sinusoidal frequency drift float dphi = 0.003f; // frequency of sinusoidal frequency drift float complex x[nfft]; char ascii[nfft+1]; ascii[nfft] = '\0'; // append null character to end of string float nstd = powf(10.0f,noise_floor/20.0f); // noise standard deviation for (n=0; n // usleep #include #include #include "liquid.h" int main() { // options unsigned int nfft = 64; // transform size unsigned int num_frames = 200; // total number of frames unsigned int msdelay = 50; // delay between transforms [ms] float noise_floor = -40.0f; // noise floor // initialize objects asgramf q = asgramf_create(nfft); asgramf_set_scale(q, noise_floor+15.0f, 5.0f); unsigned int i; unsigned int n; float theta = 0.0f; // current instantaneous phase float dtheta = 0.0f; // current instantaneous frequency float phi = 0.0f; // phase of sinusoidal frequency drift float dphi = 0.003f; // frequency of sinusoidal frequency drift float nstd = powf(10.0f,noise_floor/20.0f); // noise standard deviation for (n=0; n #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "autocorr_cccf_example.m" // print usage/help message void usage() { printf("autocorr_cccf_example:\n"); printf(" u/h : print usage/help\n"); printf(" m : sequence length, default: 32\n"); printf(" n : number of sequences (repetitions), default: 8\n"); printf(" w : autocorr window length, default: 64\n"); printf(" d : autocorr delay length (multiple of 's'), default: 32\n"); printf(" e : normalize by energy? default: off\n"); printf(" s : SNR, signal-to-noise ratio [dB], default: 20\n"); } int main(int argc, char*argv[]) { // options unsigned int sequence_len = 32; // short sequence length unsigned int n = 8; // number short sequences (repetition length) unsigned int window_size = 64; // autocorr window size unsigned int delay = sequence_len; // autocorr delay (multiple of 's') int normalize_by_energy = 0; // normalize output by E{x^2}? float SNRdB=20.0f; // signal-to-noise ratio (dB) int dopt; while ((dopt = getopt(argc,argv,"uhm:n:w:d:es:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'm': sequence_len = atof(optarg); break; case 'n': n = atof(optarg); break; case 'w': window_size = atof(optarg); break; case 'd': delay = atof(optarg); break; case 'e': normalize_by_energy = 1; break; case 's': SNRdB = atoi(optarg); break; usage(); return 1; } } // derived values unsigned int num_samples = sequence_len*(n+2); // pad end w/ zeros // data arrays float complex sequence[sequence_len]; // short sequence float complex x[num_samples]; // autocorr input sequence float complex rxx[num_samples]; // autocorr output // generate objects autocorr_cccf q = autocorr_cccf_create(window_size,delay); unsigned int i; // generate random training sequence using QPSK symbols modem mod = modem_create(LIQUID_MODEM_QPSK); for (i=0; i cabsf(rxx_peak)) rxx_peak = rxx[i]; } printf("peak auto-correlation : %12.8f, angle %12.8f\n", cabsf(rxx_peak), cargf(rxx_peak)); // destroy allocated objects autocorr_cccf_destroy(q); // // write results to file // FILE* fid = fopen(OUTPUT_FILENAME, "w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n\n"); fprintf(fid,"num_samples = %u;\n", num_samples); // write signal to output file for (i=0; i #include #include #include #include #include "liquid.h" int callback(unsigned char * _payload, int _payload_valid, unsigned int _payload_len, framesyncstats_s _stats, void * _userdata) { printf("callback invoked, payload (%u bytes) : %s\n", _payload_len, _payload_valid ? "valid" : "INVALID!"); // copy data if valid if (_payload_valid) { unsigned char * msg_dec = (unsigned char*) _userdata; memmove(msg_dec, _payload, _payload_len*sizeof(unsigned char)); } return 0; } // print usage/help message void usage() { printf("bpacketsync_example [options]\n"); printf(" u/h : print usage\n"); printf(" n : input data size (number of uncoded bytes): 8 default\n"); printf(" e : bit error rate of channel, default: 0\n"); printf(" v : data integrity check: crc32 default\n"); liquid_print_crc_schemes(); printf(" c : coding scheme (inner): h74 default\n"); printf(" k : coding scheme (outer): none default\n"); liquid_print_fec_schemes(); } int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int n=8; // original data message length crc_scheme check = LIQUID_CRC_32; // data integrity check fec_scheme fec0 = LIQUID_FEC_HAMMING74; // inner code fec_scheme fec1 = LIQUID_FEC_NONE; // outer code float bit_error_rate = 0.0f; // bit error rate // read command-line options int dopt; while((dopt = getopt(argc,argv,"uhn:e:v:c:k:")) != EOF){ switch (dopt) { case 'h': case 'u': usage(); return 0; case 'n': n = atoi(optarg); break; case 'e': bit_error_rate = atof(optarg); break; case 'v': // data integrity check check = liquid_getopt_str2crc(optarg); if (check == LIQUID_CRC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported CRC scheme \"%s\"\n\n",optarg); exit(1); } break; case 'c': // inner FEC scheme fec0 = liquid_getopt_str2fec(optarg); if (fec0 == LIQUID_FEC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported inner FEC scheme \"%s\"\n\n",optarg); exit(1); } break; case 'k': // outer FEC scheme fec1 = liquid_getopt_str2fec(optarg); if (fec1 == LIQUID_FEC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported outer FEC scheme \"%s\"\n\n",optarg); exit(1); } break; default: exit(1); } } // validate input if (n == 0) { fprintf(stderr,"error: %s, packet length must be greater than zero\n", argv[0]); exit(1); } else if (bit_error_rate < 0.0f || bit_error_rate > 1.0f) { fprintf(stderr,"error: %s, channel bit error rate must be in [0,1]\n", argv[0]); exit(1); } // create packet generator bpacketgen pg = bpacketgen_create(0, n, check, fec0, fec1); bpacketgen_print(pg); unsigned int i; // compute packet length unsigned int k = bpacketgen_get_packet_len(pg); // initialize arrays unsigned char msg_org[n]; // original message unsigned char msg_enc[k]; // encoded message unsigned char msg_rec[k+1]; // recieved message unsigned char msg_dec[n]; // decoded message // create packet synchronizer bpacketsync ps = bpacketsync_create(0, callback, (void*)msg_dec); // initialize original data message for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "bpresync_example.m" // print usage/help message void usage() { printf("bpresync_example -- test binary pre-demodulation synchronization\n"); printf("options (default values in <>):\n"); printf(" h : print usage/help\n"); printf(" k : samples/symbol, default: 2\n"); printf(" m : filter delay [symbols], default: 5\n"); printf(" n : number of data symbols, default: 64\n"); printf(" b : bandwidth-time product beta in (0,1), default: 0.3\n"); printf(" F : carrier frequency offset, default: 0.02\n"); printf(" t : fractional sample offset dt in [-0.5, 0.5], default: 0\n"); printf(" S : SNR [dB], default: 20\n"); } int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int k=2; // filter samples/symbol unsigned int m=5; // filter delay (symbols) float beta=0.3f; // bandwidth-time product float dt = 0.0f; // fractional sample timing offset unsigned int num_sync_symbols = 64; // number of synchronization symbols float SNRdB = 20.0f; // signal-to-noise ratio [dB] float dphi = 0.02f; // carrier frequency offset float phi = 2*M_PI*randf(); // carrier phase offset int dopt; while ((dopt = getopt(argc,argv,"uhk:m:n:b:t:F:t:S:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'n': num_sync_symbols = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'F': dphi = atof(optarg); break; case 't': dt = atof(optarg); break; case 'S': SNRdB = atof(optarg); break; default: exit(1); } } unsigned int i; // validate input if (beta <= 0.0f || beta >= 1.0f) { fprintf(stderr,"error: %s, bandwidth-time product must be in (0,1)\n", argv[0]); exit(1); } else if (dt < -0.5f || dt > 0.5f) { fprintf(stderr,"error: %s, fractional sample offset must be in [-0.5,0.5]\n", argv[0]); exit(1); } // derived values unsigned int num_symbols = num_sync_symbols + 2*m + 10; unsigned int num_samples = k*num_symbols; float nstd = powf(10.0f, -SNRdB/20.0f); // arrays float complex seq[num_sync_symbols]; // synchronization pattern (symbols) float complex s0[k*num_sync_symbols]; // synchronization pattern (samples) float complex x[num_samples]; // transmitted signal float complex y[num_samples]; // received signal float complex rxy[num_samples]; // pre-demod correlation output float dphi_hat[num_samples]; // carrier offset estimate // create transmit/receive interpolator/decimator firinterp_crcf interp = firinterp_crcf_create_prototype(LIQUID_FIRFILT_RRC,k,m,beta,dt); // generate synchronization pattern (BPSK) and interpolate for (i=0; i 0.6f) { printf("****** preamble found, rxy = %12.8f (dphi-hat: %12.8f), i=%3u ******\n", cabsf(rxy[i]), dphi_hat[i], i); } // retain maximum if (cabsf(rxy[i]) > rxy_max) { rxy_max = cabsf(rxy[i]); dphi_est = dphi_hat[i]; delay_est = (int)i - (int)2*k*m + 1; } } // destroy objects firinterp_crcf_destroy(interp); bpresync_cccf_destroy(sync); // print results printf("\n"); printf("rxy (max) : %12.8f\n", rxy_max); printf("dphi est. : %12.8f ,error=%12.8f\n", dphi_est, dphi-dphi_est); printf("delay est.: %12d ,error=%3d sample(s)\n", delay_est, k*num_sync_symbols - delay_est); printf("\n"); // // export results // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); fprintf(fid,"num_samples = %u;\n", num_samples); fprintf(fid,"num_symbols = %u;\n", num_symbols); fprintf(fid,"k = %u;\n", k); fprintf(fid,"x = zeros(1,num_samples);\n"); fprintf(fid,"y = zeros(1,num_samples);\n"); fprintf(fid,"rxy = zeros(1,num_samples);\n"); for (i=0; i #include #include #include "liquid.h" //#define OUTPUT_FILENAME "bsequence_example.m" int main() { // create and initialize binary sequence unsigned int n=16; bsequence q = bsequence_create(n); unsigned char v[4] = {0x35, 0x35}; bsequence_init(q,v); bsequence_push(q,1); bsequence_push(q,1); bsequence_push(q,1); bsequence_push(q,1); bsequence_push(q,0); bsequence_push(q,1); bsequence_print(q); bsequence_circshift(q); bsequence_print(q); bsequence_circshift(q); bsequence_print(q); unsigned int b; unsigned int i; for (i=0; i #include "liquid.h" int main() { float v[] = {1, 2, 3, 4, 5, 6, 7, 8}; float *r; // reader unsigned int num_requested = 3; unsigned int num_read; cbufferf cb = cbufferf_create(10); cbufferf_write(cb, v, 4); cbufferf_read(cb, num_requested, &r, &num_read); printf("cbufferf: requested %u elements, read %u elements\n", num_requested, num_read); unsigned int i; for (i=0; i #include #include #include #include "liquid.h" int main() { // options unsigned int n = 8; unsigned int i; // allocate memory for arrays float A[n*n]; float b[n]; float x[n]; float x_hat[n]; // generate symmetric positive-definite matrix by first generating // lower triangular matrix L and computing A = L*L' float L[n*n]; unsigned int j; for (i=0; i i) matrix_access(L,n,n,i,j) = 0.0; else if (j == i) matrix_access(L,n,n,i,j) = randnf(); else if ((rand()%4)==0) matrix_access(L,n,n,i,j) = randnf(); else matrix_access(L,n,n,i,j) = 0.0; #else // full matrix matrix_access(L,n,n,i,j) = (j < i) ? 0.0 : randnf(); #endif } } matrixf_mul_transpose(L, n, n, A); // generate random solution for (i=0; i #include #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "channel_cccf_example.m" // print usage/help message void usage() { printf("channel_cccf_example [options]\n"); printf(" h : print this help file\n"); printf(" k : filter samples/symbol, default: 2\n"); printf(" m : filter delay (symbols), default: 3\n"); printf(" b : filter excess bandwidth, default: 0.5\n"); printf(" H : multi-path channel length, default: 4000\n"); printf(" n : number of symbols, default: 4000\n"); printf(" s : signal-to-noise ratio, default: 30 dB\n"); printf(" w : timing pll bandwidth, default: 0.02\n"); } int main(int argc, char*argv[]) { // options unsigned int k = 2; // samples per symbol unsigned int m = 7; // filter delay (symbols) float beta = 0.25f; // filter excess bandwidth factor unsigned int num_symbols = 4000; // number of data symbols unsigned int hc_len = 5; // channel filter length float noise_floor = -60.0f; // noise floor [dB] float SNRdB = 30.0f; // signal-to-noise ratio [dB] float bandwidth = 0.02f; // loop filter bandwidth float dphi = 0.00f; // carrier frequency offset [radians/sample] float phi = 2.1f; // carrier phase offset [radians] modulation_scheme ms = LIQUID_MODEM_QPSK; int dopt; while ((dopt = getopt(argc,argv,"hk:m:b:H:n:s:w:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'H': hc_len = atoi(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'w': bandwidth = atof(optarg); break; default: exit(1); } } // validate input if (k < 2) { fprintf(stderr,"error: k (samples/symbol) must be greater than 1\n"); exit(1); } else if (m < 1) { fprintf(stderr,"error: m (filter delay) must be greater than 0\n"); exit(1); } else if (beta <= 0.0f || beta > 1.0f) { fprintf(stderr,"error: beta (excess bandwidth factor) must be in (0,1]\n"); exit(1); } else if (bandwidth <= 0.0f) { fprintf(stderr,"error: timing PLL bandwidth must be greater than 0\n"); exit(1); } else if (num_symbols == 0) { fprintf(stderr,"error: number of symbols must be greater than 0\n"); exit(1); } unsigned int i; // derived/fixed values unsigned int num_samples = num_symbols*k; float complex x[num_samples]; // input (interpolated) samples float complex y[num_samples]; // channel output samples float complex sym_out[num_symbols + 64];// synchronized symbols // // generate input sequence using symbol stream generator // symstreamcf gen = symstreamcf_create_linear(LIQUID_FIRFILT_ARKAISER,k,m,beta,ms); symstreamcf_write_samples(gen, x, num_samples); symstreamcf_destroy(gen); // create channel channel_cccf channel = channel_cccf_create(); // add channel impairments channel_cccf_add_awgn (channel, noise_floor, SNRdB); channel_cccf_add_carrier_offset(channel, dphi, phi); channel_cccf_add_multipath (channel, NULL, hc_len); channel_cccf_add_shadowing (channel, 1.0f, 0.1f); // print channel internals channel_cccf_print(channel); // apply channel to input signal channel_cccf_execute_block(channel, x, num_samples, y); // destroy channel channel_cccf_destroy(channel); // // create and run symbol synchronizer // symtrack_cccf symtrack = symtrack_cccf_create(LIQUID_FIRFILT_RRC,k,m,beta,ms); // set tracking bandwidth symtrack_cccf_set_bandwidth(symtrack,0.05f); unsigned int num_symbols_sync = 0; symtrack_cccf_execute_block(symtrack, y, num_samples, sym_out, &num_symbols_sync); symtrack_cccf_destroy(symtrack); // print results printf("symbols in : %u\n", num_symbols); printf("symbols out : %u\n", num_symbols_sync); // estimate spectrum unsigned int nfft = 1200; float psd[nfft]; spgramcf_estimate_psd(nfft, y, num_samples, psd); // // export output file // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s, auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"close all;\nclear all;\n\n"); fprintf(fid,"num_symbols=%u;\n",num_symbols_sync); for (i=0; i #include #include "liquid.internal.h" int main() { unsigned int bits_per_trait[] = {4, 8, 8, 4}; chromosome p1 = chromosome_create(bits_per_trait, 4); chromosome p2 = chromosome_create(bits_per_trait, 4); chromosome c = chromosome_create(bits_per_trait, 4); // 0000 11111111 00000000 1111 p1->traits[0] = 0x0; p1->traits[1] = 0xFF; p1->traits[2] = 0x00; p1->traits[3] = 0xF; // 0101 01010101 01010101 0101 p2->traits[0] = 0x5; p2->traits[1] = 0x55; p2->traits[2] = 0x55; p2->traits[3] = 0x5; printf("parent [1]:\n"); chromosome_print(p1); printf("parent [2]:\n"); chromosome_print(p2); printf("\n\n"); // // test crossover // printf("testing crossover...\n"); chromosome_crossover(p1, p2, c, 0); // .... ........ ........ .... // 0101 01010101 01010101 0101 chromosome_print(c); chromosome_crossover(p1, p2, c, 4); // 0000 ........ ........ .... // .... 01010101 01010101 0101 chromosome_print(c); chromosome_crossover(p1, p2, c, 6); // 0000 11...... ........ .... // .... ..010101 01010101 0101 chromosome_print(c); chromosome_crossover(p1, p2, c, 14); // 0000 11111111 00...... .... // .... ........ ..010101 0101 chromosome_print(c); chromosome_crossover(p1, p2, c, 24); // 0000 11111111 00000000 1111 // .... ........ ........ .... chromosome_print(c); // // test mutation // printf("testing mutation...\n"); unsigned int i; for (i=0; i<24; i++) { chromosome_reset(c); chromosome_mutate(c,i); // 0000 01000000 00000000 0000 chromosome_print(c); } chromosome_destroy(p1); chromosome_destroy(p2); chromosome_destroy(c); return 0; } liquid-dsp-1.3.1/examples/compand_cf_example.c000066400000000000000000000032731317124540100213600ustar00rootroot00000000000000// // compand_cf_example.c // #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "compand_cf_example.m" int main() { // options float mu=255.0f; int n=31; // open debug file FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); float complex x, y, z; int i, j; for (i=0; i ", crealf(x), cimagf(x)); printf("%8.4f + j*%8.4f > ", crealf(y), cimagf(y)); printf("%8.4f + j*%8.4f\n", crealf(z), cimagf(z)); } fprintf(fid,"x(%3d,%3d) = %12.4e + j*%12.4e;\n", i+1, j+1, crealf(x), cimagf(x)); fprintf(fid,"y(%3d,%3d) = %12.4e + j*%12.4e;\n", i+1, j+1, crealf(y), cimagf(y)); } } for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "compand_example.m" // print usage/help message void usage() { printf("compand_example\n"); printf(" u/h : print usage/help\n"); printf(" v/q : verbose/quiet, default: verbose\n"); printf(" n : number of samples, default: 31\n"); printf(" m : companding parameter: mu > 0, default: 255\n"); printf(" r : range > 0, default: 1.25\n"); } int main(int argc, char*argv[]) { // options unsigned int n=31; float mu=255.0f; float range = 1.25f; int verbose = 1; int dopt; while ((dopt = getopt(argc,argv,"uhvqn:m:r:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'v': verbose = 1; break; case 'q': verbose = 0; break; case 'n': n = atoi(optarg); break; case 'm': mu = atof(optarg); break; case 'r': range = atof(optarg); break; default: exit(1); } } // validate input if (mu < 0) { fprintf(stderr,"error: %s, mu must be positive\n", argv[0]); usage(); exit(1); } else if (range <= 0) { fprintf(stderr,"error: %s, range must be greater than zero\n", argv[0]); usage(); exit(1); } // open debug file FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); float x = -range; float y, z; float dx = 2.0*range/(float)(n-1); unsigned int i; for (i=0; i %8.4f > %8.4f\n", x, y, z); fprintf(fid,"x(%3u) = %12.4e;\n", i+1, x); fprintf(fid,"y(%3u) = %12.4e;\n", i+1, y); fprintf(fid,"z(%3u) = %12.4e;\n", i+1, z); x += dx; } // plot results fprintf(fid,"\n\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(x,y,'-b','LineWidth',2,x,z,'-r');\n"); fprintf(fid,"axis square\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"xlabel('x');\n"); fprintf(fid,"ylabel('f(x)');\n"); // close debug file fclose(fid); printf("results wrtten to %s\n", OUTPUT_FILENAME); printf("done.\n"); return 0; } liquid-dsp-1.3.1/examples/complementary_codes_example.c000066400000000000000000000076051317124540100233260ustar00rootroot00000000000000// // complementary_codes_example.c // // This example demonstrates how to generate complementary binary // codes in liquid. A pair of codes is generated using the bsequence // interface, their auto-correlations are computed, and the result is // summed and printed to the screen. The results are also printed to an // output file, which plots the sequences and their auto-correlations. // // SEE ALSO: bsequence_example.c // msequence_example.c #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "complementary_codes_example.m" // print usage/help message void usage() { printf("complementary_codes_example [options]\n"); printf(" u/h : print usage\n"); printf(" n : sequence length, 8,16,32,64,... (default: 32)\n"); } int main(int argc, char*argv[]) { // options unsigned int n = 32; int dopt; while ((dopt = getopt(argc,argv,"uhn:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'n': n = atoi(optarg); break; default: exit(1); } } // validate input if ( (1< #include #include #include "liquid.h" #define OUTPUT_FILENAME "conversion_example.m" int main() { // spectral periodogram options unsigned int nfft = 1200; // spectral periodogram FFT size unsigned int num_samples = 64000; // number of samples float fc = 0.20f; // carrier (relative to sampling rate) // create objects iirfilt_crcf filter_tx = iirfilt_crcf_create_lowpass(15, 0.05); nco_crcf mixer_tx = nco_crcf_create(LIQUID_VCO); nco_crcf mixer_rx = nco_crcf_create(LIQUID_VCO); iirfilt_crcf filter_rx = iirfilt_crcf_create_lowpass(7, 0.2); // set carrier frequencies nco_crcf_set_frequency(mixer_tx, fc * 2*M_PI); nco_crcf_set_frequency(mixer_rx, fc * 2*M_PI); // create objects for measuring power spectral density spgramcf spgram_tx = spgramcf_create_default(nfft); spgramf spgram_dac = spgramf_create_default(nfft); spgramcf spgram_rx = spgramcf_create_default(nfft); // run through loop one step at a time unsigned int i; for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "cpfskmodem_example.m" // print usage/help message void usage() { printf("cpfskmodem_example -- continuous-phase frequency-shift keying example\n"); printf("options:\n"); printf(" h : print help\n"); printf(" t : filter type: [square], rcos-full, rcos-half, gmsk\n"); printf(" p : bits/symbol, default: 1\n"); printf(" H : modulation index, default: 0.5\n"); printf(" k : samples/symbol, default: 8\n"); printf(" m : filter delay (symbols), default: 3\n"); printf(" b : filter roll-off, default: 0.35\n"); printf(" n : number of data symbols, default: 80\n"); printf(" s : SNR [dB], default: 40\n"); printf(" F : carrier frequency offset, default: 0\n"); printf(" P : carrier phase offset, default: 0\n"); printf(" T : fractional symbol offset, default: 0\n"); } int main(int argc, char*argv[]) { // options unsigned int bps = 1; // number of bits/symbol float h = 0.5f; // modulation index (h=1/2 for MSK) unsigned int k = 4; // filter samples/symbol unsigned int m = 3; // filter delay (symbols) float beta = 0.35f; // GMSK bandwidth-time factor unsigned int num_symbols = 20; // number of data symbols float SNRdB = 40.0f; // signal-to-noise ratio [dB] float cfo = 0.0f; // carrier frequency offset float cpo = 0.0f; // carrier phase offset float tau = 0.0f; // fractional symbol timing offset int filter_type = LIQUID_CPFSK_SQUARE; int dopt; while ((dopt = getopt(argc,argv,"ht:p:H:k:m:b:n:s:F:P:T:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 't': if (strcmp(optarg,"square")==0) { filter_type = LIQUID_CPFSK_SQUARE; } else if (strcmp(optarg,"rcos-full")==0) { filter_type = LIQUID_CPFSK_RCOS_FULL; } else if (strcmp(optarg,"rcos-half")==0) { filter_type = LIQUID_CPFSK_RCOS_PARTIAL; } else if (strcmp(optarg,"gmsk")==0) { filter_type = LIQUID_CPFSK_GMSK; } else { fprintf(stderr,"error: %s, unknown filter type '%s'\n", argv[0], optarg); exit(1); } break; case 'p': bps = atoi(optarg); break; case 'H': h = atof(optarg); break; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'F': cfo = atof(optarg); break; case 'P': cpo = atof(optarg); break; case 'T': tau = atof(optarg); break; default: exit(1); } } unsigned int i; // derived values unsigned int num_samples = k*num_symbols; unsigned int M = 1 << bps; float nstd = powf(10.0f, -SNRdB/20.0f); // arrays unsigned int sym_in [num_symbols]; // input symbols float complex x [num_samples]; // transmitted signal float complex y [num_samples]; // received signal unsigned int sym_out[num_symbols]; // output symbols // create modem objects cpfskmod mod = cpfskmod_create(bps, h, k, m, beta, filter_type); cpfskdem dem = cpfskdem_create(bps, h, k, m, beta, filter_type); // print modulator cpfskmod_print(mod); // get full symbol delay unsigned int delay = cpfskmod_get_delay(mod) + cpfskdem_get_delay(dem); printf("delay: %u samples\n", delay); // generate message signal for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "cpfsk_psd_example.m" // print usage/help message void usage() { printf("cpfsk_psd_example -- continuous-phase frequency-shift keying example\n"); printf("options:\n"); printf(" h : print help\n"); printf(" p : bits/symbol, default: 1\n"); printf(" H : modulation index, default: 0.5\n"); printf(" k : samples/symbol, default: 8\n"); printf(" m : filter delay (symbols), default: 3\n"); printf(" b : filter roll-off, default: 0.35\n"); printf(" n : number of data symbols, default: 80\n"); } int main(int argc, char*argv[]) { // options unsigned int bps = 1; // number of bits/symbol float h = 0.5f; // modulation index (h=1/2 for MSK) unsigned int k = 8; // filter samples/symbol unsigned int m = 7; // filter delay (symbols) float beta = 0.35f; // GMSK bandwidth-time factor unsigned int num_symbols = 48000; // number of data symbols unsigned int nfft = 2400; // spectral periodogram FFT size int dopt; while ((dopt = getopt(argc,argv,"hp:H:k:m:b:n:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'p': bps = atoi(optarg); break; case 'H': h = atof(optarg); break; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'n': num_symbols = atoi(optarg); break; default: exit(1); } } unsigned int i; // derived values unsigned int M = 1 << bps; // constellation size // create modulators cpfskmod mod_0 = cpfskmod_create(bps, h, k, m, beta, LIQUID_CPFSK_SQUARE); cpfskmod mod_1 = cpfskmod_create(bps, h, k, m, beta, LIQUID_CPFSK_RCOS_FULL); cpfskmod mod_2 = cpfskmod_create(bps, h, k, m, beta, LIQUID_CPFSK_RCOS_PARTIAL); cpfskmod mod_3 = cpfskmod_create(bps, h, k, m, beta, LIQUID_CPFSK_GMSK); // buffers float complex buf_0[k]; float complex buf_1[k]; float complex buf_2[k]; float complex buf_3[k]; // create PSD estimators // spectral periodogram options // create spectral periodogram spgramcf spgram_0 = spgramcf_create_default(nfft); spgramcf spgram_1 = spgramcf_create_default(nfft); spgramcf spgram_2 = spgramcf_create_default(nfft); spgramcf spgram_3 = spgramcf_create_default(nfft); // estimate PSD for each symbol for (i=0; i #include #include #include "liquid.h" // print usage/help message void usage() { printf("crc_example [options]\n"); printf(" u/h : print usage\n"); printf(" n : input data size (number of uncoded bytes)\n"); printf(" v : checking scheme, (crc32 default):\n"); liquid_print_crc_schemes(); } int main(int argc, char*argv[]) { // options unsigned int n = 32; // data length (bytes) crc_scheme check = LIQUID_CRC_32; // error-detection scheme int dopt; while((dopt = getopt(argc,argv,"uhn:v:")) != EOF){ switch (dopt) { case 'h': case 'u': usage(); return 0; case 'n': n = atoi(optarg); break; case 'v': check = liquid_getopt_str2crc(optarg); if (check == LIQUID_CRC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported error-detection scheme \"%s\"\n\n",optarg); exit(1); } break; default: exit(1); } } // validate input unsigned int i; // initialize data array, leaving space for key at the end unsigned char data[n+4]; for (i=0; i #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "cvsd_example.m" // print usage/help message void usage() { printf("cvsd_example [options]\n"); printf(" u/h : print usage\n"); printf(" n : number of samples, default: 512\n"); printf(" f : input signal frequency, default: 0.02\n"); printf(" b : cvsd param: num-bits, default: 3\n"); printf(" z : cvsd param: zeta, default: 1.5\n"); printf(" a : cvsd param: alpha, default: 0.95\n"); } int main(int argc, char*argv[]) { // options unsigned int n=512; // number of samples float fc = 0.02; // input signal frequency unsigned int nbits=3; // number of adjacent bits to observe float zeta=1.5f; // slope adjustment multiplier float alpha = 0.95; // pre-/post-filter coefficient int dopt; while ((dopt = getopt(argc,argv,"uhn:f:b:z:a:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'n': n = atoi(optarg); break; case 'f': fc = atof(optarg); break; case 'b': nbits = atoi(optarg); break; case 'z': zeta = atof(optarg); break; case 'a': alpha = atof(optarg); break; default: exit(1); } } // validate input unsigned int i; // data arrays float x[n]; // input time series unsigned char b[n]; // encoded bit pattern float y[n]; // reconstructed time series // create cvsd codecs cvsd cvsd_encoder = cvsd_create(nbits, zeta, alpha); cvsd cvsd_decoder = cvsd_create(nbits, zeta, alpha); cvsd_print(cvsd_encoder); // generate input time series for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "detector_example.m" // print usage/help message void usage() { printf("detector_example -- test binary pre-demodulation synchronization\n"); printf("options:\n"); printf(" h : print usage/help\n"); printf(" n : number of sync samples, default: 128\n"); printf(" F : carrier frequency offset, default: 0.02\n"); printf(" T : fractional sample offset dt in [-0.5, 0.5], default: 0\n"); printf(" S : SNR [dB], default: 20\n"); printf(" t : detection threshold, default: 0.3\n"); } int main(int argc, char*argv[]) { //srand(time(NULL)); // options unsigned int n = 128; // number of sync samples float dt = 0.0f; // fractional sample timing offset float noise_floor = -30.0f; // noise floor [dB] float SNRdB = 20.0f; // signal-to-noise ratio [dB] float dphi = 0.0f; // carrier frequency offset float phi = 0.0f; // carrier phase offset float threshold = 0.3f; // detection threshold int dopt; while ((dopt = getopt(argc,argv,"hn:T:F:S:t:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': n = atoi(optarg); break; case 'F': dphi = atof(optarg); break; case 'T': dt = atof(optarg); break; case 'S': SNRdB = atof(optarg); break; case 't': threshold = atof(optarg); break; default: exit(1); } } unsigned int i; // validate input if (dt < -0.5f || dt > 0.5f) { fprintf(stderr,"error: %s, fractional sample offset must be in [-0.5,0.5]\n", argv[0]); exit(1); } // derived values unsigned int num_samples = 3*n; float nstd = powf(10.0f, noise_floor/20.0f); float gamma = powf(10.0f, (SNRdB + noise_floor)/20.0f); // arrays float complex s[n]; // synchronization pattern (samples) float complex x[num_samples]; // transmitted signal float complex y[num_samples]; // received signal // generate synchronization pattern (OFDM symbol, slightly over-sampled) float complex S[n]; for (i=0; i 0.6*n) ? randnf() + _Complex_I*randnf() : 0.0f; fft_run(n, S, s, LIQUID_FFT_BACKWARD, 0); float s2 = 0.0f; for (i=0; i #include "liquid.h" int main() { // input array float complex x[] = { 1 + 1 * _Complex_I, 2 + 1 * _Complex_I, 3 + 1 * _Complex_I, 4 + 1 * _Complex_I, 5 + 1 * _Complex_I}; // coefficients array float complex h[] = { 1 + 1 * _Complex_I, -1 + 1 * _Complex_I, 1 + 1 * _Complex_I, -1 + 1 * _Complex_I, 1 + 1 * _Complex_I}; // dot product result float complex y; // run regular dot product dotprod_cccf_run(x,h,5,&y); printf("dotprod_cccf : %8.2f + j%8.2f\n", crealf(y), cimagf(y)); // run structured dot product dotprod_cccf q = dotprod_cccf_create(x,5); dotprod_cccf_execute(q,h,&y); printf("dotprod_cccf (structured) : %8.2f + j%8.2f\n", crealf(y), cimagf(y)); dotprod_cccf_destroy(q); return 0; } liquid-dsp-1.3.1/examples/dotprod_rrrf_example.c000066400000000000000000000012621317124540100217710ustar00rootroot00000000000000// // dotprod_rrrf_example.c // // This example demonstrates the interface to the floating-point dot // product object (dotprod_rrrf). // #include #include "liquid.h" int main() { // input array float x[] = { 1, 2, 3, 4, 5}; // coefficients array float h[] = { 1, -1, 1, -1, 1}; // dot product result float y; // run regular dot product dotprod_rrrf_run(x,h,5,&y); printf("dotprod_rrrf : %8.2f\n", y); // run structured dot product dotprod_rrrf q = dotprod_rrrf_create(x,5); dotprod_rrrf_execute(q,h,&y); printf("dotprod_rrrf (structured) : %8.2f\n", y); dotprod_rrrf_destroy(q); return 0; } liquid-dsp-1.3.1/examples/eqlms_cccf_blind_example.c000066400000000000000000000267741317124540100225510ustar00rootroot00000000000000// // eqlms_cccf_blind_example.c // // This example tests the least mean-squares (LMS) equalizer (EQ) on a // signal with an unknown modulation and carrier frequency offset. That // is, the equalization is done completely blind of the modulation // scheme or its underlying data set. The error estimate assumes a // constant modulus linear modulation scheme. This works surprisingly // well even more amplitude-modulated signals, e.g. 'qam16'. // #include #include #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "eqlms_cccf_blind_example.m" // print usage/help message void usage() { printf("Usage: eqlms_cccf_blind_example [OPTION]\n"); printf(" h : print help\n"); printf(" n : number of symbols, default: 500\n"); printf(" s : SNR [dB], default: 30\n"); printf(" c : number of channel filter taps (minimum: 1), default: 5\n"); printf(" k : samples/symbol, default: 2\n"); printf(" m : filter semi-length (symbols), default: 4\n"); printf(" b : filter excess bandwidth factor, default: 0.3\n"); printf(" p : equalizer semi-length (symbols), default: 3\n"); printf(" u : equalizer learning rate, default; 0.05\n"); printf(" M : modulation scheme (qpsk default)\n"); liquid_print_modulation_schemes(); } int main(int argc, char*argv[]) { //srand(time(NULL)); // options unsigned int num_symbols=800; // number of symbols to observe float SNRdB = 30.0f; // signal-to-noise ratio [dB] float fc = 0.002f; // carrier offset unsigned int hc_len=5; // channel filter length unsigned int k=2; // matched filter samples/symbol unsigned int m=3; // matched filter delay (symbols) float beta=0.3f; // matched filter excess bandwidth factor unsigned int p=3; // equalizer length (symbols, hp_len = 2*k*p+1) float mu = 0.08f; // equalizer learning rate // modulation type/depth modulation_scheme ms = LIQUID_MODEM_QPSK; int dopt; while ((dopt = getopt(argc,argv,"hn:s:c:k:m:b:p:u:M:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': num_symbols = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'c': hc_len = atoi(optarg); break; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'p': p = atoi(optarg); break; case 'u': mu = atof(optarg); break; case 'M': ms = liquid_getopt_str2mod(optarg); if (ms == LIQUID_MODEM_UNKNOWN) { fprintf(stderr,"error: %s, unknown/unsupported modulation scheme '%s'\n", argv[0], optarg); return 1; } break; default: exit(1); } } // validate input if (num_symbols == 0) { fprintf(stderr,"error: %s, number of symbols must be greater than zero\n", argv[0]); exit(1); } else if (hc_len == 0) { fprintf(stderr,"error: %s, channel must have at least 1 tap\n", argv[0]); exit(1); } else if (k < 2) { fprintf(stderr,"error: %s, samples/symbol must be at least 2\n", argv[0]); exit(1); } else if (m == 0) { fprintf(stderr,"error: %s, filter semi-length must be at least 1 symbol\n", argv[0]); exit(1); } else if (beta < 0.0f || beta > 1.0f) { fprintf(stderr,"error: %s, filter excess bandwidth must be in [0,1]\n", argv[0]); exit(1); } else if (p == 0) { fprintf(stderr,"error: %s, equalizer semi-length must be at least 1 symbol\n", argv[0]); exit(1); } else if (mu < 0.0f || mu > 1.0f) { fprintf(stderr,"error: %s, equalizer learning rate must be in [0,1]\n", argv[0]); exit(1); } // derived values unsigned int hm_len = 2*k*m+1; // matched filter length unsigned int hp_len = 2*k*p+1; // equalizer filter length unsigned int num_samples = k*num_symbols; // bookkeeping variables float complex syms_tx[num_symbols]; // transmitted data symbols float complex x[num_samples]; // interpolated time series float complex y[num_samples]; // channel output float complex z[num_samples]; // equalized output float complex syms_rx[num_symbols]; // received data symbols float hm[hm_len]; // matched filter response float complex hc[hc_len]; // channel filter coefficients float complex hp[hp_len]; // equalizer filter coefficients unsigned int i; // generate matched filter response liquid_firdes_prototype(LIQUID_FIRFILT_RRC, k, m, beta, 0.0f, hm); firinterp_crcf interp = firinterp_crcf_create(k, hm, hm_len); // create the modem objects modem mod = modem_create(ms); modem demod = modem_create(ms); unsigned int M = 1 << modem_get_bps(mod); // generate channel impulse response, filter hc[0] = 1.0f; for (i=1; i #include #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "eqlms_cccf_block_example.m" // print usage/help message void usage() { printf("Usage: eqlms_cccf_block_example [OPTION]\n"); printf(" h : print help\n"); printf(" n : number of symbols, default: 500\n"); printf(" c : number of channel filter taps (minimum: 1), default: 5\n"); printf(" k : samples/symbol, default: 2\n"); printf(" m : filter semi-length (symbols), default: 4\n"); printf(" b : filter excess bandwidth factor, default: 0.3\n"); printf(" p : equalizer semi-length (symbols), default: 3\n"); printf(" u : equalizer learning rate, default; 0.05\n"); } int main(int argc, char*argv[]) { //srand(time(NULL)); // options unsigned int num_samples = 2400; // number of symbols to observe unsigned int hc_len = 5; // channel filter length unsigned int k = 2; // matched filter samples/symbol unsigned int m = 3; // matched filter delay (symbols) float beta = 0.3f; // matched filter excess bandwidth factor unsigned int p = 3; // equalizer length (symbols, hp_len = 2*k*p+1) float mu = 0.15f; // equalizer learning rate modulation_scheme ms = LIQUID_MODEM_QPSK; int dopt; while ((dopt = getopt(argc,argv,"hn:c:k:m:b:p:u:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': num_samples = atoi(optarg); break; case 'c': hc_len = atoi(optarg); break; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'p': p = atoi(optarg); break; case 'u': mu = atof(optarg); break; default: exit(1); } } unsigned int i; // validate input if (num_samples == 0) { fprintf(stderr,"error: %s, number of symbols must be greater than zero\n", argv[0]); exit(1); } else if (hc_len == 0) { fprintf(stderr,"error: %s, channel must have at least 1 tap\n", argv[0]); exit(1); } else if (k < 2) { fprintf(stderr,"error: %s, samples/symbol must be at least 2\n", argv[0]); exit(1); } else if (m == 0) { fprintf(stderr,"error: %s, filter semi-length must be at least 1 symbol\n", argv[0]); exit(1); } else if (beta < 0.0f || beta > 1.0f) { fprintf(stderr,"error: %s, filter excess bandwidth must be in [0,1]\n", argv[0]); exit(1); } else if (p == 0) { fprintf(stderr,"error: %s, equalizer semi-length must be at least 1 symbol\n", argv[0]); exit(1); } else if (mu < 0.0f || mu > 1.0f) { fprintf(stderr,"error: %s, equalizer learning rate must be in [0,1]\n", argv[0]); exit(1); } // derived/fixed values unsigned int buf_len = 37; float complex buf_input [buf_len]; float complex buf_channel[buf_len]; float complex buf_output [buf_len]; // // generate input sequence using symbol stream generator // symstreamcf gen = symstreamcf_create_linear(LIQUID_FIRFILT_ARKAISER,k,m,beta,ms); // // create multi-path channel filter // float complex hc[hc_len]; for (i=0; i #include #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "eqlms_cccf_decisiondirected_example.m" // print usage/help message void usage() { printf("Usage: eqlms_cccf_decisiondirected_example [OPTION]\n"); printf(" h : print help\n"); printf(" n : number of symbols, default: 500\n"); printf(" s : SNR [dB], default: 30\n"); printf(" c : number of channel filter taps (minimum: 1), default: 5\n"); printf(" k : samples/symbol, default: 2\n"); printf(" m : filter semi-length (symbols), default: 4\n"); printf(" b : filter excess bandwidth factor, default: 0.3\n"); printf(" p : equalizer semi-length (symbols), default: 3\n"); printf(" u : equalizer learning rate, default; 0.05\n"); printf(" M : modulation scheme (qpsk default)\n"); liquid_print_modulation_schemes(); } int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int num_symbols=500; // number of symbols to observe float SNRdB = 30.0f; // signal-to-noise ratio [dB] unsigned int hc_len=5; // channel filter length unsigned int k=2; // matched filter samples/symbol unsigned int m=3; // matched filter delay (symbols) float beta=0.3f; // matched filter excess bandwidth factor unsigned int p=3; // equalizer length (symbols, hp_len = 2*k*p+1) float mu = 0.08f; // learning rate // modulation type/depth modulation_scheme ms = LIQUID_MODEM_QPSK; int dopt; while ((dopt = getopt(argc,argv,"hn:s:c:k:m:b:p:u:M:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': num_symbols = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'c': hc_len = atoi(optarg); break; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'p': p = atoi(optarg); break; case 'u': mu = atof(optarg); break; case 'M': ms = liquid_getopt_str2mod(optarg); if (ms == LIQUID_MODEM_UNKNOWN) { fprintf(stderr,"error: %s, unknown/unsupported modulation scheme '%s'\n", argv[0], optarg); return 1; } break; default: exit(1); } } // validate input if (num_symbols == 0) { fprintf(stderr,"error: %s, number of symbols must be greater than zero\n", argv[0]); exit(1); } else if (hc_len == 0) { fprintf(stderr,"error: %s, channel must have at least 1 tap\n", argv[0]); exit(1); } else if (k < 2) { fprintf(stderr,"error: %s, samples/symbol must be at least 2\n", argv[0]); exit(1); } else if (m == 0) { fprintf(stderr,"error: %s, filter semi-length must be at least 1 symbol\n", argv[0]); exit(1); } else if (beta < 0.0f || beta > 1.0f) { fprintf(stderr,"error: %s, filter excess bandwidth must be in [0,1]\n", argv[0]); exit(1); } else if (p == 0) { fprintf(stderr,"error: %s, equalizer semi-length must be at least 1 symbol\n", argv[0]); exit(1); } else if (mu < 0.0f || mu > 1.0f) { fprintf(stderr,"error: %s, equalizer learning rate must be in [0,1]\n", argv[0]); exit(1); } // derived values unsigned int hm_len = 2*k*m+1; // matched filter length unsigned int hp_len = 2*k*p+1; // equalizer filter length unsigned int num_samples = k*num_symbols; // bookkeeping variables float complex sym_tx[num_symbols]; // transmitted data sequence float complex x[num_samples]; // interpolated time series float complex y[num_samples]; // channel output float complex z[num_samples]; // equalized output float hm[hm_len]; // matched filter response float complex hc[hc_len]; // channel filter coefficients float complex hp[hp_len]; // equalizer filter coefficients unsigned int i; // generate matched filter response liquid_firdes_prototype(LIQUID_FIRFILT_RRC, k, m, beta, 0.0f, hm); firinterp_crcf interp = firinterp_crcf_create(k, hm, hm_len); // create the modem objects modem mod = modem_create(ms); modem demod = modem_create(ms); unsigned int M = 1 << modem_get_bps(mod); // generate channel impulse response, filter hc[0] = 1.0f; for (i=1; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "eqlms_cccf_example.m" int main() { // options unsigned int n=512; // number of symbols to observe unsigned int ntrain=256;// number of training symbols unsigned int h_len=6; // channel filter length unsigned int p=12; // equalizer order // bookkeeping variables float complex d[n]; // data sequence float complex y[n]; // received data sequence (filtered by channel) float complex d_hat[n]; // recovered data sequence float complex h[h_len]; // channel filter coefficients float complex w[p]; // equalizer filter coefficients unsigned int i; // create equalizer (default initial coefficients) eqlms_cccf eq = eqlms_cccf_create(NULL,p); // create channel filter (random delay taps) h[0] = 1.0f; for (i=1; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "eqrls_cccf_example.m" int main() { // options unsigned int n=512; // number of symbols to observe unsigned int ntrain=256;// number of training symbols unsigned int h_len=6; // channel filter length unsigned int p=12; // equalizer order // bookkeeping variables float complex d[n]; // data sequence float complex y[n]; // received data sequence (filtered by channel) float complex d_hat[n]; // recovered data sequence float complex h[h_len]; // channel filter coefficients float complex w[p]; // equalizer filter coefficients unsigned int i; // create equalizer (default initial coefficients) eqrls_cccf eq = eqrls_cccf_create(NULL,p); // create channel filter (random delay taps) h[0] = 1.0f; for (i=1; i #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "debug_fading_generator_example.m" int main() { // options unsigned int h_len=51; // doppler filter length float fd=0.05f; // maximum doppler frequency float K=2.0f; // Rice fading factor float omega=1.0f; // mean power float theta=0.0f; // angle of arrival unsigned int n=256; // number of samples // generate filter unsigned int i; float h[h_len]; fir_design_doppler(h_len,fd,K,theta,h); firfilt_rrrf fi = firfilt_rrrf_create(h,h_len); firfilt_rrrf fq = firfilt_rrrf_create(h,h_len); FILE*fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s, auto-generated file\n\n",OUTPUT_FILENAME); fprintf(fid,"clear all;\nclose all;\n\n"); for (i=0; i #include #include #include #include "liquid.h" // print usage/help message void usage() { printf("fec_example [options]\n"); printf(" u/h : print usage\n"); printf(" n : input data size (number of uncoded bytes)\n"); printf(" c : coding scheme, (h74 default):\n"); liquid_print_fec_schemes(); } int main(int argc, char*argv[]) { // options unsigned int n = 4; // data length (bytes) unsigned int nmax = 2048; // maximum data length fec_scheme fs = LIQUID_FEC_HAMMING74; // error-correcting scheme int dopt; while((dopt = getopt(argc,argv,"uhn:c:")) != EOF){ switch (dopt) { case 'h': case 'u': usage(); return 0; case 'n': n = atoi(optarg); break; case 'c': fs = liquid_getopt_str2fec(optarg); if (fs == LIQUID_FEC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported fec scheme \"%s\"\n\n",optarg); exit(1); } break; default: exit(1); } } // ensure proper data length n = (n > nmax) ? nmax : n; // create arrays unsigned int n_enc = fec_get_enc_msg_length(fs,n); printf("dec msg len : %u\n", n); printf("enc msg len : %u\n", n_enc); unsigned char data[n]; // original data message unsigned char msg_enc[n_enc]; // encoded data message unsigned char msg_cor[n_enc]; // corrupted data message unsigned char msg_dec[n]; // decoded data message // create object fec q = fec_create(fs,NULL); fec_print(q); unsigned int i; // create message for (i=0; i>= 1; } } //printf("number of symbol errors detected: %d\n", num_errors_detected); printf("number of symbol errors received: %3u / %3u\n", num_sym_errors, n); printf("number of bit errors received: %3u / %3u\n", num_bit_errors, n*8); // clean up objects fec_destroy(q); return 0; } liquid-dsp-1.3.1/examples/fec_soft_example.c000066400000000000000000000142521317124540100210560ustar00rootroot00000000000000// // fec_soft_example.c // // This example demonstrates the interface for forward error-correction // (FEC) codes with soft-decision decoding. A buffer of data bytes is // encoded before the data are corrupted with at least one error and // noise. The decoder then attempts to recover the original data set // from the soft input bits. The user may select the FEC scheme from // the command-line interface. // // SEE ALSO: fec_example.c // packetizer_soft_example.c #include #include #include #include #include "liquid.h" // print usage/help message void usage() { printf("fecsoft_example [options]\n"); printf(" u/h : print usage\n"); printf(" v/q : verbose/queit (print soft bits?)\n"); printf(" n : input data size (number of uncoded bytes)\n"); printf(" c : coding scheme, (h74 default):\n"); liquid_print_fec_schemes(); } int main(int argc, char*argv[]) { // options unsigned int n = 4; // data length (bytes) unsigned int nmax = 2048; // maximum data length fec_scheme fs = LIQUID_FEC_HAMMING74; // error-correcting scheme int verbose = 1; // verbose? int dopt; while((dopt = getopt(argc,argv,"uhvqn:c:")) != EOF){ switch (dopt) { case 'h': case 'u': usage(); return 0; case 'v': verbose = 1; break; case 'q': verbose = 0; break; case 'n': n = atoi(optarg); break; case 'c': fs = liquid_getopt_str2fec(optarg); if (fs == LIQUID_FEC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported fec scheme \"%s\"\n\n",optarg); exit(1); } break; default: exit(1); } } // ensure proper data length n = (n > nmax) ? nmax : n; // create arrays unsigned int n_enc = fec_get_enc_msg_length(fs,n); printf("dec msg len : %u\n", n); printf("enc msg len : %u\n", n_enc); unsigned char data[n]; // original data message unsigned char msg_enc[n_enc]; // encoded data message unsigned char msg_cor_soft[8*n_enc]; // corrupted data message (soft bits) unsigned char msg_cor_hard[n_enc]; // corrupted data message (hard bits) unsigned char msg_dec[n]; // decoded data message // create object fec q = fec_create(fs,NULL); fec_print(q); unsigned int i; // create message for (i=0; i 255) soft_bit = 255; if (soft_bit < 0) soft_bit = 0; msg_cor_soft[i] = soft_bit; } // convert to hard bits (printing purposes) for (i=0; i> 0) & 0x80; msg_cor_hard[i] |=(msg_cor_soft[8*i+1] >> 1) & 0x40; msg_cor_hard[i] |=(msg_cor_soft[8*i+2] >> 2) & 0x20; msg_cor_hard[i] |=(msg_cor_soft[8*i+3] >> 3) & 0x10; msg_cor_hard[i] |=(msg_cor_soft[8*i+4] >> 4) & 0x08; msg_cor_hard[i] |=(msg_cor_soft[8*i+5] >> 5) & 0x04; msg_cor_hard[i] |=(msg_cor_soft[8*i+6] >> 6) & 0x02; msg_cor_hard[i] |=(msg_cor_soft[8*i+7] >> 7) & 0x01; } // decode message fec_decode_soft(q, n, msg_cor_soft, msg_dec); printf("original message: [%3u] ",n); for (i=0; i> (8-j-1)) & 0x01; unsigned int bit_rec = (msg_cor_soft[8*i+j] > 127) ? 1 : 0; //printf("%1u %3u (%1u) %c", bit_enc, msg_cor_soft[i], bit_rec, bit_enc != bit_rec ? '*' : ' '); printf("%4u%c", msg_cor_soft[8*i+j], bit_enc != bit_rec ? '*' : ' '); } printf(" : %c%.2X\n", msg_cor_hard[i]==msg_enc[i] ? ' ' : '*', (unsigned int) (msg_cor_hard[i])); } } // verbose printf("decoded message: [%3u] ",n); for (i=0; i>= 1; } } //printf("number of symbol errors detected: %d\n", num_errors_detected); printf("number of symbol errors received: %3u / %3u\n", num_sym_errors, n); printf("number of bit errors received: %3u / %3u\n", num_bit_errors, n*8); // clean up objects fec_destroy(q); return 0; } liquid-dsp-1.3.1/examples/fft_example.c000066400000000000000000000053161317124540100200460ustar00rootroot00000000000000// // fft_example.c // // This example demonstrates the interface to the fast discrete Fourier // transform (FFT). // SEE ALSO: mdct_example.c // fct_example.c // #include #include #include #include #include "liquid.h" // print usage/help message void usage() { printf("fft_example [options]\n"); printf(" h : print help\n"); printf(" v/q : verbose/quiet\n"); printf(" n : fft size, default: 16\n"); } int main(int argc, char*argv[]) { // options unsigned int nfft = 16; // transform size int method = 0; // fft method (ignored) int verbose = 0; // verbose output? int dopt; while ((dopt = getopt(argc,argv,"hvqn:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'v': verbose = 1; break; case 'q': verbose = 0; break; case 'n': nfft = atoi(optarg); break; default: exit(1); } } // allocate memory arrays float complex * x = (float complex*) malloc(nfft*sizeof(float complex)); float complex * y = (float complex*) malloc(nfft*sizeof(float complex)); float complex * z = (float complex*) malloc(nfft*sizeof(float complex)); // initialize input unsigned int i; for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "fftfilt_crcf_example.m" int main() { // options unsigned int h_len=57; // filter length float fc=0.10f; // cutoff frequency float As=60.0f; // stop-band attenuation unsigned int n=64; // number of samples per block unsigned int num_blocks=6; // total number of blocks // derived values unsigned int num_samples = n * num_blocks; // design filter float h[h_len]; liquid_firdes_kaiser(h_len, fc, As, 0, h); // design FFT-based filter and scale to bandwidth fftfilt_crcf q0 = fftfilt_crcf_create(h, h_len, n); fftfilt_crcf_set_scale(q0, 2.0f*fc); // design regular FIR filter firfilt_crcf q1 = firfilt_crcf_create(h, h_len); firfilt_crcf_set_scale(q1, 2.0f*fc); unsigned int i; // allocate memory for data arrays float complex x[num_samples]; // input float complex y0[num_samples]; // output (fftfilt) float complex y1[num_samples]; // output (firfilt) // generate input signal (noise) for (i=0; i #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "firdecim_crcf_example.m" // print usage/help message void usage() { printf("firdecim_crcf_example:\n"); printf(" u/h : print usage/help\n"); printf(" k : samples/symbol (interp factor), k > 1, default: 2\n"); printf(" m : filter delay (symbols), m > 0, default: 2\n"); printf(" b : beta, excess bandwidth factor, 0 < beta < 1, default: 0.5\n"); printf(" n : number of data symbols, default: 8\n"); } int main(int argc, char*argv[]) { // options unsigned int k=2; // samples/symbol unsigned int m=2; // filter delay float beta = 0.5f; // filter excess bandwidth unsigned int num_data_symbols=8; // number of data symbols int dopt; while ((dopt = getopt(argc,argv,"uhk:m:b:n:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'n': num_data_symbols = atoi(optarg); break; default: usage(); return 1; } } // validate options if (k < 2) { fprintf(stderr,"error: %s, interp factor must be greater than 1\n", argv[0]); return 1; } else if (m < 1) { fprintf(stderr,"error: %s, filter delay must be greater than 0\n", argv[0]); return 1; } else if (beta <= 0.0 || beta > 1.0f) { fprintf(stderr,"error: %s, beta (excess bandwidth factor) must be in (0,1]\n", argv[0]); return 1; } else if (num_data_symbols < 1) { fprintf(stderr,"error: %s, must have at least one data symbol\n", argv[0]); return 1; } // derived values unsigned int h_len = 2*k*m+1; unsigned int num_symbols = num_data_symbols + 2*m; unsigned int num_samples = k*num_symbols; // design filter and create interpolator and decimator objects float h[h_len]; // transmit filter float g[h_len]; // receive filter (reverse of h) liquid_firdes_rrcos(k,m,beta,0.3f,h); unsigned int i; for (i=0; i= k*m) && ((i%k)==0)) printf(" **\n"); else printf("\n"); } printf("output symbols:\n"); for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "firdes_kaiser_example.m" // print usage/help message void usage() { printf("firdes_kaiser_example:\n"); printf(" u/h : print usage/help\n"); printf(" f : filter cutoff frequency, 0 < f < 0.5, default: 0.2\n"); printf(" s : filter stop-band attenuation [dB], 0 < s, default: 60\n"); printf(" m : fractional sample delay, -0.5 < m < 0.5, default: 0\n"); printf(" n : filter length [taps], n > 1, default: 55\n"); } int main(int argc, char*argv[]) { // options float fc=0.2f; // filter cutoff frequency float As=60.0f; // stop-band attenuation [dB] float mu=0.0f; // fractional timing offset unsigned int h_len=55; // filter length int dopt; while ((dopt = getopt(argc,argv,"uhf:n:s:m:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'f': fc = atof(optarg); break; case 'n': h_len = atoi(optarg); break; case 's': As = atof(optarg); break; case 'm': mu = atof(optarg); break; default: exit(1); } } // validate input if ( fc <= 0.0f ) { fprintf(stderr,"error: %s, filter cutoff frequency must be greater than zero\n", argv[0]); exit(1); } else if ( h_len == 0 ) { fprintf(stderr,"error: %s, filter length must be greater than zero\n", argv[0]); exit(1); } printf("filter design parameters\n"); printf(" cutoff frequency : %8.4f\n", fc); printf(" stop-band attenuation [dB] : %8.4f\n", As); printf(" fractional sample offset : %8.4f\n", mu); printf(" filter length : %u\n", h_len); // generate the filter unsigned int i; float h[h_len]; liquid_firdes_kaiser(h_len,fc,As,mu,h); // print coefficients for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "firdespm_callback_example.m" // user-defined callback function defining response and weights int callback(double _frequency, void * _userdata, double * _desired, double * _weight) { // de-reference pointer as floating-point value unsigned int n = *((unsigned int*)_userdata); double v = sincf(n*_frequency); double fc = 1.0f / (float)n; // inverse sinc if (_frequency < fc) { *_desired = 1.0f / v; // inverse of sinc *_weight = 4.0f; } else { *_desired = 0.0f; // stop-band *_weight = 10*fabs(v) * exp(4.0*_frequency); } return 0; } int main(int argc, char*argv[]) { // filter design parameters unsigned int n = 8; // sinc filter length unsigned int h_len = 81; // inverse sinc filter length liquid_firdespm_btype btype = LIQUID_FIRDESPM_BANDPASS; unsigned int num_bands = 2; float bands[4] = {0.00f, 0.75f/(float)n, // pass-band 1.05f/(float)n, 0.5f}; // stop-band // design filter float h[h_len]; firdespm q = firdespm_create_callback(h_len,num_bands,bands,btype,callback,&n); firdespm_execute(q,h); firdespm_destroy(q); // print coefficients unsigned int i; for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "firdespm_example.m" int main(int argc, char*argv[]) { // filter design parameters unsigned int h_len = 91; liquid_firdespm_btype btype = LIQUID_FIRDESPM_BANDPASS; unsigned int num_bands = 4; float bands[8] = {0.00f, 0.10f, 0.12f, 0.18f, 0.20f, 0.30f, 0.31f, 0.50f}; float des[4] = {1.0f, 0.0f, 0.1f, 0.0f}; float weights[4] = {1.0f, 4.0f, 8.0f, 4.0f}; liquid_firdespm_wtype wtype[4] = {LIQUID_FIRDESPM_FLATWEIGHT, LIQUID_FIRDESPM_FLATWEIGHT, LIQUID_FIRDESPM_FLATWEIGHT, LIQUID_FIRDESPM_EXPWEIGHT}; unsigned int i; float h[h_len]; firdespm_run(h_len,num_bands,bands,des,weights,wtype,btype,h); // print coefficients for (i=0; i #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "firdespm_lowpass_example.m" // print usage/help message void usage() { printf("firdespm_lowpass_example:\n"); printf(" -h : print usage/help\n"); printf(" -n : filter length, 1 < n default: 57\n"); printf(" -f : filter cutoff frequency, 0 < f < 0.5, default: 0.2\n"); printf(" -s : stop-band attenuation [dB], 0 < s, default: 60\n"); } int main(int argc, char*argv[]) { // options unsigned int n = 57; // filter cutoff frequency float fc = 0.2f; // filter cutoff frequency float As = 60.0f; // stop-band attenuation [dB] int dopt; while ((dopt = getopt(argc,argv,"hn:f:s:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': n = atoi(optarg); break; case 'f': fc = atof(optarg); break; case 's': As = atof(optarg); break; default: return -1; } } unsigned int i; printf("filter design parameters\n"); printf(" length : %12u\n", n); printf(" cutoff frequency : %12.8f Fs\n", fc); printf(" stop-band attenuation : %12.3f dB\n", As); // design the filter float h[n]; firdespm_lowpass(n,fc,As,0,h); #if 0 // print coefficients for (i=0; i #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "firfarrow_rrrf_example.m" // print usage/help message void usage() { printf("firfarrow_rrrf_example [options]\n"); printf(" h : print help\n"); printf(" t : fractional sample offset, t in [-0.5,0.5], default: 0.2\n"); } int main(int argc, char*argv[]) { // options unsigned int h_len = 19; // filter length unsigned int p = 5; // polynomial order float fc = 0.45f; // filter cutoff float As = 60.0f; // stop-band attenuation [dB] float mu = 0.1f; // fractional sample delay unsigned int num_samples = 60; // number of samples to evaluate int dopt; while ((dopt = getopt(argc,argv,"ht:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 't': mu = atof(optarg); break; default: exit(1); } } // data arrays float x[num_samples]; // input data array float y[num_samples]; // output data array // create and initialize Farrow filter object firfarrow_rrrf f = firfarrow_rrrf_create(h_len, p, fc, As); firfarrow_rrrf_set_delay(f, mu); // create low-pass filter for input signal iirfilt_rrrf lowpass = iirfilt_rrrf_create_lowpass(3, 0.1f); // push input through filter unsigned int i; for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "firfilt_cccf_example.m" // print usage/help message void usage() { printf("firfilt_cccf_example:\n"); printf(" h : print usage/help\n"); printf(" n : sequence length, default: 32\n"); printf(" s : SNR, signal-to-noise ratio [dB], default: 20\n"); } int main(int argc, char*argv[]) { // options unsigned int sequence_len = 256; // sequence length float SNRdB = 10.0f; // signal-to-noise ratio (dB) int dopt; while ((dopt = getopt(argc,argv,"hn:s:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': sequence_len = atof(optarg); break; case 's': SNRdB = atoi(optarg); break; default: usage(); exit(-1); } } unsigned int i; // derived values unsigned int num_samples = 3*sequence_len; // data arrays float complex sequence[sequence_len]; // sequence float complex x[num_samples]; // input sequence float complex rxy[num_samples]; // correlator output // generate random sequence for (i=0; i cabsf(rxy_peak)) rxy_peak = rxy[i]; } printf("peak cross-correlation : %12.8f, angle %12.8f\n", cabsf(rxy_peak), cargf(rxy_peak)); // destroy allocated objects firfilt_cccf_destroy(q); // // write results to file // FILE* fid = fopen(OUTPUT_FILENAME, "w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n\n"); fprintf(fid,"num_samples = %u;\n", num_samples); // write signal to output file for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "firfilt_crcf_example.m" int main() { // options unsigned int h_len=65; // filter length float fc=0.1f; // cutoff frequency float As=60.0f; // stop-band attenuation unsigned int n=240; // number of samples // design filter from prototype and scale to bandwidth firfilt_crcf q = firfilt_crcf_create_kaiser(h_len, fc, As, 0.0f); firfilt_crcf_set_scale(q, 2.0f*fc); firfilt_crcf_print(q); unsigned int i; // allocate memory for data arrays float complex x[n]; float complex y[n]; // generate input signal (sine wave with decaying amplitude) unsigned int wlen = (unsigned int)roundf(0.75*n); for (i=0; i #include #include "liquid.h" #define OUTPUT_FILENAME "firfilt_rrrf_example.m" int main() { // options unsigned int h_len=27; // filter length float fc=0.1f; // filter cutoff float As=60.0f; // stop-band attenuation [dB] float mu=0.0f; // timing offset unsigned int n=200; // number of random input samples // derived values unsigned int num_samples = n + h_len; // arrays float x[num_samples]; // filter input float y[num_samples]; // filter output unsigned int i; #if 0 float h[h_len]; liquid_firdes_kaiser(h_len,fc,As,mu,h); firfilt_rrrf f = firfilt_rrrf_create(h,h_len); #else firfilt_rrrf f = firfilt_rrrf_create_kaiser(h_len,fc,As,mu); #endif firfilt_rrrf_print(f); for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "firhilb_decim_example.m" int main() { unsigned int m=5; // Hilbert filter semi-length float As=60.0f; // stop-band attenuation [dB] float fc=0.37f; // signal center frequency unsigned int num_samples=128; // number of samples // data arrays float x[2*num_samples]; // real input float complex y[num_samples]; // complex output // initialize input array unsigned int i; for (i=0; i<2*num_samples; i++) x[i] = cosf(2*M_PI*fc*i); // create Hilbert transform object firhilbf q = firhilbf_create(m,As); // execute transform (decimator) to compute complex signal firhilbf_decim_execute_block(q, x, num_samples, y); // destroy Hilbert transform object firhilbf_destroy(q); printf("firhilb decimated %u real samples to %u complex samples\n", num_samples, 2*num_samples); // // export results to file // FILE*fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"h_len=%u;\n", 4*m+1); fprintf(fid,"num_samples=%u;\n", num_samples); for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "firhilb_example.m" int main() { unsigned int m = 7; // Hilbert filter semi-length float As = 60.0f; // stop-band attenuation [dB] float fc = 0.123456; // signal center frequency unsigned int num_input_samples=128; // number of samples // derived values unsigned int h_len = 4*m+1; // filter length unsigned int num_total_samples = num_input_samples + h_len; // create Hilbert transform object firhilbf qi = firhilbf_create(m,As); // interpolator firhilbf qd = firhilbf_create(m,As); // decimator firhilbf_print(qi); // data arrays float complex x[ num_total_samples]; // complex input float y[2*num_total_samples]; // real output float complex z[ num_total_samples]; // complex output // initialize input array unsigned int i; for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "firhilb_interp_example.m" int main() { unsigned int m=5; // Hilbert filter semi-length float As=60.0f; // stop-band attenuation [dB] float fc=0.37f; // signal center frequency unsigned int num_samples=128; // number of samples // data arrays float complex x[num_samples]; // complex input float y[2*num_samples]; // real output // initialize input array unsigned int i; for (i=0; i #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "firinterp_crcf_example.m" // print usage/help message void usage() { printf("firinterp_crcf_example:\n"); printf(" u/h : print usage/help\n"); printf(" k : samples/symbol (interp factor), k > 1, default: 4\n"); printf(" m : filter delay (symbols), m > 0, default: 3\n"); printf(" s : filter stop-band attenuation [dB], default: 60\n"); printf(" n : number of data symbols, default: 16\n"); } int main(int argc, char*argv[]) { // options unsigned int k=4; // samples/symbol unsigned int m=3; // filter delay float As = 60.0f; // filter stop-band attenuation unsigned int num_data_symbols=16; // number of data symbols int dopt; while ((dopt = getopt(argc,argv,"uhk:m:s:n:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 's': As = atof(optarg); break; case 'n': num_data_symbols = atoi(optarg); break; default: exit(1); } } // validate options if (k < 2) { fprintf(stderr,"error: %s, interp factor must be greater than 1\n", argv[0]); exit(1); } else if (m < 1) { fprintf(stderr,"error: %s, filter delay must be greater than 0\n", argv[0]); exit(1); } else if (num_data_symbols < 1) { fprintf(stderr,"error: %s, must have at least one data symbol\n", argv[0]); usage(); return 1; } // derived values unsigned int num_symbols = num_data_symbols + 2*m; // compensate for filter delay unsigned int num_samples = k*num_symbols; // create interpolator from prototype firinterp_crcf q = firinterp_crcf_create_kaiser(k,m,As); // generate input signal and interpolate float complex x[num_symbols]; // input symbols float complex y[num_samples]; // output samples unsigned int i; for (i=0; i= k*m) && ((i%k)==0)) printf(" **\n"); else printf("\n"); } // // export output file // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"k = %u;\n", k); fprintf(fid,"m = %u;\n", m); fprintf(fid,"num_symbols = %u;\n", num_symbols); fprintf(fid,"num_samples = k*num_symbols;\n"); fprintf(fid,"x = zeros(1,num_symbols);\n"); fprintf(fid,"y = zeros(1,num_samples);\n"); for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "firpfbch2_crcf_example.m" // print usage/help message void usage() { printf("%s [options]\n", __FILE__); printf(" h : print help\n"); printf(" M : number of channels, default: 6\n"); printf(" m : prototype filter semi-length, default: 4\n"); printf(" s : prototype filter stop-band attenuation, default: 80\n"); printf(" n : number of 'symbols' to analyze, default: 20\n"); } int main(int argc, char*argv[]) { // options unsigned int num_channels=6; // number of channels unsigned int m = 4; // filter semi-length (symbols) unsigned int num_symbols=20; // number of symbols float As = 80.0f; // filter stop-band attenuation int dopt; while ((dopt = getopt(argc,argv,"hM:m:s:n:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'M': num_channels = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 's': As = atof(optarg); break; case 'n': num_symbols = atof(optarg); break; default: exit(1); } } unsigned int i; // validate input if (num_channels < 2 || num_channels % 2) { fprintf(stderr,"error: %s, number of channels must be greater than 2 and even\n", argv[0]); exit(1); } else if (m == 0) { fprintf(stderr,"error: %s, filter semi-length must be greater than zero\n", argv[0]); exit(1); } else if (num_symbols == 0) { fprintf(stderr,"error: %s, number of symbols must be greater than zero", argv[0]); exit(1); } // derived values unsigned int num_samples = num_channels * num_symbols; // allocate arrays float complex x[num_samples]; float complex y[num_samples]; // generate input signal for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "firpfbch_crcf_analysis_example.m" int main() { // options unsigned int num_channels = 8; // number of channels unsigned int m = 4; // filter delay float As = 60; // stop-band attenuation unsigned int num_frames = 25; // number of frames // unsigned int i; unsigned int k; // derived values unsigned int num_samples = num_frames * num_channels; // data arrays float complex x[num_samples]; // time-domain input [size: num_samples x 1 ] float complex y[num_samples]; // channelized output [size: num_channels x num_frames] // initialize input with zeros for (i=0; i #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "firpfbch_crcf_example.m" int main() { // options unsigned int num_channels=4; // number of channels unsigned int p=3; // filter length (symbols) unsigned int num_symbols=6; // number of symbols // derived values unsigned int num_samples = num_channels * num_symbols; unsigned int i; unsigned int j; // generate synthesis filter // NOTE : these coefficients can be random; the purpose of this // exercise is to demonstrate mathematical equivalence unsigned int h_len = p*num_channels; float h[h_len]; for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "firpfbch_crcf_synthesis_example.m" int main() { // options unsigned int num_channels = 16; // number of channels unsigned int m = 5; // filter delay float As = 60; // stop-band attenuation unsigned int num_frames = 25; // number of frames // unsigned int i; unsigned int k; // derived values unsigned int num_samples = num_frames * num_channels; // data arrays float complex x[num_channels][num_frames]; // channelized input float complex y[num_samples]; // time-domain output [size: num_samples x 1] // create narrow-band pulse unsigned int pulse_len = 17; // pulse length [samples] float bw = 0.30f; // pulse width (bandwidth) float pulse[pulse_len]; // buffer liquid_firdes_kaiser(pulse_len, bw, 50.0f, 0.0f, pulse); // generate input signal(s) int enabled[num_channels]; // signal enabled? for (i=0; i #include #include #include #include #include #include #include "liquid.h" void usage() { printf("flexframesync_example [options]\n"); printf(" u/h : print usage\n"); printf(" s : signal-to-noise ratio [dB], default: 20\n"); printf(" F : carrier frequency offset, default: 0.01\n"); printf(" n : payload length [bytes], default: 480\n"); printf(" m : modulation scheme (qpsk default)\n"); liquid_print_modulation_schemes(); printf(" v : data integrity check: crc32 default\n"); liquid_print_crc_schemes(); printf(" c : coding scheme (inner): h74 default\n"); printf(" k : coding scheme (outer): none default\n"); liquid_print_fec_schemes(); printf(" d : enable debugging\n"); } // flexframesync callback function static int callback(unsigned char * _header, int _header_valid, unsigned char * _payload, unsigned int _payload_len, int _payload_valid, framesyncstats_s _stats, void * _userdata); int main(int argc, char *argv[]) { //srand( time(NULL) ); // options modulation_scheme ms = LIQUID_MODEM_QPSK; // mod. scheme crc_scheme check = LIQUID_CRC_32; // data validity check fec_scheme fec0 = LIQUID_FEC_NONE; // fec (inner) fec_scheme fec1 = LIQUID_FEC_NONE; // fec (outer) unsigned int payload_len = 480; // payload length int debug_enabled = 0; // enable debugging? float noise_floor = -60.0f; // noise floor float SNRdB = 20.0f; // signal-to-noise ratio float dphi = 0.01f; // carrier frequency offset // get options int dopt; while((dopt = getopt(argc,argv,"uhs:F:n:m:v:c:k:d")) != EOF){ switch (dopt) { case 'u': case 'h': usage(); return 0; case 's': SNRdB = atof(optarg); break; case 'F': dphi = atof(optarg); break; case 'n': payload_len = atol(optarg); break; case 'm': ms = liquid_getopt_str2mod(optarg); break; case 'v': check = liquid_getopt_str2crc(optarg); break; case 'c': fec0 = liquid_getopt_str2fec(optarg); break; case 'k': fec1 = liquid_getopt_str2fec(optarg); break; case 'd': debug_enabled = 1; break; default: exit(-1); } } // derived values unsigned int i; float nstd = powf(10.0f, noise_floor/20.0f); // noise std. dev. float gamma = powf(10.0f, (SNRdB+noise_floor)/20.0f); // channel gain // create flexframegen object flexframegenprops_s fgprops; flexframegenprops_init_default(&fgprops); fgprops.mod_scheme = ms; fgprops.check = check; fgprops.fec0 = fec0; fgprops.fec1 = fec1; flexframegen fg = flexframegen_create(&fgprops); // create flexframesync object flexframesync fs = flexframesync_create(callback,NULL); if (debug_enabled) flexframesync_debug_enable(fs); // assemble the frame (NULL pointers for default values) flexframegen_assemble(fg, NULL, NULL, payload_len); flexframegen_print(fg); // generate the frame in blocks unsigned int buf_len = 256; float complex x[buf_len]; float complex y[buf_len]; int frame_complete = 0; float phi = 0.0f; while (!frame_complete) { // write samples to buffer frame_complete = flexframegen_write_samples(fg, x, buf_len); // add noise and push through synchronizer for (i=0; i #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "flexframesync_reconfig_example.m" void usage() { printf("flexframesync_example [options]\n"); printf(" u/h : print usage\n"); printf(" s : signal-to-noise ratio [dB], default: 30\n"); printf(" n : number of frames, default: 3\n"); } int main(int argc, char *argv[]) { srand( time(NULL) ); // define parameters float SNRdB = 30.0f; float noise_floor = -30.0f; unsigned int num_frames = 3; // get options int dopt; while((dopt = getopt(argc,argv,"uhvqs:f:m:p:n:")) != EOF){ switch (dopt) { case 'u': case 'h': usage(); return 0; case 's': SNRdB = atof(optarg); break; case 'n': num_frames = atoi(optarg); break; default: exit(1); } } // create flexframegen object flexframegenprops_s fgprops; flexframegenprops_init_default(&fgprops); flexframegen fg = flexframegen_create(NULL); // frame data unsigned char header[14]; unsigned char * payload = NULL; // create flexframesync object with default properties flexframesync fs = flexframesync_create(NULL,NULL); // channel float nstd = powf(10.0f, noise_floor/20.0f); // noise std. dev. float gamma = powf(10.0f, (SNRdB+noise_floor)/20.0f); // channel gain unsigned int i; // initialize header, payload for (i=0; i<14; i++) header[i] = i; // frame buffers, properties unsigned int buf_len = 256; float complex buf[buf_len]; unsigned int j; for (j=0; j #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "framesync64_example.m" void usage() { printf("framesync64_example [options]\n"); printf(" h : print usage\n"); printf(" d : enable debugging\n"); printf(" S : signal-to-noise ratio [dB], default: 20\n"); printf(" F : carrier frequency offset, default: 0\n"); printf(" P : carrier phase offset, default: 0\n"); printf(" T : fractional sample timing offset, default: 0.01\n"); } // static callback function static int callback(unsigned char * _header, int _header_valid, unsigned char * _payload, unsigned int _payload_len, int _payload_valid, framesyncstats_s _stats, void * _userdata); // global arrays unsigned char header[8]; unsigned char payload[64]; int main(int argc, char*argv[]) { srand( time(NULL) ); // options float SNRdB = 20.0f; // signal-to-noise ratio float noise_floor = -40.0f; // noise floor float dphi = 0.01f; // carrier frequency offset float theta = 0.0f; // carrier phase offset float dt = -0.2f; // fractional sample timing offset int debug_enabled = 0; // get options int dopt; while((dopt = getopt(argc,argv,"hdS:F:P:T:")) != EOF){ switch (dopt) { case 'h': usage(); return 0; case 'd': debug_enabled = 1; break; case 'S': SNRdB = atof(optarg); break; case 'F': dphi = atof(optarg); break; case 'P': theta = atof(optarg); break; case 'T': dt = atof(optarg); break; default: exit(-1); } } // derived values unsigned int frame_len = LIQUID_FRAME64_LEN; // fixed frame length unsigned int num_samples = frame_len + 200; // total number of samples float nstd = powf(10.0f, noise_floor/20.0f); // noise std. dev. float gamma = powf(10.0f, (SNRdB+noise_floor)/20.0f); // channel gain // create frame generator framegen64 fg = framegen64_create(); framegen64_print(fg); // create frame synchronizer using default properties framesync64 fs = framesync64_create(callback,NULL); framesync64_print(fs); if (debug_enabled) framesync64_debug_enable(fs); // data payload unsigned int i; // initialize header and payload data for (i=0; i<8; i++) header[i] = i; for (i=0; i<64; i++) payload[i] = rand() & 0xff; // allocate memory for the frame samples float complex frame[frame_len]; // generated frame float complex y[num_samples]; // received sequence // generate the frame framegen64_execute(fg, header, payload, frame); // fractional sample timing offset unsigned int d = 11; // fractional sample filter delay firfilt_crcf finterp = firfilt_crcf_create_kaiser(2*d+1, 0.45f, 40.0f, -dt); for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "freqmodem_example.m" // print usage/help message void usage() { printf("freqmodem_example [options]\n"); printf(" h : print usage\n"); printf(" n : number of samples, default: 1024\n"); printf(" S : SNR [dB], default: 30\n"); printf(" k : FM modulation factor, default: 0.1\n"); } int main(int argc, char*argv[]) { // options float kf = 0.1f; // modulation factor unsigned int num_samples = 1024; // number of samples float SNRdB = 30.0f; // signal-to-noise ratio [dB] int dopt; while ((dopt = getopt(argc,argv,"hn:S:k:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': num_samples = atoi(optarg); break; case 'S': SNRdB = atof(optarg); break; case 'k': kf = atof(optarg); break; default: exit(1); } } // create mod/demod objects freqmod mod = freqmod_create(kf); // modulator freqdem dem = freqdem_create(kf); // demodulator freqmod_print(mod); unsigned int i; float m[num_samples]; // message signal float complex r[num_samples]; // received signal (complex baseband) float y[num_samples]; // demodulator output // generate message signal (sum of sines) for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "fskmodem_example.m" // print usage/help message void usage() { printf("fskmodem_example -- frequency-shift keying example\n"); printf("options:\n"); printf(" h : print help\n"); printf(" m : bits/symbol, default: 1\n"); printf(" k : samples/symbol, default: 2*2^m\n"); printf(" b : signal bandwidth default: 0.2\n"); printf(" n : number of data symbols, default: 80\n"); printf(" s : SNR [dB], default: 40\n"); } int main(int argc, char*argv[]) { // options unsigned int m = 3; // number of bits/symbol unsigned int k = 0; // filter samples/symbol unsigned int num_symbols = 8000; // number of data symbols float SNRdB = 40.0f; // signal-to-noise ratio [dB] float bandwidth = 0.20; // frequency spacing unsigned int nfft = 1200; // FFT size for compute spectrum int dopt; while ((dopt = getopt(argc,argv,"hm:k:b:n:s:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'm': m = atoi(optarg); break; case 'k': k = atoi(optarg); break; case 'b': bandwidth = atof(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; default: exit(1); } } unsigned int i; unsigned int j; // derived values if (k == 0) k = 2 << m; // set samples per symbol if not otherwise specified unsigned int M = 1 << m; float nstd = powf(10.0f, -SNRdB/20.0f); // validate input if (k < M) { fprintf(stderr,"errors: %s, samples/symbol must be at least modulation size (M=%u)\n", __FILE__,M); exit(1); } else if (k > 2048) { fprintf(stderr,"errors: %s, samples/symbol exceeds maximum (2048)\n", __FILE__); exit(1); } else if (M > 1024) { fprintf(stderr,"errors: %s, modulation size (M=%u) exceeds maximum (1024)\n", __FILE__, M); exit(1); } else if (bandwidth <= 0.0f || bandwidth >= 0.5f) { fprintf(stderr,"errors: %s, bandwidht must be in (0,0.5)\n", __FILE__); exit(1); } // create modulator/demodulator pair fskmod mod = fskmod_create(m,k,bandwidth); fskdem dem = fskdem_create(m,k,bandwidth); fskdem_print(dem); // float complex buf_tx[k]; // transmit buffer float complex buf_rx[k]; // transmit buffer // spectral periodogram spgramcf periodogram = spgramcf_create_default(nfft); // modulate, demodulate, count errors unsigned int num_symbol_errors = 0; for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "gasearch_example.m" // utility callback function float utility_callback(void * _userdata, chromosome _c); // peak callback function; value nearest {0.5, 0.5, 0.5, ...} float peak_callback(void * _userdata, chromosome _c); // rosenbrock callback function float rosenbrock_callback(void * _userdata, chromosome _c); int main() { unsigned int num_parameters = 8; // dimensionality of search (minimum 1) unsigned int bits_per_parameter = 16; // parameter resolution unsigned int num_iterations = 1000; // number of iterations to run unsigned int population_size = 20; // GA population size float mutation_rate = 0.10f; // GA mutation rate unsigned int i; float optimum_utility; // open output file FILE*fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); // create prototype chromosome chromosome prototype = chromosome_create_basic(num_parameters, bits_per_parameter); // create gasearch object gasearch ga = gasearch_create_advanced( //&utility_callback, //&rosenbrock_callback, &peak_callback, NULL, prototype, LIQUID_OPTIM_MAXIMIZE, population_size, mutation_rate); gasearch_print(ga); // execute search //optimum_utility = gasearch_run(ga, num_iterations, -1e-6f); // execute search one iteration at a time fprintf(fid,"u = zeros(1,%u);\n", num_iterations); for (i=0; i #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "gasearch_knapsack_example.m" // print usage/help message void usage() { printf("Usage: gasearch_knapsack_example [options]\n"); printf(" u/h : print usage\n"); printf(" n : number of items available, default: 1000\n"); printf(" i : number of iterations (generations) to run, default: 2000\n"); printf(" c : knapsack capacity (maximum weight), default: 20\n"); printf(" p : ga population size, default: 100\n"); printf(" m : ga mutation rate, default: 0.4\n"); } // knapsack object structure definition struct knapsack_s { unsigned int num_items; // total number of items available float * weight; // weight of each item float * value; // value of each item float capacity; // maximum weight allowable }; // print knapsack object // _bag : knapsack object pointer // _c : test chromosome void knapsack_print(struct knapsack_s * _bag, chromosome _c); // utility callback function // _userdata : knapsack object pointer // _c : test chromosome float knapsack_utility(void * _userdata, chromosome _c); int main(int argc, char*argv[]) { unsigned int num_items = 1000; // number of items available unsigned int num_iterations = 2000; // number of iterations to run float capacity = 20.0f; // total capacity of the knapsack unsigned int population_size = 100; // number of chromosomes in the population float mutation_rate = 0.40f; // mutation rate of the GA int dopt; while((dopt = getopt(argc,argv,"uhn:i:c:p:m:")) != EOF){ switch (dopt) { case 'h': case 'u': usage(); return 0; case 'n': num_items = atoi(optarg); break; case 'i': num_iterations = atoi(optarg); break; case 'c': capacity = atof(optarg); break; case 'p': population_size = atoi(optarg); break; case 'm': mutation_rate = atof(optarg); break; default: exit(1); } } // validate input if (num_items == 0) { fprintf(stderr,"error: %s, knapsack must have at least 1 item\n", argv[0]); exit(1); } else if (capacity <= 0.0f) { fprintf(stderr,"error: %s, knapsack capacity must be greater than zero\n", argv[0]); exit(1); } else if (population_size <= 0) { fprintf(stderr,"error: %s, ga population size must be greater than zero\n", argv[0]); exit(1); } else if (mutation_rate < 0.0f || mutation_rate > 1.0f) { fprintf(stderr,"error: %s, ga mutation rate must be in [0,1]\n", argv[0]); exit(1); } unsigned int i; // create knapsack/items (random weight, value) struct knapsack_s bag; bag.num_items = num_items; bag.capacity = capacity; bag.weight = (float*) malloc( bag.num_items*sizeof(float) ); bag.value = (float*) malloc( bag.num_items*sizeof(float) ); for (i=0; inum_items, _bag->capacity); for (i=0; i<_bag->num_items; i++) { printf(" %3u : %6.4f @ $%6.4f", i, _bag->weight[i], _bag->value[i]); unsigned int n = chromosome_value(_s, i); if (n != 0) printf(" *\n"); else printf("\n"); } } // utility callback function // _userdata : knapsack object pointer // _c : test chromosome float knapsack_utility(void * _userdata, chromosome _c) { struct knapsack_s * _bag = (struct knapsack_s *) _userdata; // chromosome represents number of each item in knapsack float total_value = 0; float total_weight = 0; unsigned int i; for (i=0; i<_bag->num_items; i++) { if ( chromosome_value(_c,i) == 1 ) { // include this item into knapsack total_value += _bag->value[i]; total_weight += _bag->weight[i]; } } // check for invalid solution, returning distance metric if (total_weight > _bag->capacity) return _bag->capacity - total_weight; // return total value of knapsack return total_value; } liquid-dsp-1.3.1/examples/gmskframesync_example.c000066400000000000000000000163651317124540100221460ustar00rootroot00000000000000// // gmskframesync_example.c // // Example demonstrating the GMSK flexible frame synchronizer. // #include #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "gmskframesync_example.m" void usage() { printf("gmskframesync_example [options]\n"); printf(" h : print help\n"); printf(" d : enable internal synchronizer debugging\n"); printf(" n : frame length [bytes], default: 40\n"); printf(" v : data integrity check: crc32 default\n"); liquid_print_crc_schemes(); printf(" c : coding scheme (inner): h74 default\n"); printf(" k : coding scheme (outer): none default\n"); liquid_print_fec_schemes(); printf(" s : signal-to-noise ratio [dB], default: 30\n"); printf(" F : carrier frequency offset, default: 0.05\n"); } struct framedata_s { unsigned char * payload; unsigned int payload_len; }; // callback function int callback(unsigned char * _header, int _header_valid, unsigned char * _payload, unsigned int _payload_len, int _payload_valid, framesyncstats_s _stats, void * _userdata); int main(int argc, char*argv[]) { srand(time(NULL)); unsigned int payload_len = 40; // length of payload (bytes) crc_scheme check = LIQUID_CRC_32; fec_scheme fec0 = LIQUID_FEC_HAMMING128; fec_scheme fec1 = LIQUID_FEC_NONE; float noise_floor = -60.0f; // noise floor float SNRdB = 30.0f; // signal-to-noise ratio [dB] float dphi = 0.05f; // carrier offset int debug_enabled = 0; // debug option // get options int dopt; while((dopt = getopt(argc,argv,"hdn:v:c:k:s:F:")) != EOF){ switch (dopt) { case 'u': case 'h': usage(); return 0; case 'd': debug_enabled = 1; break; case 'n': payload_len = atoi(optarg); break; case 'v': // data integrity check check = liquid_getopt_str2crc(optarg); if (check == LIQUID_CRC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported CRC scheme \"%s\"\n\n",optarg); exit(1); } break; case 'c': // inner FEC scheme fec0 = liquid_getopt_str2fec(optarg); if (fec0 == LIQUID_FEC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported inner FEC scheme \"%s\"\n\n",optarg); exit(1); } break; case 'k': // outer FEC scheme fec1 = liquid_getopt_str2fec(optarg); if (fec1 == LIQUID_FEC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported outer FEC scheme \"%s\"\n\n",optarg); exit(1); } break; case 's': SNRdB = atof(optarg); break; case 'F': dphi = atof(optarg); break; default: exit(1); } } unsigned int i; // fixed values unsigned int k = 2; // derived values float nstd = powf(10.0f, noise_floor/20.0f); float gamma = powf(10.0f, (SNRdB + noise_floor)/20.0f); // allocate memory for payload and initialize unsigned char header[8]; unsigned char payload[payload_len]; for (i=0; i<8; i++) header[i] = i; for (i=0; ipayload, _payload, _payload_len); printf(" bit errors : %-4u / %-4u\n", bit_errors, 8*_payload_len); return 0; } liquid-dsp-1.3.1/examples/gmskmodem_example.c000066400000000000000000000111711317124540100212460ustar00rootroot00000000000000// // gmskmodem_example.c // #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "gmskmodem_example.m" // print usage/help message void usage() { printf("gmskmodem_example -- Gaussian minimum-shift keying modem example\n"); printf("options (default values in <>):\n"); printf(" u/h : print usage/help\n"); printf(" k : samples/symbol, default: 4\n"); printf(" m : filter delay [symbols], default: 3\n"); printf(" n : number of data symbols, default: 200\n"); printf(" b : bandwidth-time product, 0 <= b <= 1, default: 0.3\n"); printf(" s : SNR [dB], default: 30\n"); } int main(int argc, char*argv[]) { // options unsigned int k=4; // filter samples/symbol unsigned int m=3; // filter delay (symbols) float BT=0.3f; // bandwidth-time product unsigned int num_data_symbols=200; // number of data symbols float SNRdB = 30.0f; // signal-to-noise ratio [dB] float phi = 0.0f; // carrier phase offset float dphi = 0.0f; // carrier frequency offset int dopt; while ((dopt = getopt(argc,argv,"uhk:m:n:b:s:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'n': num_data_symbols = atoi(optarg); break; case 'b': BT = atof(optarg); break; case 's': SNRdB = atof(optarg); break; default: exit(1); } } // validate input if (BT <= 0.0f || BT >= 1.0f) { fprintf(stderr,"error: %s, bandwidth-time product must be in (0,1)\n", argv[0]); exit(1); } // derived values unsigned int num_symbols = num_data_symbols + 2*m; unsigned int num_samples = k*num_symbols; float nstd = powf(10.0f,-SNRdB/20.0f); // noise standard deviation // create modulator gmskmod mod = gmskmod_create(k, m, BT); gmskmod_print(mod); // create demodulator gmskdem demod = gmskdem_create(k, m, BT); gmskdem_set_eq_bw(demod, 0.01f); gmskdem_print(demod); unsigned int i; unsigned int s[num_symbols]; float complex x[num_samples]; float complex y[num_samples]; unsigned int sym_out[num_symbols]; // generate random data sequence for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "gradsearch_datafit_example.m" // gradient search data set struct gsdataset { float * x; float * y; unsigned int n; }; // gradient search curve-fit error float gserror(void * _dataset, float * _v, unsigned int _n); // parameterized function float gsfunc(float _x, float * _v) { float c0 = _v[0]; float c1 = _v[1]; float c2 = _v[2]; return c0 + sincf(c1*(_x-c2)); } int main() { // options unsigned int num_samples = 400; // number of samples float sig = 0.1f; // noise variance unsigned int num_iterations = 1000; // number of iterations to run float v[3] = {1, 1, 1}; unsigned int i; // range float xmin = 0.0f; float xmax = 6.0f; float dx = (xmax - xmin) / (num_samples-1); // generate data set float x[num_samples]; float y[num_samples]; for (i=0; in; i++) { // compute function estimate float y_hat = gsfunc(p->x[i], _v); // compute error float e = p->y[i] - y_hat; // accumulate RMS error rmse += e*e; } // normalize error and return rmse = sqrtf(rmse / (float)(p->n)); return rmse; } liquid-dsp-1.3.1/examples/gradsearch_example.c000066400000000000000000000064141317124540100213720ustar00rootroot00000000000000// // gradsearch_example.c // #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "gradsearch_example.m" // print usage/help message void usage() { printf("%s [options]\n", __FILE__); printf(" h : print help\n"); printf(" n : number of parameters, default: 6\n"); printf(" t : number of iterations, default: 2000\n"); printf(" u : utility function: {rosenbrock, invgauss, multimodal, spiral}\n"); } int main(int argc, char*argv[]) { unsigned int num_parameters = 6; // dimensionality of search (minimum 2) unsigned int num_iterations = 2000; // number of iterations to run utility_function func = liquid_rosenbrock; int dopt; while ((dopt = getopt(argc,argv,"hn:t:u:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': num_parameters = atoi(optarg); break; case 't': num_iterations = atoi(optarg); break; case 'u': if (strcmp(optarg,"rosenbrock")==0) func = liquid_rosenbrock; else if (strcmp(optarg,"invgauss")==0) func = liquid_invgauss; else if (strcmp(optarg,"multimodal")==0) func = liquid_multimodal; else if (strcmp(optarg,"spiral")==0) func = liquid_spiral; else { fprintf(stderr,"error: %s, unknown/unsupported utility '%s'\n", argv[0], optarg); exit(1); } break; default: exit(1); } } float optimum_vect[num_parameters]; unsigned int i; for (i=0; i #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "iirdecim_crcf_example.m" // print usage/help message void usage() { printf("iirdecim_crcf_example:\n"); printf(" u/h : print usage/help\n"); printf(" M : decimation factor, M > 1, default: 4\n"); printf(" n : number of input samples, default: 400\n"); } int main(int argc, char*argv[]) { // options unsigned int M=4; // decimation rate unsigned int num_samples=400; // number of input samples int dopt; while ((dopt = getopt(argc,argv,"uhM:n:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'M': M = atoi(optarg); break; case 'n': num_samples = atoi(optarg); break; default: exit(1); } } // validate options if (M < 2) { fprintf(stderr,"error: %s, decim factor must be greater than 1\n", argv[0]); exit(1); } else if (num_samples < 1) { fprintf(stderr,"error: %s, must have at least one sample\n", argv[0]); usage(); return 1; } // ensure number of samples is divisible by M num_samples += (num_samples % M); // create decimator from prototype unsigned int order = 8; iirdecim_crcf q = iirdecim_crcf_create_default(M,order); // compute group delay float delay = iirdecim_crcf_groupdelay(q,0.0f); // generate input signal and decimate float complex x[num_samples]; // input samples float complex y[num_samples/M]; // output samples unsigned int i; unsigned int w_len = num_samples > 4*delay ? num_samples - 4*delay : num_samples; for (i=0; i= M*m) && ((i%M)==0)) printf(" **\n"); else printf("\n"); } #endif // // export output file // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"M = %u;\n", M); fprintf(fid,"delay = %f;\n", delay); fprintf(fid,"num_samples = %u;\n", num_samples); fprintf(fid,"x = zeros(1,num_samples);\n"); fprintf(fid,"y = zeros(1,num_samples/M);\n"); for (i=0; i #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "iirdes_analog_example.m" // print usage/help message void usage() { printf("iirdes_analog_example -- infinite impulse response filter design\n"); printf("options (default values in []):\n"); printf(" u/h : print usage/help\n"); printf(" t : filter type: [butter], cheby1, cheby2, ellip, bessel\n"); // printf(" b : filter transformation: [LP], HP, BP, BS\n"); printf(" n : filter order, n > 0 [5]\n"); printf(" r : passband ripple in dB (cheby1, ellip), r > 0 [3.0]\n"); printf(" s : stopband attenuation in dB (cheby2, ellip), s > 0 [60.0]\n"); printf(" f : angular passband cut-off frequency, f > 0 [1.0]\n"); // printf(" c : center frequency (BP, BS cases), 0 < c < 0.5 [0.25]\n"); // printf(" o : format [sos], tf\n"); // printf(" sos : second-order sections form\n"); // printf(" tf : regular transfer function form (potentially\n"); // printf(" unstable for large orders\n"); } int main(int argc, char*argv[]) { // options unsigned int order=3; // filter order float wc=1.0f; // angular cutoff frequency float Ap=3.0f; // pass-band Ap float As=60.0f; // stop-band attenuation // filter type liquid_iirdes_filtertype ftype = LIQUID_IIRDES_BUTTER; int dopt; while ((dopt = getopt(argc,argv,"uht:n:r:s:f:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 't': if (strcmp(optarg,"butter")==0) { ftype = LIQUID_IIRDES_BUTTER; } else if (strcmp(optarg,"cheby1")==0) { ftype = LIQUID_IIRDES_CHEBY1; } else if (strcmp(optarg,"cheby2")==0) { ftype = LIQUID_IIRDES_CHEBY2; } else if (strcmp(optarg,"ellip")==0) { ftype = LIQUID_IIRDES_ELLIP; } else if (strcmp(optarg,"bessel")==0) { ftype = LIQUID_IIRDES_BESSEL; } else { fprintf(stderr,"error: %s, unknown filter type \"%s\"\n", argv[0], optarg); usage(); exit(1); } break; case 'n': order = atoi(optarg); break; case 'r': Ap = atof(optarg); break; case 's': As = atof(optarg); break; case 'f': wc = atof(optarg); break; default: exit(1); } } // validate input if (wc <= 0) { fprintf(stderr,"error: %s, cutoff frequency out of range\n", argv[0]); usage(); exit(1); } else if (Ap <= 0) { fprintf(stderr,"error: %s, pass-band ripple out of range\n", argv[0]); usage(); exit(1); } else if (As <= 0) { fprintf(stderr,"error: %s, stop-band ripple out of range\n", argv[0]); usage(); exit(1); } // number of analaog poles/zeros unsigned int npa = order; unsigned int nza = 0; // complex analog zeros, poles, gain float complex za[order]; float complex pa[order]; float complex ka; unsigned int i; unsigned int r = order % 2; unsigned int L = (order-r)/2; float Gp, Gs; float ep = sqrtf( powf(10.0f, Ap / 10.0f) - 1.0f ); float es = powf(10.0f, -As / 20.0f); switch (ftype) { case LIQUID_IIRDES_BUTTER: printf("Butterworth filter design:\n"); nza = 0; butter_azpkf(order,za,pa,&ka); break; case LIQUID_IIRDES_CHEBY1: printf("Cheby-I filter design:\n"); nza = 0; cheby1_azpkf(order,ep,za,pa,&ka); break; case LIQUID_IIRDES_CHEBY2: printf("Cheby-II filter design:\n"); nza = 2*L; float epsilon = powf(10.0f, -As/20.0f); cheby2_azpkf(order,epsilon,za,pa,&ka); break; case LIQUID_IIRDES_ELLIP: printf("elliptic filter design:\n"); nza = 2*L; Gp = powf(10.0f, -Ap / 20.0f); Gs = powf(10.0f, -As / 20.0f); printf(" Gp = %12.8f\n", Gp); printf(" Gs = %12.8f\n", Gs); // epsilon values ep = sqrtf(1.0f/(Gp*Gp) - 1.0f); es = sqrtf(1.0f/(Gs*Gs) - 1.0f); ellip_azpkf(order,ep,es,za,pa,&ka); break; case LIQUID_IIRDES_BESSEL: printf("Bessel filter design:\n"); bessel_azpkf(order,za,pa,&ka); nza = 0; break; default: fprintf(stderr,"error: %s: unknown filter type\n", argv[0]); exit(1); } // transform zeros, poles, gain for (i=0; i 0,\n"); fprintf(fid," hold on; plot(real(za),imag(za),'ob'); hold off;\n"); fprintf(fid," legend('(\\omega_c)','poles','zeros',0);\n"); fprintf(fid,"else,\n"); fprintf(fid," legend('(\\omega_c)','poles',0);\n"); fprintf(fid,"end;\n"); fprintf(fid," axis([-1 1 -1 1]*1.2*max([wc abs(pa) abs(za)]));\n"); //fprintf(fid," real(za),imag(za),'x');\n"); fprintf(fid,"axis square;\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"xlabel('real');\n"); fprintf(fid,"ylabel('imag');\n"); fprintf(fid,"\n"); // plot group delay fprintf(fid,"figure;\n"); fprintf(fid,"gd = gradient(unwrap(arg(h)))./gradient(w);\n"); fprintf(fid,"semilogx(w,gd);\n"); fprintf(fid,"xlabel('Angular frequency, \\omega [rad/s]');\n"); fprintf(fid,"ylabel('group delay [s]');\n"); fprintf(fid,"gd_min = min(gd); if gd_min < 0, gd_min=0; end;\n"); fprintf(fid,"axis([wc/100 wc*100 gd_min 1.1*max(gd)]);\n"); fprintf(fid,"grid on;\n"); // plot magnitude response fprintf(fid,"figure;\n"); fprintf(fid,"subplot(2,1,1);\n"); fprintf(fid," semilogx(w,H,'-'); grid on;\n"); fprintf(fid," axis([wc/100 wc*100 -5 1]);\n"); fprintf(fid," xlabel('Angular frequency, \\omega [rad/s]');\n"); fprintf(fid," ylabel('PSD [dB]');\n"); fprintf(fid,"subplot(2,1,2);\n"); fprintf(fid," semilogx(w,H,'-'); grid on;\n"); fprintf(fid," axis([wc/100 wc*100 -100 10]);\n"); fprintf(fid," xlabel('Angular frequency, \\omega [rad/s]');\n"); fprintf(fid," ylabel('PSD [dB]');\n"); fclose(fid); printf("results written to %s.\n", OUTPUT_FILENAME); printf("done.\n"); return 0; } liquid-dsp-1.3.1/examples/iirdes_example.c000066400000000000000000000225761317124540100205550ustar00rootroot00000000000000// // iirdes_example.c // // Tests infinite impulse reponse (IIR) digital filter design. // SEE ALSO: iirdes_analog_example.c // iir_filter_crcf_example.c // #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "iirdes_example.m" // print usage/help message void usage() { printf("iirdes_example -- infinite impulse response filter design\n"); printf("options (default values in []):\n"); printf(" u/h : print usage/help\n"); printf(" t : filter type: [butter], cheby1, cheby2, ellip, bessel\n"); printf(" b : filter transformation: [LP], HP, BP, BS\n"); printf(" n : filter order, n > 0 [5]\n"); printf(" r : passband ripple in dB (cheby1, ellip), r > 0 [1.0]\n"); printf(" s : stopband attenuation in dB (cheby2, ellip), s > 0 [60.0]\n"); printf(" f : passband cut-off, 0 < f < 0.5 [0.2]\n"); printf(" c : center frequency (BP, BS cases), 0 < c < 0.5 [0.25]\n"); printf(" o : format [sos], tf\n"); printf(" sos : second-order sections form\n"); printf(" tf : regular transfer function form (potentially\n"); printf(" unstable for large orders\n"); } int main(int argc, char*argv[]) { // options unsigned int order=5; // filter order float fc = 0.20f; // cutoff frequency (low-pass prototype) float f0 = 0.25f; // center frequency (band-pass, band-stop) float As = 60.0f; // stopband attenuation [dB] float Ap = 1.0f; // passband ripple [dB] // filter type liquid_iirdes_filtertype ftype = LIQUID_IIRDES_BUTTER; // band type liquid_iirdes_bandtype btype = LIQUID_IIRDES_LOWPASS; // output format: second-order sections or transfer function liquid_iirdes_format format = LIQUID_IIRDES_SOS; int dopt; while ((dopt = getopt(argc,argv,"uht:b:n:r:s:f:c:o:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 't': if (strcmp(optarg,"butter")==0) { ftype = LIQUID_IIRDES_BUTTER; } else if (strcmp(optarg,"cheby1")==0) { ftype = LIQUID_IIRDES_CHEBY1; } else if (strcmp(optarg,"cheby2")==0) { ftype = LIQUID_IIRDES_CHEBY2; } else if (strcmp(optarg,"ellip")==0) { ftype = LIQUID_IIRDES_ELLIP; } else if (strcmp(optarg,"bessel")==0) { ftype = LIQUID_IIRDES_BESSEL; } else { fprintf(stderr,"error: iirdes_example, unknown filter type \"%s\"\n", optarg); usage(); exit(1); } break; case 'b': if (strcmp(optarg,"LP")==0) { btype = LIQUID_IIRDES_LOWPASS; } else if (strcmp(optarg,"HP")==0) { btype = LIQUID_IIRDES_HIGHPASS; } else if (strcmp(optarg,"BP")==0) { btype = LIQUID_IIRDES_BANDPASS; } else if (strcmp(optarg,"BS")==0) { btype = LIQUID_IIRDES_BANDSTOP; } else { fprintf(stderr,"error: iirdes_example, unknown band type \"%s\"\n", optarg); usage(); exit(1); } break; case 'n': order = atoi(optarg); break; case 'r': Ap = atof(optarg); break; case 's': As = atof(optarg); break; case 'f': fc = atof(optarg); break; case 'c': f0 = atof(optarg); break; case 'o': if (strcmp(optarg,"sos")==0) { format = LIQUID_IIRDES_SOS; } else if (strcmp(optarg,"tf")==0) { format = LIQUID_IIRDES_TF; } else { fprintf(stderr,"error: iirdes_example, unknown output format \"%s\"\n", optarg); usage(); exit(1); } break; default: exit(1); } } // validate input if (fc <= 0 || fc >= 0.5) { fprintf(stderr,"error: %s, cutoff frequency out of range\n", argv[0]); usage(); exit(1); } else if (f0 < 0 || f0 > 0.5) { fprintf(stderr,"error: %s, center frequency out of range\n", argv[0]); usage(); exit(1); } else if (Ap <= 0) { fprintf(stderr,"error: %s, pass-band ripple out of range\n", argv[0]); usage(); exit(1); } else if (As <= 0) { fprintf(stderr,"error: %s, stop-band ripple out of range\n", argv[0]); usage(); exit(1); } // derived values : compute filter length unsigned int N = order; // effective order // filter order effectively doubles for band-pass, band-stop // filters due to doubling the number of poles and zeros as // a result of filter transformation if (btype == LIQUID_IIRDES_BANDPASS || btype == LIQUID_IIRDES_BANDSTOP) { N *= 2; } unsigned int r = N % 2; // odd/even order unsigned int L = (N-r)/2; // filter semi-length // allocate memory for filter coefficients unsigned int h_len = (format == LIQUID_IIRDES_SOS) ? 3*(L+r) : N+1; float b[h_len]; float a[h_len]; // design filter liquid_iirdes(ftype, btype, format, order, fc, f0, Ap, As, b, a); // open output file FILE*fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"n=%u;\n", order); fprintf(fid,"r=%u;\n", r); fprintf(fid,"L=%u;\n", L); fprintf(fid,"nfft=1024;\n"); unsigned int i; if (format == LIQUID_IIRDES_TF) { // print coefficients for (i=0; i<=N; i++) printf("a[%3u] = %12.8f;\n", i, a[i]); for (i=0; i<=N; i++) printf("b[%3u] = %12.8f;\n", i, b[i]); fprintf(fid,"a = zeros(1,n+1);\n"); fprintf(fid,"b = zeros(1,n+1);\n"); for (i=0; i<=N; i++) { fprintf(fid,"a(%3u) = %12.4e;\n", i+1, a[i]); fprintf(fid,"b(%3u) = %12.4e;\n", i+1, b[i]); } fprintf(fid,"\n"); fprintf(fid,"H = fft(b,nfft)./fft(a,nfft);\n"); fprintf(fid,"H = fftshift(H);\n"); fprintf(fid,"%% group delay\n"); fprintf(fid,"c = conv(b,fliplr(conj(a)));\n"); fprintf(fid,"cr = c.*[0:(length(c)-1)];\n"); fprintf(fid,"t0 = fftshift(fft(cr,nfft));\n"); fprintf(fid,"t1 = fftshift(fft(c, nfft));\n"); fprintf(fid,"polebins = find(abs(t1)<1e-6);\n"); fprintf(fid,"t0(polebins)=0;\n"); fprintf(fid,"t1(polebins)=1;\n"); fprintf(fid,"gd = real(t0./t1) - length(a) + 1;\n"); } else { float * B = b; float * A = a; // print coefficients printf("B [%u x 3] :\n", L+r); for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "iirdes_pll_example.m" // print usage/help message void usage() { printf("iirdes_pll_example [options]\n"); printf(" u/h : print usage\n"); printf(" b : pll bandwidth, default: 0.01\n"); printf(" z : zeta (damping factor), default 0.70711\n"); printf(" K : loop filter gain, default: 1000\n"); printf(" n : number of samples, default: 512\n"); printf(" p : phase offset (radians), default: pi/4\n"); printf(" f : frequency offset (radians), default: 0.3\n"); } int main(int argc, char*argv[]) { srand( time(NULL) ); // options float phase_offset = M_PI / 4.0f; // phase offset float frequency_offset = 0.3f; // frequency offset float pll_bandwidth = 0.01f; // PLL bandwidth float zeta = 1/sqrtf(2.0f); // PLL damping factor float K = 1000.0f; // PLL loop gain unsigned int n=512; // number of iterations int dopt; while ((dopt = getopt(argc,argv,"uhb:z:K:n:p:f:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'b': pll_bandwidth = atof(optarg); break; case 'z': zeta = atof(optarg); break; case 'K': K = atof(optarg); break; case 'n': n = atoi(optarg); break; case 'p': phase_offset = atof(optarg); break; case 'f': frequency_offset= atof(optarg); break; default: exit(1); } } unsigned int d=n/32; // print every "d" lines // validate input if (pll_bandwidth <= 0.0f) { fprintf(stderr,"error: bandwidth must be greater than 0\n"); exit(1); } else if (zeta <= 0.0f) { fprintf(stderr,"error: damping factor must be greater than 0\n"); exit(1); } else if (K <= 0.0f) { fprintf(stderr,"error: loop gain must be greater than 0\n"); exit(1); } // data arrays float complex x[n]; // input complex sinusoid float complex y[n]; // output complex sinusoid float phase_error[n]; // output phase error // generate PLL filter float b[3]; float a[3]; iirdes_pll_active_lag(pll_bandwidth, zeta, K, b, a); iirfilt_rrrf pll = iirfilt_rrrf_create(b,3,a,3); iirfilt_rrrf_print(pll); unsigned int i; float phi; for (i=0; i #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "iirfilt_cccf_example.m" // print usage/help message void usage() { printf("iirfilt_cccf_example -- infinite impulse response filter example\n"); printf("options (default values in []):\n"); printf(" h : print help\n"); printf(" t : filter type: [butter], cheby1, cheby2, ellip, bessel\n"); printf(" b : filter transformation: [LP], HP, BP, BS\n"); printf(" n : filter order, n > 0 [5]\n"); printf(" r : passband ripple in dB (cheby1, ellip), r > 0 [1.0]\n"); printf(" s : stopband attenuation in dB (cheby2, ellip), s > 0 [40.0]\n"); printf(" f : passband cut-off, 0 < f < 0.5 [0.2]\n"); printf(" c : center frequency (BP, BS cases), 0 < c < 0.5 [0.25]\n"); printf(" o : format [sos], tf\n"); printf(" sos : second-order sections form\n"); printf(" tf : regular transfer function form (potentially\n"); printf(" unstable for large orders\n"); } int main(int argc, char*argv[]) { // options unsigned int order=4; // filter order float fc=0.1f; // cutoff frequency float f0=0.0f; // center frequency float Ap=1.0f; // pass-band ripple float As=40.0f; // stop-band attenuation unsigned int n=128; // number of samples liquid_iirdes_filtertype ftype = LIQUID_IIRDES_ELLIP; liquid_iirdes_bandtype btype = LIQUID_IIRDES_LOWPASS; liquid_iirdes_format format = LIQUID_IIRDES_SOS; int dopt; while ((dopt = getopt(argc,argv,"ht:b:n:r:s:f:c:o:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 't': if (strcmp(optarg,"butter")==0) ftype = LIQUID_IIRDES_BUTTER; else if (strcmp(optarg,"cheby1")==0) ftype = LIQUID_IIRDES_CHEBY1; else if (strcmp(optarg,"cheby2")==0) ftype = LIQUID_IIRDES_CHEBY2; else if (strcmp(optarg,"ellip") ==0) ftype = LIQUID_IIRDES_ELLIP; else if (strcmp(optarg,"bessel")==0) ftype = LIQUID_IIRDES_BESSEL; else { fprintf(stderr,"error: iirdes_example, unknown filter type '%s'\n", optarg); exit(1); } break; case 'b': if (strcmp(optarg,"LP")==0) btype = LIQUID_IIRDES_LOWPASS; else if (strcmp(optarg,"HP")==0) btype = LIQUID_IIRDES_HIGHPASS; else if (strcmp(optarg,"BP")==0) btype = LIQUID_IIRDES_BANDPASS; else if (strcmp(optarg,"BS")==0) btype = LIQUID_IIRDES_BANDSTOP; else { fprintf(stderr,"error: iirdes_example, unknown band type '%s'\n", optarg); exit(1); } break; case 'n': order = atoi(optarg); break; case 'r': Ap = atof(optarg); break; case 's': As = atof(optarg); break; case 'f': fc = atof(optarg); break; case 'c': f0 = atof(optarg); break; case 'o': if (strcmp(optarg,"sos")==0) format = LIQUID_IIRDES_SOS; else if (strcmp(optarg,"tf") ==0) format = LIQUID_IIRDES_TF; else { fprintf(stderr,"error: iirdes_example, unknown output format '%s'\n", optarg); exit(1); } break; default: exit(1); } } // design filter from prototype iirfilt_cccf q = iirfilt_cccf_create_prototype(ftype, btype, format, order, fc, f0, Ap, As); iirfilt_cccf_print(q); unsigned int i; // allocate memory for data arrays float complex x[n]; float complex y[n]; // generate input signal (noisy sine wave with decaying amplitude) unsigned int wlen = (3*n)/4; for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "iirfilt_crcf_dcblocker_example.m" int main() { // options unsigned int num_samples = 1200; // number of samples float alpha = 0.10f; // filter cut-off // design filter from prototype iirfilt_crcf q = iirfilt_crcf_create_dc_blocker(alpha); iirfilt_crcf_print(q); // allocate memory for data arrays float complex x[num_samples]; // original input float complex y[num_samples]; // input with DC offset float complex z[num_samples]; // DC-blocked result // generate signals unsigned int i; for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "iirfilt_crcf_example.m" int main() { // options unsigned int order = 4; // filter order float fc = 0.1f; // cutoff frequency float f0 = 0.0f; // center frequency float Ap = 1.0f; // pass-band ripple float As = 40.0f; // stop-band attenuation unsigned int n = 128; // number of samples liquid_iirdes_filtertype ftype = LIQUID_IIRDES_ELLIP; liquid_iirdes_bandtype btype = LIQUID_IIRDES_LOWPASS; liquid_iirdes_format format = LIQUID_IIRDES_SOS; // design filter from prototype iirfilt_crcf q = iirfilt_crcf_create_prototype( ftype, btype, format, order, fc, f0, Ap, As); iirfilt_crcf_print(q); unsigned int i; // allocate memory for data arrays float complex x[n]; float complex y[n]; // generate input signal (noisy sine wave with decaying amplitude) for (i=0; i #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "iirinterp_crcf_example.m" // print usage/help message void usage() { printf("iirinterp_crcf_example:\n"); printf(" h : print help\n"); printf(" k : samples/symbol (interp factor), k > 1, default: 4\n"); printf(" n : number of input samples, default: 64\n"); } int main(int argc, char*argv[]) { // options unsigned int k = 4; // interpolation factor unsigned int num_samples = 64; // number of input samples int dopt; while ((dopt = getopt(argc,argv,"uhk:n:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'n': num_samples = atoi(optarg); break; default: exit(1); } } // validate options if (k < 2) { fprintf(stderr,"error: %s, interp factor must be greater than 1\n", argv[0]); exit(1); } else if (num_samples < 1) { fprintf(stderr,"error: %s, must have at least one data symbol\n", argv[0]); usage(); return 1; } // create interpolator from prototype unsigned int order = 8; iirinterp_crcf q = iirinterp_crcf_create_default(k,order); // derived values float delay = iirinterp_crcf_groupdelay(q,0.0f); // generate input signal and interpolate float complex x[ num_samples]; // input samples float complex y[k*num_samples]; // output samples unsigned int i; for (i=0; i #include // for rand() #include "liquid.h" int main() { // options unsigned int n=9; // message length // create the interleaver interleaver q = interleaver_create(n); interleaver_set_depth(q, 4); interleaver_print(q); // create arrays unsigned char x[n]; // original message data unsigned char y[n]; // interleaved data unsigned char z[n]; // de-interleaved data // generate random data sequence unsigned int i; for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "interleaver_scatterplot_example.m" // print usage/help message void usage() { printf("interleaver_scatterplot_example [options]\n"); printf(" u/h : print usage\n"); printf(" n : number of bytes, default: 8\n"); printf(" d : interleaver depth, default: 4\n"); } // find most significant bit in array (starting from left) unsigned int interleaver_find_bit(unsigned char * _x, unsigned int _n); int main(int argc, char*argv[]) { // options unsigned int n=8; // message length unsigned int depth = 4; int dopt; while ((dopt = getopt(argc,argv,"uhn:d:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'n': n = atoi(optarg); break; case 'd': depth = atoi(optarg); break; default: exit(1); } } // create the interleaver interleaver q = interleaver_create(n); interleaver_set_depth(q, depth); // create arrays unsigned char x[n]; // original message data unsigned char y[n]; // interleaved data unsigned int index[8*n]; unsigned int i; unsigned int j; unsigned int k=0; // initialize data memset(x, 0, n*sizeof(unsigned char)); for (i=0; i #include // for rand() #include "liquid.h" int main() { // options unsigned int n=9; // message length (bits) // create the interleaver interleaver q = interleaver_create(n); interleaver_print(q); // create arrays unsigned char msg_org[n]; // original message data (bytes) unsigned char msg_int[n]; // interleaved data (bytes) unsigned char msg_rec[8*n]; // interleaved data (soft bits) unsigned char msg_dec[8*n]; // de-interleaved data (soft bits) unsigned char msg_ppp[n]; // de-interleaved data (bytes) // generate random data sequence unsigned int i; for (i=0; i> 7) & 0x01 ) ? 255 : 0; msg_rec[8*i+1] = ( (msg_int[i] >> 6) & 0x01 ) ? 255 : 0; msg_rec[8*i+2] = ( (msg_int[i] >> 5) & 0x01 ) ? 255 : 0; msg_rec[8*i+3] = ( (msg_int[i] >> 4) & 0x01 ) ? 255 : 0; msg_rec[8*i+4] = ( (msg_int[i] >> 3) & 0x01 ) ? 255 : 0; msg_rec[8*i+5] = ( (msg_int[i] >> 2) & 0x01 ) ? 255 : 0; msg_rec[8*i+6] = ( (msg_int[i] >> 1) & 0x01 ) ? 255 : 0; msg_rec[8*i+7] = ( (msg_int[i] >> 0) & 0x01 ) ? 255 : 0; } // de-interleave the soft bits interleaver_decode_soft(q, msg_rec, msg_dec); // pack the bits for (i=0; i 127) ? 0x80 : 0; msg_ppp[i] |= (msg_dec[8*i+1] > 127) ? 0x40 : 0; msg_ppp[i] |= (msg_dec[8*i+2] > 127) ? 0x20 : 0; msg_ppp[i] |= (msg_dec[8*i+3] > 127) ? 0x10 : 0; msg_ppp[i] |= (msg_dec[8*i+4] > 127) ? 0x08 : 0; msg_ppp[i] |= (msg_dec[8*i+5] > 127) ? 0x04 : 0; msg_ppp[i] |= (msg_dec[8*i+6] > 127) ? 0x02 : 0; msg_ppp[i] |= (msg_dec[8*i+7] > 127) ? 0x01 : 0; } // compute errors and print results unsigned int num_errors=0; printf("%6s %6s %6s\n", "org", "int", "dec"); for (i=0; i 127) ? 0x80 : 0; byte_int |= (msg_rec[8*i+1] > 127) ? 0x40 : 0; byte_int |= (msg_rec[8*i+2] > 127) ? 0x20 : 0; byte_int |= (msg_rec[8*i+3] > 127) ? 0x10 : 0; byte_int |= (msg_rec[8*i+4] > 127) ? 0x08 : 0; byte_int |= (msg_rec[8*i+5] > 127) ? 0x04 : 0; byte_int |= (msg_rec[8*i+6] > 127) ? 0x02 : 0; byte_int |= (msg_rec[8*i+7] > 127) ? 0x01 : 0; printf("%6u %6u %6u\n", msg_org[i], byte_int, msg_ppp[i]); //printf("y[%u] = %u\n", i, (unsigned int) (y[i])); //printf("y[%u] = %#0x\n", i, (unsigned int) (y[i])); num_errors += (msg_org[i] == msg_ppp[i]) ? 0 : 1; } printf("errors: %u / %u\n", num_errors, n); // destroy the interleaver object interleaver_destroy(q); printf("done.\n"); return 0; } liquid-dsp-1.3.1/examples/kbd_window_example.c000066400000000000000000000032001317124540100214040ustar00rootroot00000000000000// // kbd_window_example.c // // Kaiser-Bessel derived window example // #include #include "liquid.h" #define OUTPUT_FILENAME "kbd_window_example.m" int main() { // options unsigned int n=64; // window length float beta = 20.0f; // Kaiser beta factor unsigned int i; float w[n]; liquid_kbd_window(n,beta,w); FILE*fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n\n"); fprintf(fid,"n=%u;\n",n); for (i=0; i #include #include "liquid.h" int main() { // LIQUID_VALIDATE_LIBVERSION printf("liquid version : %s\n", liquid_version); printf("liquid libversion : %s\n", liquid_libversion()); printf("liquid libversion number : %d\n", liquid_libversion_number()); return 0; } liquid-dsp-1.3.1/examples/lpc_example.c000066400000000000000000000105111317124540100200360ustar00rootroot00000000000000// // lpc_example.c // // This example demonstrates linear prediction in liquid. An input signal // is generated which exhibits a strong temporal correlation. The linear // predictor generates an approximating all-pole filter which minimizes // the squared error between the prediction and the actual output. // #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "lpc_example.m" int main() { // options unsigned int n = 200; // input sequence length unsigned int p = 4; // prediction filter order // create low-pass filter object iirfilt_rrrf f = iirfilt_rrrf_create_lowpass(2, 0.05f); iirfilt_rrrf_print(f); unsigned int i; // allocate memory for data arrays float y[n]; // input signal (filtered noise) float a_hat[p+1]; // lpc output float g_hat[p+1]; // lpc output // generate input signal (filtered noise) for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "matched_filter_example.m" // print usage/help message void usage() { printf("matched_filter_example options:\n"); printf(" u/h : print usage/help\n"); printf(" t : filter type: [rrcos], rkaiser, arkaiser, hM3, gmsk, fexp, fsech, farcsech\n"); printf(" k : filter samples/symbol, k >= 2, default: 2\n"); printf(" m : filter delay (symbols), m >= 1, default: 3\n"); printf(" b : filter excess bandwidth factor, 0 < b < 1, default: 0.5\n"); printf(" n : number of symbols, default: 16\n"); } int main(int argc, char*argv[]) { // options unsigned int k=2; // samples/symbol unsigned int m=3; // symbol delay float beta=0.7f; // excess bandwidth factor unsigned int num_symbols=16; int ftype_tx = LIQUID_FIRFILT_RRC; int ftype_rx = LIQUID_FIRFILT_RRC; int dopt; while ((dopt = getopt(argc,argv,"uht:k:m:b:n:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 't': if (strcmp(optarg,"gmsk")==0) { ftype_tx = LIQUID_FIRFILT_GMSKTX; ftype_rx = LIQUID_FIRFILT_GMSKRX; } else { ftype_tx = liquid_getopt_str2firfilt(optarg); ftype_rx = liquid_getopt_str2firfilt(optarg); } if (ftype_tx == LIQUID_FIRFILT_UNKNOWN) { fprintf(stderr,"error: %s, unknown filter type '%s'\n", argv[0], optarg); exit(1); } break; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'n': num_symbols = atoi(optarg); break; default: exit(1); } } if (k < 2) { fprintf(stderr,"error: %s, k must be at least 2\n", argv[0]); exit(1); } else if (m < 1) { fprintf(stderr,"error: %s, m must be at least 1\n", argv[0]); exit(1); } else if (beta <= 0.0f || beta >= 1.0f) { fprintf(stderr,"error: %s, beta must be in (0,1)\n", argv[0]); exit(1); } unsigned int i; // derived values unsigned int num_samples = num_symbols*k; unsigned int h_len = 2*k*m+1; // transmit/receive filter length unsigned int hc_len = 4*k*m+1; // composite filter length // arrays float ht[h_len]; // transmit filter float hr[h_len]; // receive filter float hc[hc_len]; // composite filter // design the filter(s) liquid_firdes_prototype(ftype_tx, k, m, beta, 0, ht); liquid_firdes_prototype(ftype_rx, k, m, beta, 0, hr); for (i=0; i=2*m) printf(" *\n"); else printf("\n"); } // clean up objects firinterp_rrrf_destroy(interp); firdecim_rrrf_destroy(decim); // // export results // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"k = %u;\n", k); fprintf(fid,"m = %u;\n", m); fprintf(fid,"beta = %12.8f;\n", beta); fprintf(fid,"num_symbols = %u;\n", num_symbols); fprintf(fid,"num_samples = k*num_symbols;\n"); fprintf(fid,"y = zeros(1,num_samples);\n"); for (i=0; i #include #include #define OUTPUT_FILENAME "math_lngamma_example.m" int main() { unsigned int n = 256; // number of steps float zmin = 1e-3f; // minimum value float zmax = 6.00f; // maximum value unsigned int d = n/32; // print every d values to screen // log scale values float xmin = logf(zmin); float xmax = logf(zmax); float dx = (xmax-xmin)/(n-1); FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); unsigned int i; float z; float g; float x = xmin; // log(z) for (i=0; i #include #include "liquid.h" int main(int argc, char*argv[]) { // maximum number unsigned int n = 140; unsigned int i; printf("primitive roots of prime numbers up to %u:\n", n); for (i=3; i<=n; i++) { if (!liquid_is_prime(i)) continue; unsigned int root = liquid_primitive_root_prime(i); printf(" %4u : %4u\n", i, root); } return 0; } liquid-dsp-1.3.1/examples/modem_arb_example.c000066400000000000000000000070321317124540100212110ustar00rootroot00000000000000// // modem_arb_example.c // // This example demonstrates the functionality of the arbitrary // modem, a digital modulator/demodulator object with signal // constellation points chosen arbitrarily. A simple bit-error // rate simulation is then run to test the performance of the // modem. The results are written to a file. // SEE ALSO: modem_example.c // #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "modem_arb_example.m" // print usage/help message void usage() { printf("modem_arb_example [options]\n"); printf(" u/h : print usage\n"); printf(" p : modulation depth (default 4 bits/symbol)\n"); } int main(int argc, char*argv[]) { // options unsigned int bps=6; // bits per symbol unsigned int n=1024; // number of data points to evaluate int dopt; while ((dopt = getopt(argc,argv,"uhp:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'p': bps = atoi(optarg); break; default: exit(1); } } // validate input if (bps == 0) { fprintf(stderr,"error: %s, bits/symbol must be greater than zero\n", argv[0]); exit(1); } // derived values unsigned int i; unsigned int M = 1< #include #include #include "liquid.h" #define OUTPUT_FILENAME "modem_example.m" // print usage/help message void usage() { printf("modem_example [options]\n"); printf(" h : print help\n"); printf(" v/q : verbose/quiet\n"); printf(" m : modulation scheme (qam16 default)\n"); liquid_print_modulation_schemes(); } int main(int argc, char*argv[]) { // create mod/demod objects modulation_scheme ms = LIQUID_MODEM_QAM16; int verbose = 1; int dopt; while ((dopt = getopt(argc,argv,"hvqm:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'v': verbose = 1; break; case 'q': verbose = 0; break; case 'm': ms = liquid_getopt_str2mod(optarg); if (ms == LIQUID_MODEM_UNKNOWN) { fprintf(stderr,"error: %s, unknown/unsupported modulation scheme '%s'\n", argv[0], optarg); return 1; } break; default: exit(1); } } // create the modem objects modem mod = modem_create(ms); modem demod = modem_create(ms); // ensure bits/symbol matches modem description (only // applicable to certain specific modems) unsigned int bps = modem_get_bps(mod); modem_print(mod); // open output file FILE*fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n\n"); fprintf(fid,"m = %u;\n", bps); fprintf(fid,"M = %u;\n", 1< #include #include #include "liquid.h" #define OUTPUT_FILENAME "modem_soft_example.m" // print usage/help message void usage() { printf("modem_soft_example [options]\n"); printf(" h : print help\n"); printf(" m : modulation scheme (qpsk default)\n"); liquid_print_modulation_schemes(); } // print a string of bits to the standard output // _x : input symbol // _bps : bits/symbol // _n : number of characters to print (zero-padding) void print_bitstring(unsigned int _x, unsigned int _bps, unsigned int _n) { unsigned int i; for (i=0; i<_bps; i++) printf("%1u", (_x >> (_bps-i-1)) & 1); for (i=_bps; i<_n; i++) printf(" "); } int main(int argc, char*argv[]) { // create mod/demod objects modulation_scheme ms = LIQUID_MODEM_QPSK; int dopt; while ((dopt = getopt(argc,argv,"uhm:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'm': ms = liquid_getopt_str2mod(optarg); if (ms == LIQUID_MODEM_UNKNOWN) { fprintf(stderr,"error: %s, unknown/unsupported modulation scheme '%s'\n", argv[0], optarg); return 1; } break; default: exit(1); } } // create the modem objects modem mod = modem_create(ms); modem demod = modem_create(ms); // ensure bits/symbol matches modem description (only // applicable to certain specific modems) unsigned int bps = modem_get_bps(mod); modem_print(mod); unsigned int i; // modulated symbol unsigned int s_hard; // demodulated symbol (hard) unsigned char soft_bits[bps]; unsigned int s_soft; // demodulated symbol (soft, compacted) unsigned int num_symbols = 1< #include "liquid.h" int main() { unsigned int n=280; unsigned int factors[LIQUID_MAX_FACTORS]; unsigned int num_factors=0; // compute factors of n liquid_factor(n,factors,&num_factors); printf("factors of %u:\n", n); unsigned int i; for (i=0; i #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "msequence_example.m" int main(int argc, char*argv[]) { // options unsigned int m=5; // shift register length, n=2^m - 1 // create and initialize m-sequence msequence ms = msequence_create_default(m); msequence_print(ms); unsigned int n = msequence_get_length(ms); signed int rxx[n]; // auto-correlation // create and initialize first binary sequence on m-sequence bsequence bs1 = bsequence_create(n); bsequence_init_msequence(bs1, ms); // create and initialize second binary sequence on same m-sequence bsequence bs2 = bsequence_create(n); bsequence_init_msequence(bs2, ms); // when sequences are aligned, autocorrelation is equal to length rxx[0] = 2*bsequence_correlate(bs1, bs2) - n; // when sequences are misaligned, autocorrelation is equal to -1 unsigned int i; for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "msourcecf_example.m" int main() { // msource parameters int ms = LIQUID_MODEM_QPSK; unsigned int k = 4; unsigned int m = 9; float beta = 0.30f; // spectral periodogram options unsigned int nfft = 2400; // spectral periodogram FFT size unsigned int num_samples = 48000; // number of samples unsigned int i; // create spectral periodogram spgramcf periodogram = spgramcf_create_default(nfft); unsigned int buf_len = 1024; float complex buf[buf_len]; // create stream generator msourcecf gen = msourcecf_create(); int id; // add noise source (wide-band) id = msourcecf_add_noise(gen, 1.00f); msourcecf_set_gain(gen, id, -60.0f); // add noise source (narrow-band) id = msourcecf_add_noise(gen, 0.10f); msourcecf_set_frequency(gen, id, 0.4*2*M_PI); msourcecf_set_gain(gen, id, -20.0f); // add tone id = msourcecf_add_tone(gen); msourcecf_set_frequency(gen, id, -0.4*2*M_PI); msourcecf_set_gain(gen, id, -40.0f); // add modulated data id = msourcecf_add_modem(gen,ms,k,m,beta); //msourcecf_set_frequency(gen, id, -0.2*2*M_PI); //msourcecf_set_gain(gen, id, 0.1f); // print source generator object msourcecf_print(gen); unsigned int total_samples = 0; while (total_samples < num_samples) { // write samples to buffer msourcecf_write_samples(gen, buf, buf_len); // push resulting sample through periodogram spgramcf_write(periodogram, buf, buf_len); // accumulated samples total_samples += buf_len; } printf("total samples: %u\n", total_samples); // compute power spectral density output float psd[nfft]; spgramcf_get_psd(periodogram, psd); // destroy objects msourcecf_destroy(gen); spgramcf_destroy(periodogram); // // export output file // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n\n"); fprintf(fid,"nfft = %u;\n", nfft); fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"H = zeros(1,nfft);\n"); for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "msresamp2_crcf_example.m" // print usage/help message void usage() { printf("Usage: %s [OPTION]\n", __FILE__); printf(" h : print help\n"); printf(" r : resampling rate (output/input), default: 0.25\n"); printf(" s : stop-band attenuation [dB], default: 60\n"); printf(" n : number of low-rate samples, default: 120\n"); printf(" f : pass-band cut-off frequency, default: 0.1\n"); printf(" c : center frequency of filter, default: 0\n"); } int main(int argc, char*argv[]) { // options float r=0.25f; // resampling rate (output/input) float As=60.0f; // resampling filter stop-band attenuation [dB] unsigned int n=120; // number of low-rate samples float fc=0.1f; // complex sinusoid frequency float f0=0.f; // center frequency int dopt; while ((dopt = getopt(argc,argv,"hr:s:n:f:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'r': r = atof(optarg); break; case 's': As = atof(optarg); break; case 'n': n = atoi(optarg); break; case 'f': fc = atof(optarg); break; case 'c': f0 = atof(optarg); break; default: exit(1); } } // validate input if (n == 0) { fprintf(stderr,"error: %s, number of input samples must be greater than zero\n", argv[0]); exit(1); } else if (r <= 0.0f) { fprintf(stderr,"error: %s, resampling rate must be greater than zero\n", argv[0]); exit(1); } else if ( roundf(fabsf(log2f(r))) > 10 ) { fprintf(stderr,"error: %s, resampling rate unreasonable\n", argv[0]); exit(1); } // determine type and compute number of stages unsigned int num_stages = (unsigned int) roundf(fabsf(log2f(r))); int type = r < 1. ? LIQUID_RESAMP_DECIM : LIQUID_RESAMP_INTERP; printf("msresamp2:\n"); printf(" rate : %12.8f\n", r); printf(" log2(r) : %12.8f\n", log2f(r)); printf(" type : %s\n", type == LIQUID_RESAMP_DECIM ? "decim" : "interp"); printf(" stages : %u\n", num_stages); unsigned int i; // create multi-stage arbitrary resampler object msresamp2_crcf q = msresamp2_crcf_create(type, num_stages, fc, f0, As); msresamp2_crcf_print(q); float delay = msresamp2_crcf_get_delay(q); // number of input samples (zero-padded) unsigned int M = (1 << num_stages); // integer resampling rate unsigned int nx = (type == LIQUID_RESAMP_DECIM) ? n * M : n; unsigned int ny = (type == LIQUID_RESAMP_DECIM) ? n : n * M; unsigned int wlen = round(0.75 * nx); // allocate memory for arrays float complex x[nx]; float complex y[ny]; // generate input signal float wsum = 0.0f; for (i=0; i Ypeak || i==0) { Ypeak = Ymag; fpeak = f; } // find peak side-lobe value, ignoring frequencies // within a certain range of signal frequency if ( fabsf(f-fy) > main_lobe_width ) max_sidelobe = Ymag > max_sidelobe ? Ymag : max_sidelobe; } // print results and check frequency location printf("output results:\n"); printf(" output delay : %12.8f samples\n", delay); printf(" desired resampling rate : %12.8f\n", r); printf(" measured resampling rate : %12.8f (%u/%u)\n", r_actual, ny, nx); printf(" peak spectrum : %12.8f dB (expected 0.0 dB)\n", Ypeak); printf(" peak frequency : %12.8f (expected %-12.8f)\n", fpeak, fy); printf(" max sidelobe : %12.8f dB (expected at least %.2f dB)\n", max_sidelobe, -As); // // export results // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n",OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"delay=%f;\n", delay); fprintf(fid,"r=%12.8f;\n", r); fprintf(fid,"nx = %u;\n", nx); fprintf(fid,"x = zeros(1,nx);\n"); for (i=0; i1, fx = f/r; fy = f; %% interpolated\n"); fprintf(fid,"else, fx = f; fy = f*r; %% decimated\n"); fprintf(fid,"end;\n"); fprintf(fid,"plot(fx,X,'LineWidth',1, 'Color',[0.5 0.5 0.5],...\n"); fprintf(fid," fy,Y,'LineWidth',1.5,'Color',[0.1 0.3 0.5]);\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"xlabel('normalized frequency');\n"); fprintf(fid,"ylabel('PSD [dB]');\n"); fprintf(fid,"legend('original','resampled','location','northeast');"); fprintf(fid,"axis([-0.5 0.5 -120 20]);\n"); fclose(fid); printf("results written to %s\n",OUTPUT_FILENAME); printf("done.\n"); return 0; } liquid-dsp-1.3.1/examples/msresamp_crcf_example.c000066400000000000000000000174711317124540100221200ustar00rootroot00000000000000// // msresamp_crcf_example.c // // Demonstration of the multi-stage arbitrary resampler // #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "msresamp_crcf_example.m" // print usage/help message void usage() { printf("Usage: %s [OPTION]\n", __FILE__); printf(" h : print help\n"); printf(" r : resampling rate (output/input), default: 0.23175\n"); printf(" s : stop-band attenuation [dB], default: 60\n"); printf(" n : number of input samples, default: 400\n"); printf(" f : input signal frequency, default: 0.017\n"); } int main(int argc, char*argv[]) { // options float r=0.23175f; // resampling rate (output/input) float As=60.0f; // resampling filter stop-band attenuation [dB] unsigned int n=400; // number of input samples float fc=0.017f; // complex sinusoid frequency int dopt; while ((dopt = getopt(argc,argv,"hr:s:n:f:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'r': r = atof(optarg); break; case 's': As = atof(optarg); break; case 'n': n = atoi(optarg); break; case 'f': fc = atof(optarg); break; default: exit(1); } } // validate input if (n == 0) { fprintf(stderr,"error: %s, number of input samples must be greater than zero\n", argv[0]); exit(1); } else if (r <= 0.0f) { fprintf(stderr,"error: %s, resampling rate must be greater than zero\n", argv[0]); exit(1); } else if ( fabsf(log2f(r)) > 10 ) { fprintf(stderr,"error: %s, resampling rate unreasonable\n", argv[0]); exit(1); } unsigned int i; // create multi-stage arbitrary resampler object msresamp_crcf q = msresamp_crcf_create(r,As); msresamp_crcf_print(q); float delay = msresamp_crcf_get_delay(q); // number of input samples (zero-padded) unsigned int nx = n + (int)ceilf(delay) + 10; // output buffer with extra padding for good measure unsigned int ny_alloc = (unsigned int) (2*(float)nx * r); // allocation for output // allocate memory for arrays float complex x[nx]; float complex y[ny_alloc]; // generate input signal float wsum = 0.0f; for (i=0; i Ypeak || i==0) { Ypeak = Ymag; fpeak = f; } // find peak side-lobe value, ignoring frequencies // within a certain range of signal frequency if ( fabsf(f-fy) > main_lobe_width ) max_sidelobe = Ymag > max_sidelobe ? Ymag : max_sidelobe; } // print results and check frequency location printf("output results:\n"); printf(" output delay : %12.8f samples\n", delay); printf(" desired resampling rate : %12.8f\n", r); printf(" measured resampling rate : %12.8f (%u/%u)\n", r_actual, ny, nx); printf(" peak spectrum : %12.8f dB (expected 0.0 dB)\n", Ypeak); printf(" peak frequency : %12.8f (expected %-12.8f)\n", fpeak, fy); printf(" max sidelobe : %12.8f dB (expected at least %.2f dB)\n", max_sidelobe, -As); // // export results // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n",OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"delay=%f;\n", delay); fprintf(fid,"r=%12.8f;\n", r); fprintf(fid,"nx = %u;\n", nx); fprintf(fid,"x = zeros(1,nx);\n"); for (i=0; i1, fx = f/r; fy = f; %% interpolated\n"); fprintf(fid,"else, fx = f; fy = f*r; %% decimated\n"); fprintf(fid,"end;\n"); fprintf(fid,"plot(fx,X,'LineWidth',1, 'Color',[0.5 0.5 0.5],...\n"); fprintf(fid," fy,Y,'LineWidth',1.5,'Color',[0.1 0.3 0.5]);\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"xlabel('normalized frequency');\n"); fprintf(fid,"ylabel('PSD [dB]');\n"); fprintf(fid,"legend('original','resampled','location','northeast');"); fprintf(fid,"axis([-0.5 0.5 -120 20]);\n"); fclose(fid); printf("results written to %s\n",OUTPUT_FILENAME); printf("done.\n"); return 0; } liquid-dsp-1.3.1/examples/nco_example.c000066400000000000000000000013371317124540100200450ustar00rootroot00000000000000// // nco_example.c // // This example demonstrates the most basic functionality of the // numerically-controlled oscillator (NCO) object. // // SEE ALSO: nco_pll_example.c // nco_pll_modem_example.c // #include #include #include "liquid.h" int main() { // create the NCO object nco_crcf p = nco_crcf_create(LIQUID_NCO); nco_crcf_set_phase(p, 0.0f); nco_crcf_set_frequency(p, M_PI/10); unsigned int i; float s, c; for (i=0; i<11; i++) { nco_crcf_sincos(p, &s, &c); printf(" %3u : %8.5f + j %8.5f\n", i, c, s); nco_crcf_step(p); } // clean up allocated memory nco_crcf_destroy(p); printf("done.\n"); return 0; } liquid-dsp-1.3.1/examples/nco_pll_example.c000066400000000000000000000112661317124540100207160ustar00rootroot00000000000000// // nco_pll_example.c // // This example demonstrates how the use the nco/pll object // (numerically-controlled oscillator with phase-locked loop) interface for // tracking to a complex sinusoid. The loop bandwidth, phase offset, and // other parameter can be specified via the command-line interface. // // SEE ALSO: nco_example.c // nco_pll_modem_example.c // #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "nco_pll_example.m" // print usage/help message void usage() { printf("nco_pll_example [options]\n"); printf(" u/h : print usage\n"); printf(" b : pll bandwidth, default: 0.01\n"); printf(" n : number of samples, default: 512\n"); printf(" p : phase offset (radians), default: pi/4\n"); printf(" f : frequency offset (radians), default: 0.3\n"); } int main(int argc, char*argv[]) { // set random seed srand( time(NULL) ); // parameters float phase_offset = 0.0f; // initial phase offset float frequency_offset = 0.40f; // initial frequency offset float pll_bandwidth = 0.003f; // phase-locked loop bandwidth unsigned int n = 512; // number of iterations int dopt; while ((dopt = getopt(argc,argv,"uhb:n:p:f:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'b': pll_bandwidth = atof(optarg); break; case 'n': n = atoi(optarg); break; case 'p': phase_offset = atof(optarg); break; case 'f': frequency_offset= atof(optarg); break; default: exit(1); } } // objects nco_crcf nco_tx = nco_crcf_create(LIQUID_VCO); nco_crcf nco_rx = nco_crcf_create(LIQUID_VCO); // initialize objects nco_crcf_set_phase(nco_tx, phase_offset); nco_crcf_set_frequency(nco_tx, frequency_offset); nco_crcf_pll_set_bandwidth(nco_rx, pll_bandwidth); // generate input float complex x[n]; float complex y[n]; float phase_error[n]; unsigned int i; for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "nco_pll_modem_example.m" // print usage/help message void usage() { printf("nco_pll_modem_example [options]\n"); printf(" u/h : print usage\n"); printf(" s : signal-to-noise ratio, default: 30dB\n"); printf(" b : pll bandwidth, default: 1e-3\n"); printf(" n : number of symbols, default: 256\n"); printf(" P : phase offset (radians), default: pi/10 ~ 0.3146\n"); printf(" F : frequency offset (radians), default: 0.001\n"); printf(" m : modulation scheme, default: qpsk\n"); liquid_print_modulation_schemes(); } int main(int argc, char*argv[]) { srand( time(NULL) ); // parameters float phase_offset = M_PI/10; float frequency_offset = 0.001f; float SNRdB = 30.0f; float pll_bandwidth = 0.02f; modulation_scheme ms = LIQUID_MODEM_QPSK; unsigned int n=256; // number of iterations int dopt; while ((dopt = getopt(argc,argv,"uhs:b:n:P:F:m:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 's': SNRdB = atof(optarg); break; case 'b': pll_bandwidth = atof(optarg); break; case 'n': n = atoi(optarg); break; case 'P': phase_offset = atof(optarg); break; case 'F': frequency_offset= atof(optarg); break; case 'm': ms = liquid_getopt_str2mod(optarg); if (ms == LIQUID_MODEM_UNKNOWN) { fprintf(stderr,"error: %s, unknown/unsupported modulation scheme \"%s\"\n", argv[0], optarg); return 1; } break; default: exit(1); } } unsigned int d=n/32; // print every "d" lines FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid, "%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid, "clear all;\n"); fprintf(fid, "phi=zeros(1,%u);\n",n); fprintf(fid, "r=zeros(1,%u);\n",n); // objects nco_crcf nco_tx = nco_crcf_create(LIQUID_VCO); nco_crcf nco_rx = nco_crcf_create(LIQUID_VCO); modem mod = modem_create(ms); modem demod = modem_create(ms); unsigned int bps = modem_get_bps(mod); // initialize objects nco_crcf_set_phase(nco_tx, phase_offset); nco_crcf_set_frequency(nco_tx, frequency_offset); nco_crcf_pll_set_bandwidth(nco_rx, pll_bandwidth); float noise_power = powf(10.0f, -SNRdB/20.0f); // print parameters printf("PLL example :\n"); printf("modem : %u-%s\n", 1<theta - nco_rx->theta; // print every line in a format that octave can read fprintf(fid, "phi(%u) = %10.6E;\n", i+1, phase_error); fprintf(fid, "r(%u) = %10.6E + j*%10.6E;\n", i+1, crealf(v), cimagf(v)); if ((i+1)%d == 0 || i==n-1) { printf(" %4u: e_hat : %6.3f, phase error : %6.3f, freq error : %6.3f\n", i+1, // iteration phase_error, // estimated phase error nco_crcf_get_phase(nco_tx) - nco_crcf_get_phase(nco_rx),// true phase error nco_crcf_get_frequency(nco_tx) - nco_crcf_get_frequency(nco_rx)// true frequency error ); } // update tx nco object nco_crcf_step(nco_tx); // update pll nco_crcf_pll_step(nco_rx, phase_error); // update rx nco object nco_crcf_step(nco_rx); } fprintf(fid, "figure;\n"); fprintf(fid, "plot(1:length(phi),phi,'LineWidth',2,'Color',[0 0.25 0.5]);\n"); fprintf(fid, "xlabel('Symbol Index');\n"); fprintf(fid, "ylabel('Phase Error [radians]');\n"); fprintf(fid, "grid on;\n"); fprintf(fid, "t0 = round(0.25*length(r));\n"); fprintf(fid, "figure;\n"); fprintf(fid, "plot(r(1:t0),'x','Color',[0.6 0.6 0.6],r(t0:end),'x','Color',[0 0.25 0.5]);\n"); fprintf(fid, "grid on;\n"); fprintf(fid, "axis([-1.5 1.5 -1.5 1.5]);\n"); fprintf(fid, "axis('square');\n"); fprintf(fid, "xlabel('In-Phase');\n"); fprintf(fid, "ylabel('Quadrature');\n"); fprintf(fid, "legend(['first 25%%'],['last 75%%'],1);\n"); fclose(fid); printf("results written to %s.\n",OUTPUT_FILENAME); nco_crcf_destroy(nco_tx); nco_crcf_destroy(nco_rx); modem_destroy(mod); modem_destroy(demod); printf("bit errors: %u / %u\n", num_errors, bps*n); printf("done.\n"); return 0; } liquid-dsp-1.3.1/examples/nyquist_filter_example.c000066400000000000000000000075171317124540100223550ustar00rootroot00000000000000// // nyquist_filter_example.c // #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "nyquist_filter_example.m" // print usage/help message void usage() { printf("nyquist_filter_example options:\n"); printf(" u/h : print usage/help\n"); printf(" t : filter type: [kaiser], pm, rcos, fexp, fsech, farcsech\n"); printf(" k : filter samples/symbol, k >= 2, default: 2\n"); printf(" m : filter delay (symbols), m >= 1, default: 4\n"); printf(" b : filter excess bandwidth factor, 0 < b < 1, default: 0.33\n"); } int main(int argc, char*argv[]) { // options unsigned int k=2; // samples/symbol unsigned int m=4; // symbol delay float beta=0.33f; // excess bandwidth factor int ftype = LIQUID_FIRFILT_RCOS; int dopt; while ((dopt = getopt(argc,argv,"uht:k:m:b:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 't': if (strcmp(optarg,"kaiser")==0) { ftype = LIQUID_FIRFILT_KAISER; } else if (strcmp(optarg,"pm")==0) { ftype = LIQUID_FIRFILT_PM; } else if (strcmp(optarg,"rcos")==0) { ftype = LIQUID_FIRFILT_RCOS; } else if (strcmp(optarg,"fexp")==0) { ftype = LIQUID_FIRFILT_FEXP; } else if (strcmp(optarg,"fsech")==0) { ftype = LIQUID_FIRFILT_FSECH; } else if (strcmp(optarg,"farcsech")==0) { ftype = LIQUID_FIRFILT_FARCSECH; } else { fprintf(stderr,"error: %s, unknown filter type '%s'\n", argv[0], optarg); exit(1); } break; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; default: exit(1); } } if (k < 2) { fprintf(stderr,"error: %s, k must be at least 2\n", argv[0]); exit(1); } else if (m < 1) { fprintf(stderr,"error: %s, m must be at least 1\n", argv[0]); exit(1); } else if (beta <= 0.0f || beta >= 1.0f) { fprintf(stderr,"error: %s, beta must be in (0,1)\n", argv[0]); exit(1); } // initialize objects unsigned int h_len = 2*k*m+1; float h[h_len]; // design the filter liquid_firdes_prototype(ftype,k,m,beta,0,h); // print the coefficients to the screen unsigned int i; for (i=0; i #include #include #include #include #include #include "liquid.h" void usage() { printf("ofdmflexframesync_example [options]\n"); printf(" -h : print usage\n"); printf(" -s : signal-to-noise ratio [dB], default: 20\n"); printf(" -F : carrier frequency offset, default: 0.002\n"); printf(" -M : number of subcarriers (must be even), default: 64\n"); printf(" -C : cyclic prefix length, default: 16\n"); printf(" -n : payload length [bytes], default: 120\n"); printf(" -m : modulation scheme (qpsk default)\n"); liquid_print_modulation_schemes(); printf(" -v : data integrity check: crc32 default\n"); liquid_print_crc_schemes(); printf(" -c : coding scheme (inner): h74 default\n"); printf(" -k : coding scheme (outer): none default\n"); liquid_print_fec_schemes(); printf(" -d : enable debugging\n"); } // callback function int callback(unsigned char * _header, int _header_valid, unsigned char * _payload, unsigned int _payload_len, int _payload_valid, framesyncstats_s _stats, void * _userdata); int main(int argc, char*argv[]) { //srand(time(NULL)); // options unsigned int M = 64; // number of subcarriers unsigned int cp_len = 16; // cyclic prefix length unsigned int taper_len = 4; // taper length unsigned int payload_len = 120; // length of payload (bytes) modulation_scheme ms = LIQUID_MODEM_QPSK; // modulation scheme fec_scheme fec0 = LIQUID_FEC_NONE; // inner code fec_scheme fec1 = LIQUID_FEC_HAMMING128; // outer code crc_scheme check = LIQUID_CRC_32; // validity check float noise_floor = -80.0f; // noise floor [dB] float SNRdB = 20.0f; // signal-to-noise ratio [dB] float dphi = 0.02f; // carrier frequency offset int debug = 0; // enable debugging? // get options int dopt; while((dopt = getopt(argc,argv,"uhds:F:M:C:n:m:v:c:k:")) != EOF){ switch (dopt) { case 'u': case 'h': usage(); return 0; case 'd': debug = 1; break; case 's': SNRdB = atof(optarg); break; case 'F': dphi = atof(optarg); break; case 'M': M = atoi(optarg); break; case 'C': cp_len = atoi(optarg); break; case 'n': payload_len = atol(optarg); break; case 'm': ms = liquid_getopt_str2mod(optarg); break; case 'v': check = liquid_getopt_str2crc(optarg); break; case 'c': fec0 = liquid_getopt_str2fec(optarg); break; case 'k': fec1 = liquid_getopt_str2fec(optarg); break; default: exit(-1); } } unsigned int i; // TODO : validate options // derived values unsigned int buf_len = 256; float complex buf[buf_len]; // time-domain buffer // allocate memory for header, payload unsigned char header[8]; unsigned char payload[payload_len]; // create frame generator ofdmflexframegenprops_s fgprops; ofdmflexframegenprops_init_default(&fgprops); fgprops.check = check; fgprops.fec0 = fec0; fgprops.fec1 = fec1; fgprops.mod_scheme = ms; ofdmflexframegen fg = ofdmflexframegen_create(M, cp_len, taper_len, NULL, &fgprops); // create frame synchronizer ofdmflexframesync fs = ofdmflexframesync_create(M, cp_len, taper_len, NULL, callback, (void*)payload); if (debug) ofdmflexframesync_debug_enable(fs); // initialize header/payload and assemble frame for (i=0; i<8; i++) header[i] = i & 0xff; for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "ofdmframegen_example.m" int main() { // options unsigned int num_subcarriers=64;// unsigned int cp_len=16; // cyclic prefix length //unsigned int num_symbols=2; // number of ofdm symbols // unsigned int frame_len = num_subcarriers + cp_len; //unsigned int num_samples = num_subcarriers * num_frames; // create synthesizer/analyzer objects ofdmframegen fg = ofdmframegen_create(num_subcarriers, cp_len); ofdmframegen_print(fg); FILE*fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\nclose all;\n\n"); fprintf(fid,"num_subcarriers=%u;\n", num_subcarriers); fprintf(fid,"cp_len=%u;\n", cp_len); fprintf(fid,"frame_len=%u;\n", frame_len); fprintf(fid,"X = zeros(1,num_subcarriers);\n"); fprintf(fid,"x = zeros(1,frame_len);\n"); unsigned int i; float complex X[num_subcarriers]; // channelized symbols float complex x[frame_len]; // time-domain samples for (i=0; i #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "ofdmframesync_example.m" void usage() { printf("Usage: ofdmframesync_example [OPTION]\n"); printf(" h : print help\n"); printf(" M : number of subcarriers (must be even), default: 1200\n"); printf(" C : cyclic prefix length, default: 60\n"); printf(" T : taper length, default: 50\n"); printf(" s : signal-to-noise ratio [dB], default: 30\n"); } // forward declaration of callback function; this will be invoked for every // OFDM symbol received by the parent ofdmframesync object. The object will // reset when something other than a zero is returned. // _X : array of received subcarrier samples [size: _M x 1] // _p : subcarrier allocation array [size: _M x 1] // _M : number of subcarriers // _userdata : user-defined data pointer static int callback(float complex * _X, unsigned char * _p, unsigned int _M, void * _userdata); // custom data type to pass to callback function struct rx_symbols { float complex syms_bpsk[2000]; // even subcarrier symbols float complex syms_qpsk[2000]; // odd subcarrier symbols unsigned int num_bpsk; // counter unsigned int num_qpsk; // counter }; // main function int main(int argc, char*argv[]) { // set the random seed differently for each run srand(time(NULL)); // options unsigned int M = 1200; // number of subcarriers unsigned int cp_len = 60; // cyclic prefix length unsigned int taper_len = 50; // taper length unsigned int num_symbols = 20; // number of data symbols float noise_floor = -120.0f; // noise floor [dB] float SNRdB = 30.0f; // signal-to-noise ratio [dB] // get options int dopt; while((dopt = getopt(argc,argv,"hdM:C:T:s:")) != EOF){ switch (dopt) { case 'h': usage(); return 0; case 'M': M = atoi(optarg); break; case 'C': cp_len = atoi(optarg); break; case 'T': taper_len = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; default: exit(1); } } unsigned int i; // derived values unsigned int frame_len = M + cp_len; unsigned int num_samples = (3+num_symbols)*frame_len; float nstd = powf(10.0f, noise_floor/20.0f); float gamma = powf(10.0f, (SNRdB + noise_floor)/20.0f); unsigned char p[M]; float complex X[M]; // channelized symbols float complex y[num_samples]; // output time series // initialize subcarrier allocation ofdmframe_init_default_sctype(M, p); // create subcarrier notch in upper half of band unsigned int n0 = (unsigned int) (0.13 * M); // lower edge of notch unsigned int n1 = (unsigned int) (0.21 * M); // upper edge of notch for (i=n0; inum_bpsk < 2000) { // save at most 2000 BPSK symbols data->syms_bpsk[data->num_bpsk] = _X[i]; data->num_bpsk++; } else if ( (i % 2) == 1 && data->num_qpsk < 2000) { // save at most 2000 QPSK symbols data->syms_qpsk[data->num_qpsk] = _X[i]; data->num_qpsk++; } } // return return 0; } liquid-dsp-1.3.1/examples/packetizer_example.c000066400000000000000000000112061317124540100214230ustar00rootroot00000000000000// // packetizer_example.c // // Demonstrates the functionality of the packetizer object. Data are encoded // using two forward error-correction schemes (an inner and outer code) before // data errors are introduced. The decoder then tries to recover the original // data message. // // SEE ALSO: fec_example.c // crc_example.c // packetizer_soft_example.c // #include #include #include #include #include "liquid.h" // print usage/help message void usage() { printf("packetizer_example [options]\n"); printf(" u/h : print usage\n"); printf(" n : input data size (number of uncoded bytes): 8 default\n"); printf(" v : data integrity check: crc32 default\n"); liquid_print_crc_schemes(); printf(" c : coding scheme (inner): h74 default\n"); printf(" k : coding scheme (outer): none default\n"); liquid_print_fec_schemes(); } int main(int argc, char*argv[]) { // options unsigned int n=8; // original data message length crc_scheme check = LIQUID_CRC_32; // data integrity check fec_scheme fec0 = LIQUID_FEC_HAMMING74; // inner code fec_scheme fec1 = LIQUID_FEC_NONE; // outer code // read command-line options int dopt; while((dopt = getopt(argc,argv,"uhn:v:c:k:")) != EOF){ switch (dopt) { case 'h': case 'u': usage(); return 0; case 'n': n = atoi(optarg); if (n < 1) { printf("error: packet length must be positive\n"); usage(); exit(-1); } break; case 'v': // data integrity check check = liquid_getopt_str2crc(optarg); if (check == LIQUID_CRC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported CRC scheme \"%s\"\n\n",optarg); exit(1); } break; case 'c': // inner FEC scheme fec0 = liquid_getopt_str2fec(optarg); if (fec0 == LIQUID_FEC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported inner FEC scheme \"%s\"\n\n",optarg); exit(1); } break; case 'k': // outer FEC scheme fec1 = liquid_getopt_str2fec(optarg); if (fec1 == LIQUID_FEC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported outer FEC scheme \"%s\"\n\n",optarg); exit(1); } break; default: exit(1); } } unsigned int i; unsigned int k = packetizer_compute_enc_msg_len(n,check,fec0,fec1); packetizer p = packetizer_create(n,check,fec0,fec1); packetizer_print(p); // initialize arrays unsigned char msg_org[n]; // original message unsigned char msg_enc[k]; // encoded message unsigned char msg_rec[k]; // recieved message unsigned char msg_dec[n]; // decoded message int crc_pass; // initialize original data message for (i=0; i #include #include #include #include "liquid.h" // print usage/help message void usage() { printf("packetizer_example [options]\n"); printf(" u/h : print usage\n"); printf(" n : input data size (number of uncoded bytes): 8 default\n"); printf(" v : data integrity check: crc32 default\n"); liquid_print_crc_schemes(); printf(" c : coding scheme (inner): h74 default\n"); printf(" k : coding scheme (outer): none default\n"); liquid_print_fec_schemes(); } int main(int argc, char*argv[]) { // options unsigned int n=8; // original data message length crc_scheme check = LIQUID_CRC_32; // data integrity check fec_scheme fec0 = LIQUID_FEC_HAMMING74; // inner code fec_scheme fec1 = LIQUID_FEC_NONE; // outer code // read command-line options int dopt; while((dopt = getopt(argc,argv,"uhn:v:c:k:")) != EOF){ switch (dopt) { case 'h': case 'u': usage(); return 0; case 'n': n = atoi(optarg); if (n < 1) { printf("error: packet length must be positive\n"); usage(); exit(-1); } break; case 'v': // data integrity check check = liquid_getopt_str2crc(optarg); if (check == LIQUID_CRC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported CRC scheme \"%s\"\n\n",optarg); exit(1); } break; case 'c': // inner FEC scheme fec0 = liquid_getopt_str2fec(optarg); if (fec0 == LIQUID_FEC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported inner FEC scheme \"%s\"\n\n",optarg); exit(1); } break; case 'k': // outer FEC scheme fec1 = liquid_getopt_str2fec(optarg); if (fec1 == LIQUID_FEC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported outer FEC scheme \"%s\"\n\n",optarg); exit(1); } break; default: exit(1); } } unsigned int i; unsigned int k = packetizer_compute_enc_msg_len(n,check,fec0,fec1); packetizer p = packetizer_create(n,check,fec0,fec1); packetizer_print(p); // initialize arrays unsigned char msg_org[n]; // original message unsigned char msg_enc[k]; // encoded message unsigned char msg_rec[8*k]; // recieved message (soft bits) unsigned char msg_dec[n]; // decoded message int crc_pass; // initialize original data message for (i=0; i 255) soft_bit = 255; if (soft_bit < 0) soft_bit = 0; msg_rec[i] = soft_bit; } // decode packet crc_pass = packetizer_decode_soft(p,msg_rec,msg_dec); // clean up allocated objects packetizer_destroy(p); // print results printf("original message: [%3u] ",n); for (i=0; i 127) ? 1<<(8-j-1) : 0; unsigned int bit_enc = (msg_enc[i] >> (8-j-1)) & 0x01; unsigned int bit_rec = (msg_rec[8*i+j] > 127) ? 1 : 0; //printf("%1u %3u (%1u) %c", bit_enc, msg_rec[i], bit_rec, bit_enc != bit_rec ? '*' : ' '); printf("%4u%c", msg_rec[8*i+j], bit_enc != bit_rec ? '*' : ' '); } printf(" : %c%.2X\n", msg_cor_hard==msg_enc[i] ? ' ' : '*', (unsigned int) (msg_cor_hard)); } } // verbose printf("decoded message: [%3u] ",n); for (i=0; i #include #include #include #include #include "liquid.h" // output to octave-friendly format #define OUTPUT_FILENAME "pll_example.m" int main() { // parameters float phase_offset = 0.8f; // carrier phase offset float frequency_offset = 0.01f; // carrier frequency offset float wn = 0.05f; // pll bandwidth float zeta = 0.707f; // pll damping factor float K = 1000; // pll loop gain unsigned int n = 256; // number of samples unsigned int d = n/32; // print every "d" lines // float theta[n]; // input phase float complex x[n]; // input sinusoid float phi[n]; // output phase float complex y[n]; // output sinusoid // generate iir loop filter object iirfilt_rrrf H = iirfilt_rrrf_create_pll(wn, zeta, K); iirfilt_rrrf_print(H); unsigned int i; // generate input float t=phase_offset; float dt = frequency_offset; for (i=0; i #include #include "liquid.internal.h" int main() { unsigned int n=6; // polynomial length (order+1) unsigned int i; // generate polynomial float p[6] = {6,11,-33,-33,11,6}; float complex roots[n-1]; // print polynomial printf("polynomial:\n"); for (i=0; i #include "liquid.h" #define OUTPUT_FILENAME "polyfit_example.m" int main() { unsigned int n=15; // number of samples unsigned int order=2; // polynomial order FILE * fid = fopen(OUTPUT_FILENAME, "w"); fprintf(fid,"%% %s : auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\nclose all;\n\n"); // initialize data vectors float x[n]; float y[n]; unsigned int i; for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "polyfit_lagrange_example.m" int main() { unsigned int n=15; // number of samples FILE * fid = fopen(OUTPUT_FILENAME, "w"); fprintf(fid,"%% %s : auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\nclose all;\n\n"); // initialize data vectors float x[n]; float y[n]; unsigned int i; for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "qdetector_cccf_example.m" // print usage/help message void usage() { printf("qdetector_cccf_example\n"); printf("options:\n"); printf(" h : print usage/help\n"); printf(" n : number of sync symbols, default: 80\n"); printf(" k : samples/symbol, default: 2\n"); printf(" m : filter delay, default: 7 sybmols\n"); printf(" b : excess bandwidth factor, default: 0.3\n"); printf(" F : carrier frequency offset, default: -0.01\n"); printf(" T : fractional sample offset, default: 0\n"); printf(" S : SNR [dB], default: 20 dB\n"); printf(" t : detection threshold, default: 0.3\n"); printf(" r : carrier offset search range,default: 0.05\n"); } int main(int argc, char*argv[]) { // options unsigned int sequence_len = 80; // number of sync symbols unsigned int k = 2; // samples/symbol unsigned int m = 7; // filter delay [symbols] float beta = 0.3f; // excess bandwidth factor int ftype = LIQUID_FIRFILT_ARKAISER; float gamma = 10.0f; // channel gain float tau = -0.3f; // fractional sample timing offset float dphi = -0.01f; // carrier frequency offset float phi = 0.5f; // carrier phase offset float SNRdB = 20.0f; // signal-to-noise ratio [dB] float threshold = 0.5f; // detection threshold float range = 0.05f; // carrier offset search range [radians/sample] int dopt; while ((dopt = getopt(argc,argv,"hn:k:m:b:F:T:S:t:r:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': sequence_len = atoi(optarg); break; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'F': dphi = atof(optarg); break; case 'T': tau = atof(optarg); break; case 'S': SNRdB = atof(optarg); break; case 't': threshold = atof(optarg); break; case 'r': range = atof(optarg); break; default: exit(1); } } unsigned int i; // validate input if (tau < -0.5f || tau > 0.5f) { fprintf(stderr,"error: %s, fractional sample offset must be in [-0.5,0.5]\n", argv[0]); exit(1); } // generate synchronization sequence (QPSK symbols) float complex sequence[sequence_len]; for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "qnsearch_example.m" int main() { unsigned int num_parameters = 8; // dimensionality of search (minimum 2) unsigned int num_iterations = 4000; // number of iterations to run float optimum_vect[num_parameters]; unsigned int i; for (i=0; i #include #include #include #include #include #include #include "liquid.h" void usage() { printf("ofdmflexframesync_example [options]\n"); printf(" h : print usage\n"); printf(" n : payload length [bytes], default: 400\n"); printf(" m : modulation scheme (qpsk default)\n"); liquid_print_modulation_schemes(); printf(" v : data integrity check: crc32 default\n"); liquid_print_crc_schemes(); printf(" c : coding scheme (inner): g2412 default\n"); printf(" k : coding scheme (outer): none default\n"); liquid_print_fec_schemes(); printf(" s : signal-to-noise ratio [dB], default: 6\n"); } int main(int argc, char *argv[]) { //srand( time(NULL) ); // options modulation_scheme ms = LIQUID_MODEM_QPSK; // mod. scheme crc_scheme check = LIQUID_CRC_32; // data validity check fec_scheme fec0 = LIQUID_FEC_GOLAY2412; // fec (inner) fec_scheme fec1 = LIQUID_FEC_NONE; // fec (outer) unsigned int payload_len = 400; // payload length float SNRdB = 6.0f; // SNR [dB] const char filename[] = "qpacketmodem_example.m"; // output filename // get options int dopt; while((dopt = getopt(argc,argv,"hn:m:v:c:k:s:")) != EOF){ switch (dopt) { case 'h': usage(); return 0; case 'n': payload_len = atol(optarg); break; case 'm': ms = liquid_getopt_str2mod(optarg); break; case 'v': check = liquid_getopt_str2crc(optarg); break; case 'c': fec0 = liquid_getopt_str2fec(optarg); break; case 'k': fec1 = liquid_getopt_str2fec(optarg); break; case 's': SNRdB = atof(optarg); break; default: exit(-1); } } unsigned int i; // derived values float nstd = powf(10.0f, -SNRdB/20.0f); // create and configure packet encoder/decoder object qpacketmodem q = qpacketmodem_create(); qpacketmodem_configure(q, payload_len, check, fec0, fec1, ms); qpacketmodem_print(q); // initialize payload unsigned char payload_tx[payload_len]; unsigned char payload_rx[payload_len]; // initialize payload for (i=0; i #include #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "qpacketmodem_performance_example.m" void usage() { printf("qpacketmodem_performance_example [options]\n"); printf(" h : print usage\n"); printf(" p : payload length [bytes], default: 400\n"); printf(" m : modulation scheme (qpsk default)\n"); liquid_print_modulation_schemes(); printf(" v : data integrity check: crc32 default\n"); liquid_print_crc_schemes(); printf(" c : coding scheme (inner): g2412 default\n"); printf(" k : coding scheme (outer): none default\n"); liquid_print_fec_schemes(); printf(" s : SNR start [dB], default: -2\n"); printf(" x : SNR max [dB], default: 13\n"); printf(" n : number of SNR steps, default: 16\n"); printf(" t : number of trials, default: 800\n"); } int main(int argc, char *argv[]) { //srand( time(NULL) ); // options modulation_scheme ms = LIQUID_MODEM_QPSK; // mod. scheme crc_scheme check = LIQUID_CRC_32; // data validity check fec_scheme fec0 = LIQUID_FEC_GOLAY2412; // fec (inner) fec_scheme fec1 = LIQUID_FEC_NONE; // fec (outer) unsigned int payload_len = 400; // payload length float SNRdB_min = -5.0f; // signal-to-noise ratio (minimum) float SNRdB_max = 10.0f; // signal-to-noise ratio (maximum) unsigned int num_snr = 31; // number of SNR steps unsigned int num_packet_trials = 800; // number of trials // get options int dopt; while((dopt = getopt(argc,argv,"hp:m:v:c:k:s:x:n:t:")) != EOF){ switch (dopt) { case 'h': usage(); return 0; case 'p': payload_len = atol(optarg); break; case 'm': ms = liquid_getopt_str2mod(optarg); break; case 'v': check = liquid_getopt_str2crc(optarg); break; case 'c': fec0 = liquid_getopt_str2fec(optarg); break; case 'k': fec1 = liquid_getopt_str2fec(optarg); break; case 's': SNRdB_min = atof(optarg); break; case 'x': SNRdB_max = atof(optarg); break; case 'n': num_snr = atoi(optarg); break; case 't': num_packet_trials = atoi(optarg); break; default: exit(-1); } } unsigned int i; // derived values float SNRdB_step = (SNRdB_max - SNRdB_min) / (num_snr-1); // create and configure packet encoder/decoder object qpacketmodem q = qpacketmodem_create(); qpacketmodem_configure(q, payload_len, check, fec0, fec1, ms); qpacketmodem_print(q); // get frame length unsigned int frame_len = qpacketmodem_get_frame_len(q); unsigned int num_bit_trials = 8*num_packet_trials*payload_len; // initialize payload unsigned char payload_tx [payload_len]; // payload (transmitted) unsigned char payload_rx [payload_len]; // payload (received) float complex frame_tx [frame_len]; // frame samples (transmitted) float complex frame_rx [frame_len]; // frame samples (received) unsigned int num_bit_errors [num_snr]; // bit errors for each SNR point unsigned int num_packet_errors[num_snr]; // packet errors for each SNR point float BER [num_snr]; // bit error rate float PER [num_snr]; // packet error rate printf(" %8s %8s %8s %12s %8s %8s %6s\n", "SNR [dB]", "errors", "bits", "BER", "errors", "packets", "PER"); unsigned int s; for (s=0; s #include #include #include #include #include #include #include "liquid.h" void usage() { printf("%s [options]\n", __FILE__); printf(" h : print usage\n"); printf(" n : payload length [symbols], default: 400\n"); printf(" p : pilot spacing [symbols], default: 20\n"); printf(" s : SNR [dB], default: 20\n"); printf(" m : modulation scheme, default: qam16\n"); liquid_print_modulation_schemes(); } int main(int argc, char *argv[]) { //srand( time(NULL) ); // options int ms = LIQUID_MODEM_QAM16; // mod. scheme unsigned int payload_len = 400; // payload length unsigned int pilot_spacing = 20; // pilot spacing float SNRdB = 20.0f; // signal-to-noise ratio [dB] const char filename[] = "qpilotsync_example.m"; // output filename float dphi = -0.0075f; // carrier frequency offset float phi = 2.1800f; // carrier phase offset float gain = 0.5f; // channel gain // get options int dopt; while((dopt = getopt(argc,argv,"hn:p:s:m:")) != EOF){ switch (dopt) { case 'h': usage(); return 0; case 'n': payload_len = atoi(optarg); break; case 'p': pilot_spacing = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'm': ms = liquid_getopt_str2mod(optarg); break; default: exit(-1); } } unsigned int i; // derived values float nstd = powf(10.0f, -SNRdB/20.0f); // create pilot generator and synchronizer objects qpilotgen pg = qpilotgen_create( payload_len, pilot_spacing); qpilotsync ps = qpilotsync_create(payload_len, pilot_spacing); qpilotgen_print(pg); // get frame length unsigned int frame_len = qpilotgen_get_frame_len(pg); // allocate arrays unsigned char payload_sym_tx[payload_len]; // transmitted payload symbols float complex payload_tx [payload_len]; // transmitted payload samples float complex frame_tx [frame_len]; // transmitted frame samples float complex frame_rx [frame_len]; // received frame samples float complex payload_rx [payload_len]; // received payload samples unsigned char payload_sym_rx[payload_len]; // received payload symbols // create modem objects for payload modem mod = modem_create(ms); modem dem = modem_create(ms); // assemble payload symbols for (i=0; i #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "quantize_example.m" // print usage/help message void usage() { printf("quantize_example [options]\n"); printf(" u/h : print usage\n"); printf(" b : number of bits, 0 < b <= 16 [default: 4]\n"); printf(" m : mu, compression factor, mu > 0 [default: 255.0]\n"); } int main(int argc, char*argv[]) { unsigned int num_bits=4; float mu = 255.0f; unsigned int num_samples = 64; int dopt; while ((dopt = getopt(argc,argv,"uhb:m:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'b': num_bits = atoi(optarg); break; case 'm': mu = atof(optarg); break; default: exit(1); } } // validate input if (num_bits > 16 || num_bits < 1) { fprintf(stderr,"error: %s, quantizer bits must be in [1,16]\n", argv[0]); exit(1); } else if (mu < 0.0f) { fprintf(stderr,"error: %s, mu must be greater than 0\n", argv[0]); exit(1); } unsigned int i; float x[num_samples]; float y[num_samples]; float v; // compressed sample unsigned int q; // quantized sample float u; // uncompressed sample float e; // error float rmse = 0.0f; printf(" input ADC output\n"); printf(" ----- --- ------\n"); float phi = 0.0f; float dphi = 0.02f * 256.0f / (float) num_samples; for (i=0; i 0x%4.4x > %12.8f\n", i, x[i], q, y[i]); } rmse = sqrtf(rmse / (float)num_samples); printf("-----------------------\n"); printf("rmse : %12.4e\n", rmse); // open debug file FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); fprintf(fid,"num_samples = %u;\n", num_samples); for (i=0; i #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "random_histogram_example.m" // print usage/help message void usage() { printf("random_histogram_example [options]\n"); printf(" u/h : print usage\n"); printf(" N : number of trials\n"); printf(" n : number of histogram bins\n"); printf(" d : distribution: {uniform, normal, exp, weib, gamma, nak, rice}\n"); printf(" e : eta NORMAL: mean\n"); printf(" s : sigma NORMAL: standard deviation\n"); printf(" l : lambda EXPONENTIAL: decay factor\n"); printf(" a : alpha WEIBULL: shape\n"); printf(" b : beta WEIBULL: spread\n"); printf(" g : gamma WEIBULL: threshold\n"); printf(" A : alpha GAMMA: shape\n"); printf(" B : beta GAMMA: spread\n"); printf(" m : m NAKAGAMI: shape\n"); printf(" o : omega NAKAGAMI: spread\n"); printf(" K : K RICE-K: spread\n"); printf(" O : omega RICE-K: spread\n"); } int main(int argc, char*argv[]) { srand(time(NULL)); unsigned long int num_trials = 100000; // number of trials unsigned int num_bins = 30; enum { UNIFORM=0, NORMAL, EXPONENTIAL, WEIBULL, GAMMA, NAKAGAMIM, RICEK } distribution=NORMAL; // distribution parameters float eta = 0.0f; // NORMAL: mean float sigma = 1.0f; // NORMAL: standard deviation float lambda = 3.0f; // EXPONENTIAL: decay factor float alphaw = 1.0f; // WEIBULL: shape float betaw = 1.0f; // WEIBULL: spread float gammaw = 1.0f; // WEIBULL: threshold float alphag = 4.5f; // GAMMA: shape float betag = 1.0f; // GAMMA: spread float m = 4.5f; // NAKAGAMI: shape factor float omeganak = 1.0f; // NAKAGMAI: spread factor float K = 4.0f; // RICE-K: K-factor (shape) float omegarice = 1.0f; // RICE-K: spread factor int dopt; while ((dopt = getopt(argc,argv,"uhN:n:d:e:s:l:a:b:g:A:B:m:o:K:O:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'N': num_trials = atoi(optarg); break; case 'n': num_bins = atoi(optarg); break; case 'd': if (strcmp(optarg,"uniform")==0) distribution = UNIFORM; else if (strcmp(optarg,"normal")==0) distribution = NORMAL; else if (strcmp(optarg,"exp")==0) distribution = EXPONENTIAL; else if (strcmp(optarg,"weib")==0) distribution = WEIBULL; else if (strcmp(optarg,"gamma")==0) distribution = GAMMA; else if (strcmp(optarg,"nak")==0) distribution = NAKAGAMIM; else if (strcmp(optarg,"rice")==0) distribution = RICEK; else { fprintf(stderr,"error: %s, unknown/unsupported distribution '%s'\n", argv[0], optarg); exit(1); } case 'e': eta = atof(optarg); break; case 's': sigma = atof(optarg); break; case 'l': lambda = atof(optarg); break; case 'a': alphaw = atof(optarg); break; case 'b': betaw = atof(optarg); break; case 'g': gammaw = atof(optarg); break; case 'A': alphag = atof(optarg); break; case 'B': betag = atof(optarg); break; case 'm': m = atof(optarg); break; case 'o': omeganak = atof(optarg); break; case 'K': K = atof(optarg); break; case 'O': omegarice = atof(optarg); break; default: exit(1); } } // validate input if (num_bins == 0) { fprintf(stderr,"error: %s, number of bins must be greater than zero\n", argv[0]); exit(1); } else if (num_trials == 0) { fprintf(stderr,"error: %s, number of trials must be greater than zero\n", argv[0]); exit(1); } float xmin = 0.0f; float xmax = 1.0f; unsigned long int i; // make a guess at the histogram range so we don't need to // store all the generated random variables in a giant array. if (distribution == UNIFORM) { xmin = 0.0f; xmax = 1.0f; } else if (distribution == NORMAL) { xmin = eta - 4.0f*sigma; xmax = eta + 4.0f*sigma; } else if (distribution == EXPONENTIAL) { xmin = 0.0f; xmax = 7.0f / lambda; } else if (distribution == WEIBULL) { xmin = gammaw; xmax = gammaw + betaw*powf( -logf(1e-3f), 1.0f/alphaw ); } else if (distribution == GAMMA) { xmin = 0.0f; xmax = 6.5 * betag + 2.0*alphag; } else if (distribution == NAKAGAMIM) { xmin = 0.0f; xmax = 1.5f*( powf(omeganak, 0.8f) + 1.0f/m ); } else if (distribution == RICEK) { xmin = 0.0f; xmax = 3.0f*logf(omegarice+1.0f) + 1.5f/(K+1.0f); } else { fprintf(stderr, "error: %s, unknown/unsupported distribution\n", argv[0]); exit(1); } // //float xspan = xmax - xmin; float bin_width = (xmax - xmin) / (num_bins); // initialize histogram unsigned int hist[num_bins]; for (i=0; i= num_bins) index = num_bins-1; hist[index]++; // update statistics m1 += x; // first moment m2 += x*x; // second moment } // m1 /= (float)num_trials; m2 /= (float)num_trials; // compute expected distribution unsigned int num_steps = 100; float xstep = (xmax - xmin) / (num_steps - 1); float f[num_steps]; float F[num_steps]; for (i=0; i hist_max ? hist[i] : hist_max; printf("%8s : %6s [%6s]\n", "x", "count", "prob."); for (i=0; i #include "liquid.h" // print symbol to screen, one bit at a time void print_symbol(unsigned char _sym, unsigned int _bits_per_symbol) { unsigned int i; unsigned int n; // shift amount for (i=0; i<_bits_per_symbol; i++) { n = _bits_per_symbol - i - 1; printf("%c", (_sym >> n) & 0x01 ? '1' : '0'); } } // print symbol array to screen void print_symbol_array(unsigned char * _sym, unsigned int _bits_per_symbol, unsigned int _num_symbols) { unsigned int i; for (i=0; i<_num_symbols; i++) { print_symbol(_sym[i], _bits_per_symbol); printf("%c", i < _num_symbols-1 ? ',' : '\n'); } } int main() { // input symbols: 111 000 111 // expected output: 11 10 00 11 1(0) unsigned char input[3] = { 0x07, // 111 0x00, // 000 0x07 // 111(0) }; // allocate memory for output array unsigned char output[5]; unsigned int N; // print input symbol array printf("input symbols: "); print_symbol_array(input,3,3); // repack bytes into output array liquid_repack_bytes( input, 3, 3, output, 2, 5, &N ); // print output array printf("output symbols: "); print_symbol_array(output,2,5); return 0; } liquid-dsp-1.3.1/examples/resamp2_cccf_example.c000066400000000000000000000117551317124540100216220ustar00rootroot00000000000000// // resamp2_cccf_example.c // // This example demonstrates the halfband resampler cenetered at the // quarter sample rate to split the signal into positive and negative // frequency bands. Two distinct narrow-band signals are generated; one // at a positive frequency and one at a negative frequency. The resamp2 // object is run as a filter to separate the two about the zero- // frequency center point. // #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "resamp2_cccf_example.m" int main() { unsigned int m = 12; // filter semi-length (actual length: 4*m+1) float As = 60.0f; // stop-band attenuation [dB] unsigned int num_samples = 400; // number of input samples unsigned int i; // allocate memory for data arrays float complex x [num_samples]; // input signal float complex y0[num_samples]; // float complex y1[num_samples]; // // generate the two signals iirfilt_crcf lowpass = iirfilt_crcf_create_lowpass(6,0.02); for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "resamp2_crcf_decim_example.m" // print usage/help message void usage() { printf("%s [options]\n", __FILE__); printf(" h : print help\n"); printf(" n : number of output samples, default: 64\n"); printf(" m : filter semi-length, default: 5\n"); printf(" s : filter stop-band attenuation, default: 60 dB\n"); } int main(int argc, char*argv[]) { unsigned int m=5; // filter semi-length float fc=0.037f; // input tone frequency unsigned int num_samples = 64; // number of output samples float As=60.0f; // stop-band attenuation [dB] int dopt; while ((dopt = getopt(argc,argv,"hn:m:s:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': num_samples = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 's': As = atof(optarg); break; default: exit(1); } } unsigned int i; // allocate arrays float complex x[2*num_samples]; // input array float complex y[ num_samples]; // output array // generate input unsigned int w_len = 2*num_samples - 4*m; // window length float beta = 8.0f; // kaiser window factor float w_sum = 0.0f; // gain due to window for (i=0; i<2*num_samples; i++) { // compute windowing function and keep track of gain float w = (i < w_len ? kaiser(i,w_len,beta,0) : 0.0f); w_sum += w; // compute windowed complex sinusoid x[i] = w * cexpf(_Complex_I*2*M_PI*fc*i); } // create/print the half-band resampler resamp2_crcf q = resamp2_crcf_create(m,0,As); resamp2_crcf_print(q); unsigned int delay = resamp2_crcf_get_delay(q); // run the resampler for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "resamp2_crcf_example.m" int main() { unsigned int m=5; // filter semi-length (actual length: 4*m+1) float bw=0.13f; // input signal bandwidth float fc=-0.597f; // input signal carrier frequency (radians/sample) unsigned int num_samples=37; // number of input samples float As=60.0f; // stop-band attenuation [dB] unsigned int i; // derived values unsigned int n = num_samples + 2*m + 1; // adjusted input sequence length // allocate memory for data arrays float complex x[ n]; float complex y[2*n]; float complex z[ n]; // generate the baseband signal (filter pulse) float h[num_samples]; liquid_firdes_kaiser(num_samples,bw,60.0f,0.0f,h); for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "resamp2_crcf_filter_example.m" int main() { unsigned int m=9; // filter semi-length unsigned int num_samples=128; // number of input samples float As=60.0f; // stop-band attenuation [dB] // derived values unsigned int h_len = 4*m+1; // half-band filter length unsigned int N = num_samples + h_len; // arrays float complex x[N]; // input time series float complex y0[N]; // output time series (lower band) float complex y1[N]; // output time series (upper band) // generate input sequence unsigned int i; for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "resamp2_crcf_interp_example.m" // print usage/help message void usage() { printf("%s [options]\n", __FILE__); printf(" h : print help\n"); printf(" n : number of input samples, default: 64\n"); printf(" m : filter semi-length, default: 5\n"); printf(" s : filter stop-band attenuation, default: 60 dB\n"); } int main(int argc, char*argv[]) { unsigned int m=5; // filter semi-length float fc=0.074f; // input tone frequency unsigned int num_samples = 64; // number of input samples float As=60.0f; // stop-band attenuation [dB] int dopt; while ((dopt = getopt(argc,argv,"hn:m:s:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': num_samples = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 's': As = atof(optarg); break; default: exit(1); } } unsigned int i; // allocate arrays float complex x[ num_samples]; // input array float complex y[2*num_samples]; // output array // generate input unsigned int w_len = num_samples - 2*m; // window length float beta = 8.0f; // kaiser window factor float w_sum = 0.0f; // gain due to window for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "resamp_crcf_example.m" // print usage/help message void usage() { printf("Usage: %s [OPTION]\n", __FILE__); printf(" h : print help\n"); printf(" r : resampling rate (output/input), default: 1.1\n"); printf(" m : filter semi-length (delay), default: 13\n"); printf(" b : filter bandwidth, 0 < b < 0.5, default: 0.4\n"); printf(" s : filter stop-band attenuation [dB], default: 60\n"); printf(" p : filter bank size, default: 64\n"); printf(" n : number of input samples, default: 400\n"); printf(" f : input signal frequency, default: 0.044\n"); } int main(int argc, char*argv[]) { // options float r = 1.1f; // resampling rate (output/input) unsigned int m = 13; // resampling filter semi-length (filter delay) float As = 60.0f; // resampling filter stop-band attenuation [dB] float bw = 0.45f; // resampling filter bandwidth unsigned int npfb = 64; // number of filters in bank (timing resolution) unsigned int n = 400; // number of input samples float fc = 0.044f; // complex sinusoid frequency int dopt; while ((dopt = getopt(argc,argv,"hr:m:b:s:p:n:f:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'r': r = atof(optarg); break; case 'm': m = atoi(optarg); break; case 'b': bw = atof(optarg); break; case 's': As = atof(optarg); break; case 'p': npfb = atoi(optarg); break; case 'n': n = atoi(optarg); break; case 'f': fc = atof(optarg); break; default: exit(1); } } // validate input if (r <= 0.0f) { fprintf(stderr,"error: %s, resampling rate must be greater than zero\n", argv[0]); exit(1); } else if (m == 0) { fprintf(stderr,"error: %s, filter semi-length must be greater than zero\n", argv[0]); exit(1); } else if (bw == 0.0f || bw >= 0.5f) { fprintf(stderr,"error: %s, filter bandwidth must be in (0,0.5)\n", argv[0]); exit(1); } else if (As < 0.0f) { fprintf(stderr,"error: %s, filter stop-band attenuation must be greater than zero\n", argv[0]); exit(1); } else if (npfb == 0) { fprintf(stderr,"error: %s, filter bank size must be greater than zero\n", argv[0]); exit(1); } else if (n == 0) { fprintf(stderr,"error: %s, number of input samples must be greater than zero\n", argv[0]); exit(1); } unsigned int i; // number of input samples (zero-padded) unsigned int nx = n + m; // output buffer with extra padding for good measure unsigned int y_len = (unsigned int) ceilf(1.1 * nx * r) + 4; // arrays float complex x[nx]; float complex y[y_len]; // create resampler resamp_crcf q = resamp_crcf_create(r,m,bw,As,npfb); // generate input signal float wsum = 0.0f; for (i=0; i Ypeak || i==0) { Ypeak = Ymag; fpeak = f; } // find peak side-lobe value, ignoring frequencies // within a certain range of signal frequency if ( fabsf(f-fy) > main_lobe_width ) max_sidelobe = Ymag > max_sidelobe ? Ymag : max_sidelobe; } // print results and check frequency location printf(" desired resampling rate : %12.8f\n", r); printf(" measured resampling rate : %12.8f (%u/%u)\n", r_actual, ny, nx); printf(" peak spectrum : %12.8f dB (expected 0.0 dB)\n", Ypeak); printf(" peak frequency : %12.8f (expected %-12.8f)\n", fpeak, fy); printf(" max sidelobe : %12.8f dB (expected at least %.2f dB)\n", max_sidelobe, -As); // // export results // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n",OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"m=%u;\n", m); fprintf(fid,"npfb=%u;\n", npfb); fprintf(fid,"r=%12.8f;\n", r); fprintf(fid,"n=%u;\n", n); fprintf(fid,"nx = %u;\n", nx); fprintf(fid,"x = zeros(1,nx);\n"); for (i=0; i1, fx = f/r; fy = f; %% interpolated\n"); fprintf(fid,"else, fx = f; fy = f*r; %% decimated\n"); fprintf(fid,"end;\n"); fprintf(fid,"subplot(4,1,3:4);\n"); fprintf(fid," plot(fx,X,'Color',[0.5 0.5 0.5],fy,Y,'LineWidth',2);\n"); fprintf(fid," grid on;\n"); fprintf(fid," xlabel('normalized frequency');\n"); fprintf(fid," ylabel('PSD [dB]');\n"); fprintf(fid," legend('original','resampled','location','northeast');"); fprintf(fid," axis([-0.5 0.5 -120 20]);\n"); fclose(fid); printf("results written to %s\n",OUTPUT_FILENAME); printf("done.\n"); return 0; } liquid-dsp-1.3.1/examples/ricek_channel_example.c000066400000000000000000000142771317124540100220620ustar00rootroot00000000000000// // Rice-K fading generator example. // // This example generates correlated circular complex Gauss random variables // using an approximation to the ideal Doppler filter. The resulting Gauss // random variables are converted to Rice-K random variables using a simple // transformation. The resulting output file plots the filter's power // spectral density, the fading power envelope as a function of time, and the // distribution of Rice-K random variables alongside the theoretical PDF to // demonstrate that the technique is valid. // #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "ricek_channel_example.m" // print usage/help message void usage() { printf("%s [options]\n", __FILE__); printf(" h : print help\n"); printf(" n : number of samples\n"); printf(" f : maximum doppler frequency (0,0.5)\n"); printf(" K : Rice K factor, linear, greater than zero\n"); printf(" O : mean power, linear (Rice-K distribution 'omega')\n"); } int main(int argc, char*argv[]) { // options unsigned int h_len = 51; // doppler filter length float fd = 0.1f; // maximum doppler frequency float K = 2.0f; // Rice fading factor float omega = 1.0f; // mean power float theta = 0.0f; // angle of arrival unsigned int num_samples=1200; // number of samples int dopt; while ((dopt = getopt(argc,argv,"hn:f:K:O:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': num_samples = atoi(optarg); break; case 'f': fd = atof(optarg); break; case 'K': K = atof(optarg); break; case 'O': omega = atof(optarg); break; default: exit(1); } } // validate input if (K < 0.0f) { fprintf(stderr,"error: %s, fading factor K must be greater than zero\n", argv[0]); exit(1); } else if (omega < 0.0f) { fprintf(stderr,"error: %s, signal power Omega must be greater than zero\n", argv[0]); exit(1); } else if (fd <= 0.0f || fd >= 0.5f) { fprintf(stderr,"error: %s, Doppler frequency must be in (0,0.5)\n", argv[0]); exit(1); } else if (h_len < 4) { fprintf(stderr,"error: %s, Doppler filter length too small\n", argv[0]); exit(1); } else if (num_samples == 0) { fprintf(stderr,"error: %s, number of samples must be greater than zero\n", argv[0]); exit(1); } unsigned int i; // allocate array for output samples float complex * y = (float complex*) malloc(num_samples*sizeof(float complex)); // generate Doppler filter coefficients float h[h_len]; liquid_firdes_doppler(h_len, fd, K, theta, h); // normalize filter coefficients such that output Gauss random // variables have unity variance float std = 0.0f; for (i=0; i #include #include #include #include "liquid.h" float compute_entropy(unsigned char * _x, unsigned int _n); int main() { unsigned int n=32; // number of data bytes unsigned char x[n]; // input data unsigned char y[n]; // scrambled data unsigned char z[n]; // unscrambled data unsigned int i; // generate data for (i=0; i> j) & 0x01 ]++; // b:2 for (j=0; j<8; j+=2) c2[ (_x[i] >> j) & 0x03 ]++; // b:4 for (j=0; j<8; j+=4) c4[ (_x[i] >> j) & 0x0f ]++; // b:8 c8[ _x[i] ]++; } // compute entropy float H1 = 0.0f; float H2 = 0.0f; float H4 = 0.0f; float H8 = 0.0f; float p; for (i=0; i<2; i++) { p = (float) c1[i] / (float)(8*_n); H1 -= p * log2f(p+1e-12f); } H1 /= 1.0f; for (i=0; i<4; i++) { p = (float) c2[i] / (float)(4*_n); H2 -= p * log2f(p+1e-12f); } H2 /= 2.0f; for (i=0; i<16; i++) { p = (float) c4[i] / (float)(2*_n); H4 -= p * log2f(p+1e-12f); } H4 /= 4.0f; for (i=0; i<256; i++) { p = (float) c8[i] / (float)(_n); H8 -= p * log2f(p+1e-12f); } H8 /= 8.0f; #if 0 printf("H1 : %12.8f\n", H1); printf("H2 : %12.8f\n", H2); printf("H4 : %12.8f\n", H4); printf("H8 : %12.8f\n", H8); #endif // not sure if product is truly the entropy, but // it is a fair assessment return H1 * H2 * H4 * H8; } liquid-dsp-1.3.1/examples/smatrix_example.c000066400000000000000000000111111317124540100207440ustar00rootroot00000000000000// // smatrix_example.c // #include #include #include #include #include "liquid.internal.h" int main(int argc, char*argv[]) { #if 0 unsigned int M = 12; unsigned int N = 16; // create empty list smatrixb q = smatrixb_create(M,N); // set value(s) smatrixb_set(q,1,2, 1); smatrixb_set(q,2,2, 1); smatrixb_set(q,2,3, 1); smatrixb_set(q,2,7, 1); smatrixb_set(q,2,8, 1); smatrixb_set(q,2,11, 1); smatrixb_delete(q,2,2); printf("\ncompact form:\n"); smatrixb_print(q); printf("\nexpanded form:\n"); smatrixb_print_expanded(q); printf("\ncertain values:\n"); printf(" A[%2u,%2u] = %1u\n", 1, 1, smatrixb_get(q,1,1)); printf(" A[%2u,%2u] = %1u\n", 1, 2, smatrixb_get(q,1,2)); // generate vectors unsigned char x[N]; unsigned char y[M]; unsigned int i; unsigned int j; for (j=0; j #include #include #include "liquid.h" #define OUTPUT_FILENAME "spgramcf_example.m" int main() { // spectral periodogram options unsigned int nfft = 1024; // spectral periodogram FFT size unsigned int num_samples = 2e6; // number of samples float noise_floor = -60.0f; // noise floor [dB] unsigned int i; // derived values float nstd = powf(10.0f, noise_floor/20.0f); // create spectral periodogram spgramcf q = spgramcf_create_default(nfft); spgramcf_print(q); // generate signal (band-pass filter with Hilbert transform) iirfilt_rrrf filter = iirfilt_rrrf_create_prototype( LIQUID_IIRDES_BUTTER, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, 9, 0.17f, 0.20f, 0.1f, 60.0f); firhilbf ht = firhilbf_create(13,60.0f); for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "spgramcf_waterfall_example.gnu" int main() { // spectral periodogram options unsigned int nfft = 1200; // spectral periodogram FFT size unsigned int num_samples = 2000000; // number of samples // derived values unsigned int num_estimates = 800; // target number of PSD estimates unsigned int samples_per_estimate = (unsigned int)(num_samples/num_estimates); unsigned int i; // create time-varying multi-path channel object unsigned int c_len = 17; float std = 0.1f; float tau = 1e-4f; tvmpch_cccf channel = tvmpch_cccf_create(c_len, std, tau); unsigned int buf_len = 64; float complex buf[buf_len]; // create spectral periodogram spgramcf periodogram = spgramcf_create_default(nfft); // create stream generator msourcecf gen = msourcecf_create(); // add noise source (narrow-band) int id_noise = msourcecf_add_noise(gen, 0.10f); msourcecf_set_frequency(gen, id_noise, 0.4*2*M_PI); msourcecf_set_gain (gen, id_noise, -20.0f); // add tone int id_tone = msourcecf_add_tone(gen); msourcecf_set_frequency(gen, id_tone, -0.4*2*M_PI); msourcecf_set_gain (gen, id_tone, -10.0f); // add modulated data int id_modem = msourcecf_add_modem(gen,LIQUID_MODEM_QPSK,4,12,0.30f); msourcecf_set_frequency(gen, id_modem, -0.1*2*M_PI); msourcecf_set_gain (gen, id_modem, 0.0f); FILE * fid = fopen("waterfall.bin","wb"); // write header float nfftf = (float)nfft; fwrite(&nfftf, sizeof(float), 1, fid); for (i=0; i samples_per_estimate) { // compute power spectral density output spgramcf_get_psd(periodogram, psd); // write output float n = (float)total_samples; fwrite(&n, sizeof(float), 1, fid); fwrite(psd, sizeof(float), nfft, fid); // soft reset of internal state, counters spgramcf_clear(periodogram); // update counter for total number of PSD estimates taken total_estimates++; } // accumulated samples total_samples += buf_len; // update state for noise source if (state == 0 && randf() < 0.01f) { state = 1; msourcecf_enable(gen, id_noise); } else if (state == 1 && randf() < 0.01f) { state = 0; msourcecf_disable(gen, id_noise); } } printf("samples per PSD estimate : %u\n", samples_per_estimate); printf("total samples : %u (%u)\n", total_samples, num_samples); printf("total estimates : %u (%u)\n", total_estimates, num_estimates); fclose(fid); // destroy objects msourcecf_destroy(gen); spgramcf_destroy(periodogram); tvmpch_cccf_destroy(channel); // export output file fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"#!/usr/bin/gnuplot\n"); fprintf(fid,"reset\n"); fprintf(fid,"set terminal png size 800,800 enhanced font 'Verdana,10'\n"); fprintf(fid,"set output '%s.png'\n", OUTPUT_FILENAME); fprintf(fid,"unset key\n"); fprintf(fid,"set style line 11 lc rgb '#808080' lt 1\n"); fprintf(fid,"set border 3 front ls 11\n"); fprintf(fid,"set style line 12 lc rgb '#888888' lt 0 lw 1\n"); fprintf(fid,"set grid front ls 12\n"); fprintf(fid,"set tics nomirror out scale 0.75\n"); fprintf(fid,"set xrange [-0.5:0.5]\n"); fprintf(fid,"set yrange [0:%f]\n", (float)(num_samples-1)*1e-3f); fprintf(fid,"set xlabel 'Normalized Frequency [f/F_s]'\n"); fprintf(fid,"set ylabel 'Sample Index'\n"); fprintf(fid,"set format y '%%.0f k'\n"); fprintf(fid,"# disable colorbar tics\n"); fprintf(fid,"set cbtics scale 0\n"); fprintf(fid,"set palette negative defined ( \\\n"); fprintf(fid," 0 '#D53E4F',\\\n"); fprintf(fid," 1 '#F46D43',\\\n"); fprintf(fid," 2 '#FDAE61',\\\n"); fprintf(fid," 3 '#FEE08B',\\\n"); fprintf(fid," 4 '#E6F598',\\\n"); fprintf(fid," 5 '#ABDDA4',\\\n"); fprintf(fid," 6 '#66C2A5',\\\n"); fprintf(fid," 7 '#3288BD' )\n"); fprintf(fid,"\n"); fprintf(fid,"plot 'waterfall.bin' u 1:($2*1e-3):3 binary matrix with image\n"); fclose(fid); printf("results written to %s.\n", "waterfall.bin"); printf("results written to %s.\n", OUTPUT_FILENAME); printf("done.\n"); return 0; } liquid-dsp-1.3.1/examples/spgramf_example.c000066400000000000000000000045211317124540100207230ustar00rootroot00000000000000// // spgramf_example.c // // Spectral periodogram example with real inputs. // #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "spgramf_example.m" int main() { // spectral periodogram options unsigned int nfft = 1024; // spectral periodogram FFT size unsigned int num_samples = 1e6; // number of samples float noise_floor = -60.0f; // noise floor [dB] unsigned int i; // derived values float nstd = powf(10.0f, noise_floor/20.0f); // create spectral periodogram spgramf q = spgramf_create_default(nfft); spgramf_print(q); // generate signal (band-pass filter) iirfilt_rrrf filter = iirfilt_rrrf_create_prototype( LIQUID_IIRDES_BUTTER, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, 9, 0.17f, 0.20f, 0.1f, 60.0f); for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "spwaterfallcf_waterfall_example.gnu" int main() { // spectral periodogram options unsigned int nfft = 1200; // spectral periodogram FFT size unsigned int time = 250; // minimum time buffer unsigned int num_samples = 20e6; // number of samples // create time-varying multi-path channel object unsigned int buf_len = 64; float complex buf[buf_len]; // create spectral periodogram spwaterfallcf periodogram = spwaterfallcf_create_default(nfft,time); spwaterfallcf_print(periodogram); // create stream generator msourcecf gen = msourcecf_create(); // add noise source (narrow-band) int id_noise = msourcecf_add_noise(gen, 0.10f); msourcecf_set_frequency(gen, id_noise, 0.4*2*M_PI); msourcecf_set_gain (gen, id_noise, -20.0f); // add tone int id_tone = msourcecf_add_tone(gen); msourcecf_set_frequency(gen, id_tone, -0.4*2*M_PI); msourcecf_set_gain (gen, id_tone, -10.0f); // add modulated data int id_modem = msourcecf_add_modem(gen,LIQUID_MODEM_QPSK,4,12,0.30f); msourcecf_set_frequency(gen, id_modem, -0.1*2*M_PI); msourcecf_set_gain (gen, id_modem, 0.0f); unsigned int total_samples = 0; int state = 1; while (total_samples < num_samples) { // write samples to buffer msourcecf_write_samples(gen, buf, buf_len); // push resulting sample through periodogram spwaterfallcf_write(periodogram, buf, buf_len); // accumulated samples total_samples += buf_len; // update state for noise source if (state == 0 && randf() < 1e-4f) { state = 1; msourcecf_enable(gen, id_noise); //printf("turning noise on\n"); } else if (state == 1 && randf() < 3e-4f) { state = 0; msourcecf_disable(gen, id_noise); //printf("turning noise off\n"); } } // export output files spwaterfallcf_export(periodogram,"spwaterfallcf_example"); // destroy objects msourcecf_destroy(gen); spwaterfallcf_destroy(periodogram); printf("done.\n"); return 0; } liquid-dsp-1.3.1/examples/symstreamcf_example.c000066400000000000000000000044241317124540100216230ustar00rootroot00000000000000// // symstreamcf_example.c // #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "symstreamcf_example.m" int main() { // symstream parameters int ftype = LIQUID_FIRFILT_ARKAISER; unsigned int k = 4; unsigned int m = 9; float beta = 0.30f; int ms = LIQUID_MODEM_QPSK; // spectral periodogram options unsigned int nfft = 2400; // spectral periodogram FFT size unsigned int num_samples = 80000; // number of samples unsigned int i; // create spectral periodogram spgramcf periodogram = spgramcf_create_default(nfft); unsigned int buf_len = 1024; float complex buf[buf_len]; // create stream generator symstreamcf gen = symstreamcf_create_linear(ftype,k,m,beta,ms); unsigned int total_samples = 0; while (total_samples < num_samples) { // write samples to buffer symstreamcf_write_samples(gen, buf, buf_len); // push resulting sample through periodogram spgramcf_write(periodogram, buf, buf_len); // accumulated samples total_samples += buf_len; } printf("total samples: %u\n", total_samples); // compute power spectral density output float psd[nfft]; spgramcf_get_psd(periodogram, psd); // destroy objects symstreamcf_destroy(gen); spgramcf_destroy(periodogram); // // export output file // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n\n"); fprintf(fid,"nfft = %u;\n", nfft); fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"H = zeros(1,nfft);\n"); for (i=0; i #include #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "symsync_crcf_example.m" // print usage/help message void usage() { printf("symsync_crcf_example [options]\n"); printf(" h : print help\n"); printf(" k : filter samples/symbol, default: 2\n"); printf(" m : filter delay (symbols), default: 5\n"); printf(" b : filter excess bandwidth, default: 0.5\n"); printf(" B : filter polyphase banks, default: 32\n"); printf(" n : number of symbols, default: 400\n"); } int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int k = 2; // samples/symbol (input) unsigned int m = 5; // filter delay (symbols) float beta = 0.5f; // filter excess bandwidth factor unsigned int num_filters = 32; // number of filters in the bank unsigned int num_symbols = 400; // number of data symbols int dopt; while ((dopt = getopt(argc,argv,"hk:m:b:B:s:n:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'B': num_filters = atoi(optarg); break; case 'n': num_symbols = atoi(optarg); break; default: exit(1); } } // validate input if (k < 2) { fprintf(stderr,"error: k (samples/symbol) must be at least 2\n"); exit(1); } else if (m < 1) { fprintf(stderr,"error: m (filter delay) must be greater than 0\n"); exit(1); } else if (beta <= 0.0f || beta > 1.0f) { fprintf(stderr,"error: beta (excess bandwidth factor) must be in (0,1]\n"); exit(1); } else if (num_filters == 0) { fprintf(stderr,"error: number of polyphase filters must be greater than 0\n"); exit(1); } else if (num_symbols == 0) { fprintf(stderr,"error: number of symbols must be greater than 0\n"); exit(1); } unsigned int i; // static values liquid_firfilt_type ftype = LIQUID_FIRFILT_ARKAISER; float bandwidth = 0.02f; // loop filter bandwidth float dt = -0.5f; // fractional sample offset // derived values unsigned int num_samples = k*num_symbols; float complex s[num_symbols]; // data symbols float complex x[num_samples]; // interpolated samples float complex y[num_symbols + 64]; // synchronized symbols // generate random QPSK symbols for (i=0; i #include #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "symsync_crcf_full_example.m" // print usage/help message void usage() { printf("symsync_crcf_full_example [options]\n"); printf(" h : print usage\n"); printf(" T : filter type: [rrcos], rkaiser, arkaiser, hM3, gmsk\n"); printf(" k : filter samples/symbol, default: 2\n"); printf(" K : output samples/symbol, default: 2\n"); printf(" m : filter delay (symbols), default: 5\n"); printf(" b : filter excess bandwidth, default: 0.5\n"); printf(" B : filter polyphase banks, default: 32\n"); printf(" s : signal-to-noise ratio, default: 30dB\n"); printf(" w : timing pll bandwidth, default: 0.02\n"); printf(" n : number of symbols, default: 400\n"); printf(" t : timing phase offset [%% symbol], t in [-0.5,0.5], default: -0.2\n"); printf(" r : timing freq. offset [%% symbol], default: 1.000\n"); } int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int k = 2; // samples/symbol (input) unsigned int k_out = 2; // samples/symbol (output) unsigned int m = 5; // filter delay (symbols) float beta = 0.5f; // filter excess bandwidth factor unsigned int num_filters = 32; // number of filters in the bank unsigned int num_symbols = 400; // number of data symbols float SNRdB = 30.0f; // signal-to-noise ratio // transmit/receive filter types liquid_firfilt_type ftype_tx = LIQUID_FIRFILT_RRC; liquid_firfilt_type ftype_rx = LIQUID_FIRFILT_RRC; float bt = 0.02f; // loop filter bandwidth float tau = -0.2f; // fractional symbol offset float r = 1.00f; // resampled rate // use random data or 101010 phasing pattern int random_data=1; int dopt; while ((dopt = getopt(argc,argv,"hT:k:K:m:b:B:s:w:n:t:r:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'T': if (strcmp(optarg,"gmsk")==0) { ftype_tx = LIQUID_FIRFILT_GMSKTX; ftype_rx = LIQUID_FIRFILT_GMSKRX; } else { ftype_tx = liquid_getopt_str2firfilt(optarg); ftype_rx = liquid_getopt_str2firfilt(optarg); } if (ftype_tx == LIQUID_FIRFILT_UNKNOWN) { fprintf(stderr,"error: %s, unknown filter type '%s'\n", argv[0], optarg); exit(1); } break; case 'k': k = atoi(optarg); break; case 'K': k_out = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'B': num_filters = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'w': bt = atof(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 't': tau = atof(optarg); break; case 'r': r = atof(optarg); break; default: exit(1); } } // validate input if (k < 2) { fprintf(stderr,"error: k (samples/symbol) must be at least 2\n"); exit(1); } else if (m < 1) { fprintf(stderr,"error: m (filter delay) must be greater than 0\n"); exit(1); } else if (beta <= 0.0f || beta > 1.0f) { fprintf(stderr,"error: beta (excess bandwidth factor) must be in (0,1]\n"); exit(1); } else if (num_filters == 0) { fprintf(stderr,"error: number of polyphase filters must be greater than 0\n"); exit(1); } else if (bt <= 0.0f) { fprintf(stderr,"error: timing PLL bandwidth must be greater than 0\n"); exit(1); } else if (num_symbols == 0) { fprintf(stderr,"error: number of symbols must be greater than 0\n"); exit(1); } else if (tau < -1.0f || tau > 1.0f) { fprintf(stderr,"error: timing phase offset must be in [-1,1]\n"); exit(1); } else if (r < 0.5f || r > 2.0f) { fprintf(stderr,"error: timing frequency offset must be in [0.5,2]\n"); exit(1); } // compute delay while (tau < 0) tau += 1.0f; // ensure positive tau float g = k*tau; // number of samples offset int ds=floorf(g); // additional symbol delay float dt = (g - (float)ds); // fractional sample offset if (dt > 0.5f) { // force dt to be in [0.5,0.5] dt -= 1.0f; ds++; } unsigned int i, n=0; unsigned int num_samples = k*num_symbols; unsigned int num_samples_resamp = (unsigned int) ceilf(num_samples*r*1.1f) + 4; float complex s[num_symbols]; // data symbols float complex x[num_samples]; // interpolated samples float complex y[num_samples_resamp]; // resampled data (resamp_crcf) float complex z[k_out*num_symbols + 64];// synchronized samples float complex sym_out[num_symbols + 64];// synchronized symbols for (i=0; i #include #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "symsync_crcf_kaiser_example.m" // print usage/help message void usage(void); void usage(void) { printf("symsync_crcf_example [options]\n"); printf(" -h : print help\n"); printf(" -k : filter samples/symbol, default: 2\n"); printf(" -m : filter delay (symbols), default: 3\n"); printf(" -b : filter excess bandwidth, default: 0.5\n"); printf(" -B : filter polyphase banks, default: 32\n"); printf(" -s : signal-to-noise ratio, default: 30 dB\n"); printf(" -w : timing pll bandwidth, default: 0.02\n"); printf(" -n : number of symbols, default: 400\n"); printf(" -t : timing offset, default: -0.2\n"); } int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int k = 2; // samples/symbol (input) unsigned int m = 3; // filter delay (symbols) float beta = 0.5f; // filter excess bandwidth factor unsigned int num_filters = 32; // number of filters in the bank float SNRdB = 30.0f; // signal-to-noise ratio float bt = 0.02f; // loop filter bandwidth unsigned int num_symbols = 400; // number of data symbols float tau = -0.20f; // fractional symbol offset // Nyquist filter type liquid_firfilt_type ftype = LIQUID_FIRFILT_KAISER; int dopt; while ((dopt = getopt(argc,argv,"uhk:m:b:B:s:w:n:t:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'B': num_filters = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'w': bt = atof(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 't': tau = atof(optarg); break; default: exit(1); } } unsigned int i; // validate input if (k < 2) { fprintf(stderr,"error: k (samples/symbol) must be at least 2\n"); exit(1); } else if (m < 1) { fprintf(stderr,"error: m (filter delay) must be greater than 0\n"); exit(1); } else if (beta <= 0.0f || beta > 1.0f) { fprintf(stderr,"error: beta (excess bandwidth factor) must be in (0,1]\n"); exit(1); } else if (num_filters == 0) { fprintf(stderr,"error: number of polyphase filters must be greater than 0\n"); exit(1); } else if (bt <= 0.0f) { fprintf(stderr,"error: timing PLL bandwidth must be greater than 0\n"); exit(1); } else if (num_symbols == 0) { fprintf(stderr,"error: number of symbols must be greater than 0\n"); exit(1); } else if (tau < -1.0f || tau > 1.0f) { fprintf(stderr,"error: timing phase offset must be in [-1,1]\n"); exit(1); } // derived values unsigned int num_samples = k*num_symbols; float complex x[num_samples]; // interpolated samples float complex y[num_samples]; // received signal (with noise) float tau_hat[num_samples]; // instantaneous timing offset estimate float complex sym_out[num_symbols + 64];// synchronized symbols // create sequence of Nyquist-interpolated QPSK symbols firinterp_crcf interp = firinterp_crcf_create_prototype(ftype,k,m,beta,tau); for (i=0; i #include #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "symtrack_cccf_example.m" // print usage/help message void usage() { printf("symtrack_cccf_example [options]\n"); printf(" h : print this help file\n"); printf(" k : filter samples/symbol, default: 2\n"); printf(" m : filter delay (symbols), default: 3\n"); printf(" b : filter excess bandwidth, default: 0.5\n"); printf(" s : signal-to-noise ratio, default: 30 dB\n"); printf(" w : timing pll bandwidth, default: 0.02\n"); printf(" n : number of symbols, default: 4000\n"); } int main(int argc, char*argv[]) { // options int ftype = LIQUID_FIRFILT_ARKAISER; int ms = LIQUID_MODEM_QAM16; unsigned int k = 2; // samples per symbol unsigned int m = 7; // filter delay (symbols) float beta = 0.20f; // filter excess bandwidth factor unsigned int num_symbols = 4000; // number of data symbols unsigned int hc_len = 4; // channel filter length float noise_floor = -60.0f; // noise floor [dB] float SNRdB = 30.0f; // signal-to-noise ratio [dB] float bandwidth = 0.10f; // loop filter bandwidth float dphi = 0.02f; // carrier frequency offset [radians/sample] float phi = 2.1f; // carrier phase offset [radians] unsigned int nfft = 2400; // spectral periodogram FFT size unsigned int num_samples = 200000; // number of samples int dopt; while ((dopt = getopt(argc,argv,"hk:m:b:s:w:n:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 's': SNRdB = atof(optarg); break; case 'w': bandwidth = atof(optarg); break; case 'n': num_symbols = atoi(optarg); break; default: exit(1); } } // validate input if (k < 2) { fprintf(stderr,"error: k (samples/symbol) must be greater than 1\n"); exit(1); } else if (m < 1) { fprintf(stderr,"error: m (filter delay) must be greater than 0\n"); exit(1); } else if (beta <= 0.0f || beta > 1.0f) { fprintf(stderr,"error: beta (excess bandwidth factor) must be in (0,1]\n"); exit(1); } else if (bandwidth <= 0.0f) { fprintf(stderr,"error: timing PLL bandwidth must be greater than 0\n"); exit(1); } else if (num_symbols == 0) { fprintf(stderr,"error: number of symbols must be greater than 0\n"); exit(1); } unsigned int i; // buffers unsigned int buf_len = 800; // buffer size float complex x [buf_len]; // original signal float complex y [buf_len]; // channel output float complex syms[buf_len]; // recovered symbols // window for saving last few symbols windowcf sym_buf = windowcf_create(buf_len); // create stream generator symstreamcf gen = symstreamcf_create_linear(ftype,k,m,beta,ms); // create channel emulator and add impairments channel_cccf channel = channel_cccf_create(); channel_cccf_add_awgn (channel, noise_floor, SNRdB); channel_cccf_add_carrier_offset(channel, dphi, phi); channel_cccf_add_multipath (channel, NULL, hc_len); // create symbol tracking synchronizer symtrack_cccf symtrack = symtrack_cccf_create(ftype,k,m,beta,ms); symtrack_cccf_set_bandwidth(symtrack,bandwidth); // create spectral periodogram for estimating spectrum spgramcf periodogram = spgramcf_create_default(nfft); unsigned int total_samples = 0; unsigned int total_symbols = 0; while (total_samples < num_samples) { // write samples to buffer symstreamcf_write_samples(gen, x, buf_len); // apply channel channel_cccf_execute_block(channel, x, buf_len, y); // push resulting sample through periodogram spgramcf_write(periodogram, y, buf_len); // run resulting stream through synchronizer unsigned int num_symbols_sync; symtrack_cccf_execute_block(symtrack, y, buf_len, syms, &num_symbols_sync); total_symbols += num_symbols_sync; // write resulting symbols to window buffer for plotting windowcf_write(sym_buf, syms, num_symbols_sync); // accumulated samples total_samples += buf_len; } printf("total samples: %u\n", total_samples); printf("total symbols: %u\n", total_symbols); // write accumulated power spectral density estimate float psd[nfft]; spgramcf_get_psd(periodogram, psd); // // export output file // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s, auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); // read buffer and write last symbols to file float complex * rc; windowcf_read(sym_buf, &rc); fprintf(fid,"syms = zeros(1,%u);\n", buf_len); for (i=0; i #include "liquid.h" #define OUTPUT_FILENAME "wdelayf_example.m" int main() { unsigned int delay = 10; unsigned int num_samples = 64; // create wdelay, all elements initialized to 0 wdelayf w = wdelayf_create(delay); float y; // output FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"num_samples = %u;\n", num_samples); fprintf(fid,"delay = %u;\n", delay); // push several elements unsigned int i; float x; for (i=0; i #include "liquid.h" int main() { // initialize vector of data for testing float v[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; float *r; // reader unsigned int i; // create window: 10 elements, initialized to 0 // w: 0 0 0 0 0 0 0 0 0 0 windowf w = windowf_create(10); // push 4 elements // w: 0 0 0 0 0 0 1 1 1 1 windowf_push(w, 1); windowf_push(w, 1); windowf_push(w, 1); windowf_push(w, 1); // push 4 more elements // w: 0 0 1 1 1 1 9 8 7 6 windowf_write(w, v, 4); // push 4 more elements // w: 1 1 9 8 7 6 3 3 3 3 windowf_push(w, 3); windowf_push(w, 3); windowf_push(w, 3); windowf_push(w, 3); // read the buffer by assigning the pointer // appropriately windowf_read(w, &r); // manual print printf("manual output:\n"); for (i=0; i<10; i++) printf("%6u : %f\n", i, r[i]); windowf_debug_print(w); // clean it up windowf_destroy(w); printf("done.\n"); return 0; } liquid-dsp-1.3.1/include/000077500000000000000000000000001317124540100152105ustar00rootroot00000000000000liquid-dsp-1.3.1/include/liquid.h000066400000000000000000012251451317124540100166620ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2017 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef __LIQUID_H__ #define __LIQUID_H__ #ifdef __cplusplus extern "C" { # define LIQUID_USE_COMPLEX_H 0 #else # define LIQUID_USE_COMPLEX_H 1 #endif // __cplusplus // common headers #include // // Make sure the version and version number macros weren't defined by // some prevoiusly included header file. // #ifdef LIQUID_VERSION # undef LIQUID_VERSION #endif #ifdef LIQUID_VERSION_NUMBER # undef LIQUID_VERSION_NUMBER #endif // // Compile-time version numbers // // LIQUID_VERSION = "X.Y.Z" // LIQUID_VERSION_NUMBER = (X*1000000 + Y*1000 + Z) // #define LIQUID_VERSION "1.3.0" #define LIQUID_VERSION_NUMBER 1003000 // // Run-time library version numbers // extern const char liquid_version[]; const char * liquid_libversion(void); int liquid_libversion_number(void); // run-time library validation #define LIQUID_VALIDATE_LIBVERSION \ if (LIQUID_VERSION_NUMBER != liquid_libversion_number()) { \ fprintf(stderr,"%s:%u: ", __FILE__,__LINE__); \ fprintf(stderr,"error: invalid liquid runtime library\n"); \ exit(1); \ } \ #define LIQUID_CONCAT(prefix, name) prefix ## name #define LIQUID_VALIDATE_INPUT /* * Compile-time complex data type definitions * * Default: use the C99 complex data type, otherwise * define complex type compatible with the C++ complex standard, * otherwise resort to defining binary compatible array. */ #if LIQUID_USE_COMPLEX_H==1 # include # define LIQUID_DEFINE_COMPLEX(R,C) typedef R _Complex C #elif defined _GLIBCXX_COMPLEX || defined _LIBCPP_COMPLEX # define LIQUID_DEFINE_COMPLEX(R,C) typedef std::complex C #else # define LIQUID_DEFINE_COMPLEX(R,C) typedef struct {R real; R imag;} C; #endif //# define LIQUID_DEFINE_COMPLEX(R,C) typedef R C[2] LIQUID_DEFINE_COMPLEX(float, liquid_float_complex); LIQUID_DEFINE_COMPLEX(double, liquid_double_complex); // // MODULE : agc (automatic gain control) // // available squelch modes typedef enum { LIQUID_AGC_SQUELCH_UNKNOWN=0, // unknown/unavailable squelch mode LIQUID_AGC_SQUELCH_ENABLED, // squelch enabled but signal not detected LIQUID_AGC_SQUELCH_RISE, // signal first hit/exceeded threshold LIQUID_AGC_SQUELCH_SIGNALHI, // signal level high (above threshold) LIQUID_AGC_SQUELCH_FALL, // signal first dropped below threshold LIQUID_AGC_SQUELCH_SIGNALLO, // signal level low (below threshold) LIQUID_AGC_SQUELCH_TIMEOUT, // signal level low (below threshold for a certain time) LIQUID_AGC_SQUELCH_DISABLED, // squelch not enabled } agc_squelch_mode; #define LIQUID_AGC_MANGLE_CRCF(name) LIQUID_CONCAT(agc_crcf, name) #define LIQUID_AGC_MANGLE_RRRF(name) LIQUID_CONCAT(agc_rrrf, name) // large macro // AGC : name-mangling macro // T : primitive data type // TC : input/output data type #define LIQUID_AGC_DEFINE_API(AGC,T,TC) \ typedef struct AGC(_s) * AGC(); \ \ /* create automatic gain control object */ \ AGC() AGC(_create)(void); \ \ /* destroy object, freeing all internally-allocated memory */ \ void AGC(_destroy)(AGC() _q); \ \ /* print object properties to stdout */ \ void AGC(_print)(AGC() _q); \ \ /* reset object's internal state */ \ void AGC(_reset)(AGC() _q); \ \ /* execute automatic gain control on an single input sample */ \ /* _q : automatic gain control object */ \ /* _x : input sample */ \ /* _y : output sample */ \ void AGC(_execute)(AGC() _q, \ TC _x, \ TC * _y); \ \ /* execute automatic gain control on block of samples */ \ /* _q : automatic gain control object */ \ /* _x : input data array, [size: _n x 1] */ \ /* _n : number of input, output samples */ \ /* _y : output data array, [size: _n x 1] */ \ void AGC(_execute_block)(AGC() _q, \ TC * _x, \ unsigned int _n, \ TC * _y); \ \ /* lock/unlock gain control */ \ void AGC(_lock)( AGC() _q); \ void AGC(_unlock)(AGC() _q); \ \ /* get/set loop filter bandwidth; attack/release time */ \ float AGC(_get_bandwidth)(AGC() _q); \ void AGC(_set_bandwidth)(AGC() _q, float _bt); \ \ /* get/set signal level (linear) relative to unity energy */ \ float AGC(_get_signal_level)(AGC() _q); \ void AGC(_set_signal_level)(AGC() _q, float _signal_level); \ \ /* get/set signal level (dB) relative to unity energy */ \ float AGC(_get_rssi)(AGC() _q); \ void AGC(_set_rssi)(AGC() _q, float _rssi); \ \ /* get/set gain value (linear) relative to unity energy */ \ float AGC(_get_gain)(AGC() _q); \ void AGC(_set_gain)(AGC() _q, float _gain); \ \ /* initialize internal gain on input array */ \ /* _q : automatic gain control object */ \ /* _x : input data array, [size: _n x 1] */ \ /* _n : number of input, output samples */ \ void AGC(_init)(AGC() _q, \ TC * _x, \ unsigned int _n); \ \ /* enable squelch mode */ \ void AGC(_squelch_enable)(AGC() _q); \ \ /* disable squelch mode */ \ void AGC(_squelch_disable)(AGC() _q); \ \ /* is squelch enabled? */ \ int AGC(_squelch_is_enabled)(AGC() _q); \ \ /* set squelch threshold */ \ /* _q : automatic gain control object */ \ /* _thresh_dB : threshold for enabling squelch [dB] */ \ void AGC(_squelch_set_threshold)(AGC() _q, \ T _threshold); \ \ /* get squelch threshold [dB] */ \ T AGC(_squelch_get_threshold)(AGC() _q); \ \ /* set squelch timeout */ \ /* _q : automatic gain control object */ \ /* _timeout : timeout before enabling squelch [samples] */ \ void AGC(_squelch_set_timeout)(AGC() _q, \ unsigned int _timeout); \ \ /* get squelch timeout [samples] */ \ unsigned int AGC(_squelch_get_timeout)(AGC() _q); \ \ /* get squelch status */ \ int AGC(_squelch_get_status)(AGC() _q); \ // Define agc APIs LIQUID_AGC_DEFINE_API(LIQUID_AGC_MANGLE_CRCF, float, liquid_float_complex) LIQUID_AGC_DEFINE_API(LIQUID_AGC_MANGLE_RRRF, float, float) // // MODULE : audio // // CVSD: continuously variable slope delta typedef struct cvsd_s * cvsd; // create cvsd object // _num_bits : number of adjacent bits to observe (4 recommended) // _zeta : slope adjustment multiplier (1.5 recommended) // _alpha : pre-/post-emphasis filter coefficient (0.9 recommended) // NOTE: _alpha must be in [0,1] cvsd cvsd_create(unsigned int _num_bits, float _zeta, float _alpha); // destroy cvsd object void cvsd_destroy(cvsd _q); // print cvsd object parameters void cvsd_print(cvsd _q); // encode/decode single sample unsigned char cvsd_encode(cvsd _q, float _audio_sample); float cvsd_decode(cvsd _q, unsigned char _bit); // encode/decode 8 samples at a time void cvsd_encode8(cvsd _q, float * _audio, unsigned char * _data); void cvsd_decode8(cvsd _q, unsigned char _data, float * _audio); // // MODULE : buffer // // circular buffer #define LIQUID_CBUFFER_MANGLE_FLOAT(name) LIQUID_CONCAT(cbufferf, name) #define LIQUID_CBUFFER_MANGLE_CFLOAT(name) LIQUID_CONCAT(cbuffercf, name) // large macro // CBUFFER : name-mangling macro // T : data type #define LIQUID_CBUFFER_DEFINE_API(CBUFFER,T) \ typedef struct CBUFFER(_s) * CBUFFER(); \ \ /* create circular buffer object of a particular size */ \ /* _max_size : maximum buffer size, _max_size > 0 */ \ CBUFFER() CBUFFER(_create)(unsigned int _max_size); \ \ /* create circular buffer object of a particular size and */ \ /* specify the maximum number of elements that can be read */ \ /* at any given time. */ \ /* _max_size : maximum buffer size, _max_size > 0 */ \ /* _max_read : maximum size that will be read from buffer */ \ CBUFFER() CBUFFER(_create_max)(unsigned int _max_size, \ unsigned int _max_read); \ \ /* destroy cbuffer object, freeing all internal memory */ \ void CBUFFER(_destroy)(CBUFFER() _q); \ \ /* print cbuffer object properties */ \ void CBUFFER(_print)(CBUFFER() _q); \ \ /* print cbuffer object properties and internal state */ \ void CBUFFER(_debug_print)(CBUFFER() _q); \ \ /* clear internal buffer */ \ void CBUFFER(_reset)(CBUFFER() _q); \ \ /* get the number of elements currently in the buffer */ \ unsigned int CBUFFER(_size)(CBUFFER() _q); \ \ /* get the maximum number of elements the buffer can hold */ \ unsigned int CBUFFER(_max_size)(CBUFFER() _q); \ \ /* get the maximum number of elements you may read at once */ \ unsigned int CBUFFER(_max_read)(CBUFFER() _q); \ \ /* get the number of available slots (max_size - size) */ \ unsigned int CBUFFER(_space_available)(CBUFFER() _q); \ \ /* is buffer full? */ \ int CBUFFER(_is_full)(CBUFFER() _q); \ \ /* write a single sample into the buffer */ \ /* _q : circular buffer object */ \ /* _v : input sample */ \ void CBUFFER(_push)(CBUFFER() _q, \ T _v); \ \ /* write samples to the buffer */ \ /* _q : circular buffer object */ \ /* _v : output array */ \ /* _n : number of samples to write */ \ void CBUFFER(_write)(CBUFFER() _q, \ T * _v, \ unsigned int _n); \ \ /* remove and return a single element from the buffer */ \ /* _q : circular buffer object */ \ /* _v : pointer to sample output */ \ void CBUFFER(_pop)(CBUFFER() _q, \ T * _v); \ \ /* read buffer contents */ \ /* _q : circular buffer object */ \ /* _num_requested : number of elements requested */ \ /* _v : output pointer */ \ /* _num_read : number of elements referenced by _v */ \ void CBUFFER(_read)(CBUFFER() _q, \ unsigned int _num_requested, \ T ** _v, \ unsigned int * _num_read); \ \ /* release _n samples from the buffer */ \ /* _q : circular buffer object */ \ /* _n : number of elements to release */ \ void CBUFFER(_release)(CBUFFER() _q, \ unsigned int _n); \ // Define buffer APIs LIQUID_CBUFFER_DEFINE_API(LIQUID_CBUFFER_MANGLE_FLOAT, float) LIQUID_CBUFFER_DEFINE_API(LIQUID_CBUFFER_MANGLE_CFLOAT, liquid_float_complex) // Windowing functions #define LIQUID_WINDOW_MANGLE_FLOAT(name) LIQUID_CONCAT(windowf, name) #define LIQUID_WINDOW_MANGLE_CFLOAT(name) LIQUID_CONCAT(windowcf, name) // large macro // WINDOW : name-mangling macro // T : data type #define LIQUID_WINDOW_DEFINE_API(WINDOW,T) \ \ typedef struct WINDOW(_s) * WINDOW(); \ \ /* create window buffer object of length _n */ \ WINDOW() WINDOW(_create)(unsigned int _n); \ \ /* recreate window buffer object with new length */ \ /* _q : old window object */ \ /* _n : new window length */ \ WINDOW() WINDOW(_recreate)(WINDOW() _q, unsigned int _n); \ \ /* destroy window object, freeing all internally memory */ \ void WINDOW(_destroy)(WINDOW() _q); \ \ /* print window object to stdout */ \ void WINDOW(_print)(WINDOW() _q); \ \ /* print window object to stdout (with extra information) */ \ void WINDOW(_debug_print)(WINDOW() _q); \ \ /* reset window object (initialize to zeros) */ \ void WINDOW(_reset)(WINDOW() _q); \ \ /* read window buffer contents */ \ /* _q : window object */ \ /* _v : output pointer (set to internal array) */ \ void WINDOW(_read)(WINDOW() _q, T ** _v); \ \ /* index single element in buffer at a particular index */ \ /* _q : window object */ \ /* _i : index of element to read */ \ /* _v : output value pointer */ \ void WINDOW(_index)(WINDOW() _q, \ unsigned int _i, \ T * _v); \ \ /* push single element onto window buffer */ \ /* _q : window object */ \ /* _v : single input element */ \ void WINDOW(_push)(WINDOW() _q, \ T _v); \ \ /* write array of elements onto window buffer */ \ /* _q : window object */ \ /* _v : input array of values to write */ \ /* _n : number of input values to write */ \ void WINDOW(_write)(WINDOW() _q, \ T * _v, \ unsigned int _n); \ // Define window APIs LIQUID_WINDOW_DEFINE_API(LIQUID_WINDOW_MANGLE_FLOAT, float) LIQUID_WINDOW_DEFINE_API(LIQUID_WINDOW_MANGLE_CFLOAT, liquid_float_complex) //LIQUID_WINDOW_DEFINE_API(LIQUID_WINDOW_MANGLE_UINT, unsigned int) // wdelay functions : windowed-delay // Implements an efficient z^-k delay with minimal memory #define LIQUID_WDELAY_MANGLE_FLOAT(name) LIQUID_CONCAT(wdelayf, name) #define LIQUID_WDELAY_MANGLE_CFLOAT(name) LIQUID_CONCAT(wdelaycf, name) //#define LIQUID_WDELAY_MANGLE_UINT(name) LIQUID_CONCAT(wdelayui, name) // large macro // WDELAY : name-mangling macro // T : data type #define LIQUID_WDELAY_DEFINE_API(WDELAY,T) \ typedef struct WDELAY(_s) * WDELAY(); \ \ /* create delay buffer object with '_delay' samples */ \ WDELAY() WDELAY(_create)(unsigned int _delay); \ \ /* re-create delay buffer object with '_delay' samples */ \ /* _q : old delay buffer object */ \ /* _delay : delay for new object */ \ WDELAY() WDELAY(_recreate)(WDELAY() _q, \ unsigned int _delay); \ \ /* destroy delay buffer object, freeing internal memory */ \ void WDELAY(_destroy)(WDELAY() _q); \ \ /* print delay buffer object's state to stdout */ \ void WDELAY(_print)(WDELAY() _q); \ \ /* clear/reset state of object */ \ void WDELAY(_reset)(WDELAY() _q); \ \ /* read delayed sample from delay buffer object */ \ /* _q : delay buffer object */ \ /* _v : value of delayed element */ \ void WDELAY(_read)(WDELAY() _q, \ T * _v); \ \ /* push new sample into delay buffer object */ \ /* _q : delay buffer object */ \ /* _v : new value to be added to buffer */ \ void WDELAY(_push)(WDELAY() _q, \ T _v); \ // Define wdelay APIs LIQUID_WDELAY_DEFINE_API(LIQUID_WDELAY_MANGLE_FLOAT, float) LIQUID_WDELAY_DEFINE_API(LIQUID_WDELAY_MANGLE_CFLOAT, liquid_float_complex) //LIQUID_WDELAY_DEFINE_API(LIQUID_WDELAY_MANGLE_UINT, unsigned int) // // MODULE : channel // #define LIQUID_CHANNEL_MANGLE_CCCF(name) LIQUID_CONCAT(channel_cccf,name) // large macro // CHANNEL : name-mangling macro // TO : output data type // TC : coefficients data type // TI : input data type #define LIQUID_CHANNEL_DEFINE_API(CHANNEL,TO,TC,TI) \ \ typedef struct CHANNEL(_s) * CHANNEL(); \ \ /* create channel object with default parameters */ \ CHANNEL() CHANNEL(_create)(void); \ \ /* destroy channel object, freeing all internal memory */ \ void CHANNEL(_destroy)(CHANNEL() _q); \ \ /* print channel object internals to standard output */ \ void CHANNEL(_print)(CHANNEL() _q); \ \ /* apply additive white Gausss noise impairment */ \ /* _q : channel object */ \ /* _N0dB : noise floor power spectral density [dB] */ \ /* _SNRdB : signal-to-noise ratio [dB] */ \ void CHANNEL(_add_awgn)(CHANNEL() _q, \ float _N0dB, \ float _SNRdB); \ \ /* apply carrier offset impairment */ \ /* _q : channel object */ \ /* _frequency : carrier frequency offset [radians/sample] */ \ /* _phase : carrier phase offset [radians] */ \ void CHANNEL(_add_carrier_offset)(CHANNEL() _q, \ float _frequency, \ float _phase); \ \ /* apply multi-path channel impairment */ \ /* _q : channel object */ \ /* _h : channel coefficients (NULL for random) */ \ /* _h_len : number of channel coefficients */ \ void CHANNEL(_add_multipath)(CHANNEL() _q, \ TC * _h, \ unsigned int _h_len); \ \ /* apply slowly-varying shadowing impairment */ \ /* _q : channel object */ \ /* _sigma : std. deviation for log-normal shadowing */ \ /* _fd : Doppler frequency, _fd in (0,0.5) */ \ void CHANNEL(_add_shadowing)(CHANNEL() _q, \ float _sigma, \ float _fd); \ \ /* apply channel impairments on single input sample */ \ /* _q : channel object */ \ /* _x : input sample */ \ /* _y : pointer to output sample */ \ void CHANNEL(_execute)(CHANNEL() _q, \ TI _x, \ TO * _y); \ \ /* apply channel impairments on block of samples */ \ /* _q : channel object */ \ /* _x : input array, [size: _n x 1] */ \ /* _n : input array, length */ \ /* _y : output array, [size: _n x 1] */ \ void CHANNEL(_execute_block)(CHANNEL() _q, \ TI * _x, \ unsigned int _n, \ TO * _y); \ LIQUID_CHANNEL_DEFINE_API(LIQUID_CHANNEL_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // // time-varying multi-path channel // #define LIQUID_TVMPCH_MANGLE_CCCF(name) LIQUID_CONCAT(tvmpch_cccf,name) // large macro // TVMPCH : name-mangling macro // TO : output data type // TC : coefficients data type // TI : input data type #define LIQUID_TVMPCH_DEFINE_API(TVMPCH,TO,TC,TI) \ \ typedef struct TVMPCH(_s) * TVMPCH(); \ \ /* create channel object with default parameters */ \ /* create time-varying multi-path channel emulator object */ \ /* _n : number of coefficients, _n > 0 */ \ /* _std : standard deviation */ \ /* _tau : coherence time */ \ TVMPCH() TVMPCH(_create)(unsigned int _n, \ float _std, \ float _tau); \ \ /* destroy channel object, freeing all internal memory */ \ void TVMPCH(_destroy)(TVMPCH() _q); \ \ /* reset object */ \ void TVMPCH(_reset)(TVMPCH() _q); \ \ /* print channel object internals to standard output */ \ void TVMPCH(_print)(TVMPCH() _q); \ \ /* push sample into emulator */ \ /* _q : channel object */ \ /* _x : input sample */ \ void TVMPCH(_push)(TVMPCH() _q, \ TI _x); \ \ /* compute output sample */ \ /* _q : channel object */ \ /* _y : output sample */ \ void TVMPCH(_execute)(TVMPCH() _q, \ TO * _y); \ \ /* apply channel impairments on a block of samples */ \ /* _q : channel object */ \ /* _x : input array [size: _nx x 1] */ \ /* _nx : input array length */ \ /* _y : output array */ \ void TVMPCH(_execute_block)(TVMPCH() _q, \ TI * _x, \ unsigned int _nx, \ TO * _y); \ LIQUID_TVMPCH_DEFINE_API(LIQUID_TVMPCH_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // // MODULE : dotprod (vector dot product) // #define LIQUID_DOTPROD_MANGLE_RRRF(name) LIQUID_CONCAT(dotprod_rrrf,name) #define LIQUID_DOTPROD_MANGLE_CCCF(name) LIQUID_CONCAT(dotprod_cccf,name) #define LIQUID_DOTPROD_MANGLE_CRCF(name) LIQUID_CONCAT(dotprod_crcf,name) // large macro // DOTPROD : name-mangling macro // TO : output data type // TC : coefficients data type // TI : input data type #define LIQUID_DOTPROD_DEFINE_API(DOTPROD,TO,TC,TI) \ \ /* run dot product without creating object [unrolled loop] */ \ /* _v : coefficients array [size: _n x 1] */ \ /* _x : input array [size: _n x 1] */ \ /* _n : dotprod length, _n > 0 */ \ /* _y : output sample pointer */ \ void DOTPROD(_run)( TC *_v, TI *_x, unsigned int _n, TO *_y); \ void DOTPROD(_run4)(TC *_v, TI *_x, unsigned int _n, TO *_y); \ \ typedef struct DOTPROD(_s) * DOTPROD(); \ \ /* create dot product object */ \ /* _v : coefficients array [size: _n x 1] */ \ /* _n : dotprod length, _n > 0 */ \ DOTPROD() DOTPROD(_create)(TC * _v, \ unsigned int _n); \ \ /* re-create dot product object */ \ /* _q : old dotprod object */ \ /* _v : coefficients array [size: _n x 1] */ \ /* _n : dotprod length, _n > 0 */ \ DOTPROD() DOTPROD(_recreate)(DOTPROD() _q, \ TC * _v, \ unsigned int _n); \ \ /* destroy dotprod object, freeing all internal memory */ \ void DOTPROD(_destroy)(DOTPROD() _q); \ \ /* print dotprod object internals to standard output */ \ void DOTPROD(_print)(DOTPROD() _q); \ \ /* execute dot product */ \ /* _q : dotprod object */ \ /* _x : input array [size: _n x 1] */ \ /* _y : output sample pointer */ \ void DOTPROD(_execute)(DOTPROD() _q, \ TI * _x, \ TO * _y); \ LIQUID_DOTPROD_DEFINE_API(LIQUID_DOTPROD_MANGLE_RRRF, float, float, float) LIQUID_DOTPROD_DEFINE_API(LIQUID_DOTPROD_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) LIQUID_DOTPROD_DEFINE_API(LIQUID_DOTPROD_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) // // sum squared methods // float liquid_sumsqf(float * _v, unsigned int _n); float liquid_sumsqcf(liquid_float_complex * _v, unsigned int _n); // // MODULE : equalization // // least mean-squares (LMS) #define LIQUID_EQLMS_MANGLE_RRRF(name) LIQUID_CONCAT(eqlms_rrrf,name) #define LIQUID_EQLMS_MANGLE_CCCF(name) LIQUID_CONCAT(eqlms_cccf,name) // large macro // EQLMS : name-mangling macro // T : data type #define LIQUID_EQLMS_DEFINE_API(EQLMS,T) \ typedef struct EQLMS(_s) * EQLMS(); \ \ /* create LMS EQ initialized with external coefficients */ \ /* _h : filter coefficients (NULL for {1,0,0...}) */ \ /* _h_len : filter length */ \ EQLMS() EQLMS(_create)(T * _h, \ unsigned int _h_len); \ \ /* create LMS EQ initialized with square-root Nyquist */ \ /* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \ /* _k : samples/symbol */ \ /* _m : filter delay (symbols) */ \ /* _beta : rolloff factor (0 < beta <= 1) */ \ /* _dt : fractional sample delay */ \ EQLMS() EQLMS(_create_rnyquist)(int _type, \ unsigned int _k, \ unsigned int _m, \ float _beta, \ float _dt); \ \ /* create LMS EQ initialized with low-pass filter */ \ /* _h_len : filter length */ \ /* _fc : filter cut-off, _fc in (0,0.5] */ \ EQLMS() EQLMS(_create_lowpass)(unsigned int _h_len, \ float _fc); \ \ /* re-create EQ initialized with external coefficients */ \ /* _q : equalizer object */ \ /* _h : filter coefficients (NULL for {1,0,0...}) */ \ /* _h_len : filter length */ \ EQLMS() EQLMS(_recreate)(EQLMS() _q, \ T * _h, \ unsigned int _h_len); \ \ /* destroy equalizer object, freeing all internal memory */ \ void EQLMS(_destroy)(EQLMS() _q); \ \ /* reset equalizer object, clearing internal state */ \ void EQLMS(_reset)(EQLMS() _q); \ \ /* print equalizer internal state */ \ void EQLMS(_print)(EQLMS() _q); \ \ /* get/set equalizer learning rate */ \ float EQLMS(_get_bw)(EQLMS() _q); \ void EQLMS(_set_bw)(EQLMS() _q, \ float _lambda); \ \ /* push sample into equalizer internal buffer */ \ void EQLMS(_push)(EQLMS() _q, \ T _x); \ \ /* push sample into equalizer internal buffer as block */ \ /* _q : equalizer object */ \ /* _x : input sample array */ \ /* _n : input sample array length */ \ void EQLMS(_push_block)(EQLMS() _q, \ T * _x, \ unsigned int _n); \ \ /* execute internal dot product and return result */ \ /* _q : equalizer object */ \ /* _y : output sample */ \ void EQLMS(_execute)(EQLMS() _q, \ T * _y); \ \ /* execute equalizer with block of samples using constant */ \ /* modulus algorithm, operating on a decimation rate of _k */ \ /* samples. */ \ /* _q : equalizer object */ \ /* _k : down-sampling rate */ \ /* _x : input sample array [size: _n x 1] */ \ /* _n : input sample array length */ \ /* _y : output sample array [size: _n x 1] */ \ void EQLMS(_execute_block)(EQLMS() _q, \ unsigned int _k, \ T * _x, \ unsigned int _n, \ T * _y); \ \ /* step through one cycle of equalizer training */ \ /* _q : equalizer object */ \ /* _d : desired output */ \ /* _d_hat : actual output */ \ void EQLMS(_step)(EQLMS() _q, \ T _d, \ T _d_hat); \ \ /* step through one cycle of equalizer training (blind) */ \ /* _q : equalizer object */ \ /* _d_hat : actual output */ \ void EQLMS(_step_blind)(EQLMS() _q, \ T _d_hat); \ \ /* get equalizer's internal coefficients */ \ /* _q : equalizer object */ \ /* _w : weights [size: _p x 1] */ \ void EQLMS(_get_weights)(EQLMS() _q, \ T * _w); \ \ /* train equalizer object on group of samples */ \ /* _q : equalizer object */ \ /* _w : input/output weights [size: _p x 1] */ \ /* _x : received sample vector [size: _n x 1] */ \ /* _d : desired output vector [size: _n x 1] */ \ /* _n : input, output vector length */ \ void EQLMS(_train)(EQLMS() _q, \ T * _w, \ T * _x, \ T * _d, \ unsigned int _n); \ LIQUID_EQLMS_DEFINE_API(LIQUID_EQLMS_MANGLE_RRRF, float) LIQUID_EQLMS_DEFINE_API(LIQUID_EQLMS_MANGLE_CCCF, liquid_float_complex) // recursive least-squares (RLS) #define LIQUID_EQRLS_MANGLE_RRRF(name) LIQUID_CONCAT(eqrls_rrrf,name) #define LIQUID_EQRLS_MANGLE_CCCF(name) LIQUID_CONCAT(eqrls_cccf,name) // large macro // EQRLS : name-mangling macro // T : data type #define LIQUID_EQRLS_DEFINE_API(EQRLS,T) \ typedef struct EQRLS(_s) * EQRLS(); \ \ /* create RLS EQ initialized with external coefficients */ \ /* _h : filter coefficients (NULL for {1,0,0...}) */ \ /* _p : filter length */ \ EQRLS() EQRLS(_create)(T * _h, \ unsigned int _p); \ \ /* re-create RLS EQ initialized with external coefficients */ \ /* _q : initial equalizer object */ \ /* _h : filter coefficients (NULL for {1,0,0...}) */ \ /* _p : filter length */ \ EQRLS() EQRLS(_recreate)(EQRLS() _q, \ T * _h, \ unsigned int _p); \ \ /* destroy equalizer object, freeing all internal memory */ \ void EQRLS(_destroy)(EQRLS() _q); \ \ /* print equalizer internal state */ \ void EQRLS(_print)(EQRLS() _q); \ \ /* reset equalizer object, clearing internal state */ \ void EQRLS(_reset)(EQRLS() _q); \ \ /* get/set equalizer learning rate */ \ float EQRLS(_get_bw)(EQRLS() _q); \ void EQRLS(_set_bw)(EQRLS() _q, \ float _mu); \ \ /* push sample into equalizer internal buffer */ \ void EQRLS(_push)(EQRLS() _q, T _x); \ \ /* execute internal dot product and return result */ \ /* _q : equalizer object */ \ /* _y : output sample */ \ void EQRLS(_execute)(EQRLS() _q, T * _y); \ \ /* step through one cycle of equalizer training */ \ /* _q : equalizer object */ \ /* _d : desired output */ \ /* _d_hat : actual output */ \ void EQRLS(_step)(EQRLS() _q, T _d, T _d_hat); \ \ /* retrieve internal filter coefficients */ \ /* _q : equalizer object */ \ /* _w : weights [size: _p x 1] */ \ void EQRLS(_get_weights)(EQRLS() _q, \ T * _w); \ \ /* train equalizer object on group of samples */ \ /* _q : equalizer object */ \ /* _w : input/output weights [size: _p x 1] */ \ /* _x : received sample vector [size: _n x 1] */ \ /* _d : desired output vector [size: _n x 1] */ \ /* _n : input, output vector length */ \ void EQRLS(_train)(EQRLS() _q, \ T * _w, \ T * _x, \ T * _d, \ unsigned int _n); \ LIQUID_EQRLS_DEFINE_API(LIQUID_EQRLS_MANGLE_RRRF, float) LIQUID_EQRLS_DEFINE_API(LIQUID_EQRLS_MANGLE_CCCF, liquid_float_complex) // // MODULE : fec (forward error-correction) // // soft bit values #define LIQUID_SOFTBIT_0 (0) #define LIQUID_SOFTBIT_1 (255) #define LIQUID_SOFTBIT_ERASURE (127) // available CRC schemes #define LIQUID_CRC_NUM_SCHEMES 7 typedef enum { LIQUID_CRC_UNKNOWN=0, // unknown/unavailable CRC scheme LIQUID_CRC_NONE, // no error-detection LIQUID_CRC_CHECKSUM, // 8-bit checksum LIQUID_CRC_8, // 8-bit CRC LIQUID_CRC_16, // 16-bit CRC LIQUID_CRC_24, // 24-bit CRC LIQUID_CRC_32 // 32-bit CRC } crc_scheme; // pretty names for crc schemes extern const char * crc_scheme_str[LIQUID_CRC_NUM_SCHEMES][2]; // Print compact list of existing and available CRC schemes void liquid_print_crc_schemes(); // returns crc_scheme based on input string crc_scheme liquid_getopt_str2crc(const char * _str); // get length of CRC (bytes) unsigned int crc_get_length(crc_scheme _scheme); // generate error-detection key // _scheme : error-detection scheme // _msg : input data message, [size: _n x 1] // _n : input data message size unsigned int crc_generate_key(crc_scheme _scheme, unsigned char * _msg, unsigned int _n); // generate error-detection key and append to end of message // _scheme : error-detection scheme (resulting in 'p' bytes) // _msg : input data message, [size: _n+p x 1] // _n : input data message size (excluding key at end) void crc_append_key(crc_scheme _scheme, unsigned char * _msg, unsigned int _n); // validate message using error-detection key // _scheme : error-detection scheme // _msg : input data message, [size: _n x 1] // _n : input data message size // _key : error-detection key int crc_validate_message(crc_scheme _scheme, unsigned char * _msg, unsigned int _n, unsigned int _key); // check message with key appended to end of array // _scheme : error-detection scheme (resulting in 'p' bytes) // _msg : input data message, [size: _n+p x 1] // _n : input data message size (excluding key at end) int crc_check_key(crc_scheme _scheme, unsigned char * _msg, unsigned int _n); // get size of key (bytes) unsigned int crc_sizeof_key(crc_scheme _scheme); // available FEC schemes #define LIQUID_FEC_NUM_SCHEMES 28 typedef enum { LIQUID_FEC_UNKNOWN=0, // unknown/unsupported scheme LIQUID_FEC_NONE, // no error-correction LIQUID_FEC_REP3, // simple repeat code, r1/3 LIQUID_FEC_REP5, // simple repeat code, r1/5 LIQUID_FEC_HAMMING74, // Hamming (7,4) block code, r1/2 (really 4/7) LIQUID_FEC_HAMMING84, // Hamming (7,4) with extra parity bit, r1/2 LIQUID_FEC_HAMMING128, // Hamming (12,8) block code, r2/3 LIQUID_FEC_GOLAY2412, // Golay (24,12) block code, r1/2 LIQUID_FEC_SECDED2216, // SEC-DED (22,16) block code, r8/11 LIQUID_FEC_SECDED3932, // SEC-DED (39,32) block code LIQUID_FEC_SECDED7264, // SEC-DED (72,64) block code, r8/9 // codecs not defined internally (see http://www.ka9q.net/code/fec/) LIQUID_FEC_CONV_V27, // r1/2, K=7, dfree=10 LIQUID_FEC_CONV_V29, // r1/2, K=9, dfree=12 LIQUID_FEC_CONV_V39, // r1/3, K=9, dfree=18 LIQUID_FEC_CONV_V615, // r1/6, K=15, dfree<=57 (Heller 1968) // punctured (perforated) codes LIQUID_FEC_CONV_V27P23, // r2/3, K=7, dfree=6 LIQUID_FEC_CONV_V27P34, // r3/4, K=7, dfree=5 LIQUID_FEC_CONV_V27P45, // r4/5, K=7, dfree=4 LIQUID_FEC_CONV_V27P56, // r5/6, K=7, dfree=4 LIQUID_FEC_CONV_V27P67, // r6/7, K=7, dfree=3 LIQUID_FEC_CONV_V27P78, // r7/8, K=7, dfree=3 LIQUID_FEC_CONV_V29P23, // r2/3, K=9, dfree=7 LIQUID_FEC_CONV_V29P34, // r3/4, K=9, dfree=6 LIQUID_FEC_CONV_V29P45, // r4/5, K=9, dfree=5 LIQUID_FEC_CONV_V29P56, // r5/6, K=9, dfree=5 LIQUID_FEC_CONV_V29P67, // r6/7, K=9, dfree=4 LIQUID_FEC_CONV_V29P78, // r7/8, K=9, dfree=4 // Reed-Solomon codes LIQUID_FEC_RS_M8 // m=8, n=255, k=223 } fec_scheme; // pretty names for fec schemes extern const char * fec_scheme_str[LIQUID_FEC_NUM_SCHEMES][2]; // Print compact list of existing and available FEC schemes void liquid_print_fec_schemes(); // returns fec_scheme based on input string fec_scheme liquid_getopt_str2fec(const char * _str); // fec object (pointer to fec structure) typedef struct fec_s * fec; // return the encoded message length using a particular error- // correction scheme (object-independent method) // _scheme : forward error-correction scheme // _msg_len : raw, uncoded message length unsigned int fec_get_enc_msg_length(fec_scheme _scheme, unsigned int _msg_len); // get the theoretical rate of a particular forward error- // correction scheme (object-independent method) float fec_get_rate(fec_scheme _scheme); // create a fec object of a particular scheme // _scheme : error-correction scheme // _opts : (ignored) fec fec_create(fec_scheme _scheme, void *_opts); // recreate fec object // _q : old fec object // _scheme : new error-correction scheme // _opts : (ignored) fec fec_recreate(fec _q, fec_scheme _scheme, void *_opts); // destroy fec object void fec_destroy(fec _q); // print fec object internals void fec_print(fec _q); // encode a block of data using a fec scheme // _q : fec object // _dec_msg_len : decoded message length // _msg_dec : decoded message // _msg_enc : encoded message void fec_encode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_dec, unsigned char * _msg_enc); // decode a block of data using a fec scheme // _q : fec object // _dec_msg_len : decoded message length // _msg_enc : encoded message // _msg_dec : decoded message void fec_decode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); // decode a block of data using a fec scheme (soft decision) // _q : fec object // _dec_msg_len : decoded message length // _msg_enc : encoded message (soft bits) // _msg_dec : decoded message void fec_decode_soft(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); // // Packetizer // // computes the number of encoded bytes after packetizing // // _n : number of uncoded input bytes // _crc : error-detecting scheme // _fec0 : inner forward error-correction code // _fec1 : outer forward error-correction code unsigned int packetizer_compute_enc_msg_len(unsigned int _n, int _crc, int _fec0, int _fec1); // computes the number of decoded bytes before packetizing // // _k : number of encoded bytes // _crc : error-detecting scheme // _fec0 : inner forward error-correction code // _fec1 : outer forward error-correction code unsigned int packetizer_compute_dec_msg_len(unsigned int _k, int _crc, int _fec0, int _fec1); typedef struct packetizer_s * packetizer; // create packetizer object // // _n : number of uncoded input bytes // _crc : error-detecting scheme // _fec0 : inner forward error-correction code // _fec1 : outer forward error-correction code packetizer packetizer_create(unsigned int _dec_msg_len, int _crc, int _fec0, int _fec1); // re-create packetizer object // // _p : initialz packetizer object // _n : number of uncoded input bytes // _crc : error-detecting scheme // _fec0 : inner forward error-correction code // _fec1 : outer forward error-correction code packetizer packetizer_recreate(packetizer _p, unsigned int _dec_msg_len, int _crc, int _fec0, int _fec1); // destroy packetizer object void packetizer_destroy(packetizer _p); // print packetizer object internals void packetizer_print(packetizer _p); // access methods unsigned int packetizer_get_dec_msg_len(packetizer _p); unsigned int packetizer_get_enc_msg_len(packetizer _p); crc_scheme packetizer_get_crc (packetizer _p); fec_scheme packetizer_get_fec0 (packetizer _p); fec_scheme packetizer_get_fec1 (packetizer _p); // Execute the packetizer on an input message // // _p : packetizer object // _msg : input message (uncoded bytes) // _pkt : encoded output message void packetizer_encode(packetizer _p, const unsigned char * _msg, unsigned char * _pkt); // Execute the packetizer to decode an input message, return validity // check of resulting data // // _p : packetizer object // _pkt : input message (coded bytes) // _msg : decoded output message int packetizer_decode(packetizer _p, const unsigned char * _pkt, unsigned char * _msg); // Execute the packetizer to decode an input message, return validity // check of resulting data // // _p : packetizer object // _pkt : input message (coded soft bits) // _msg : decoded output message int packetizer_decode_soft(packetizer _p, const unsigned char * _pkt, unsigned char * _msg); // // interleaver // typedef struct interleaver_s * interleaver; // create interleaver // _n : number of bytes interleaver interleaver_create(unsigned int _n); // destroy interleaver object void interleaver_destroy(interleaver _q); // print interleaver object internals void interleaver_print(interleaver _q); // set depth (number of internal iterations) // _q : interleaver object // _depth : depth void interleaver_set_depth(interleaver _q, unsigned int _depth); // execute forward interleaver (encoder) // _q : interleaver object // _msg_dec : decoded (un-interleaved) message // _msg_enc : encoded (interleaved) message void interleaver_encode(interleaver _q, unsigned char * _msg_dec, unsigned char * _msg_enc); // execute forward interleaver (encoder) on soft bits // _q : interleaver object // _msg_dec : decoded (un-interleaved) message // _msg_enc : encoded (interleaved) message void interleaver_encode_soft(interleaver _q, unsigned char * _msg_dec, unsigned char * _msg_enc); // execute reverse interleaver (decoder) // _q : interleaver object // _msg_enc : encoded (interleaved) message // _msg_dec : decoded (un-interleaved) message void interleaver_decode(interleaver _q, unsigned char * _msg_enc, unsigned char * _msg_dec); // execute reverse interleaver (decoder) on soft bits // _q : interleaver object // _msg_enc : encoded (interleaved) message // _msg_dec : decoded (un-interleaved) message void interleaver_decode_soft(interleaver _q, unsigned char * _msg_enc, unsigned char * _msg_dec); // // MODULE : fft (fast Fourier transform) // // type of transform typedef enum { LIQUID_FFT_UNKNOWN = 0, // unknown transform type // regular complex one-dimensional transforms LIQUID_FFT_FORWARD = +1, // complex one-dimensional FFT LIQUID_FFT_BACKWARD = -1, // complex one-dimensional inverse FFT // discrete cosine transforms LIQUID_FFT_REDFT00 = 10, // real one-dimensional DCT-I LIQUID_FFT_REDFT10 = 11, // real one-dimensional DCT-II LIQUID_FFT_REDFT01 = 12, // real one-dimensional DCT-III LIQUID_FFT_REDFT11 = 13, // real one-dimensional DCT-IV // discrete sine transforms LIQUID_FFT_RODFT00 = 20, // real one-dimensional DST-I LIQUID_FFT_RODFT10 = 21, // real one-dimensional DST-II LIQUID_FFT_RODFT01 = 22, // real one-dimensional DST-III LIQUID_FFT_RODFT11 = 23, // real one-dimensional DST-IV // modified discrete cosine transform LIQUID_FFT_MDCT = 30, // MDCT LIQUID_FFT_IMDCT = 31, // IMDCT } liquid_fft_type; #define LIQUID_FFT_MANGLE_FLOAT(name) LIQUID_CONCAT(fft,name) // Macro : FFT // FFT : name-mangling macro // T : primitive data type // TC : primitive data type (complex) #define LIQUID_FFT_DEFINE_API(FFT,T,TC) \ \ typedef struct FFT(plan_s) * FFT(plan); \ \ /* create regular complex one-dimensional transform */ \ /* _n : transform size */ \ /* _x : pointer to input array [size: _n x 1] */ \ /* _y : pointer to output array [size: _n x 1] */ \ /* _dir : direction (e.g. LIQUID_FFT_FORWARD) */ \ /* _flags : options, optimization */ \ FFT(plan) FFT(_create_plan)(unsigned int _n, \ TC * _x, \ TC * _y, \ int _dir, \ int _flags); \ \ /* create real-to-real transform */ \ /* _n : transform size */ \ /* _x : pointer to input array [size: _n x 1] */ \ /* _y : pointer to output array [size: _n x 1] */ \ /* _type : transform type (e.g. LIQUID_FFT_REDFT00) */ \ /* _flags : options, optimization */ \ FFT(plan) FFT(_create_plan_r2r_1d)(unsigned int _n, \ T * _x, \ T * _y, \ int _type, \ int _flags); \ \ /* destroy transform */ \ void FFT(_destroy_plan)(FFT(plan) _p); \ \ /* print transform plan and internal strategy */ \ void FFT(_print_plan)(FFT(plan) _p); \ \ /* run the transform */ \ void FFT(_execute)(FFT(plan) _p); \ \ /* object-independent methods */ \ \ /* perform n-point FFT allocating plan internally */ \ /* _nfft : fft size */ \ /* _x : input array [size: _nfft x 1] */ \ /* _y : output array [size: _nfft x 1] */ \ /* _dir : fft direction: LIQUID_FFT_{FORWARD,BACKWARD} */ \ /* _flags : fft flags */ \ void FFT(_run)(unsigned int _n, \ TC * _x, \ TC * _y, \ int _dir, \ int _flags); \ \ /* perform n-point real FFT allocating plan internally */ \ /* _nfft : fft size */ \ /* _x : input array [size: _nfft x 1] */ \ /* _y : output array [size: _nfft x 1] */ \ /* _type : fft type, e.g. LIQUID_FFT_REDFT10 */ \ /* _flags : fft flags */ \ void FFT(_r2r_1d_run)(unsigned int _n, \ T * _x, \ T * _y, \ int _type, \ int _flags); \ \ /* perform _n-point fft shift */ \ void FFT(_shift)(TC * _x, \ unsigned int _n); \ LIQUID_FFT_DEFINE_API(LIQUID_FFT_MANGLE_FLOAT,float,liquid_float_complex) // antiquated fft methods // FFT(plan) FFT(_create_plan_mdct)(unsigned int _n, // T * _x, // T * _y, // int _kind, // int _flags); // // spectral periodogram // #define LIQUID_SPGRAM_MANGLE_CFLOAT(name) LIQUID_CONCAT(spgramcf,name) #define LIQUID_SPGRAM_MANGLE_FLOAT(name) LIQUID_CONCAT(spgramf, name) // Macro : SPGRAM // SPGRAM : name-mangling macro // T : primitive data type // TC : primitive data type (complex) // TI : primitive data type (input) #define LIQUID_SPGRAM_DEFINE_API(SPGRAM,T,TC,TI) \ \ typedef struct SPGRAM(_s) * SPGRAM(); \ \ /* create spgram object */ \ /* _nfft : FFT size */ \ /* _wtype : window type, e.g. LIQUID_WINDOW_HAMMING */ \ /* _window_len : window length, _window_len in [1,_nfft] */ \ /* _delay : delay between transforms, _delay > 0 */ \ SPGRAM() SPGRAM(_create)(unsigned int _nfft, \ int _wtype, \ unsigned int _window_len, \ unsigned int _delay); \ \ /* create default spgram object (Kaiser-Bessel window) */ \ SPGRAM() SPGRAM(_create_default)(unsigned int _nfft); \ \ /* destroy spgram object */ \ void SPGRAM(_destroy)(SPGRAM() _q); \ \ /* clears the internal state of the spgram object, but not */ \ /* the internal buffer */ \ void SPGRAM(_clear)(SPGRAM() _q); \ \ /* reset the spgram object to its original state completely */ \ void SPGRAM(_reset)(SPGRAM() _q); \ \ /* print internal state of the spgram object */ \ void SPGRAM(_print)(SPGRAM() _q); \ \ /* set methods */ \ int SPGRAM(_set_alpha)(SPGRAM() _q, float _alpha); \ \ /* access methods */ \ unsigned int SPGRAM(_get_nfft) (SPGRAM() _q); \ unsigned int SPGRAM(_get_window_len) (SPGRAM() _q); \ unsigned int SPGRAM(_get_delay) (SPGRAM() _q); \ uint64_t SPGRAM(_get_num_samples) (SPGRAM() _q); \ uint64_t SPGRAM(_get_num_samples_total) (SPGRAM() _q); \ uint64_t SPGRAM(_get_num_transforms) (SPGRAM() _q); \ uint64_t SPGRAM(_get_num_transforms_total)(SPGRAM() _q); \ float SPGRAM(_get_alpha) (SPGRAM() _q); \ \ /* push a single sample into the spgram object */ \ /* _q : spgram object */ \ /* _x : input sample */ \ void SPGRAM(_push)(SPGRAM() _q, \ TI _x); \ \ /* write a block of samples to the spgram object */ \ /* _q : spgram object */ \ /* _x : input buffer [size: _n x 1] */ \ /* _n : input buffer length */ \ void SPGRAM(_write)(SPGRAM() _q, \ TI * _x, \ unsigned int _n); \ \ /* compute spectral periodogram output (fft-shifted values */ \ /* in dB) from current buffer contents */ \ /* _q : spgram object */ \ /* _X : output spectrum (dB) [size: _nfft x 1] */ \ void SPGRAM(_get_psd)(SPGRAM() _q, \ T * _X); \ \ /* export gnuplot file */ \ /* _q : spgram object */ \ /* _filename : input buffer [size: _n x 1] */ \ int SPGRAM(_export_gnuplot)(SPGRAM() _q, \ const char * _filename); \ \ /* object-independent methods */ \ \ /* estimate spectrum on input signal */ \ /* _nfft : FFT size */ \ /* _x : input signal [size: _n x 1] */ \ /* _n : input signal length */ \ /* _psd : output spectrum, [size: _nfft x 1] */ \ void SPGRAM(_estimate_psd)(unsigned int _nfft, \ TI * _x, \ unsigned int _n, \ T * _psd); \ LIQUID_SPGRAM_DEFINE_API(LIQUID_SPGRAM_MANGLE_CFLOAT, float, liquid_float_complex, liquid_float_complex) LIQUID_SPGRAM_DEFINE_API(LIQUID_SPGRAM_MANGLE_FLOAT, float, liquid_float_complex, float) // // asgram : ascii spectral periodogram // #define LIQUID_ASGRAM_MANGLE_CFLOAT(name) LIQUID_CONCAT(asgramcf,name) #define LIQUID_ASGRAM_MANGLE_FLOAT(name) LIQUID_CONCAT(asgramf, name) // Macro : ASGRAM // ASGRAM : name-mangling macro // T : primitive data type // TC : primitive data type (complex) // TI : primitive data type (input) #define LIQUID_ASGRAM_DEFINE_API(ASGRAM,T,TC,TI) \ \ typedef struct ASGRAM(_s) * ASGRAM(); \ \ /* create asgram object with size _nfft */ \ ASGRAM() ASGRAM(_create)(unsigned int _nfft); \ \ /* destroy asgram object */ \ void ASGRAM(_destroy)(ASGRAM() _q); \ \ /* resets the internal state of the asgram object */ \ void ASGRAM(_reset)(ASGRAM() _q); \ \ /* set scale and offset for spectrogram */ \ /* _q : asgram object */ \ /* _ref : signal reference level [dB] */ \ /* _div : signal division [dB] */ \ void ASGRAM(_set_scale)(ASGRAM() _q, \ float _ref, \ float _div); \ \ /* set display characters for output string */ \ /* _q : asgram object */ \ /* _ascii : 10-character display, default: " .,-+*&NM#" */ \ void ASGRAM(_set_display)(ASGRAM() _q, \ const char * _ascii); \ \ /* push a single sample into the asgram object */ \ /* _q : asgram object */ \ /* _x : input sample */ \ void ASGRAM(_push)(ASGRAM() _q, \ TI _x); \ \ /* write a block of samples to the asgram object */ \ /* _q : asgram object */ \ /* _x : input buffer [size: _n x 1] */ \ /* _n : input buffer length */ \ void ASGRAM(_write)(ASGRAM() _q, \ TI * _x, \ unsigned int _n); \ \ /* compute spectral periodogram output from current buffer */ \ /* contents */ \ /* _q : spgram object */ \ /* _ascii : output ASCII string [size: _nfft x 1] */ \ /* _peakval : peak power spectral density value [dB] */ \ /* _peakfreq : peak power spectral density frequency */ \ void ASGRAM(_execute)(ASGRAM() _q, \ char * _ascii, \ float * _peakval, \ float * _peakfreq); \ \ /* compute spectral periodogram output from current buffer */ \ /* contents and print standard format to stdout */ \ void ASGRAM(_print)(ASGRAM() _q); \ LIQUID_ASGRAM_DEFINE_API(LIQUID_ASGRAM_MANGLE_CFLOAT, float, liquid_float_complex, liquid_float_complex) LIQUID_ASGRAM_DEFINE_API(LIQUID_ASGRAM_MANGLE_FLOAT, float, liquid_float_complex, float) // // spectral periodogram waterfall // #define LIQUID_SPWATERFALL_MANGLE_CFLOAT(name) LIQUID_CONCAT(spwaterfallcf,name) #define LIQUID_SPWATERFALL_MANGLE_FLOAT(name) LIQUID_CONCAT(spwaterfallf, name) // Macro : SPWATERFALL // SPWATERFALL : name-mangling macro // T : primitive data type // TC : primitive data type (complex) // TI : primitive data type (input) #define LIQUID_SPWATERFALL_DEFINE_API(SPWATERFALL,T,TC,TI) \ \ typedef struct SPWATERFALL(_s) * SPWATERFALL(); \ \ /* create spgram object */ \ /* _nfft : FFT size */ \ /* _wtype : window type, e.g. LIQUID_WINDOW_HAMMING */ \ /* _window_len : window length, _window_len in [1,_nfft] */ \ /* _delay : delay between transforms, _delay > 0 */ \ /* _time : number of aggregated transforms, _time > 0*/ \ SPWATERFALL() SPWATERFALL(_create)(unsigned int _nfft, \ int _wtype, \ unsigned int _window_len, \ unsigned int _delay, \ unsigned int _time); \ \ /* create default spgram object (Kaiser-Bessel window) */ \ SPWATERFALL() SPWATERFALL(_create_default)(unsigned int _nfft, \ unsigned int _time); \ \ /* destroy spgram object */ \ void SPWATERFALL(_destroy)(SPWATERFALL() _q); \ \ /* clears the internal state of the spgram object, but not */ \ /* the internal buffer */ \ void SPWATERFALL(_clear)(SPWATERFALL() _q); \ \ /* reset the spgram object to its original state completely */ \ void SPWATERFALL(_reset)(SPWATERFALL() _q); \ \ /* print internal state of the spgram object */ \ void SPWATERFALL(_print)(SPWATERFALL() _q); \ \ /* push a single sample into the spgram object */ \ /* _q : spgram object */ \ /* _x : input sample */ \ void SPWATERFALL(_push)(SPWATERFALL() _q, \ TI _x); \ \ /* write a block of samples to the spgram object */ \ /* _q : spgram object */ \ /* _x : input buffer [size: _n x 1] */ \ /* _n : input buffer length */ \ void SPWATERFALL(_write)(SPWATERFALL() _q, \ TI * _x, \ unsigned int _n); \ \ /* export files for plotting */ \ /* _q : spgram object */ \ /* _filename_base : base filename (will export files with */ \ /* .gnu, .bin, and .png extensions) */ \ int SPWATERFALL(_export)(SPWATERFALL() _q, \ const char * _filename_base); \ LIQUID_SPWATERFALL_DEFINE_API(LIQUID_SPWATERFALL_MANGLE_CFLOAT, float, liquid_float_complex, liquid_float_complex) LIQUID_SPWATERFALL_DEFINE_API(LIQUID_SPWATERFALL_MANGLE_FLOAT, float, liquid_float_complex, float) // // MODULE : filter // // // firdes: finite impulse response filter design // // prototypes typedef enum { LIQUID_FIRFILT_UNKNOWN=0, // unknown filter type // Nyquist filter prototypes LIQUID_FIRFILT_KAISER, // Nyquist Kaiser filter LIQUID_FIRFILT_PM, // Parks-McClellan filter LIQUID_FIRFILT_RCOS, // raised-cosine filter LIQUID_FIRFILT_FEXP, // flipped exponential LIQUID_FIRFILT_FSECH, // flipped hyperbolic secant LIQUID_FIRFILT_FARCSECH, // flipped arc-hyperbolic secant // root-Nyquist filter prototypes LIQUID_FIRFILT_ARKAISER, // root-Nyquist Kaiser (approximate optimum) LIQUID_FIRFILT_RKAISER, // root-Nyquist Kaiser (true optimum) LIQUID_FIRFILT_RRC, // root raised-cosine LIQUID_FIRFILT_hM3, // harris-Moerder-3 filter LIQUID_FIRFILT_GMSKTX, // GMSK transmit filter LIQUID_FIRFILT_GMSKRX, // GMSK receive filter LIQUID_FIRFILT_RFEXP, // flipped exponential LIQUID_FIRFILT_RFSECH, // flipped hyperbolic secant LIQUID_FIRFILT_RFARCSECH, // flipped arc-hyperbolic secant } liquid_firfilt_type; // Design (root-)Nyquist filter from prototype // _type : filter type (e.g. LIQUID_FIRFILT_RRC) // _k : samples/symbol, _k > 1 // _m : symbol delay, _m > 0 // _beta : excess bandwidth factor, _beta in [0,1) // _dt : fractional sample delay, _dt in [-1,1] // _h : output coefficient buffer (length: 2*_k*_m+1) void liquid_firdes_prototype(liquid_firfilt_type _type, unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h); // returns filter type based on input string int liquid_getopt_str2firfilt(const char * _str); // estimate required filter length given // _df : transition bandwidth (0 < _b < 0.5) // _As : stop-band attenuation [dB], _As > 0 unsigned int estimate_req_filter_len(float _df, float _As); // estimate filter stop-band attenuation given // _df : transition bandwidth (0 < _b < 0.5) // _N : filter length float estimate_req_filter_As(float _df, unsigned int _N); // estimate filter transition bandwidth given // _As : stop-band attenuation [dB], _As > 0 // _N : filter length float estimate_req_filter_df(float _As, unsigned int _N); // returns the Kaiser window beta factor give the filter's target // stop-band attenuation (As) [Vaidyanathan:1993] // _As : target filter's stop-band attenuation [dB], _As > 0 float kaiser_beta_As(float _As); // Design FIR filter using Parks-McClellan algorithm // band type specifier typedef enum { LIQUID_FIRDESPM_BANDPASS=0, // regular band-pass filter LIQUID_FIRDESPM_DIFFERENTIATOR, // differentiating filter LIQUID_FIRDESPM_HILBERT // Hilbert transform } liquid_firdespm_btype; // weighting type specifier typedef enum { LIQUID_FIRDESPM_FLATWEIGHT=0, // flat weighting LIQUID_FIRDESPM_EXPWEIGHT, // exponential weighting LIQUID_FIRDESPM_LINWEIGHT, // linear weighting } liquid_firdespm_wtype; // run filter design (full life cycle of object) // _h_len : length of filter (number of taps) // _num_bands : number of frequency bands // _bands : band edges, f in [0,0.5], [size: _num_bands x 2] // _des : desired response [size: _num_bands x 1] // _weights : response weighting [size: _num_bands x 1] // _wtype : weight types (e.g. LIQUID_FIRDESPM_FLATWEIGHT) [size: _num_bands x 1] // _btype : band type (e.g. LIQUID_FIRDESPM_BANDPASS) // _h : output coefficients array [size: _h_len x 1] void firdespm_run(unsigned int _h_len, unsigned int _num_bands, float * _bands, float * _des, float * _weights, liquid_firdespm_wtype * _wtype, liquid_firdespm_btype _btype, float * _h); // run filter design for basic low-pass filter // _n : filter length, _n > 0 // _fc : cutoff frequency, 0 < _fc < 0.5 // _As : stop-band attenuation [dB], _As > 0 // _mu : fractional sample offset, -0.5 < _mu < 0.5 [ignored] // _h : output coefficient buffer, [size: _n x 1] void firdespm_lowpass(unsigned int _n, float _fc, float _As, float _mu, float * _h); // firdespm response callback function // _frequency : normalized frequency // _userdata : pointer to userdata // _desired : (return) desired response // _weight : (return) weight typedef int (*firdespm_callback)(double _frequency, void * _userdata, double * _desired, double * _weight); // structured object typedef struct firdespm_s * firdespm; // create firdespm object // _h_len : length of filter (number of taps) // _num_bands : number of frequency bands // _bands : band edges, f in [0,0.5], [size: _num_bands x 2] // _des : desired response [size: _num_bands x 1] // _weights : response weighting [size: _num_bands x 1] // _wtype : weight types (e.g. LIQUID_FIRDESPM_FLATWEIGHT) [size: _num_bands x 1] // _btype : band type (e.g. LIQUID_FIRDESPM_BANDPASS) firdespm firdespm_create(unsigned int _h_len, unsigned int _num_bands, float * _bands, float * _des, float * _weights, liquid_firdespm_wtype * _wtype, liquid_firdespm_btype _btype); // create firdespm object with user-defined callback // _h_len : length of filter (number of taps) // _num_bands : number of frequency bands // _bands : band edges, f in [0,0.5], [size: _num_bands x 2] // _btype : band type (e.g. LIQUID_FIRDESPM_BANDPASS) // _callback : user-defined callback for specifying desired response & weights // _userdata : user-defined data structure for callback function firdespm firdespm_create_callback(unsigned int _h_len, unsigned int _num_bands, float * _bands, liquid_firdespm_btype _btype, firdespm_callback _callback, void * _userdata); // destroy firdespm object void firdespm_destroy(firdespm _q); // print firdespm object internals void firdespm_print(firdespm _q); // execute filter design, storing result in _h void firdespm_execute(firdespm _q, float * _h); // Design FIR using kaiser window // _n : filter length, _n > 0 // _fc : cutoff frequency, 0 < _fc < 0.5 // _As : stop-band attenuation [dB], _As > 0 // _mu : fractional sample offset, -0.5 < _mu < 0.5 // _h : output coefficient buffer, [size: _n x 1] void liquid_firdes_kaiser(unsigned int _n, float _fc, float _As, float _mu, float *_h); // Design FIR doppler filter // _n : filter length // _fd : normalized doppler frequency (0 < _fd < 0.5) // _K : Rice fading factor (K >= 0) // _theta : LoS component angle of arrival // _h : output coefficient buffer void liquid_firdes_doppler(unsigned int _n, float _fd, float _K, float _theta, float * _h); // Design Nyquist raised-cosine filter // _k : samples/symbol // _m : symbol delay // _beta : rolloff factor (0 < beta <= 1) // _dt : fractional sample delay // _h : output coefficient buffer (length: 2*k*m+1) void liquid_firdes_rcos(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h); // Design root-Nyquist raised-cosine filter void liquid_firdes_rrcos(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h); // Design root-Nyquist Kaiser filter void liquid_firdes_rkaiser(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h); // Design (approximate) root-Nyquist Kaiser filter void liquid_firdes_arkaiser(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h); // Design root-Nyquist harris-Moerder filter void liquid_firdes_hM3(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h); // Design GMSK transmit and receive filters void liquid_firdes_gmsktx(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h); void liquid_firdes_gmskrx(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h); // Design flipped exponential Nyquist/root-Nyquist filters void liquid_firdes_fexp( unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h); void liquid_firdes_rfexp(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h); // Design flipped hyperbolic secand Nyquist/root-Nyquist filters void liquid_firdes_fsech( unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h); void liquid_firdes_rfsech(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h); // Design flipped arc-hyperbolic secand Nyquist/root-Nyquist filters void liquid_firdes_farcsech( unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h); void liquid_firdes_rfarcsech(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h); // Compute group delay for an FIR filter // _h : filter coefficients array // _n : filter length // _fc : frequency at which delay is evaluated (-0.5 < _fc < 0.5) float fir_group_delay(float * _h, unsigned int _n, float _fc); // Compute group delay for an IIR filter // _b : filter numerator coefficients // _nb : filter numerator length // _a : filter denominator coefficients // _na : filter denominator length // _fc : frequency at which delay is evaluated (-0.5 < _fc < 0.5) float iir_group_delay(float * _b, unsigned int _nb, float * _a, unsigned int _na, float _fc); // liquid_filter_autocorr() // // Compute auto-correlation of filter at a specific lag. // // _h : filter coefficients [size: _h_len x 1] // _h_len : filter length // _lag : auto-correlation lag (samples) float liquid_filter_autocorr(float * _h, unsigned int _h_len, int _lag); // liquid_filter_crosscorr() // // Compute cross-correlation of two filters at a specific lag. // // _h : filter coefficients [size: _h_len] // _h_len : filter length // _g : filter coefficients [size: _g_len] // _g_len : filter length // _lag : cross-correlation lag (samples) float liquid_filter_crosscorr(float * _h, unsigned int _h_len, float * _g, unsigned int _g_len, int _lag); // liquid_filter_isi() // // Compute inter-symbol interference (ISI)--both RMS and // maximum--for the filter _h. // // _h : filter coefficients [size: 2*_k*_m+1 x 1] // _k : filter over-sampling rate (samples/symbol) // _m : filter delay (symbols) // _rms : output root mean-squared ISI // _max : maximum ISI void liquid_filter_isi(float * _h, unsigned int _k, unsigned int _m, float * _rms, float * _max); // Compute relative out-of-band energy // // _h : filter coefficients [size: _h_len x 1] // _h_len : filter length // _fc : analysis cut-off frequency // _nfft : fft size float liquid_filter_energy(float * _h, unsigned int _h_len, float _fc, unsigned int _nfft); // // IIR filter design // // IIR filter design filter type typedef enum { LIQUID_IIRDES_BUTTER=0, LIQUID_IIRDES_CHEBY1, LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_ELLIP, LIQUID_IIRDES_BESSEL } liquid_iirdes_filtertype; // IIR filter design band type typedef enum { LIQUID_IIRDES_LOWPASS=0, LIQUID_IIRDES_HIGHPASS, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_BANDSTOP } liquid_iirdes_bandtype; // IIR filter design coefficients format typedef enum { LIQUID_IIRDES_SOS=0, LIQUID_IIRDES_TF } liquid_iirdes_format; // IIR filter design template // _ftype : filter type (e.g. LIQUID_IIRDES_BUTTER) // _btype : band type (e.g. LIQUID_IIRDES_BANDPASS) // _format : coefficients format (e.g. LIQUID_IIRDES_SOS) // _n : filter order // _fc : low-pass prototype cut-off frequency // _f0 : center frequency (band-pass, band-stop) // _Ap : pass-band ripple in dB // _As : stop-band ripple in dB // _B : numerator // _A : denominator void liquid_iirdes(liquid_iirdes_filtertype _ftype, liquid_iirdes_bandtype _btype, liquid_iirdes_format _format, unsigned int _n, float _fc, float _f0, float _Ap, float _As, float * _B, float * _A); // compute analog zeros, poles, gain for specific filter types void butter_azpkf(unsigned int _n, liquid_float_complex * _za, liquid_float_complex * _pa, liquid_float_complex * _ka); void cheby1_azpkf(unsigned int _n, float _ep, liquid_float_complex * _z, liquid_float_complex * _p, liquid_float_complex * _k); void cheby2_azpkf(unsigned int _n, float _es, liquid_float_complex * _z, liquid_float_complex * _p, liquid_float_complex * _k); void ellip_azpkf(unsigned int _n, float _ep, float _es, liquid_float_complex * _z, liquid_float_complex * _p, liquid_float_complex * _k); void bessel_azpkf(unsigned int _n, liquid_float_complex * _z, liquid_float_complex * _p, liquid_float_complex * _k); // compute frequency pre-warping factor float iirdes_freqprewarp(liquid_iirdes_bandtype _btype, float _fc, float _f0); // convert analog z/p/k form to discrete z/p/k form (bilinear z-transform) // _za : analog zeros [length: _nza] // _nza : number of analog zeros // _pa : analog poles [length: _npa] // _npa : number of analog poles // _m : frequency pre-warping factor // _zd : output digital zeros [length: _npa] // _pd : output digital poles [length: _npa] // _kd : output digital gain (should actually be real-valued) void bilinear_zpkf(liquid_float_complex * _za, unsigned int _nza, liquid_float_complex * _pa, unsigned int _npa, liquid_float_complex _ka, float _m, liquid_float_complex * _zd, liquid_float_complex * _pd, liquid_float_complex * _kd); // digital z/p/k low-pass to high-pass // _zd : digital zeros (low-pass prototype), [length: _n] // _pd : digital poles (low-pass prototype), [length: _n] // _n : low-pass filter order // _zdt : output digital zeros transformed [length: _n] // _pdt : output digital poles transformed [length: _n] void iirdes_dzpk_lp2hp(liquid_float_complex * _zd, liquid_float_complex * _pd, unsigned int _n, liquid_float_complex * _zdt, liquid_float_complex * _pdt); // digital z/p/k low-pass to band-pass // _zd : digital zeros (low-pass prototype), [length: _n] // _pd : digital poles (low-pass prototype), [length: _n] // _n : low-pass filter order // _f0 : center frequency // _zdt : output digital zeros transformed [length: 2*_n] // _pdt : output digital poles transformed [length: 2*_n] void iirdes_dzpk_lp2bp(liquid_float_complex * _zd, liquid_float_complex * _pd, unsigned int _n, float _f0, liquid_float_complex * _zdt, liquid_float_complex * _pdt); // convert discrete z/p/k form to transfer function // _zd : digital zeros [length: _n] // _pd : digital poles [length: _n] // _n : filter order // _kd : digital gain // _b : output numerator [length: _n+1] // _a : output denominator [length: _n+1] void iirdes_dzpk2tff(liquid_float_complex * _zd, liquid_float_complex * _pd, unsigned int _n, liquid_float_complex _kd, float * _b, float * _a); // convert discrete z/p/k form to second-order sections // _zd : digital zeros [length: _n] // _pd : digital poles [length: _n] // _n : filter order // _kd : digital gain // _B : output numerator [size: 3 x L+r] // _A : output denominator [size: 3 x L+r] // where r = _n%2, L = (_n-r)/2 void iirdes_dzpk2sosf(liquid_float_complex * _zd, liquid_float_complex * _pd, unsigned int _n, liquid_float_complex _kd, float * _B, float * _A); // additional IIR filter design templates // design 2nd-order IIR filter (active lag) // 1 + t2 * s // F(s) = ------------ // 1 + t1 * s // // _w : filter bandwidth // _zeta : damping factor (1/sqrt(2) suggested) // _K : loop gain (1000 suggested) // _b : output feed-forward coefficients [size: 3 x 1] // _a : output feed-back coefficients [size: 3 x 1] void iirdes_pll_active_lag(float _w, float _zeta, float _K, float * _b, float * _a); // design 2nd-order IIR filter (active PI) // 1 + t2 * s // F(s) = ------------ // t1 * s // // _w : filter bandwidth // _zeta : damping factor (1/sqrt(2) suggested) // _K : loop gain (1000 suggested) // _b : output feed-forward coefficients [size: 3 x 1] // _a : output feed-back coefficients [size: 3 x 1] void iirdes_pll_active_PI(float _w, float _zeta, float _K, float * _b, float * _a); // checks stability of iir filter // _b : feed-forward coefficients [size: _n x 1] // _a : feed-back coefficients [size: _n x 1] // _n : number of coefficients int iirdes_isstable(float * _b, float * _a, unsigned int _n); // // linear prediction // // compute the linear prediction coefficients for an input signal _x // _x : input signal [size: _n x 1] // _n : input signal length // _p : prediction filter order // _a : prediction filter [size: _p+1 x 1] // _e : prediction error variance [size: _p+1 x 1] void liquid_lpc(float * _x, unsigned int _n, unsigned int _p, float * _a, float * _g); // solve the Yule-Walker equations using Levinson-Durbin recursion // for _symmetric_ autocorrelation // _r : autocorrelation array [size: _p+1 x 1] // _p : filter order // _a : output coefficients [size: _p+1 x 1] // _e : error variance [size: _p+1 x 1] // // NOTES: // By definition _a[0] = 1.0 void liquid_levinson(float * _r, unsigned int _p, float * _a, float * _e); // // auto-correlator (delay cross-correlation) // #define LIQUID_AUTOCORR_MANGLE_CCCF(name) LIQUID_CONCAT(autocorr_cccf,name) #define LIQUID_AUTOCORR_MANGLE_RRRF(name) LIQUID_CONCAT(autocorr_rrrf,name) // Macro: // AUTOCORR : name-mangling macro // TO : output data type // TC : coefficients data type // TI : input data type #define LIQUID_AUTOCORR_DEFINE_API(AUTOCORR,TO,TC,TI) \ \ typedef struct AUTOCORR(_s) * AUTOCORR(); \ \ /* create auto-correlator object */ \ /* _window_size : size of the correlator window */ \ /* _delay : correlator delay [samples] */ \ AUTOCORR() AUTOCORR(_create)(unsigned int _window_size, \ unsigned int _delay); \ \ /* destroy auto-correlator object, freeing internal memory */ \ void AUTOCORR(_destroy)(AUTOCORR() _q); \ \ /* reset auto-correlator object's internals */ \ void AUTOCORR(_reset)(AUTOCORR() _q); \ \ /* print auto-correlator parameters to stdout */ \ void AUTOCORR(_print)(AUTOCORR() _q); \ \ /* push sample into auto-correlator object */ \ void AUTOCORR(_push)(AUTOCORR() _q, \ TI _x); \ \ /* compute single auto-correlation output */ \ void AUTOCORR(_execute)(AUTOCORR() _q, \ TO * _rxx); \ \ /* compute auto-correlation on block of samples; the input */ \ /* and output arrays may have the same pointer */ \ /* _q : auto-correlation object */ \ /* _x : input array [size: _n x 1] */ \ /* _n : number of input, output samples */ \ /* _rxx : input array [size: _n x 1] */ \ void AUTOCORR(_execute_block)(AUTOCORR() _q, \ TI * _x, \ unsigned int _n, \ TO * _rxx); \ \ /* return sum of squares of buffered samples */ \ float AUTOCORR(_get_energy)(AUTOCORR() _q); \ LIQUID_AUTOCORR_DEFINE_API(LIQUID_AUTOCORR_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) LIQUID_AUTOCORR_DEFINE_API(LIQUID_AUTOCORR_MANGLE_RRRF, float, float, float) // // Finite impulse response filter // #define LIQUID_FIRFILT_MANGLE_RRRF(name) LIQUID_CONCAT(firfilt_rrrf,name) #define LIQUID_FIRFILT_MANGLE_CRCF(name) LIQUID_CONCAT(firfilt_crcf,name) #define LIQUID_FIRFILT_MANGLE_CCCF(name) LIQUID_CONCAT(firfilt_cccf,name) // Macro: // FIRFILT : name-mangling macro // TO : output data type // TC : coefficients data type // TI : input data type #define LIQUID_FIRFILT_DEFINE_API(FIRFILT,TO,TC,TI) \ typedef struct FIRFILT(_s) * FIRFILT(); \ \ FIRFILT() FIRFILT(_create)(TC * _h, unsigned int _n); \ \ /* create using Kaiser-Bessel windowed sinc method */ \ /* _n : filter length, _n > 0 */ \ /* _fc : filter cut-off frequency 0 < _fc < 0.5 */ \ /* _As : filter stop-band attenuation [dB], _As > 0 */ \ /* _mu : fractional sample offset, -0.5 < _mu < 0.5 */ \ FIRFILT() FIRFILT(_create_kaiser)(unsigned int _n, \ float _fc, \ float _As, \ float _mu); \ \ /* create from square-root Nyquist prototype */ \ /* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \ /* _k : nominal samples/symbol, _k > 1 */ \ /* _m : filter delay [symbols], _m > 0 */ \ /* _beta : rolloff factor, 0 < beta <= 1 */ \ /* _mu : fractional sample offset,-0.5 < _mu < 0.5 */ \ FIRFILT() FIRFILT(_create_rnyquist)(int _type, \ unsigned int _k, \ unsigned int _m, \ float _beta, \ float _mu); \ \ /* create rectangular filter prototype */ \ FIRFILT() FIRFILT(_create_rect)(unsigned int _n); \ \ /* re-create filter */ \ /* _q : original filter object */ \ /* _h : pointer to filter coefficients [size: _n x 1] */ \ /* _n : filter length, _n > 0 */ \ FIRFILT() FIRFILT(_recreate)(FIRFILT() _q, \ TC * _h, \ unsigned int _n); \ \ /* destroy filter object and free all internal memory */ \ void FIRFILT(_destroy)(FIRFILT() _q); \ \ /* reset filter object's internal buffer */ \ void FIRFILT(_reset)(FIRFILT() _q); \ \ /* print filter object information */ \ void FIRFILT(_print)(FIRFILT() _q); \ \ /* set output scaling for filter */ \ void FIRFILT(_set_scale)(FIRFILT() _q, \ TC _scale); \ \ /* push sample into filter object's internal buffer */ \ /* _q : filter object */ \ /* _x : single input sample */ \ void FIRFILT(_push)(FIRFILT() _q, \ TI _x); \ \ /* execute the filter on internal buffer and coefficients */ \ /* _q : filter object */ \ /* _y : pointer to single output sample */ \ void FIRFILT(_execute)(FIRFILT() _q, \ TO * _y); \ \ /* execute the filter on a block of input samples; the */ \ /* input and output buffers may be the same */ \ /* _q : filter object */ \ /* _x : pointer to input array [size: _n x 1] */ \ /* _n : number of input, output samples */ \ /* _y : pointer to output array [size: _n x 1] */ \ void FIRFILT(_execute_block)(FIRFILT() _q, \ TI * _x, \ unsigned int _n, \ TO * _y); \ \ /* return length of filter object */ \ unsigned int FIRFILT(_get_length)(FIRFILT() _q); \ \ /* compute complex frequency response of filter object */ \ /* _q : filter object */ \ /* _fc : frequency to evaluate */ \ /* _H : pointer to output complex frequency response */ \ void FIRFILT(_freqresponse)(FIRFILT() _q, \ float _fc, \ liquid_float_complex * _H); \ \ /* compute and return group delay of filter object */ \ /* _q : filter object */ \ /* _fc : frequency to evaluate */ \ float FIRFILT(_groupdelay)(FIRFILT() _q, \ float _fc); \ LIQUID_FIRFILT_DEFINE_API(LIQUID_FIRFILT_MANGLE_RRRF, float, float, float) LIQUID_FIRFILT_DEFINE_API(LIQUID_FIRFILT_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) LIQUID_FIRFILT_DEFINE_API(LIQUID_FIRFILT_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // // FIR Hilbert transform // 2:1 real-to-complex decimator // 1:2 complex-to-real interpolator // #define LIQUID_FIRHILB_MANGLE_FLOAT(name) LIQUID_CONCAT(firhilbf, name) //#define LIQUID_FIRHILB_MANGLE_DOUBLE(name) LIQUID_CONCAT(firhilb, name) // NOTES: // Although firhilb is a placeholder for both decimation and // interpolation, separate objects should be used for each task. #define LIQUID_FIRHILB_DEFINE_API(FIRHILB,T,TC) \ typedef struct FIRHILB(_s) * FIRHILB(); \ \ /* create finite impulse reponse Hilbert transform */ \ /* _m : filter semi-length, delay is 2*m+1 */ \ /* _As : filter stop-band attenuation [dB] */ \ FIRHILB() FIRHILB(_create)(unsigned int _m, \ float _As); \ \ /* destroy finite impulse reponse Hilbert transform */ \ void FIRHILB(_destroy)(FIRHILB() _q); \ \ /* print firhilb object internals to stdout */ \ void FIRHILB(_print)(FIRHILB() _q); \ \ /* reset firhilb object internal state */ \ void FIRHILB(_reset)(FIRHILB() _q); \ \ /* execute Hilbert transform (real to complex) */ \ /* _q : Hilbert transform object */ \ /* _x : real-valued input sample */ \ /* _y : complex-valued output sample */ \ void FIRHILB(_r2c_execute)(FIRHILB() _q, \ T _x, \ TC * _y); \ \ /* execute Hilbert transform (complex to real) */ \ /* _q : Hilbert transform object */ \ /* _x : complex-valued input sample */ \ /* _y : real-valued output sample */ \ void FIRHILB(_c2r_execute)(FIRHILB() _q, \ TC _x, \ T * _y); \ \ /* execute Hilbert transform decimator (real to complex) */ \ /* _q : Hilbert transform object */ \ /* _x : real-valued input array [size: 2 x 1] */ \ /* _y : complex-valued output sample */ \ void FIRHILB(_decim_execute)(FIRHILB() _q, \ T * _x, \ TC * _y); \ \ /* execute Hilbert transform decimator (real to complex) on */ \ /* a block of samples */ \ /* _q : Hilbert transform object */ \ /* _x : real-valued input array [size: 2*_n x 1] */ \ /* _n : number of *output* samples */ \ /* _y : complex-valued output array [size: _n x 1] */ \ void FIRHILB(_decim_execute_block)(FIRHILB() _q, \ T * _x, \ unsigned int _n, \ TC * _y); \ \ /* execute Hilbert transform interpolator (real to complex) */ \ /* _q : Hilbert transform object */ \ /* _x : complex-valued input sample */ \ /* _y : real-valued output array [size: 2 x 1] */ \ void FIRHILB(_interp_execute)(FIRHILB() _q, \ TC _x, \ T * _y); \ \ /* execute Hilbert transform interpolator (complex to real) */ \ /* on a block of samples */ \ /* _q : Hilbert transform object */ \ /* _x : complex-valued input array [size: _n x 1] */ \ /* _n : number of *input* samples */ \ /* _y : real-valued output array [size: 2*_n x 1] */ \ void FIRHILB(_interp_execute_block)(FIRHILB() _q, \ TC * _x, \ unsigned int _n, \ T * _y); \ LIQUID_FIRHILB_DEFINE_API(LIQUID_FIRHILB_MANGLE_FLOAT, float, liquid_float_complex) //LIQUID_FIRHILB_DEFINE_API(LIQUID_FIRHILB_MANGLE_DOUBLE, double, liquid_double_complex) // // FFT-based finite impulse response filter // #define LIQUID_FFTFILT_MANGLE_RRRF(name) LIQUID_CONCAT(fftfilt_rrrf,name) #define LIQUID_FFTFILT_MANGLE_CRCF(name) LIQUID_CONCAT(fftfilt_crcf,name) #define LIQUID_FFTFILT_MANGLE_CCCF(name) LIQUID_CONCAT(fftfilt_cccf,name) // Macro: // FFTFILT : name-mangling macro // TO : output data type // TC : coefficients data type // TI : input data type #define LIQUID_FFTFILT_DEFINE_API(FFTFILT,TO,TC,TI) \ typedef struct FFTFILT(_s) * FFTFILT(); \ \ /* create FFT-based FIR filter using external coefficients */ \ /* _h : filter coefficients [size: _h_len x 1] */ \ /* _h_len : filter length, _h_len > 0 */ \ /* _n : block size = nfft/2, at least _h_len-1 */ \ FFTFILT() FFTFILT(_create)(TC * _h, \ unsigned int _h_len, \ unsigned int _n); \ \ /* destroy filter object and free all internal memory */ \ void FFTFILT(_destroy)(FFTFILT() _q); \ \ /* reset filter object's internal buffer */ \ void FFTFILT(_reset)(FFTFILT() _q); \ \ /* print filter object information */ \ void FFTFILT(_print)(FFTFILT() _q); \ \ /* set output scaling for filter */ \ void FFTFILT(_set_scale)(FFTFILT() _q, \ TC _scale); \ \ /* execute the filter on internal buffer and coefficients */ \ /* _q : filter object */ \ /* _x : pointer to input data array [size: _n x 1] */ \ /* _y : pointer to output data array [size: _n x 1] */ \ void FFTFILT(_execute)(FFTFILT() _q, \ TI * _x, \ TO * _y); \ \ /* return length of filter object's internal coefficients */ \ unsigned int FFTFILT(_get_length)(FFTFILT() _q); \ LIQUID_FFTFILT_DEFINE_API(LIQUID_FFTFILT_MANGLE_RRRF, float, float, float) LIQUID_FFTFILT_DEFINE_API(LIQUID_FFTFILT_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) LIQUID_FFTFILT_DEFINE_API(LIQUID_FFTFILT_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // // Infinite impulse response filter // #define LIQUID_IIRFILT_MANGLE_RRRF(name) LIQUID_CONCAT(iirfilt_rrrf,name) #define LIQUID_IIRFILT_MANGLE_CRCF(name) LIQUID_CONCAT(iirfilt_crcf,name) #define LIQUID_IIRFILT_MANGLE_CCCF(name) LIQUID_CONCAT(iirfilt_cccf,name) // Macro: // IIRFILT : name-mangling macro // TO : output data type // TC : coefficients data type // TI : input data type #define LIQUID_IIRFILT_DEFINE_API(IIRFILT,TO,TC,TI) \ \ typedef struct IIRFILT(_s) * IIRFILT(); \ \ /* create infinite impulse reponse filter */ \ /* _b : feed-forward coefficients [size: _nb x 1] */ \ /* _nb : number of feed-forward coefficients */ \ /* _a : feed-back coefficients [size: _na x 1] */ \ /* _na : number of feed-back coefficients */ \ IIRFILT() IIRFILT(_create)(TC * _b, \ unsigned int _nb, \ TC * _a, \ unsigned int _na); \ \ /* create IIR filter using 2nd-order secitons */ \ /* _B : feed-forward coefficients [size: _nsos x 3] */ \ /* _A : feed-back coefficients [size: _nsos x 3] */ \ IIRFILT() IIRFILT(_create_sos)(TC * _B, \ TC * _A, \ unsigned int _nsos); \ \ /* create IIR filter from design template */ \ /* _ftype : filter type (e.g. LIQUID_IIRDES_BUTTER) */ \ /* _btype : band type (e.g. LIQUID_IIRDES_BANDPASS) */ \ /* _format : coefficients format (e.g. LIQUID_IIRDES_SOS) */ \ /* _order : filter order */ \ /* _fc : low-pass prototype cut-off frequency */ \ /* _f0 : center frequency (band-pass, band-stop) */ \ /* _Ap : pass-band ripple in dB */ \ /* _As : stop-band ripple in dB */ \ IIRFILT() IIRFILT(_create_prototype)( \ liquid_iirdes_filtertype _ftype, \ liquid_iirdes_bandtype _btype, \ liquid_iirdes_format _format, \ unsigned int _order, \ float _fc, \ float _f0, \ float _Ap, \ float _As); \ \ /* create simplified low-pass Butterworth IIR filter */ \ /* _order : filter order */ \ /* _fc : low-pass prototype cut-off frequency */ \ IIRFILT() IIRFILT(_create_lowpass)( \ unsigned int _order, \ float _fc); \ \ /* create 8th-order integrator filter */ \ IIRFILT() IIRFILT(_create_integrator)(); \ \ /* create 8th-order differentiator filter */ \ IIRFILT() IIRFILT(_create_differentiator)(); \ \ /* create simple DC-blocking filter */ \ IIRFILT() IIRFILT(_create_dc_blocker)(float _alpha); \ \ /* create phase-locked loop iirfilt object */ \ /* _w : filter bandwidth */ \ /* _zeta : damping factor (1/sqrt(2) suggested) */ \ /* _K : loop gain (1000 suggested) */ \ IIRFILT() IIRFILT(_create_pll)(float _w, \ float _zeta, \ float _K); \ \ /* destroy iirfilt object, freeing all internal memory */ \ void IIRFILT(_destroy)(IIRFILT() _q); \ \ /* print iirfilt object properties to stdout */ \ void IIRFILT(_print)(IIRFILT() _q); \ \ /* clear/reset iirfilt object internals */ \ void IIRFILT(_reset)(IIRFILT() _q); \ \ /* compute filter output */ \ /* _q : iirfilt object */ \ /* _x : input sample */ \ /* _y : output sample pointer */ \ void IIRFILT(_execute)(IIRFILT() _q, \ TI _x, \ TO * _y); \ \ /* execute the filter on a block of input samples; the */ \ /* input and output buffers may be the same */ \ /* _q : filter object */ \ /* _x : pointer to input array [size: _n x 1] */ \ /* _n : number of input, output samples */ \ /* _y : pointer to output array [size: _n x 1] */ \ void IIRFILT(_execute_block)(IIRFILT() _q, \ TI * _x, \ unsigned int _n, \ TO * _y); \ \ /* return iirfilt object's filter length (order + 1) */ \ unsigned int IIRFILT(_get_length)(IIRFILT() _q); \ \ /* compute complex frequency response of filter object */ \ /* _q : filter object */ \ /* _fc : frequency to evaluate */ \ /* _H : pointer to output complex frequency response */ \ void IIRFILT(_freqresponse)(IIRFILT() _q, \ float _fc, \ liquid_float_complex * _H); \ \ /* compute and return group delay of filter object */ \ /* _q : filter object */ \ /* _fc : frequency to evaluate */ \ float IIRFILT(_groupdelay)(IIRFILT() _q, float _fc); \ LIQUID_IIRFILT_DEFINE_API(LIQUID_IIRFILT_MANGLE_RRRF, float, float, float) LIQUID_IIRFILT_DEFINE_API(LIQUID_IIRFILT_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) LIQUID_IIRFILT_DEFINE_API(LIQUID_IIRFILT_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // // FIR Polyphase filter bank // #define LIQUID_FIRPFB_MANGLE_RRRF(name) LIQUID_CONCAT(firpfb_rrrf,name) #define LIQUID_FIRPFB_MANGLE_CRCF(name) LIQUID_CONCAT(firpfb_crcf,name) #define LIQUID_FIRPFB_MANGLE_CCCF(name) LIQUID_CONCAT(firpfb_cccf,name) // Macro: // FIRPFB : name-mangling macro // TO : output data type // TC : coefficients data type // TI : input data type #define LIQUID_FIRPFB_DEFINE_API(FIRPFB,TO,TC,TI) \ \ typedef struct FIRPFB(_s) * FIRPFB(); \ \ /* create firpfb from external coefficients */ \ /* _M : number of filters in the bank */ \ /* _h : coefficients [size: _M*_h_len x 1] */ \ /* _h_len : filter delay (symbols) */ \ FIRPFB() FIRPFB(_create)(unsigned int _M, \ TC * _h, \ unsigned int _h_len); \ \ /* create firpfb from external coefficients */ \ /* _M : number of filters in the bank */ \ /* _m : filter semi-length [samples] */ \ /* _fc : filter cut-off frequency 0 < _fc < 0.5 */ \ /* _As : filter stop-band suppression [dB] */ \ FIRPFB() FIRPFB(_create_kaiser)(unsigned int _M, \ unsigned int _m, \ float _fc, \ float _As); \ \ /* create firpfb from square-root Nyquist prototype */ \ /* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \ /* _npfb : number of filters in the bank */ \ /* _k : nominal samples/symbol */ \ /* _m : filter delay (symbols) */ \ /* _beta : rolloff factor (0 < beta <= 1) */ \ FIRPFB() FIRPFB(_create_rnyquist)(int _type, \ unsigned int _npfb, \ unsigned int _k, \ unsigned int _m, \ float _beta); \ \ /* create from square-root derivative Nyquist prototype */ \ /* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \ /* _npfb : number of filters in the bank */ \ /* _k : nominal samples/symbol */ \ /* _m : filter delay (symbols) */ \ /* _beta : rolloff factor (0 < beta <= 1) */ \ FIRPFB() FIRPFB(_create_drnyquist)(int _type, \ unsigned int _npfb, \ unsigned int _k, \ unsigned int _m, \ float _beta); \ \ /* re-create filterbank object */ \ /* _q : original firpfb object */ \ /* _M : number of filters in the bank */ \ /* _h : coefficients [size: _M x _h_len] */ \ /* _h_len : length of each filter */ \ FIRPFB() FIRPFB(_recreate)(FIRPFB() _q, \ unsigned int _M, \ TC * _h, \ unsigned int _h_len); \ \ /* destroy firpfb object, freeing all internal memory */ \ void FIRPFB(_destroy)(FIRPFB() _q); \ \ /* print firpfb object's parameters */ \ void FIRPFB(_print)(FIRPFB() _q); \ \ /* set output scaling for filter */ \ void FIRPFB(_set_scale)(FIRPFB() _q, \ TC _g); \ \ /* clear/reset firpfb object internal state */ \ void FIRPFB(_reset)(FIRPFB() _q); \ \ /* push sample into firpfb internal buffer */ \ void FIRPFB(_push)(FIRPFB() _q, TI _x); \ \ /* execute the filter on internal buffer and coefficients */ \ /* _q : firpfb object */ \ /* _i : index of filter to use */ \ /* _y : pointer to output sample */ \ void FIRPFB(_execute)(FIRPFB() _q, \ unsigned int _i, \ TO * _y); \ \ /* execute the filter on a block of input samples; the */ \ /* input and output buffers may be the same */ \ /* _q : firpfb object */ \ /* _i : index of filter to use */ \ /* _x : pointer to input array [size: _n x 1] */ \ /* _n : number of input, output samples */ \ /* _y : pointer to output array [size: _n x 1] */ \ void FIRPFB(_execute_block)(FIRPFB() _q, \ unsigned int _i, \ TI * _x, \ unsigned int _n, \ TO * _y); \ LIQUID_FIRPFB_DEFINE_API(LIQUID_FIRPFB_MANGLE_RRRF, float, float, float) LIQUID_FIRPFB_DEFINE_API(LIQUID_FIRPFB_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) LIQUID_FIRPFB_DEFINE_API(LIQUID_FIRPFB_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // // Interpolators // // firinterp : finite impulse response interpolator #define LIQUID_FIRINTERP_MANGLE_RRRF(name) LIQUID_CONCAT(firinterp_rrrf,name) #define LIQUID_FIRINTERP_MANGLE_CRCF(name) LIQUID_CONCAT(firinterp_crcf,name) #define LIQUID_FIRINTERP_MANGLE_CCCF(name) LIQUID_CONCAT(firinterp_cccf,name) #define LIQUID_FIRINTERP_DEFINE_API(FIRINTERP,TO,TC,TI) \ \ typedef struct FIRINTERP(_s) * FIRINTERP(); \ \ /* create interpolator from external coefficients */ \ /* _M : interpolation factor */ \ /* _h : filter coefficients [size: _h_len x 1] */ \ /* _h_len : filter length */ \ FIRINTERP() FIRINTERP(_create)(unsigned int _M, \ TC * _h, \ unsigned int _h_len); \ \ /* create interpolator from Kaiser prototype */ \ /* _M : interpolation factor */ \ /* _m : filter delay (symbols) */ \ /* _As : stop-band attenuation [dB] */ \ FIRINTERP() FIRINTERP(_create_kaiser)(unsigned int _M, \ unsigned int _m, \ float _As); \ \ /* create prorotype (root-)Nyquist interpolator */ \ /* _type : filter type (e.g. LIQUID_FIRFILT_RCOS) */ \ /* _k : samples/symbol, _k > 1 */ \ /* _m : filter delay (symbols), _m > 0 */ \ /* _beta : excess bandwidth factor, _beta < 1 */ \ /* _dt : fractional sample delay, _dt in (-1, 1) */ \ FIRINTERP() FIRINTERP(_create_prototype)(int _type, \ unsigned int _k, \ unsigned int _m, \ float _beta, \ float _dt); \ \ /* destroy firinterp object, freeing all internal memory */ \ void FIRINTERP(_destroy)(FIRINTERP() _q); \ \ /* print firinterp object's internal properties to stdout */ \ void FIRINTERP(_print)(FIRINTERP() _q); \ \ /* reset internal state */ \ void FIRINTERP(_reset)(FIRINTERP() _q); \ \ /* execute interpolation on single input sample */ \ /* _q : firinterp object */ \ /* _x : input sample */ \ /* _y : output sample array [size: _M x 1] */ \ void FIRINTERP(_execute)(FIRINTERP() _q, \ TI _x, \ TO * _y); \ \ /* execute interpolation on block of input samples */ \ /* _q : firinterp object */ \ /* _x : input array [size: _n x 1] */ \ /* _n : size of input array */ \ /* _y : output sample array [size: _M*_n x 1] */ \ void FIRINTERP(_execute_block)(FIRINTERP() _q, \ TI * _x, \ unsigned int _n, \ TO * _y); \ LIQUID_FIRINTERP_DEFINE_API(LIQUID_FIRINTERP_MANGLE_RRRF, float, float, float) LIQUID_FIRINTERP_DEFINE_API(LIQUID_FIRINTERP_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) LIQUID_FIRINTERP_DEFINE_API(LIQUID_FIRINTERP_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // iirinterp : infinite impulse response interpolator #define LIQUID_IIRINTERP_MANGLE_RRRF(name) LIQUID_CONCAT(iirinterp_rrrf,name) #define LIQUID_IIRINTERP_MANGLE_CRCF(name) LIQUID_CONCAT(iirinterp_crcf,name) #define LIQUID_IIRINTERP_MANGLE_CCCF(name) LIQUID_CONCAT(iirinterp_cccf,name) #define LIQUID_IIRINTERP_DEFINE_API(IIRINTERP,TO,TC,TI) \ typedef struct IIRINTERP(_s) * IIRINTERP(); \ \ /* create interpolator from external coefficients */ \ /* _M : interpolation factor */ \ /* _b : feed-back coefficients [size: _nb x 1] */ \ /* _nb : feed-back coefficients length */ \ /* _a : feed-forward coefficients [size: _na x 1] */ \ /* _na : feed-forward coefficients length */ \ IIRINTERP() IIRINTERP(_create)(unsigned int _M, \ TC * _b, \ unsigned int _nb, \ TC * _a, \ unsigned int _na); \ \ /* create decimator with default Butterworth prototype */ \ /* _M : decimation factor */ \ /* _order : filter order */ \ IIRINTERP() IIRINTERP(_create_default)(unsigned int _M, \ unsigned int _order); \ \ /* create interpolator from prototype */ \ /* _M : interpolation factor */ \ IIRINTERP() IIRINTERP(_create_prototype)( \ unsigned int _M, \ liquid_iirdes_filtertype _ftype, \ liquid_iirdes_bandtype _btype, \ liquid_iirdes_format _format, \ unsigned int _order, \ float _fc, \ float _f0, \ float _Ap, \ float _As); \ \ /* destroy interpolator object and free internal memory */ \ void IIRINTERP(_destroy)(IIRINTERP() _q); \ \ /* print interpolator object internals */ \ void IIRINTERP(_print)(IIRINTERP() _q); \ \ /* reset interpolator object */ \ void IIRINTERP(_reset)(IIRINTERP() _q); \ \ /* execute interpolation on single input sample */ \ /* _q : iirinterp object */ \ /* _x : input sample */ \ /* _y : output sample array [size: _M x 1] */ \ void IIRINTERP(_execute)(IIRINTERP() _q, \ TI _x, \ TO * _y); \ \ /* execute interpolation on block of input samples */ \ /* _q : iirinterp object */ \ /* _x : input array [size: _n x 1] */ \ /* _n : size of input array */ \ /* _y : output sample array [size: _M*_n x 1] */ \ void IIRINTERP(_execute_block)(IIRINTERP() _q, \ TI * _x, \ unsigned int _n, \ TO * _y); \ \ /* get system group delay at frequency _fc */ \ float IIRINTERP(_groupdelay)(IIRINTERP() _q, float _fc); \ LIQUID_IIRINTERP_DEFINE_API(LIQUID_IIRINTERP_MANGLE_RRRF, float, float, float) LIQUID_IIRINTERP_DEFINE_API(LIQUID_IIRINTERP_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) LIQUID_IIRINTERP_DEFINE_API(LIQUID_IIRINTERP_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // // Decimators // // firdecim : finite impulse response decimator #define LIQUID_FIRDECIM_MANGLE_RRRF(name) LIQUID_CONCAT(firdecim_rrrf,name) #define LIQUID_FIRDECIM_MANGLE_CRCF(name) LIQUID_CONCAT(firdecim_crcf,name) #define LIQUID_FIRDECIM_MANGLE_CCCF(name) LIQUID_CONCAT(firdecim_cccf,name) #define LIQUID_FIRDECIM_DEFINE_API(FIRDECIM,TO,TC,TI) \ typedef struct FIRDECIM(_s) * FIRDECIM(); \ \ /* create decimator from external coefficients */ \ /* _M : decimation factor */ \ /* _h : filter coefficients [size: _h_len x 1] */ \ /* _h_len : filter coefficients length */ \ FIRDECIM() FIRDECIM(_create)(unsigned int _M, \ TC * _h, \ unsigned int _h_len); \ \ /* create decimator from Kaiser prototype */ \ /* _M : decimation factor */ \ /* _m : filter delay (symbols) */ \ /* _As : stop-band attenuation [dB] */ \ FIRDECIM() FIRDECIM(_create_kaiser)(unsigned int _M, \ unsigned int _m, \ float _As); \ \ /* create square-root Nyquist decimator */ \ /* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \ /* _M : samples/symbol (decimation factor) */ \ /* _m : filter delay (symbols) */ \ /* _beta : rolloff factor (0 < beta <= 1) */ \ /* _dt : fractional sample delay */ \ FIRDECIM() FIRDECIM(_create_prototype)(int _type, \ unsigned int _M, \ unsigned int _m, \ float _beta, \ float _dt); \ \ /* destroy decimator object */ \ void FIRDECIM(_destroy)(FIRDECIM() _q); \ \ /* print decimator object propreties to stdout */ \ void FIRDECIM(_print)(FIRDECIM() _q); \ \ /* reset decimator object internal state */ \ void FIRDECIM(_reset)(FIRDECIM() _q); \ \ /* execute decimator on _M input samples */ \ /* _q : decimator object */ \ /* _x : input samples [size: _M x 1] */ \ /* _y : output sample pointer */ \ void FIRDECIM(_execute)(FIRDECIM() _q, \ TI * _x, \ TO * _y); \ \ /* execute decimator on block of _n*_M input samples */ \ /* _q : decimator object */ \ /* _x : input array [size: _n*_M x 1] */ \ /* _n : number of _output_ samples */ \ /* _y : output array [_size: _n x 1] */ \ void FIRDECIM(_execute_block)(FIRDECIM() _q, \ TI * _x, \ unsigned int _n, \ TO * _y); \ LIQUID_FIRDECIM_DEFINE_API(LIQUID_FIRDECIM_MANGLE_RRRF, float, float, float) LIQUID_FIRDECIM_DEFINE_API(LIQUID_FIRDECIM_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) LIQUID_FIRDECIM_DEFINE_API(LIQUID_FIRDECIM_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // iirdecim : infinite impulse response decimator #define LIQUID_IIRDECIM_MANGLE_RRRF(name) LIQUID_CONCAT(iirdecim_rrrf,name) #define LIQUID_IIRDECIM_MANGLE_CRCF(name) LIQUID_CONCAT(iirdecim_crcf,name) #define LIQUID_IIRDECIM_MANGLE_CCCF(name) LIQUID_CONCAT(iirdecim_cccf,name) #define LIQUID_IIRDECIM_DEFINE_API(IIRDECIM,TO,TC,TI) \ typedef struct IIRDECIM(_s) * IIRDECIM(); \ \ /* create decimator from external coefficients */ \ /* _M : decimation factor */ \ /* _b : feed-back coefficients [size: _nb x 1] */ \ /* _nb : feed-back coefficients length */ \ /* _a : feed-forward coefficients [size: _na x 1] */ \ /* _na : feed-forward coefficients length */ \ IIRDECIM() IIRDECIM(_create)(unsigned int _M, \ TC * _b, \ unsigned int _nb, \ TC * _a, \ unsigned int _na); \ \ /* create decimator with default Butterworth prototype */ \ /* _M : decimation factor */ \ /* _order : filter order */ \ IIRDECIM() IIRDECIM(_create_default)(unsigned int _M, \ unsigned int _order); \ \ /* create decimator from prototype */ \ /* _M : decimation factor */ \ /* _ftype : filter type (e.g. LIQUID_IIRDES_BUTTER) */ \ /* _btype : band type (e.g. LIQUID_IIRDES_BANDPASS) */ \ /* _format : coefficients format (e.g. LIQUID_IIRDES_SOS) */ \ /* _n : filter order */ \ /* _fc : low-pass prototype cut-off frequency */ \ /* _f0 : center frequency (band-pass, band-stop) */ \ /* _Ap : pass-band ripple in dB */ \ /* _As : stop-band ripple in dB */ \ IIRDECIM() IIRDECIM(_create_prototype)( \ unsigned int _M, \ liquid_iirdes_filtertype _ftype, \ liquid_iirdes_bandtype _btype, \ liquid_iirdes_format _format, \ unsigned int _order, \ float _fc, \ float _f0, \ float _Ap, \ float _As); \ \ /* destroy decimator object and free internal memory */ \ void IIRDECIM(_destroy)(IIRDECIM() _q); \ \ /* print decimator object internals */ \ void IIRDECIM(_print)(IIRDECIM() _q); \ \ /* reset decimator object */ \ void IIRDECIM(_reset)(IIRDECIM() _q); \ \ /* execute decimator on _M input samples */ \ /* _q : decimator object */ \ /* _x : input samples [size: _M x 1] */ \ /* _y : output sample pointer */ \ void IIRDECIM(_execute)(IIRDECIM() _q, \ TI * _x, \ TO * _y); \ \ /* execute decimator on block of _n*_M input samples */ \ /* _q : decimator object */ \ /* _x : input array [size: _n*_M x 1] */ \ /* _n : number of _output_ samples */ \ /* _y : output array [_sze: _n x 1] */ \ void IIRDECIM(_execute_block)(IIRDECIM() _q, \ TI * _x, \ unsigned int _n, \ TO * _y); \ \ /* get system group delay at frequency _fc */ \ float IIRDECIM(_groupdelay)(IIRDECIM() _q, float _fc); \ LIQUID_IIRDECIM_DEFINE_API(LIQUID_IIRDECIM_MANGLE_RRRF, float, float, float) LIQUID_IIRDECIM_DEFINE_API(LIQUID_IIRDECIM_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) LIQUID_IIRDECIM_DEFINE_API(LIQUID_IIRDECIM_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // // Half-band resampler // #define LIQUID_RESAMP2_MANGLE_RRRF(name) LIQUID_CONCAT(resamp2_rrrf,name) #define LIQUID_RESAMP2_MANGLE_CRCF(name) LIQUID_CONCAT(resamp2_crcf,name) #define LIQUID_RESAMP2_MANGLE_CCCF(name) LIQUID_CONCAT(resamp2_cccf,name) #define LIQUID_RESAMP2_DEFINE_API(RESAMP2,TO,TC,TI) \ typedef struct RESAMP2(_s) * RESAMP2(); \ \ /* create half-band resampler */ \ /* _m : filter semi-length (h_len = 4*m+1) */ \ /* _f0 : filter center frequency */ \ /* _As : stop-band attenuation [dB] */ \ RESAMP2() RESAMP2(_create)(unsigned int _m, \ float _f0, \ float _As); \ \ /* re-create half-band resampler with new properties */ \ /* _q : original half-band resampler object */ \ /* _m : filter semi-length (h_len = 4*m+1) */ \ /* _f0 : filter center frequency */ \ /* _As : stop-band attenuation [dB] */ \ RESAMP2() RESAMP2(_recreate)(RESAMP2() _q, \ unsigned int _m, \ float _f0, \ float _As); \ \ /* destroy half-band resampler */ \ void RESAMP2(_destroy)(RESAMP2() _q); \ \ /* print resamp2 object's internals */ \ void RESAMP2(_print)(RESAMP2() _q); \ \ /* reset internal buffer */ \ void RESAMP2(_reset)(RESAMP2() _q); \ \ /* get resampler filter delay (semi-length m) */ \ unsigned int RESAMP2(_get_delay)(RESAMP2() _q); \ \ /* execute resamp2 as half-band filter */ \ /* _q : resamp2 object */ \ /* _x : input sample */ \ /* _y0 : output sample pointer (low frequency) */ \ /* _y1 : output sample pointer (high frequency) */ \ void RESAMP2(_filter_execute)(RESAMP2() _q, \ TI _x, \ TO * _y0, \ TO * _y1); \ \ /* execute resamp2 as half-band analysis filterbank */ \ /* _q : resamp2 object */ \ /* _x : input array [size: 2 x 1] */ \ /* _y : output array [size: 2 x 1] */ \ void RESAMP2(_analyzer_execute)(RESAMP2() _q, \ TI * _x, \ TO * _y); \ \ /* execute resamp2 as half-band synthesis filterbank */ \ /* _q : resamp2 object */ \ /* _x : input array [size: 2 x 1] */ \ /* _y : output array [size: 2 x 1] */ \ void RESAMP2(_synthesizer_execute)(RESAMP2() _q, \ TI * _x, \ TO * _y); \ \ /* execute resamp2 as half-band decimator */ \ /* _q : resamp2 object */ \ /* _x : input array [size: 2 x 1] */ \ /* _y : output sample pointer */ \ void RESAMP2(_decim_execute)(RESAMP2() _q, \ TI * _x, \ TO * _y); \ \ /* execute resamp2 as half-band interpolator */ \ /* _q : resamp2 object */ \ /* _x : input sample */ \ /* _y : output array [size: 2 x 1] */ \ void RESAMP2(_interp_execute)(RESAMP2() _q, \ TI _x, \ TO * _y); \ LIQUID_RESAMP2_DEFINE_API(LIQUID_RESAMP2_MANGLE_RRRF, float, float, float) LIQUID_RESAMP2_DEFINE_API(LIQUID_RESAMP2_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) LIQUID_RESAMP2_DEFINE_API(LIQUID_RESAMP2_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // // Arbitrary resampler // #define LIQUID_RESAMP_MANGLE_RRRF(name) LIQUID_CONCAT(resamp_rrrf,name) #define LIQUID_RESAMP_MANGLE_CRCF(name) LIQUID_CONCAT(resamp_crcf,name) #define LIQUID_RESAMP_MANGLE_CCCF(name) LIQUID_CONCAT(resamp_cccf,name) #define LIQUID_RESAMP_DEFINE_API(RESAMP,TO,TC,TI) \ typedef struct RESAMP(_s) * RESAMP(); \ \ /* create arbitrary resampler object */ \ /* _rate : arbitrary resampling rate */ \ /* _m : filter semi-length (delay) */ \ /* _fc : filter cutoff frequency, 0 < _fc < 0.5 */ \ /* _As : filter stop-band attenuation [dB] */ \ /* _npfb : number of filters in the bank */ \ RESAMP() RESAMP(_create)(float _rate, \ unsigned int _m, \ float _fc, \ float _As, \ unsigned int _npfb); \ \ /* create arbitrary resampler object with a specified input */ \ /* resampling rate and default parameters */ \ /* m : (filter semi-length) = 7 */ \ /* fc : (filter cutoff frequency) = 0.25 */ \ /* As : (filter stop-band attenuation) = 60 dB */ \ /* npfb : (number of filters in the bank) = 64 */ \ RESAMP() RESAMP(_create_default)(float _rate); \ \ /* destroy arbitrary resampler object */ \ void RESAMP(_destroy)(RESAMP() _q); \ \ /* print resamp object internals to stdout */ \ void RESAMP(_print)(RESAMP() _q); \ \ /* reset resamp object internals */ \ void RESAMP(_reset)(RESAMP() _q); \ \ /* get resampler delay (output samples) */ \ unsigned int RESAMP(_get_delay)(RESAMP() _q); \ \ /* set rate of arbitrary resampler */ \ /* _q : resampling object */ \ /* _rate : new sampling rate, _rate > 0 */ \ void RESAMP(_set_rate)(RESAMP() _q, \ float _rate); \ \ /* adjust rate of arbitrary resampler */ \ /* _q : resampling object */ \ /* _delta : rate adjustment; _rate <- _rate + _delta */ \ void RESAMP(_adjust_rate)(RESAMP() _q, \ float _delta); \ \ /* set resampling timing phase */ \ /* _q : resampling object */ \ /* _tau : sample timing */ \ void RESAMP(_set_timing_phase)(RESAMP() _q, \ float _tau); \ \ /* adjust resampling timing phase */ \ /* _q : resampling object */ \ /* _delta : sample timing adjustment */ \ void RESAMP(_adjust_timing_phase)(RESAMP() _q, \ float _delta); \ \ /* execute arbitrary resampler */ \ /* _q : resamp object */ \ /* _x : single input sample */ \ /* _y : output sample array (pointer) */ \ /* _num_written : number of samples written to _y */ \ void RESAMP(_execute)(RESAMP() _q, \ TI _x, \ TO * _y, \ unsigned int * _num_written); \ \ /* execute arbitrary resampler on a block of samples */ \ /* _q : resamp object */ \ /* _x : input buffer [size: _nx x 1] */ \ /* _nx : input buffer */ \ /* _y : output sample array (pointer) */ \ /* _ny : number of samples written to _y */ \ void RESAMP(_execute_block)(RESAMP() _q, \ TI * _x, \ unsigned int _nx, \ TO * _y, \ unsigned int * _ny); \ LIQUID_RESAMP_DEFINE_API(LIQUID_RESAMP_MANGLE_RRRF, float, float, float) LIQUID_RESAMP_DEFINE_API(LIQUID_RESAMP_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) LIQUID_RESAMP_DEFINE_API(LIQUID_RESAMP_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // // Multi-stage half-band resampler // // resampling type (interpolator/decimator) typedef enum { LIQUID_RESAMP_INTERP=0, // interpolator LIQUID_RESAMP_DECIM, // decimator } liquid_resamp_type; #define LIQUID_MSRESAMP2_MANGLE_RRRF(name) LIQUID_CONCAT(msresamp2_rrrf,name) #define LIQUID_MSRESAMP2_MANGLE_CRCF(name) LIQUID_CONCAT(msresamp2_crcf,name) #define LIQUID_MSRESAMP2_MANGLE_CCCF(name) LIQUID_CONCAT(msresamp2_cccf,name) #define LIQUID_MSRESAMP2_DEFINE_API(MSRESAMP2,TO,TC,TI) \ typedef struct MSRESAMP2(_s) * MSRESAMP2(); \ \ /* create multi-stage half-band resampler */ \ /* _type : resampler type (e.g. LIQUID_RESAMP_DECIM) */ \ /* _num_stages : number of resampling stages */ \ /* _fc : filter cut-off frequency 0 < _fc < 0.5 */ \ /* _f0 : filter center frequency */ \ /* _As : stop-band attenuation [dB] */ \ MSRESAMP2() MSRESAMP2(_create)(int _type, \ unsigned int _num_stages, \ float _fc, \ float _f0, \ float _As); \ \ /* destroy multi-stage half-bandresampler */ \ void MSRESAMP2(_destroy)(MSRESAMP2() _q); \ \ /* print msresamp object internals to stdout */ \ void MSRESAMP2(_print)(MSRESAMP2() _q); \ \ /* reset msresamp object internal state */ \ void MSRESAMP2(_reset)(MSRESAMP2() _q); \ \ /* get group delay (number of output samples) */ \ float MSRESAMP2(_get_delay)(MSRESAMP2() _q); \ \ /* execute multi-stage resampler, M = 2^num_stages */ \ /* LIQUID_RESAMP_INTERP: input: 1, output: M */ \ /* LIQUID_RESAMP_DECIM: input: M, output: 1 */ \ /* _q : msresamp object */ \ /* _x : input sample array */ \ /* _y : output sample array */ \ void MSRESAMP2(_execute)(MSRESAMP2() _q, \ TI * _x, \ TO * _y); \ LIQUID_MSRESAMP2_DEFINE_API(LIQUID_MSRESAMP2_MANGLE_RRRF, float, float, float) LIQUID_MSRESAMP2_DEFINE_API(LIQUID_MSRESAMP2_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) LIQUID_MSRESAMP2_DEFINE_API(LIQUID_MSRESAMP2_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // // Multi-stage arbitrary resampler // #define LIQUID_MSRESAMP_MANGLE_RRRF(name) LIQUID_CONCAT(msresamp_rrrf,name) #define LIQUID_MSRESAMP_MANGLE_CRCF(name) LIQUID_CONCAT(msresamp_crcf,name) #define LIQUID_MSRESAMP_MANGLE_CCCF(name) LIQUID_CONCAT(msresamp_cccf,name) #define LIQUID_MSRESAMP_DEFINE_API(MSRESAMP,TO,TC,TI) \ typedef struct MSRESAMP(_s) * MSRESAMP(); \ \ /* create multi-stage arbitrary resampler */ \ /* _r : resampling rate [output/input] */ \ /* _As : stop-band attenuation [dB] */ \ MSRESAMP() MSRESAMP(_create)(float _r, \ float _As); \ \ /* destroy multi-stage arbitrary resampler */ \ void MSRESAMP(_destroy)(MSRESAMP() _q); \ \ /* print msresamp object internals to stdout */ \ void MSRESAMP(_print)(MSRESAMP() _q); \ \ /* reset msresamp object internal state */ \ void MSRESAMP(_reset)(MSRESAMP() _q); \ \ /* get filter delay (output samples) */ \ float MSRESAMP(_get_delay)(MSRESAMP() _q); \ \ /* execute multi-stage resampler */ \ /* _q : msresamp object */ \ /* _x : input sample array [size: _nx x 1] */ \ /* _nx : input sample array size */ \ /* _y : output sample array [size: variable] */ \ /* _ny : number of samples written to _y */ \ void MSRESAMP(_execute)(MSRESAMP() _q, \ TI * _x, \ unsigned int _nx, \ TO * _y, \ unsigned int * _ny); \ LIQUID_MSRESAMP_DEFINE_API(LIQUID_MSRESAMP_MANGLE_RRRF, float, float, float) LIQUID_MSRESAMP_DEFINE_API(LIQUID_MSRESAMP_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) LIQUID_MSRESAMP_DEFINE_API(LIQUID_MSRESAMP_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // // Symbol timing recovery (symbol synchronizer) // #define LIQUID_SYMSYNC_MANGLE_RRRF(name) LIQUID_CONCAT(symsync_rrrf,name) #define LIQUID_SYMSYNC_MANGLE_CRCF(name) LIQUID_CONCAT(symsync_crcf,name) #define LIQUID_SYMSYNC_DEFINE_API(SYMSYNC,TO,TC,TI) \ \ typedef struct SYMSYNC(_s) * SYMSYNC(); \ \ /* create synchronizer object from external coefficients */ \ /* _k : samples per symbol */ \ /* _M : number of filters in the bank */ \ /* _h : matched filter coefficients [size: */ \ /* _h_len : length of matched filter */ \ SYMSYNC() SYMSYNC(_create)(unsigned int _k, \ unsigned int _M, \ TC * _h, \ unsigned int _h_len); \ \ /* create square-root Nyquist symbol synchronizer */ \ /* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \ /* _k : samples/symbol */ \ /* _m : symbol delay */ \ /* _beta : rolloff factor, beta in (0,1] */ \ /* _M : number of filters in the bank */ \ SYMSYNC() SYMSYNC(_create_rnyquist)(int _type, \ unsigned int _k, \ unsigned int _m, \ float _beta, \ unsigned int _M); \ \ /* create symsync using Kaiser filter interpolator; useful */ \ /* when the input signal has matched filter applied already */ \ /* _k : input samples/symbol */ \ /* _m : symbol delay */ \ /* _beta : rolloff factor, beta in (0,1] */ \ /* _M : number of filters in the bank */ \ SYMSYNC() SYMSYNC(_create_kaiser)(unsigned int _k, \ unsigned int _m, \ float _beta, \ unsigned int _M); \ \ /* destroy symsync object, freeing all internal memory */ \ void SYMSYNC(_destroy)(SYMSYNC() _q); \ \ /* print symsync object's parameters */ \ void SYMSYNC(_print)(SYMSYNC() _q); \ \ /* reset symsync internal state */ \ void SYMSYNC(_reset)(SYMSYNC() _q); \ \ /* lock/unlock loop control */ \ void SYMSYNC(_lock)( SYMSYNC() _q); \ void SYMSYNC(_unlock)(SYMSYNC() _q); \ \ /* set synchronizer output rate (samples/symbol) */ \ /* _q : synchronizer object */ \ /* _k_out : output samples/symbol */ \ void SYMSYNC(_set_output_rate)(SYMSYNC() _q, \ unsigned int _k_out); \ \ /* set loop-filter bandwidth */ \ /* _q : synchronizer object */ \ /* _bt : loop bandwidth */ \ void SYMSYNC(_set_lf_bw)(SYMSYNC() _q, \ float _bt); \ \ /* return instantaneous fractional timing offset estimate */ \ float SYMSYNC(_get_tau)(SYMSYNC() _q); \ \ /* execute synchronizer on input data array */ \ /* _q : synchronizer object */ \ /* _x : input data array */ \ /* _nx : number of input samples */ \ /* _y : output data array */ \ /* _ny : number of samples written to output buffer */ \ void SYMSYNC(_execute)(SYMSYNC() _q, \ TI * _x, \ unsigned int _nx, \ TO * _y, \ unsigned int * _ny); \ LIQUID_SYMSYNC_DEFINE_API(LIQUID_SYMSYNC_MANGLE_RRRF, float, float, float) LIQUID_SYMSYNC_DEFINE_API(LIQUID_SYMSYNC_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) // // Finite impulse response Farrow filter // #define LIQUID_FIRFARROW_MANGLE_RRRF(name) LIQUID_CONCAT(firfarrow_rrrf,name) #define LIQUID_FIRFARROW_MANGLE_CRCF(name) LIQUID_CONCAT(firfarrow_crcf,name) //#define LIQUID_FIRFARROW_MANGLE_CCCF(name) LIQUID_CONCAT(firfarrow_cccf,name) // Macro: // FIRFARROW : name-mangling macro // TO : output data type // TC : coefficients data type // TI : input data type #define LIQUID_FIRFARROW_DEFINE_API(FIRFARROW,TO,TC,TI) \ \ typedef struct FIRFARROW(_s) * FIRFARROW(); \ \ /* create firfarrow object */ \ /* _h_len : filter length */ \ /* _p : polynomial order */ \ /* _fc : filter cutoff frequency */ \ /* _As : stopband attenuation [dB] */ \ FIRFARROW() FIRFARROW(_create)(unsigned int _h_len, \ unsigned int _p, \ float _fc, \ float _As); \ \ /* destroy firfarrow object, freeing all internal memory */ \ void FIRFARROW(_destroy)(FIRFARROW() _q); \ \ /* print firfarrow object's internal properties */ \ void FIRFARROW(_print)(FIRFARROW() _q); \ \ /* reset firfarrow object's internal state */ \ void FIRFARROW(_reset)(FIRFARROW() _q); \ \ /* push sample into firfarrow object */ \ /* _q : firfarrow object */ \ /* _x : input sample */ \ void FIRFARROW(_push)(FIRFARROW() _q, \ TI _x); \ \ /* set fractional delay of firfarrow object */ \ /* _q : firfarrow object */ \ /* _mu : fractional sample delay */ \ void FIRFARROW(_set_delay)(FIRFARROW() _q, \ float _mu); \ \ /* execute firfarrow internal dot product */ \ /* _q : firfarrow object */ \ /* _y : output sample pointer */ \ void FIRFARROW(_execute)(FIRFARROW() _q, \ TO * _y); \ \ /* compute firfarrow filter on block of samples; the input */ \ /* and output arrays may have the same pointer */ \ /* _q : firfarrow object */ \ /* _x : input array [size: _n x 1] */ \ /* _n : input, output array size */ \ /* _y : output array [size: _n x 1] */ \ void FIRFARROW(_execute_block)(FIRFARROW() _q, \ TI * _x, \ unsigned int _n, \ TO * _y); \ \ /* get length of firfarrow object (number of filter taps) */ \ unsigned int FIRFARROW(_get_length)(FIRFARROW() _q); \ \ /* get coefficients of firfarrow object */ \ /* _q : firfarrow object */ \ /* _h : output coefficients pointer */ \ void FIRFARROW(_get_coefficients)(FIRFARROW() _q, \ float * _h); \ \ /* compute complex frequency response */ \ /* _q : filter object */ \ /* _fc : frequency */ \ /* _H : output frequency response */ \ void FIRFARROW(_freqresponse)(FIRFARROW() _q, \ float _fc, \ liquid_float_complex * _H); \ \ /* compute group delay [samples] */ \ /* _q : filter object */ \ /* _fc : frequency */ \ float FIRFARROW(_groupdelay)(FIRFARROW() _q, \ float _fc); \ LIQUID_FIRFARROW_DEFINE_API(LIQUID_FIRFARROW_MANGLE_RRRF, float, float, float) LIQUID_FIRFARROW_DEFINE_API(LIQUID_FIRFARROW_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) // // MODULE : framing // // framesyncstats : generic frame synchronizer statistic structure typedef struct { // signal quality float evm; // error vector magnitude [dB] float rssi; // received signal strength indicator [dB] float cfo; // carrier frequency offset (f/Fs) // demodulated frame symbols liquid_float_complex * framesyms; // pointer to array [size: framesyms x 1] unsigned int num_framesyms; // length of framesyms // modulation/coding scheme etc. unsigned int mod_scheme; // modulation scheme unsigned int mod_bps; // modulation depth (bits/symbol) unsigned int check; // data validity check (crc, checksum) unsigned int fec0; // forward error-correction (inner) unsigned int fec1; // forward error-correction (outer) } framesyncstats_s; // external framesyncstats default object extern framesyncstats_s framesyncstats_default; // initialize framesyncstats object on default void framesyncstats_init_default(framesyncstats_s * _stats); // print framesyncstats object void framesyncstats_print(framesyncstats_s * _stats); // framedatastats : gather frame data typedef struct { unsigned int num_frames_detected; unsigned int num_headers_valid; unsigned int num_payloads_valid; unsigned long int num_bytes_received; } framedatastats_s; // reset framedatastats object void framedatastats_reset(framedatastats_s * _stats); // print framedatastats object void framedatastats_print(framedatastats_s * _stats); // Generic frame synchronizer callback function type // _header : header data [size: 8 bytes] // _header_valid : is header valid? (0:no, 1:yes) // _payload : payload data [size: _payload_len] // _payload_len : length of payload (bytes) // _payload_valid : is payload valid? (0:no, 1:yes) // _stats : frame statistics object // _userdata : pointer to userdata typedef int (*framesync_callback)(unsigned char * _header, int _header_valid, unsigned char * _payload, unsigned int _payload_len, int _payload_valid, framesyncstats_s _stats, void * _userdata); // framesync csma callback functions invoked when signal levels is high or low // _userdata : user-defined data pointer typedef void (*framesync_csma_callback)(void * _userdata); // // packet encoder/decoder // typedef struct qpacketmodem_s * qpacketmodem; // create packet encoder qpacketmodem qpacketmodem_create (); void qpacketmodem_destroy(qpacketmodem _q); void qpacketmodem_reset (qpacketmodem _q); void qpacketmodem_print (qpacketmodem _q); int qpacketmodem_configure(qpacketmodem _q, unsigned int _payload_len, crc_scheme _check, fec_scheme _fec0, fec_scheme _fec1, int _ms); // get length of encoded frame in symbols unsigned int qpacketmodem_get_frame_len(qpacketmodem _q); // get unencoded/decoded payload length (bytes) unsigned int qpacketmodem_get_payload_len(qpacketmodem _q); // regular access methods unsigned int qpacketmodem_get_crc (qpacketmodem _q); unsigned int qpacketmodem_get_fec0 (qpacketmodem _q); unsigned int qpacketmodem_get_fec1 (qpacketmodem _q); unsigned int qpacketmodem_get_modscheme(qpacketmodem _q); // encode packet into un-modulated frame symbol indices // _q : qpacketmodem object // _payload : unencoded payload bytes // _syms : encoded but un-modulated payload symbol indices void qpacketmodem_encode_syms(qpacketmodem _q, const unsigned char * _payload, unsigned char * _syms); // decode packet from demodulated frame symbol indices (hard-decision decoding) // _q : qpacketmodem object // _syms : received hard-decision symbol indices [size: frame_len x 1] // _payload : recovered decoded payload bytes int qpacketmodem_decode_syms(qpacketmodem _q, unsigned char * _syms, unsigned char * _payload); // decode packet from demodulated frame bits (soft-decision decoding) // _q : qpacketmodem object // _bits : received soft-decision bits, [size: bps*frame_len x 1] // _payload : recovered decoded payload bytes int qpacketmodem_decode_bits(qpacketmodem _q, unsigned char * _bits, unsigned char * _payload); // encode and modulate packet into modulated frame samples // _q : qpacketmodem object // _payload : unencoded payload bytes // _frame : encoded/modulated payload symbols void qpacketmodem_encode(qpacketmodem _q, const unsigned char * _payload, liquid_float_complex * _frame); // decode packet from modulated frame samples, returning flag if CRC passed // NOTE: hard-decision decoding // _q : qpacketmodem object // _frame : encoded/modulated payload symbols // _payload : recovered decoded payload bytes int qpacketmodem_decode(qpacketmodem _q, liquid_float_complex * _frame, unsigned char * _payload); // decode packet from modulated frame samples, returning flag if CRC passed // NOTE: soft-decision decoding // _q : qpacketmodem object // _frame : encoded/modulated payload symbols // _payload : recovered decoded payload bytes int qpacketmodem_decode_soft(qpacketmodem _q, liquid_float_complex * _frame, unsigned char * _payload); // // pilot generator for streaming applications // typedef struct qpilotgen_s * qpilotgen; // create packet encoder qpilotgen qpilotgen_create(unsigned int _payload_len, unsigned int _pilot_spacing); qpilotgen qpilotgen_recreate(qpilotgen _q, unsigned int _payload_len, unsigned int _pilot_spacing); void qpilotgen_destroy(qpilotgen _q); void qpilotgen_reset( qpilotgen _q); void qpilotgen_print( qpilotgen _q); unsigned int qpilotgen_get_frame_len(qpilotgen _q); // insert pilot symbols void qpilotgen_execute(qpilotgen _q, liquid_float_complex * _payload, liquid_float_complex * _frame); // // pilot synchronizer for streaming applications // typedef struct qpilotsync_s * qpilotsync; // create packet encoder qpilotsync qpilotsync_create(unsigned int _payload_len, unsigned int _pilot_spacing); qpilotsync qpilotsync_recreate(qpilotsync _q, unsigned int _payload_len, unsigned int _pilot_spacing); void qpilotsync_destroy(qpilotsync _q); void qpilotsync_reset( qpilotsync _q); void qpilotsync_print( qpilotsync _q); unsigned int qpilotsync_get_frame_len(qpilotsync _q); // recover frame symbols from received frame void qpilotsync_execute(qpilotsync _q, liquid_float_complex * _frame, liquid_float_complex * _payload); // get estimates float qpilotsync_get_dphi(qpilotsync _q); float qpilotsync_get_phi (qpilotsync _q); float qpilotsync_get_gain(qpilotsync _q); // // Basic frame generator (64 bytes data payload) // // frame length in samples #define LIQUID_FRAME64_LEN (1440) typedef struct framegen64_s * framegen64; // create frame generator framegen64 framegen64_create(); // destroy frame generator void framegen64_destroy(framegen64 _q); // print frame generator internal properties void framegen64_print(framegen64 _q); // generate frame // _q : frame generator object // _header : 8-byte header data // _payload : 64-byte payload data // _frame : output frame samples [size: LIQUID_FRAME64_LEN x 1] void framegen64_execute(framegen64 _q, unsigned char * _header, unsigned char * _payload, liquid_float_complex * _frame); typedef struct framesync64_s * framesync64; // create framesync64 object // _callback : callback function // _userdata : user data pointer passed to callback function framesync64 framesync64_create(framesync_callback _callback, void * _userdata); // destroy frame synchronizer void framesync64_destroy(framesync64 _q); // print frame synchronizer internal properties void framesync64_print(framesync64 _q); // reset frame synchronizer internal state void framesync64_reset(framesync64 _q); // push samples through frame synchronizer // _q : frame synchronizer object // _x : input samples [size: _n x 1] // _n : number of input samples void framesync64_execute(framesync64 _q, liquid_float_complex * _x, unsigned int _n); // enable/disable debugging void framesync64_debug_enable(framesync64 _q); void framesync64_debug_disable(framesync64 _q); void framesync64_debug_print(framesync64 _q, const char * _filename); #if 0 // advanced modes void framesync64_set_csma_callbacks(framesync64 _q, framesync_csma_callback _csma_lock, framesync_csma_callback _csma_unlock, void * _csma_userdata); #endif // // Flexible frame : adjustable payload, mod scheme, etc., but bring // your own error correction, redundancy check // // frame generator typedef struct { unsigned int check; // data validity check unsigned int fec0; // forward error-correction scheme (inner) unsigned int fec1; // forward error-correction scheme (outer) unsigned int mod_scheme; // modulation scheme } flexframegenprops_s; void flexframegenprops_init_default(flexframegenprops_s * _fgprops); typedef struct flexframegen_s * flexframegen; // create flexframegen object // _props : frame properties (modulation scheme, etc.) flexframegen flexframegen_create(flexframegenprops_s * _props); // destroy flexframegen object void flexframegen_destroy(flexframegen _q); // print flexframegen object internals void flexframegen_print(flexframegen _q); // reset flexframegen object internals void flexframegen_reset(flexframegen _q); // is frame assembled? int flexframegen_is_assembled(flexframegen _q); // get frame properties void flexframegen_getprops(flexframegen _q, flexframegenprops_s * _props); // set frame properties int flexframegen_setprops(flexframegen _q, flexframegenprops_s * _props); // get length of assembled frame (samples) unsigned int flexframegen_getframelen(flexframegen _q); // assemble a frame from an array of data // _q : frame generator object // _header : frame header // _payload : payload data [size: _payload_len x 1] // _payload_len : payload data length void flexframegen_assemble(flexframegen _q, const unsigned char * _header, const unsigned char * _payload, unsigned int _payload_len); // write samples of assembled frame, two samples at a time, returning // '1' when frame is complete, '0' otherwise. Zeros will be written // to the buffer if the frame is not assembled // _q : frame generator object // _buffer : output buffer [size: _buffer_len x 1] // _buffer_len : output buffer length int flexframegen_write_samples(flexframegen _q, liquid_float_complex * _buffer, unsigned int _buffer_len); // frame synchronizer typedef struct flexframesync_s * flexframesync; // create flexframesync object // _callback : callback function // _userdata : user data pointer passed to callback function flexframesync flexframesync_create(framesync_callback _callback, void * _userdata); // destroy frame synchronizer void flexframesync_destroy(flexframesync _q); // print frame synchronizer internal properties void flexframesync_print(flexframesync _q); // reset frame synchronizer internal state void flexframesync_reset(flexframesync _q); // has frame been detected? int flexframesync_is_frame_open(flexframesync _q); // push samples through frame synchronizer // _q : frame synchronizer object // _x : input samples [size: _n x 1] // _n : number of input samples void flexframesync_execute(flexframesync _q, liquid_float_complex * _x, unsigned int _n); // frame data statistics void flexframesync_reset_framedatastats(flexframesync _q); framedatastats_s flexframesync_get_framedatastats (flexframesync _q); // enable/disable debugging void flexframesync_debug_enable(flexframesync _q); void flexframesync_debug_disable(flexframesync _q); void flexframesync_debug_print(flexframesync _q, const char * _filename); // // bpacket : binary packet suitable for data streaming // // // bpacket generator/encoder // typedef struct bpacketgen_s * bpacketgen; // create bpacketgen object // _m : p/n sequence length (ignored) // _dec_msg_len : decoded message length (original uncoded data) // _crc : data validity check (e.g. cyclic redundancy check) // _fec0 : inner forward error-correction code scheme // _fec1 : outer forward error-correction code scheme bpacketgen bpacketgen_create(unsigned int _m, unsigned int _dec_msg_len, int _crc, int _fec0, int _fec1); // re-create bpacketgen object from old object // _q : old bpacketgen object // _m : p/n sequence length (ignored) // _dec_msg_len : decoded message length (original uncoded data) // _crc : data validity check (e.g. cyclic redundancy check) // _fec0 : inner forward error-correction code scheme // _fec1 : outer forward error-correction code scheme bpacketgen bpacketgen_recreate(bpacketgen _q, unsigned int _m, unsigned int _dec_msg_len, int _crc, int _fec0, int _fec1); // destroy bpacketgen object, freeing all internally-allocated memory void bpacketgen_destroy(bpacketgen _q); // print bpacketgen internals void bpacketgen_print(bpacketgen _q); // return length of full packet unsigned int bpacketgen_get_packet_len(bpacketgen _q); // encode packet void bpacketgen_encode(bpacketgen _q, unsigned char * _msg_dec, unsigned char * _packet); // // bpacket synchronizer/decoder // typedef struct bpacketsync_s * bpacketsync; typedef int (*bpacketsync_callback)(unsigned char * _payload, int _payload_valid, unsigned int _payload_len, framesyncstats_s _stats, void * _userdata); bpacketsync bpacketsync_create(unsigned int _m, bpacketsync_callback _callback, void * _userdata); void bpacketsync_destroy(bpacketsync _q); void bpacketsync_print(bpacketsync _q); void bpacketsync_reset(bpacketsync _q); // run synchronizer on array of input bytes // _q : bpacketsync object // _bytes : input data array [size: _n x 1] // _n : input array size void bpacketsync_execute(bpacketsync _q, unsigned char * _bytes, unsigned int _n); // run synchronizer on input byte // _q : bpacketsync object // _byte : input byte void bpacketsync_execute_byte(bpacketsync _q, unsigned char _byte); // run synchronizer on input symbol // _q : bpacketsync object // _sym : input symbol with _bps significant bits // _bps : number of bits in input symbol void bpacketsync_execute_sym(bpacketsync _q, unsigned char _sym, unsigned int _bps); // execute one bit at a time void bpacketsync_execute_bit(bpacketsync _q, unsigned char _bit); // // GMSK frame generator // typedef struct gmskframegen_s * gmskframegen; // create GMSK frame generator gmskframegen gmskframegen_create(); void gmskframegen_destroy (gmskframegen _q); int gmskframegen_is_assembled (gmskframegen _q); void gmskframegen_print (gmskframegen _q); void gmskframegen_reset (gmskframegen _q); void gmskframegen_assemble (gmskframegen _q, const unsigned char * _header, const unsigned char * _payload, unsigned int _payload_len, crc_scheme _check, fec_scheme _fec0, fec_scheme _fec1); unsigned int gmskframegen_getframelen(gmskframegen _q); int gmskframegen_write_samples(gmskframegen _q, liquid_float_complex * _y); // // GMSK frame synchronizer // typedef struct gmskframesync_s * gmskframesync; // create GMSK frame synchronizer // _callback : callback function // _userdata : user data pointer passed to callback function gmskframesync gmskframesync_create(framesync_callback _callback, void * _userdata); void gmskframesync_destroy(gmskframesync _q); void gmskframesync_print(gmskframesync _q); void gmskframesync_reset(gmskframesync _q); int gmskframesync_is_frame_open(gmskframesync _q); void gmskframesync_execute(gmskframesync _q, liquid_float_complex * _x, unsigned int _n); // debugging void gmskframesync_debug_enable(gmskframesync _q); void gmskframesync_debug_disable(gmskframesync _q); void gmskframesync_debug_print(gmskframesync _q, const char * _filename); // // OFDM flexframe generator // // ofdm frame generator properties typedef struct { unsigned int check; // data validity check unsigned int fec0; // forward error-correction scheme (inner) unsigned int fec1; // forward error-correction scheme (outer) unsigned int mod_scheme; // modulation scheme //unsigned int block_size; // framing block size } ofdmflexframegenprops_s; void ofdmflexframegenprops_init_default(ofdmflexframegenprops_s * _props); typedef struct ofdmflexframegen_s * ofdmflexframegen; // create OFDM flexible framing generator object // _M : number of subcarriers, >10 typical // _cp_len : cyclic prefix length // _taper_len : taper length (OFDM symbol overlap) // _p : subcarrier allocation (null, pilot, data), [size: _M x 1] // _fgprops : frame properties (modulation scheme, etc.) ofdmflexframegen ofdmflexframegen_create(unsigned int _M, unsigned int _cp_len, unsigned int _taper_len, unsigned char * _p, ofdmflexframegenprops_s * _fgprops); // destroy ofdmflexframegen object void ofdmflexframegen_destroy(ofdmflexframegen _q); // print parameters, properties, etc. void ofdmflexframegen_print(ofdmflexframegen _q); // reset ofdmflexframegen object internals void ofdmflexframegen_reset(ofdmflexframegen _q); // is frame assembled? int ofdmflexframegen_is_assembled(ofdmflexframegen _q); // get properties void ofdmflexframegen_getprops(ofdmflexframegen _q, ofdmflexframegenprops_s * _props); // set properties void ofdmflexframegen_setprops(ofdmflexframegen _q, ofdmflexframegenprops_s * _props); // get length of frame (symbols) // _q : OFDM frame generator object unsigned int ofdmflexframegen_getframelen(ofdmflexframegen _q); // assemble a frame from an array of data (NULL pointers will use random data) // _q : OFDM frame generator object // _header : frame header [8 bytes] // _payload : payload data [size: _payload_len x 1] // _payload_len : payload data length void ofdmflexframegen_assemble(ofdmflexframegen _q, const unsigned char * _header, const unsigned char * _payload, unsigned int _payload_len); // write samples of assembled frame // _q : OFDM frame generator object // _buf : output buffer [size: _buf_len x 1] // _buf_len : output buffer length int ofdmflexframegen_write(ofdmflexframegen _q, liquid_float_complex * _buf, unsigned int _buf_len); // // OFDM flex frame synchronizer // typedef struct ofdmflexframesync_s * ofdmflexframesync; // create OFDM flexible framing synchronizer object // _M : number of subcarriers // _cp_len : cyclic prefix length // _taper_len : taper length (OFDM symbol overlap) // _p : subcarrier allocation (null, pilot, data), [size: _M x 1] // _callback : user-defined callback function // _userdata : user-defined data pointer ofdmflexframesync ofdmflexframesync_create(unsigned int _M, unsigned int _cp_len, unsigned int _taper_len, unsigned char * _p, framesync_callback _callback, void * _userdata); void ofdmflexframesync_destroy(ofdmflexframesync _q); void ofdmflexframesync_print(ofdmflexframesync _q); void ofdmflexframesync_reset(ofdmflexframesync _q); int ofdmflexframesync_is_frame_open(ofdmflexframesync _q); void ofdmflexframesync_execute(ofdmflexframesync _q, liquid_float_complex * _x, unsigned int _n); // query the received signal strength indication float ofdmflexframesync_get_rssi(ofdmflexframesync _q); // query the received carrier offset estimate float ofdmflexframesync_get_cfo(ofdmflexframesync _q); // enable/disable debugging void ofdmflexframesync_debug_enable(ofdmflexframesync _q); void ofdmflexframesync_debug_disable(ofdmflexframesync _q); void ofdmflexframesync_debug_print(ofdmflexframesync _q, const char * _filename); // // Binary P/N synchronizer // #define LIQUID_BSYNC_MANGLE_RRRF(name) LIQUID_CONCAT(bsync_rrrf,name) #define LIQUID_BSYNC_MANGLE_CRCF(name) LIQUID_CONCAT(bsync_crcf,name) #define LIQUID_BSYNC_MANGLE_CCCF(name) LIQUID_CONCAT(bsync_cccf,name) // Macro: // BSYNC : name-mangling macro // TO : output data type // TC : coefficients data type // TI : input data type #define LIQUID_BSYNC_DEFINE_API(BSYNC,TO,TC,TI) \ typedef struct BSYNC(_s) * BSYNC(); \ \ BSYNC() BSYNC(_create)(unsigned int _n, TC * _v); \ \ /* create binary synchronizer from m-sequence */ \ /* _g : m-sequence generator polynomial */ \ /* _k : samples/symbol (over-sampling factor) */ \ BSYNC() BSYNC(_create_msequence)(unsigned int _g, \ unsigned int _k); \ void BSYNC(_destroy)(BSYNC() _fs); \ void BSYNC(_print)(BSYNC() _fs); \ void BSYNC(_correlate)(BSYNC() _fs, TI _sym, TO * _y); LIQUID_BSYNC_DEFINE_API(LIQUID_BSYNC_MANGLE_RRRF, float, float, float) LIQUID_BSYNC_DEFINE_API(LIQUID_BSYNC_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) LIQUID_BSYNC_DEFINE_API(LIQUID_BSYNC_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // // Pre-demodulation synchronizers (binary and otherwise) // #define LIQUID_PRESYNC_MANGLE_CCCF(name) LIQUID_CONCAT( presync_cccf,name) #define LIQUID_BPRESYNC_MANGLE_CCCF(name) LIQUID_CONCAT(bpresync_cccf,name) // Macro: // PRESYNC : name-mangling macro // TO : output data type // TC : coefficients data type // TI : input data type #define LIQUID_PRESYNC_DEFINE_API(PRESYNC,TO,TC,TI) \ typedef struct PRESYNC(_s) * PRESYNC(); \ \ /* create pre-demod synchronizer */ \ /* _v : baseband sequence */ \ /* _n : baseband sequence length */ \ /* _dphi_max : maximum absolute frequency deviation */ \ /* _m : number of correlators */ \ PRESYNC() PRESYNC(_create)(TC * _v, \ unsigned int _n, \ float _dphi_max, \ unsigned int _m); \ \ /* destroy pre-demod synchronizer */ \ void PRESYNC(_destroy)(PRESYNC() _q); \ \ /* print pre-demod synchronizer internal state */ \ void PRESYNC(_print)(PRESYNC() _q); \ \ /* reset pre-demod synchronizer internal state */ \ void PRESYNC(_reset)(PRESYNC() _q); \ \ /* push input sample into pre-demod synchronizer */ \ /* _q : pre-demod synchronizer object */ \ /* _x : input sample */ \ void PRESYNC(_push)(PRESYNC() _q, \ TI _x); \ \ /* correlate input sequence */ \ /* _q : pre-demod synchronizer object */ \ /* _rxy : output cross correlation */ \ /* _dphi_hat : output frequency offset estiamte */ \ void PRESYNC(_correlate)(PRESYNC() _q, \ TO * _rxy, \ float * _dphi_hat); \ // non-binary pre-demodulation synchronizer LIQUID_PRESYNC_DEFINE_API(LIQUID_PRESYNC_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // binary pre-demodulation synchronizer LIQUID_PRESYNC_DEFINE_API(LIQUID_BPRESYNC_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // // Frame detector // typedef struct qdetector_cccf_s * qdetector_cccf; // create detector with generic sequence // _s : sample sequence // _s_len : length of sample sequence qdetector_cccf qdetector_cccf_create(liquid_float_complex * _s, unsigned int _s_len); // create detector from sequence of symbols using internal linear interpolator // _sequence : symbol sequence // _sequence_len : length of symbol sequence // _ftype : filter prototype (e.g. LIQUID_FIRFILT_RRC) // _k : samples/symbol // _m : filter delay // _beta : excess bandwidth factor qdetector_cccf qdetector_cccf_create_linear(liquid_float_complex * _sequence, unsigned int _sequence_len, int _ftype, unsigned int _k, unsigned int _m, float _beta); // create detector from sequence of GMSK symbols // _sequence : bit sequence // _sequence_len : length of bit sequence // _k : samples/symbol // _m : filter delay // _beta : excess bandwidth factor qdetector_cccf qdetector_cccf_create_gmsk(unsigned char * _sequence, unsigned int _sequence_len, unsigned int _k, unsigned int _m, float _beta); void qdetector_cccf_destroy(qdetector_cccf _q); void qdetector_cccf_print (qdetector_cccf _q); void qdetector_cccf_reset (qdetector_cccf _q); // run detector, looking for sequence; return pointer to aligned, buffered samples void * qdetector_cccf_execute(qdetector_cccf _q, liquid_float_complex _x); // set detection threshold (should be between 0 and 1, good starting point is 0.5) void qdetector_cccf_set_threshold(qdetector_cccf _q, float _threshold); // set carrier offset search range void qdetector_cccf_set_range(qdetector_cccf _q, float _dphi_max); // access methods unsigned int qdetector_cccf_get_seq_len (qdetector_cccf _q); // sequence length const void * qdetector_cccf_get_sequence(qdetector_cccf _q); // pointer to sequence unsigned int qdetector_cccf_get_buf_len (qdetector_cccf _q); // buffer length float qdetector_cccf_get_tau (qdetector_cccf _q); // fractional timing offset estimate float qdetector_cccf_get_gamma (qdetector_cccf _q); // channel gain float qdetector_cccf_get_dphi (qdetector_cccf _q); // carrier frequency offset estimate float qdetector_cccf_get_phi (qdetector_cccf _q); // carrier phase offset estimate // // Pre-demodulation detector // typedef struct detector_cccf_s * detector_cccf; // create pre-demod detector // _s : sequence // _n : sequence length // _threshold : detection threshold (default: 0.7) // _dphi_max : maximum carrier offset detector_cccf detector_cccf_create(liquid_float_complex * _s, unsigned int _n, float _threshold, float _dphi_max); // destroy pre-demo detector object void detector_cccf_destroy(detector_cccf _q); // print pre-demod detector internal state void detector_cccf_print(detector_cccf _q); // reset pre-demod detector internal state void detector_cccf_reset(detector_cccf _q); // Run sample through pre-demod detector's correlator. // Returns '1' if signal was detected, '0' otherwise // _q : pre-demod detector // _x : input sample // _tau_hat : fractional sample offset estimate (set when detected) // _dphi_hat : carrier frequency offset estimate (set when detected) // _gamma_hat : channel gain estimate (set when detected) int detector_cccf_correlate(detector_cccf _q, liquid_float_complex _x, float * _tau_hat, float * _dphi_hat, float * _gamma_hat); // // symbol streaming for testing (no meaningful data, just symbols) // #define LIQUID_SYMSTREAM_MANGLE_CFLOAT(name) LIQUID_CONCAT(symstreamcf,name) #define LIQUID_SYMSTREAM_DEFINE_API(SYMSTREAM,TO) \ \ typedef struct SYMSTREAM(_s) * SYMSTREAM(); \ \ /* create default symstream object */ \ /* (LIQUID_RNYQUIST_ARKAISER, k=2, m=7, beta=0.3, QPSK) */ \ SYMSTREAM() SYMSTREAM(_create)(void); \ \ /* create symstream object with linear modulation */ \ /* _ftype : filter type (e.g. LIQUID_RNYQUIST_RRC) */ \ /* _k : samples per symbol */ \ /* _m : filter delay (symbols) */ \ /* _beta : filter excess bandwidth */ \ /* _ms : modulation scheme (e.g. LIQUID_MODEM_QPSK) */ \ SYMSTREAM() SYMSTREAM(_create_linear)(int _ftype, \ unsigned int _k, \ unsigned int _m, \ float _beta, \ int _ms); \ \ /* destroy symstream object, freeing all internal memory */ \ void SYMSTREAM(_destroy)(SYMSTREAM() _q); \ \ /* print symstream object's parameters */ \ void SYMSTREAM(_print)(SYMSTREAM() _q); \ \ /* reset symstream internal state */ \ void SYMSTREAM(_reset)(SYMSTREAM() _q); \ \ /* write block of samples to output buffer */ \ /* _q : synchronizer object */ \ /* _buf : output buffer [size: _buf_len x 1] */ \ /* _buf_len: output buffer size */ \ void SYMSTREAM(_write_samples)(SYMSTREAM() _q, \ TO * _buf, \ unsigned int _buf_len); \ LIQUID_SYMSTREAM_DEFINE_API(LIQUID_SYMSTREAM_MANGLE_CFLOAT, liquid_float_complex) // // multi-signal source for testing (no meaningful data, just signals) // #define LIQUID_MSOURCE_MANGLE_CFLOAT(name) LIQUID_CONCAT(msourcecf,name) #define LIQUID_MSOURCE_DEFINE_API(MSOURCE,TO) \ \ typedef struct MSOURCE(_s) * MSOURCE(); \ \ /* create default msource object */ \ MSOURCE() MSOURCE(_create)(void); \ \ /* destroy msource object */ \ void MSOURCE(_destroy)(MSOURCE() _q); \ \ /* print msrouce object */ \ void MSOURCE(_print)(MSOURCE() _q); \ \ /* reset msrouce object */ \ void MSOURCE(_reset)(MSOURCE() _q); \ \ /* add signal sources */ \ int MSOURCE(_add_tone) (MSOURCE() _q); \ int MSOURCE(_add_noise)(MSOURCE() _q, float _bandwidth); \ int MSOURCE(_add_modem)(MSOURCE() _q, \ int _ms, \ unsigned int _k, \ unsigned int _m, \ float _beta); \ \ /* remove signal */ \ void MSOURCE(_remove)(MSOURCE() _q, int _id); \ \ /* enable/disable signal */ \ void MSOURCE(_enable) (MSOURCE() _q, int _id); \ void MSOURCE(_disable)(MSOURCE() _q, int _id); \ \ /* set signal gain */ \ /* _q : msource object */ \ /* _id : source id */ \ /* _gain : signal gain */ \ void MSOURCE(_set_gain)(MSOURCE() _q, \ int _id, \ float _gain_dB); \ \ /* set carrier offset to signal */ \ /* _q : msource object */ \ /* _id : source id */ \ /* _fc : carrier offset, fc in [-0.5,0.5] */ \ void MSOURCE(_set_frequency)(MSOURCE() _q, \ int _id, \ float _dphi); \ \ /* write block of samples to output buffer */ \ /* _q : synchronizer object */ \ /* _buf : output buffer [size: _buf_len x 1] */ \ /* _buf_len: output buffer size */ \ void MSOURCE(_write_samples)(MSOURCE() _q, \ TO * _buf, \ unsigned int _buf_len); \ LIQUID_MSOURCE_DEFINE_API(LIQUID_MSOURCE_MANGLE_CFLOAT, liquid_float_complex) // // Symbol tracking: AGC > symsync > EQ > carrier recovery // #define LIQUID_SYMTRACK_MANGLE_RRRF(name) LIQUID_CONCAT(symtrack_rrrf,name) #define LIQUID_SYMTRACK_MANGLE_CCCF(name) LIQUID_CONCAT(symtrack_cccf,name) // large macro // SYMTRACK : name-mangling macro // T : data type, primitive // TO : data type, output // TC : data type, coefficients // TI : data type, input #define LIQUID_SYMTRACK_DEFINE_API(SYMTRACK,T,TO,TC,TI) \ \ typedef struct SYMTRACK(_s) * SYMTRACK(); \ \ /* create symtrack object with default parameters */ \ /* _ftype : filter type (e.g. LIQUID_RNYQUIST_RRC) */ \ /* _k : samples per symbol */ \ /* _m : filter delay (symbols) */ \ /* _beta : filter excess bandwidth */ \ /* _ms : modulation scheme (e.g. LIQUID_MODEM_QPSK) */ \ SYMTRACK() SYMTRACK(_create)(int _ftype, \ unsigned int _k, \ unsigned int _m, \ float _beta, \ int _ms); \ \ /* create symtrack object using default parameters */ \ SYMTRACK() SYMTRACK(_create_default)(); \ \ /* destroy symtrack object, freeing all internal memory */ \ void SYMTRACK(_destroy)(SYMTRACK() _q); \ \ /* print symtrack object's parameters */ \ void SYMTRACK(_print)(SYMTRACK() _q); \ \ /* reset symtrack internal state */ \ void SYMTRACK(_reset)(SYMTRACK() _q); \ \ /* set symtrack modulation scheme */ \ void SYMTRACK(_set_modscheme)(SYMTRACK() _q, int _ms); \ \ /* set symtrack internal bandwidth */ \ void SYMTRACK(_set_bandwidth)(SYMTRACK() _q, float _bw); \ \ /* adjust internal nco by requested phase */ \ void SYMTRACK(_adjust_phase)(SYMTRACK() _q, T _dphi); \ \ /* execute synchronizer on single input sample */ \ /* _q : synchronizer object */ \ /* _x : input data sample */ \ /* _y : output data array */ \ /* _ny : number of samples written to output buffer */ \ void SYMTRACK(_execute)(SYMTRACK() _q, \ TI _x, \ TO * _y, \ unsigned int * _ny); \ \ /* execute synchronizer on input data array */ \ /* _q : synchronizer object */ \ /* _x : input data array */ \ /* _nx : number of input samples */ \ /* _y : output data array */ \ /* _ny : number of samples written to output buffer */ \ void SYMTRACK(_execute_block)(SYMTRACK() _q, \ TI * _x, \ unsigned int _nx, \ TO * _y, \ unsigned int * _ny); \ LIQUID_SYMTRACK_DEFINE_API(LIQUID_SYMTRACK_MANGLE_RRRF, float, float, float, float) LIQUID_SYMTRACK_DEFINE_API(LIQUID_SYMTRACK_MANGLE_CCCF, float, liquid_float_complex, liquid_float_complex, liquid_float_complex) // // MODULE : math // // ln( Gamma(z) ) float liquid_lngammaf(float _z); // Gamma(z) float liquid_gammaf(float _z); // ln( gamma(z,alpha) ) : lower incomplete gamma function float liquid_lnlowergammaf(float _z, float _alpha); // ln( Gamma(z,alpha) ) : upper incomplete gamma function float liquid_lnuppergammaf(float _z, float _alpha); // gamma(z,alpha) : lower incomplete gamma function float liquid_lowergammaf(float _z, float _alpha); // Gamma(z,alpha) : upper incomplete gamma function float liquid_uppergammaf(float _z, float _alpha); // n! float liquid_factorialf(unsigned int _n); // ln(I_v(z)) : log Modified Bessel function of the first kind float liquid_lnbesselif(float _nu, float _z); // I_v(z) : Modified Bessel function of the first kind float liquid_besselif(float _nu, float _z); // I_0(z) : Modified Bessel function of the first kind (order zero) float liquid_besseli0f(float _z); // J_v(z) : Bessel function of the first kind float liquid_besseljf(float _nu, float _z); // J_0(z) : Bessel function of the first kind (order zero) float liquid_besselj0f(float _z); // Q function float liquid_Qf(float _z); // Marcum Q-function float liquid_MarcumQf(int _M, float _alpha, float _beta); // Marcum Q-function (M=1) float liquid_MarcumQ1f(float _alpha, float _beta); // sin(pi x) / (pi x) float sincf(float _x); // next power of 2 : y = ceil(log2(_x)) unsigned int liquid_nextpow2(unsigned int _x); // (n choose k) = n! / ( k! (n-k)! ) float liquid_nchoosek(unsigned int _n, unsigned int _k); // // Windowing functions // // Modulation schemes available #define LIQUID_WINDOW_NUM_FUNCTIONS (10) // prototypes typedef enum { LIQUID_WINDOW_UNKNOWN=0, // unknown/unsupported scheme LIQUID_WINDOW_HAMMING, // Hamming LIQUID_WINDOW_HANN, // Hann LIQUID_WINDOW_BLACKMANHARRIS, // Blackman-harris (4-term) LIQUID_WINDOW_BLACKMANHARRIS7, // Blackman-harris (7-term) LIQUID_WINDOW_KAISER, // Kaiser (beta factor unspecified) LIQUID_WINDOW_FLATTOP, // flat top (includes negative values) LIQUID_WINDOW_TRIANGULAR, // triangular LIQUID_WINDOW_RCOSTAPER, // raised-cosine taper (taper size unspecified) LIQUID_WINDOW_KBD, // Kaiser-Bessel derived window (beta factor unspecified) } liquid_window_type; // pretty names for window extern const char * liquid_window_str[LIQUID_WINDOW_NUM_FUNCTIONS][2]; // Print compact list of existing and available windowing functions void liquid_print_windows(); // returns modulation_scheme based on input string liquid_window_type liquid_getopt_str2window(const char * _str); // Kaiser-Bessel derived window (single sample) // _n : index (0 <= _n < _N) // _N : length of filter (must be even) // _beta : Kaiser window parameter (_beta > 0) float liquid_kbd(unsigned int _n, unsigned int _N, float _beta); // Kaiser-Bessel derived window (full window) // _n : length of filter (must be even) // _beta : Kaiser window parameter (_beta > 0) // _w : resulting window void liquid_kbd_window(unsigned int _n, float _beta, float * _w); // Kaiser window // _n : window index // _N : full window length // _beta : Kaiser-Bessel window shape parameter // _dt : fractional sample offset float kaiser(unsigned int _n, unsigned int _N, float _beta, float _dt); // Hamming window // _n : window index // _N : full window length float hamming(unsigned int _n, unsigned int _N); // Hann window // _n : window index // _N : full window length float hann(unsigned int _n, unsigned int _N); // Blackman-harris window // _n : window index // _N : full window length float blackmanharris(unsigned int _n, unsigned int _N); // 7th order Blackman-harris window // _n : window index // _N : full window length float blackmanharris7(unsigned int _n, unsigned int _N); // Flat-top window // _n : window index // _N : full window length float flattop(unsigned int _n, unsigned int _N); // Triangular window // _n : window index // _N : full window length // _L : triangle length, _L in {_N, _N+1, _N-1} float triangular(unsigned int _n, unsigned int _N, unsigned int _L); // raised-cosine tapering window // _n : window index // _t : taper length // _N : full window length float liquid_rcostaper_windowf(unsigned int _n, unsigned int _t, unsigned int _N); // polynomials #define LIQUID_POLY_MANGLE_DOUBLE(name) LIQUID_CONCAT(poly, name) #define LIQUID_POLY_MANGLE_FLOAT(name) LIQUID_CONCAT(polyf, name) #define LIQUID_POLY_MANGLE_CDOUBLE(name) LIQUID_CONCAT(polyc, name) #define LIQUID_POLY_MANGLE_CFLOAT(name) LIQUID_CONCAT(polycf, name) // large macro // POLY : name-mangling macro // T : data type // TC : data type (complex) #define LIQUID_POLY_DEFINE_API(POLY,T,TC) \ /* evaluate polynomial _p (order _k-1) at value _x */ \ T POLY(_val)(T * _p, unsigned int _k, T _x); \ \ /* least-squares polynomial fit (order _k-1) */ \ void POLY(_fit)(T * _x, \ T * _y, \ unsigned int _n, \ T * _p, \ unsigned int _k); \ \ /* Lagrange polynomial exact fit (order _n-1) */ \ void POLY(_fit_lagrange)(T * _x, \ T * _y, \ unsigned int _n, \ T * _p); \ \ /* Lagrange polynomial interpolation */ \ T POLY(_interp_lagrange)(T * _x, \ T * _y, \ unsigned int _n, \ T _x0); \ \ /* Lagrange polynomial fit (barycentric form) */ \ void POLY(_fit_lagrange_barycentric)(T * _x, \ unsigned int _n, \ T * _w); \ \ /* Lagrange polynomial interpolation (barycentric form) */ \ T POLY(_val_lagrange_barycentric)(T * _x, \ T * _y, \ T * _w, \ T _x0, \ unsigned int _n); \ \ /* expands the polynomial: \ * P_n(x) = (1+x)^n \ * as \ * P_n(x) = p[0] + p[1]*x + p[2]*x^2 + ... + p[n]x^n \ * NOTE: _p has order n=m+k (array is length n+1) \ */ \ void POLY(_expandbinomial)(unsigned int _n, \ T * _p); \ \ /* expands the polynomial: \ * P_n(x) = (1+x)^m * (1-x)^k \ * as \ * P_n(x) = p[0] + p[1]*x + p[2]*x^2 + ... + p[n]x^n \ * NOTE: _p has order n=m+k (array is length n+1) \ */ \ void POLY(_expandbinomial_pm)(unsigned int _m, \ unsigned int _k, \ T * _p); \ \ /* expands the polynomial: \ * P_n(x) = (x-r[0]) * (x-r[1]) * ... * (x-r[n-1]) \ * as \ * P_n(x) = c[0] + c[1]*x + ... + c[n]*x^n \ * where r[0],r[1],...,r[n-1] are the roots of P_n(x) \ * NOTE: _c has order _n (array is length _n+1) \ */ \ void POLY(_expandroots)(T * _a, \ unsigned int _n, \ T * _c); \ \ /* expands the polynomial: \ * P_n(x) = \ * (x*b[0]-a[0]) * (x*b[1]-a[1]) * ... * (x*b[n-1]-a[n-1]) \ * as \ * P_n(x) = c[0] + c[1]*x + ... + c[n]*x^n \ * NOTE: _c has order _n (array is length _n+1) \ */ \ void POLY(_expandroots2)(T * _a, \ T * _b, \ unsigned int _n, \ T * _c); \ \ /* find roots of the polynomial (complex) */ \ /* _poly : poly array, ascending powers [size: _k x 1] */ \ /* _k : poly length (poly order = _k - 1) */ \ /* _roots : resulting complex roots [size: _k-1 x 1] */ \ void POLY(_findroots)(T * _poly, \ unsigned int _n, \ TC * _roots); \ \ /* find the complex roots of the polynomial using the */ \ /* Durand-Kerner method */ \ void POLY(_findroots_durandkerner)(T * _poly, \ unsigned int _k, \ TC * _roots); \ \ /* find the complex roots of the polynomial using */ \ /* Bairstow's method */ \ void POLY(_findroots_bairstow)(T * _poly, \ unsigned int _k, \ TC * _roots); \ \ /* expands the multiplication of two polynomials */ \ void POLY(_mul)(T * _a, \ unsigned int _order_a, \ T * _b, \ unsigned int _order_b, \ T * _c); \ LIQUID_POLY_DEFINE_API(LIQUID_POLY_MANGLE_DOUBLE, double, liquid_double_complex) LIQUID_POLY_DEFINE_API(LIQUID_POLY_MANGLE_FLOAT, float, liquid_float_complex) LIQUID_POLY_DEFINE_API(LIQUID_POLY_MANGLE_CDOUBLE, liquid_double_complex, liquid_double_complex) LIQUID_POLY_DEFINE_API(LIQUID_POLY_MANGLE_CFLOAT, liquid_float_complex, liquid_float_complex) #if 0 // expands the polynomial: (1+x)^n void poly_binomial_expand(unsigned int _n, int * _c); // expands the polynomial: (1+x)^k * (1-x)^(n-k) void poly_binomial_expand_pm(unsigned int _n, unsigned int _k, int * _c); #endif // // modular arithmetic, etc. // // maximum number of factors #define LIQUID_MAX_FACTORS (40) // is number prime? int liquid_is_prime(unsigned int _n); // compute number's prime factors // _n : number to factor // _factors : pre-allocated array of factors [size: LIQUID_MAX_FACTORS x 1] // _num_factors: number of factors found, sorted ascending void liquid_factor(unsigned int _n, unsigned int * _factors, unsigned int * _num_factors); // compute number's unique prime factors // _n : number to factor // _factors : pre-allocated array of factors [size: LIQUID_MAX_FACTORS x 1] // _num_factors: number of unique factors found, sorted ascending void liquid_unique_factor(unsigned int _n, unsigned int * _factors, unsigned int * _num_factors); // compute c = base^exp (mod n) unsigned int liquid_modpow(unsigned int _base, unsigned int _exp, unsigned int _n); // find smallest primitive root of _n unsigned int liquid_primitive_root(unsigned int _n); // find smallest primitive root of _n, assuming _n is prime unsigned int liquid_primitive_root_prime(unsigned int _n); // Euler's totient function unsigned int liquid_totient(unsigned int _n); // // MODULE : matrix // #define LIQUID_MATRIX_MANGLE_DOUBLE(name) LIQUID_CONCAT(matrix, name) #define LIQUID_MATRIX_MANGLE_FLOAT(name) LIQUID_CONCAT(matrixf, name) #define LIQUID_MATRIX_MANGLE_CDOUBLE(name) LIQUID_CONCAT(matrixc, name) #define LIQUID_MATRIX_MANGLE_CFLOAT(name) LIQUID_CONCAT(matrixcf, name) // large macro // MATRIX : name-mangling macro // T : data type #define LIQUID_MATRIX_DEFINE_API(MATRIX,T) \ \ /* print array as matrix */ \ /* _x : input matrix [size: _r x _c] */ \ /* _r : rows */ \ /* _c : columns */ \ void MATRIX(_print)(T * _x, \ unsigned int _r, \ unsigned int _c); \ \ /* add two matrices _x and _y saving the result in _z */ \ /* _x : input matrix [size: _r x _c] */ \ /* _y : input matrix [size: _r x _c] */ \ /* _z : output matrix [size: _r x _c] */ \ /* _r : rows */ \ /* _c : columns */ \ void MATRIX(_add)(T * _x, \ T * _y, \ T * _z, \ unsigned int _r, \ unsigned int _c); \ \ /* subtract two matrices _x and _y saving the result in _z */ \ /* _x : input matrix [size: _r x _c] */ \ /* _y : input matrix [size: _r x _c] */ \ /* _z : output matrix [size: _r x _c] */ \ /* _r : rows */ \ /* _c : columns */ \ void MATRIX(_sub)(T * _x, \ T * _y, \ T * _z, \ unsigned int _r, \ unsigned int _c); \ \ /* perform point-wise multiplication of two matrices _x */ \ /* and _y saving the result in _z */ \ /* _x : input matrix [size: _r x _c] */ \ /* _y : input matrix [size: _r x _c] */ \ /* _z : output matrix [size: _r x _c] */ \ /* _r : rows */ \ /* _c : columns */ \ void MATRIX(_pmul)(T * _x, \ T * _y, \ T * _z, \ unsigned int _r, \ unsigned int _c); \ \ /* perform point-wise division of two matrices _x and _y */ \ /* saving the result in _z */ \ /* _x : input matrix [size: _r x _c] */ \ /* _y : input matrix [size: _r x _c] */ \ /* _z : output matrix [size: _r x _c] */ \ /* _r : rows */ \ /* _c : columns */ \ void MATRIX(_pdiv)(T * _x, \ T * _y, \ T * _z, \ unsigned int _r, \ unsigned int _c); \ \ /* multiply two matrices _x and _y storing the result in _z */ \ /* NOTE: _rz = _rx, _cz = _cy, and _cx = _ry */ \ /* _x : input matrix [size: _rx x _cx] */ \ /* _y : input matrix [size: _ry x _cy] */ \ /* _z : output matrix [size: _rz x _cz] */ \ void MATRIX(_mul)(T * _x, unsigned int _rx, unsigned int _cx, \ T * _y, unsigned int _ry, unsigned int _cy, \ T * _z, unsigned int _rz, unsigned int _cz); \ \ /* solve _x = _y*_z for _z for square matrices of size _n */ \ /* _x : input matrix [size: _n x _n] */ \ /* _y : input matrix [size: _n x _n] */ \ /* _z : output matrix [size: _n x _n] */ \ void MATRIX(_div)(T * _x, \ T * _y, \ T * _z, \ unsigned int _n); \ \ /* compute the determinant of a square matrix _x */ \ /* _x : input matrix [size: _r x _c] */ \ /* _r : rows */ \ /* _c : columns */ \ T MATRIX(_det)(T * _x, \ unsigned int _r, \ unsigned int _c); \ \ /* compute the in-place transpose of the matrix _x */ \ /* _x : input matrix [size: _r x _c] */ \ /* _r : rows */ \ /* _c : columns */ \ void MATRIX(_trans)(T * _x, \ unsigned int _r, \ unsigned int _c); \ \ /* compute the in-place Hermitian transpose of _x */ \ /* _x : input matrix [size: _r x _c] */ \ /* _r : rows */ \ /* _c : columns */ \ void MATRIX(_hermitian)(T * _x, \ unsigned int _r, \ unsigned int _c); \ \ /* compute x*x' on [m x n] matrix, result: [m x m] */ \ /* _x : input matrix [size: _m x _n] */ \ /* _m : input rows */ \ /* _n : input columns */ \ /* _xxT : output matrix [size: _m x _m] */ \ void MATRIX(_mul_transpose)(T * _x, \ unsigned int _m, \ unsigned int _n, \ T * _xxT); \ \ /* compute x'*x on [m x n] matrix, result: [n x n] */ \ /* _x : input matrix [size: _m x _n] */ \ /* _m : input rows */ \ /* _n : input columns */ \ /* _xTx : output matrix [size: _n x _n] */ \ void MATRIX(_transpose_mul)(T * _x, \ unsigned int _m, \ unsigned int _n, \ T * _xTx); \ \ /* compute x*x.' on [m x n] matrix, result: [m x m] */ \ /* _x : input matrix [size: _m x _n] */ \ /* _m : input rows */ \ /* _n : input columns */ \ /* _xxH : output matrix [size: _m x _m] */ \ void MATRIX(_mul_hermitian)(T * _x, \ unsigned int _m, \ unsigned int _n, \ T * _xxH); \ \ /* compute x.'*x on [m x n] matrix, result: [n x n] */ \ /* _x : input matrix [size: _m x _n] */ \ /* _m : input rows */ \ /* _n : input columns */ \ /* _xHx : output matrix [size: _n x _n] */ \ void MATRIX(_hermitian_mul)(T * _x, \ unsigned int _m, \ unsigned int _n, \ T * _xHx); \ \ \ /* augment two matrices _x and _y storing the result in _z */ \ /* NOTE: _rz = _rx = _ry, _rx = _ry, and _cz = _cx + _cy */ \ /* _x : input matrix [size: _rx x _cx] */ \ /* _y : input matrix [size: _ry x _cy] */ \ /* _z : output matrix [size: _rz x _cz] */ \ void MATRIX(_aug)(T * _x, unsigned int _rx, unsigned int _cx, \ T * _y, unsigned int _ry, unsigned int _cy, \ T * _z, unsigned int _rz, unsigned int _cz); \ \ /* compute the inverse of a square matrix _x */ \ /* _x : input/output matrix [size: _r x _c] */ \ /* _r : rows */ \ /* _c : columns */ \ void MATRIX(_inv)(T * _x, \ unsigned int _r, \ unsigned int _c); \ \ /* generate the identity square matrix of size _n */ \ /* _x : output matrix [size: _n x _n] */ \ /* _n : dimensions of _x */ \ void MATRIX(_eye)(T * _x, \ unsigned int _n); \ \ /* generate the all-ones matrix of size _n */ \ /* _x : output matrix [size: _r x _c] */ \ /* _r : rows */ \ /* _c : columns */ \ void MATRIX(_ones)(T * _n, \ unsigned int _r, \ unsigned int _c); \ \ /* generate the all-zeros matrix of size _n */ \ /* _x : output matrix [size: _r x _c] */ \ /* _r : rows */ \ /* _c : columns */ \ void MATRIX(_zeros)(T * _x, \ unsigned int _r, \ unsigned int _c); \ \ /* perform Gauss-Jordan elimination on matrix _x */ \ /* _x : input/output matrix [size: _r x _c] */ \ /* _r : rows */ \ /* _c : columns */ \ void MATRIX(_gjelim)(T * _x, \ unsigned int _r, \ unsigned int _c); \ \ /* pivot on element _x[_r,_c] */ \ /* _x : output matrix [size: _rx x _cx] */ \ /* _rx : rows of _x */ \ /* _cx : columns of _x */ \ /* _r : pivot row */ \ /* _c : pivot column */ \ void MATRIX(_pivot)(T * _x, \ unsigned int _rx, \ unsigned int _cx, \ unsigned int _r, \ unsigned int _c); \ \ /* swap rows _r1 and _r2 of matrix _x */ \ /* _x : input/output matrix [size: _rx x _cx] */ \ /* _rx : rows of _x */ \ /* _cx : columns of _x */ \ /* _r1 : first row to swap */ \ /* _r2 : second row to swap */ \ void MATRIX(_swaprows)(T * _x, \ unsigned int _rx, \ unsigned int _cx, \ unsigned int _r1, \ unsigned int _r2); \ \ /* solve linear system of _n equations: _A*_x = _b */ \ /* _A : system matrix [size: _n x _n] */ \ /* _n : system size */ \ /* _b : equality vector [size: _n x 1] */ \ /* _x : solution vector [size: _n x 1] */ \ /* _opts : options (ignored for now) */ \ void MATRIX(_linsolve)(T * _A, \ unsigned int _n, \ T * _b, \ T * _x, \ void * _opts); \ \ /* solve linear system of equations using conjugate */ \ /* gradient method */ \ /* _A : symmetric positive definite square matrix */ \ /* _n : system dimension */ \ /* _b : equality [size: _n x 1] */ \ /* _x : solution estimate [size: _n x 1] */ \ /* _opts : options (ignored for now) */ \ void MATRIX(_cgsolve)(T * _A, \ unsigned int _n, \ T * _b, \ T * _x, \ void * _opts); \ \ /* L/U/P decomposition, Crout's method */ \ /* _x : input/output matrix [size: _rx x _cx] */ \ /* _rx : rows of _x */ \ /* _cx : columns of _x */ \ /* _L : first row to swap */ \ /* _U : first row to swap */ \ /* _P : first row to swap */ \ void MATRIX(_ludecomp_crout)(T * _x, \ unsigned int _rx, \ unsigned int _cx, \ T * _L, \ T * _U, \ T * _P); \ \ /* L/U/P decomposition, Doolittle's method */ \ /* _x : input/output matrix [size: _rx x _cx] */ \ /* _rx : rows of _x */ \ /* _cx : columns of _x */ \ /* _L : first row to swap */ \ /* _U : first row to swap */ \ /* _P : first row to swap */ \ void MATRIX(_ludecomp_doolittle)(T * _x, \ unsigned int _rx, \ unsigned int _cx, \ T * _L, \ T * _U, \ T * _P); \ \ /* Orthnormalization using the Gram-Schmidt algorithm */ \ /* _A : input matrix [size: _r x _c] */ \ /* _r : rows */ \ /* _c : columns */ \ /* _v : output matrix */ \ void MATRIX(_gramschmidt)(T * _A, \ unsigned int _r, \ unsigned int _c, \ T * _v); \ \ /* Q/R decomposition using the Gram-Schmidt algorithm such */ \ /* that _A = _Q*_R and _Q^T * _Q = _In and _R is a diagonal */ \ /* matrix */ \ /* NOTE: all matrices are square */ \ /* _A : input matrix [size: _m x _m] */ \ /* _m : rows */ \ /* _n : columns (same as cols) */ \ /* _Q : output matrix [size: _m x _m] */ \ /* _R : output matrix [size: _m x _m] */ \ void MATRIX(_qrdecomp_gramschmidt)(T * _A, \ unsigned int _m, \ unsigned int _n, \ T * _Q, \ T * _R); \ \ /* Compute Cholesky decomposition of a symmetric/Hermitian */ \ /* positive-definite matrix as A = L * L^T */ \ /* _A : input square matrix [size: _n x _n] */ \ /* _n : input matrix dimension */ \ /* _L : output lower-triangular matrix */ \ void MATRIX(_chol)(T * _A, \ unsigned int _n, \ T * _L); \ #define matrix_access(X,R,C,r,c) ((X)[(r)*(C)+(c)]) #define matrixc_access(X,R,C,r,c) matrix_access(X,R,C,r,c) #define matrixf_access(X,R,C,r,c) matrix_access(X,R,C,r,c) #define matrixcf_access(X,R,C,r,c) matrix_access(X,R,C,r,c) LIQUID_MATRIX_DEFINE_API(LIQUID_MATRIX_MANGLE_FLOAT, float) LIQUID_MATRIX_DEFINE_API(LIQUID_MATRIX_MANGLE_DOUBLE, double) LIQUID_MATRIX_DEFINE_API(LIQUID_MATRIX_MANGLE_CFLOAT, liquid_float_complex) LIQUID_MATRIX_DEFINE_API(LIQUID_MATRIX_MANGLE_CDOUBLE, liquid_double_complex) #define LIQUID_SMATRIX_MANGLE_BOOL(name) LIQUID_CONCAT(smatrixb, name) #define LIQUID_SMATRIX_MANGLE_FLOAT(name) LIQUID_CONCAT(smatrixf, name) #define LIQUID_SMATRIX_MANGLE_INT(name) LIQUID_CONCAT(smatrixi, name) // sparse 'alist' matrix type (similar to MacKay, Davey Lafferty convention) // large macro // SMATRIX : name-mangling macro // T : primitive data type #define LIQUID_SMATRIX_DEFINE_API(SMATRIX,T) \ typedef struct SMATRIX(_s) * SMATRIX(); \ \ /* create _M x _N matrix, initialized with zeros */ \ SMATRIX() SMATRIX(_create)(unsigned int _M, \ unsigned int _N); \ \ /* create _M x _N matrix, initialized on array */ \ SMATRIX() SMATRIX(_create_array)(T * _x, \ unsigned int _m, \ unsigned int _n); \ \ /* destroy object */ \ void SMATRIX(_destroy)(SMATRIX() _q); \ \ /* print compact form */ \ void SMATRIX(_print)(SMATRIX() _q); \ \ /* print expanded form */ \ void SMATRIX(_print_expanded)(SMATRIX() _q); \ \ /* query properties methods */ \ void SMATRIX(_size)(SMATRIX() _q, \ unsigned int * _m, \ unsigned int * _n); \ \ /* zero all elements and keep memory */ \ void SMATRIX(_clear)(SMATRIX() _q); \ \ /* zero all elements and clear memory */ \ void SMATRIX(_reset)(SMATRIX() _q); \ \ /* determine if value has been set (allocated memory) */ \ int SMATRIX(_isset)(SMATRIX() _q, \ unsigned int _m, \ unsigned int _n); \ \ /* inserts/deletes element at index (memory allocation) */ \ void SMATRIX(_insert)(SMATRIX() _q, \ unsigned int _m, \ unsigned int _n, \ T _v); \ void SMATRIX(_delete)(SMATRIX() _q, \ unsigned int _m, \ unsigned int _n); \ \ /* sets/gets the value (with memory allocation if needed) */ \ void SMATRIX(_set)(SMATRIX() _q, \ unsigned int _m, \ unsigned int _n, \ T _v); \ T SMATRIX(_get)(SMATRIX() _q, \ unsigned int _m, \ unsigned int _n); \ \ /* initialize to identity matrix */ \ void SMATRIX(_eye)(SMATRIX() _q); \ \ /* multiply two sparse binary matrices */ \ void SMATRIX(_mul)(SMATRIX() _x, \ SMATRIX() _y, \ SMATRIX() _z); \ \ /* multiply sparse matrix by vector */ \ /* _q : sparse matrix */ \ /* _x : input vector [size: _N x 1] */ \ /* _y : output vector [size: _M x 1] */ \ void SMATRIX(_vmul)(SMATRIX() _q, \ T * _x, \ T * _y); \ LIQUID_SMATRIX_DEFINE_API(LIQUID_SMATRIX_MANGLE_BOOL, unsigned char) LIQUID_SMATRIX_DEFINE_API(LIQUID_SMATRIX_MANGLE_FLOAT, float) LIQUID_SMATRIX_DEFINE_API(LIQUID_SMATRIX_MANGLE_INT, short int) // // smatrix cross methods // // multiply sparse binary matrix by floating-point matrix // _q : sparse matrix [size: A->M x A->N] // _x : input vector [size: mx x nx ] // _y : output vector [size: my x ny ] void smatrixb_mulf(smatrixb _A, float * _x, unsigned int _mx, unsigned int _nx, float * _y, unsigned int _my, unsigned int _ny); // multiply sparse binary matrix by floating-point vector // _q : sparse matrix // _x : input vector [size: _N x 1] // _y : output vector [size: _M x 1] void smatrixb_vmulf(smatrixb _q, float * _x, float * _y); // // MODULE : modem (modulator/demodulator) // // Maximum number of allowed bits per symbol #define MAX_MOD_BITS_PER_SYMBOL 8 // Modulation schemes available #define LIQUID_MODEM_NUM_SCHEMES (52) typedef enum { LIQUID_MODEM_UNKNOWN=0, // Unknown modulation scheme // Phase-shift keying (PSK) LIQUID_MODEM_PSK2, LIQUID_MODEM_PSK4, LIQUID_MODEM_PSK8, LIQUID_MODEM_PSK16, LIQUID_MODEM_PSK32, LIQUID_MODEM_PSK64, LIQUID_MODEM_PSK128, LIQUID_MODEM_PSK256, // Differential phase-shift keying (DPSK) LIQUID_MODEM_DPSK2, LIQUID_MODEM_DPSK4, LIQUID_MODEM_DPSK8, LIQUID_MODEM_DPSK16, LIQUID_MODEM_DPSK32, LIQUID_MODEM_DPSK64, LIQUID_MODEM_DPSK128, LIQUID_MODEM_DPSK256, // amplitude-shift keying LIQUID_MODEM_ASK2, LIQUID_MODEM_ASK4, LIQUID_MODEM_ASK8, LIQUID_MODEM_ASK16, LIQUID_MODEM_ASK32, LIQUID_MODEM_ASK64, LIQUID_MODEM_ASK128, LIQUID_MODEM_ASK256, // rectangular quadrature amplitude-shift keying (QAM) LIQUID_MODEM_QAM4, LIQUID_MODEM_QAM8, LIQUID_MODEM_QAM16, LIQUID_MODEM_QAM32, LIQUID_MODEM_QAM64, LIQUID_MODEM_QAM128, LIQUID_MODEM_QAM256, // amplitude phase-shift keying (APSK) LIQUID_MODEM_APSK4, LIQUID_MODEM_APSK8, LIQUID_MODEM_APSK16, LIQUID_MODEM_APSK32, LIQUID_MODEM_APSK64, LIQUID_MODEM_APSK128, LIQUID_MODEM_APSK256, // specific modem types LIQUID_MODEM_BPSK, // Specific: binary PSK LIQUID_MODEM_QPSK, // specific: quaternary PSK LIQUID_MODEM_OOK, // Specific: on/off keying LIQUID_MODEM_SQAM32, // 'square' 32-QAM LIQUID_MODEM_SQAM128, // 'square' 128-QAM LIQUID_MODEM_V29, // V.29 star constellation LIQUID_MODEM_ARB16OPT, // optimal 16-QAM LIQUID_MODEM_ARB32OPT, // optimal 32-QAM LIQUID_MODEM_ARB64OPT, // optimal 64-QAM LIQUID_MODEM_ARB128OPT, // optimal 128-QAM LIQUID_MODEM_ARB256OPT, // optimal 256-QAM LIQUID_MODEM_ARB64VT, // Virginia Tech logo // arbitrary modem type LIQUID_MODEM_ARB // arbitrary QAM } modulation_scheme; // structure for holding full modulation type descriptor struct modulation_type_s { const char * name; // short name (e.g. 'bpsk') const char * fullname; // full name (e.g. 'binary phase-shift keying') modulation_scheme scheme; // modulation scheme (e.g. LIQUID_MODEM_BPSK) unsigned int bps; // modulation depth (e.g. 1) }; // full modulation type descriptor extern const struct modulation_type_s modulation_types[LIQUID_MODEM_NUM_SCHEMES]; // Print compact list of existing and available modulation schemes void liquid_print_modulation_schemes(); // returns modulation_scheme based on input string modulation_scheme liquid_getopt_str2mod(const char * _str); // query basic modulation types int liquid_modem_is_psk(modulation_scheme _ms); int liquid_modem_is_dpsk(modulation_scheme _ms); int liquid_modem_is_ask(modulation_scheme _ms); int liquid_modem_is_qam(modulation_scheme _ms); int liquid_modem_is_apsk(modulation_scheme _ms); // useful functions // counts the number of different bits between two symbols unsigned int count_bit_errors(unsigned int _s1, unsigned int _s2); // counts the number of different bits between two arrays of symbols // _msg0 : original message [size: _n x 1] // _msg1 : copy of original message [size: _n x 1] // _n : message size unsigned int count_bit_errors_array(unsigned char * _msg0, unsigned char * _msg1, unsigned int _n); // converts binary-coded decimal (BCD) to gray, ensuring successive values // differ by exactly one bit unsigned int gray_encode(unsigned int symbol_in); // converts a gray-encoded symbol to binary-coded decimal (BCD) unsigned int gray_decode(unsigned int symbol_in); // pack soft bits into symbol // _soft_bits : soft input bits [size: _bps x 1] // _bps : bits per symbol // _sym_out : output symbol, value in [0,2^_bps) void liquid_pack_soft_bits(unsigned char * _soft_bits, unsigned int _bps, unsigned int * _sym_out); // unpack soft bits into symbol // _sym_in : input symbol, value in [0,2^_bps) // _bps : bits per symbol // _soft_bits : soft output bits [size: _bps x 1] void liquid_unpack_soft_bits(unsigned int _sym_in, unsigned int _bps, unsigned char * _soft_bits); // // Linear modem // #define LIQUID_MODEM_MANGLE_FLOAT(name) LIQUID_CONCAT(modem,name) // Macro : MODEM // MODEM : name-mangling macro // T : primitive data type // TC : primitive data type (complex) #define LIQUID_MODEM_DEFINE_API(MODEM,T,TC) \ typedef struct MODEM(_s) * MODEM(); \ \ /* create digital modem object */ \ MODEM() MODEM(_create)(modulation_scheme _scheme); \ \ /* create arbitrary digital modem object */ \ /* _table : array of complex constellation points */ \ /* _M : modulation order and table size */ \ MODEM() MODEM(_create_arbitrary)(TC * _table, \ unsigned int _M); \ \ /* recreate modulation scheme, re-allocating memory as */ \ /* necessary */ \ MODEM() MODEM(_recreate)(MODEM() _q, \ modulation_scheme _scheme); \ \ void MODEM(_destroy)(MODEM() _q); \ void MODEM(_print)( MODEM() _q); \ void MODEM(_reset)( MODEM() _q); \ \ /* generate random symbol */ \ unsigned int MODEM(_gen_rand_sym)(MODEM() _q); \ \ /* Accessor functions */ \ unsigned int MODEM(_get_bps) (MODEM() _q); \ modulation_scheme MODEM(_get_scheme)(MODEM() _q); \ \ /* generic modulate function; simply queries modem scheme */ \ /* and calls appropriate subroutine */ \ /* _q : modem object */ \ /* _s : input symbol */ \ /* _x : output sample */ \ void MODEM(_modulate)(MODEM() _q, \ unsigned int _s, \ TC * _y); \ \ /* generic hard-decision demodulation function */ \ /* _q : modem object */ \ /* _x : input sample */ \ /* _s : output symbol */ \ void MODEM(_demodulate)(MODEM() _q, \ TC _x, \ unsigned int * _s); \ \ /* generic soft-decision demodulation function */ \ /* _q : modem object */ \ /* _x : input sample */ \ /* _s : output hard symbol */ \ /* _soft_bits : output soft bits */ \ void MODEM(_demodulate_soft)(MODEM() _q, \ TC _x, \ unsigned int * _s, \ unsigned char * _soft_bits); \ \ /* get demodulator's estimated transmit sample */ \ void MODEM(_get_demodulator_sample)(MODEM() _q, \ TC * _x_hat); \ \ /* get demodulator phase error */ \ float MODEM(_get_demodulator_phase_error)(MODEM() _q); \ \ /* get demodulator error vector magnitude */ \ float MODEM(_get_demodulator_evm)(MODEM() _q); \ // define modem APIs LIQUID_MODEM_DEFINE_API(LIQUID_MODEM_MANGLE_FLOAT,float,liquid_float_complex) // // continuous-phase modulation // // gmskmod : GMSK modulator typedef struct gmskmod_s * gmskmod; // create gmskmod object // _k : samples/symbol // _m : filter delay (symbols) // _BT : excess bandwidth factor gmskmod gmskmod_create(unsigned int _k, unsigned int _m, float _BT); void gmskmod_destroy(gmskmod _q); void gmskmod_print(gmskmod _q); void gmskmod_reset(gmskmod _q); void gmskmod_modulate(gmskmod _q, unsigned int _sym, liquid_float_complex * _y); // gmskdem : GMSK demodulator typedef struct gmskdem_s * gmskdem; // create gmskdem object // _k : samples/symbol // _m : filter delay (symbols) // _BT : excess bandwidth factor gmskdem gmskdem_create(unsigned int _k, unsigned int _m, float _BT); void gmskdem_destroy(gmskdem _q); void gmskdem_print(gmskdem _q); void gmskdem_reset(gmskdem _q); void gmskdem_set_eq_bw(gmskdem _q, float _bw); void gmskdem_demodulate(gmskdem _q, liquid_float_complex * _y, unsigned int * _sym); // // continuous phase frequency-shift keying (CP-FSK) modems // // CP-FSK filter prototypes typedef enum { LIQUID_CPFSK_SQUARE=0, // square pulse LIQUID_CPFSK_RCOS_FULL, // raised-cosine (full response) LIQUID_CPFSK_RCOS_PARTIAL, // raised-cosine (partial response) LIQUID_CPFSK_GMSK, // Gauss minimum-shift keying pulse } liquid_cpfsk_filter; // CP-FSK modulator typedef struct cpfskmod_s * cpfskmod; // create cpfskmod object (frequency modulator) // _bps : bits per symbol, _bps > 0 // _h : modulation index, _h > 0 // _k : samples/symbol, _k > 1, _k even // _m : filter delay (symbols), _m > 0 // _beta : filter bandwidth parameter, _beta > 0 // _type : filter type (e.g. LIQUID_CPFSK_SQUARE) cpfskmod cpfskmod_create(unsigned int _bps, float _h, unsigned int _k, unsigned int _m, float _beta, int _type); //cpfskmod cpfskmod_create_msk(unsigned int _k); //cpfskmod cpfskmod_create_gmsk(unsigned int _k, float _BT); // destroy cpfskmod object void cpfskmod_destroy(cpfskmod _q); // print cpfskmod object internals void cpfskmod_print(cpfskmod _q); // reset state void cpfskmod_reset(cpfskmod _q); // get transmit delay [symbols] unsigned int cpfskmod_get_delay(cpfskmod _q); // modulate sample // _q : frequency modulator object // _s : input symbol // _y : output sample array [size: _k x 1] void cpfskmod_modulate(cpfskmod _q, unsigned int _s, liquid_float_complex * _y); // CP-FSK demodulator typedef struct cpfskdem_s * cpfskdem; // create cpfskdem object (frequency modulator) // _bps : bits per symbol, _bps > 0 // _h : modulation index, _h > 0 // _k : samples/symbol, _k > 1, _k even // _m : filter delay (symbols), _m > 0 // _beta : filter bandwidth parameter, _beta > 0 // _type : filter type (e.g. LIQUID_CPFSK_SQUARE) cpfskdem cpfskdem_create(unsigned int _bps, float _h, unsigned int _k, unsigned int _m, float _beta, int _type); //cpfskdem cpfskdem_create_msk(unsigned int _k); //cpfskdem cpfskdem_create_gmsk(unsigned int _k, float _BT); // destroy cpfskdem object void cpfskdem_destroy(cpfskdem _q); // print cpfskdem object internals void cpfskdem_print(cpfskdem _q); // reset state void cpfskdem_reset(cpfskdem _q); // get receive delay [symbols] unsigned int cpfskdem_get_delay(cpfskdem _q); #if 0 // demodulate array of samples // _q : continuous-phase frequency demodulator object // _y : input sample array [size: _n x 1] // _n : input sample array length // _s : output symbol array // _nw : number of output symbols written void cpfskdem_demodulate(cpfskdem _q, liquid_float_complex * _y, unsigned int _n, unsigned int * _s, unsigned int * _nw); #else // demodulate array of samples, assuming perfect timing // _q : continuous-phase frequency demodulator object // _y : input sample array [size: _k x 1] unsigned int cpfskdem_demodulate(cpfskdem _q, liquid_float_complex * _y); #endif // // M-ary frequency-shift keying (MFSK) modems // // FSK modulator typedef struct fskmod_s * fskmod; // create fskmod object (frequency modulator) // _m : bits per symbol, _bps > 0 // _k : samples/symbol, _k >= 2^_m // _bandwidth : total signal bandwidth, (0,0.5) fskmod fskmod_create(unsigned int _m, unsigned int _k, float _bandwidth); // destroy fskmod object void fskmod_destroy(fskmod _q); // print fskmod object internals void fskmod_print(fskmod _q); // reset state void fskmod_reset(fskmod _q); // modulate sample // _q : frequency modulator object // _s : input symbol // _y : output sample array [size: _k x 1] void fskmod_modulate(fskmod _q, unsigned int _s, liquid_float_complex * _y); // FSK demodulator typedef struct fskdem_s * fskdem; // create fskdem object (frequency demodulator) // _m : bits per symbol, _bps > 0 // _k : samples/symbol, _k >= 2^_m // _bandwidth : total signal bandwidth, (0,0.5) fskdem fskdem_create(unsigned int _m, unsigned int _k, float _bandwidth); // destroy fskdem object void fskdem_destroy(fskdem _q); // print fskdem object internals void fskdem_print(fskdem _q); // reset state void fskdem_reset(fskdem _q); // demodulate symbol, assuming perfect symbol timing // _q : fskdem object // _y : input sample array [size: _k x 1] unsigned int fskdem_demodulate(fskdem _q, liquid_float_complex * _y); // get demodulator frequency error float fskdem_get_frequency_error(fskdem _q); // // Analog frequency modulator // #define LIQUID_FREQMOD_MANGLE_FLOAT(name) LIQUID_CONCAT(freqmod,name) // Macro : FREQMOD (analog frequency modulator) // FREQMOD : name-mangling macro // T : primitive data type // TC : primitive data type (complex) #define LIQUID_FREQMOD_DEFINE_API(FREQMOD,T,TC) \ typedef struct FREQMOD(_s) * FREQMOD(); \ \ /* create freqmod object (frequency modulator) */ \ /* _kf : modulation factor */ \ FREQMOD() FREQMOD(_create)(float _kf); \ \ /* destroy freqmod object */ \ void FREQMOD(_destroy)(FREQMOD() _q); \ \ /* print freqmod object internals */ \ void FREQMOD(_print)(FREQMOD() _q); \ \ /* reset state */ \ void FREQMOD(_reset)(FREQMOD() _q); \ \ /* modulate single sample */ \ /* _q : frequency modulator object */ \ /* _m : message signal m(t) */ \ /* _s : complex baseband signal s(t) */ \ void FREQMOD(_modulate)(FREQMOD() _q, \ T _m, \ TC * _s); \ \ /* modulate block of samples */ \ /* _q : frequency modulator object */ \ /* _m : message signal m(t), [size: _n x 1] */ \ /* _n : number of input, output samples */ \ /* _s : complex baseband signal s(t) [size: _n x 1] */ \ void FREQMOD(_modulate_block)(FREQMOD() _q, \ T * _m, \ unsigned int _n, \ TC * _s); \ // define freqmod APIs LIQUID_FREQMOD_DEFINE_API(LIQUID_FREQMOD_MANGLE_FLOAT,float,liquid_float_complex) // // Analog frequency demodulator // #define LIQUID_FREQDEM_MANGLE_FLOAT(name) LIQUID_CONCAT(freqdem,name) // Macro : FREQDEM (analog frequency modulator) // FREQDEM : name-mangling macro // T : primitive data type // TC : primitive data type (complex) #define LIQUID_FREQDEM_DEFINE_API(FREQDEM,T,TC) \ typedef struct FREQDEM(_s) * FREQDEM(); \ \ /* create freqdem object (frequency modulator) */ \ /* _kf : modulation factor */ \ FREQDEM() FREQDEM(_create)(float _kf); \ \ /* destroy freqdem object */ \ void FREQDEM(_destroy)(FREQDEM() _q); \ \ /* print freqdem object internals */ \ void FREQDEM(_print)(FREQDEM() _q); \ \ /* reset state */ \ void FREQDEM(_reset)(FREQDEM() _q); \ \ /* demodulate sample */ \ /* _q : frequency modulator object */ \ /* _r : received signal r(t) */ \ /* _m : output message signal m(t) */ \ void FREQDEM(_demodulate)(FREQDEM() _q, \ TC _r, \ T * _m); \ \ /* demodulate block of samples */ \ /* _q : frequency demodulator object */ \ /* _r : received signal r(t) [size: _n x 1] */ \ /* _n : number of input, output samples */ \ /* _m : message signal m(t), [size: _n x 1] */ \ void FREQDEM(_demodulate_block)(FREQDEM() _q, \ TC * _r, \ unsigned int _n, \ T * _m); \ // define freqdem APIs LIQUID_FREQDEM_DEFINE_API(LIQUID_FREQDEM_MANGLE_FLOAT,float,liquid_float_complex) // amplitude modulation types typedef enum { LIQUID_AMPMODEM_DSB=0, // double side-band LIQUID_AMPMODEM_USB, // single side-band (upper) LIQUID_AMPMODEM_LSB // single side-band (lower) } liquid_ampmodem_type; typedef struct ampmodem_s * ampmodem; // create ampmodem object // _m : modulation index // _fc : carrier frequency, range: [-0.5,0.5] // _type : AM type (e.g. LIQUID_AMPMODEM_DSB) // _suppressed_carrier : carrier suppression flag ampmodem ampmodem_create(float _m, float _fc, liquid_ampmodem_type _type, int _suppressed_carrier); // destroy ampmodem object void ampmodem_destroy(ampmodem _fm); // print ampmodem object internals void ampmodem_print(ampmodem _fm); // reset ampmodem object state void ampmodem_reset(ampmodem _fm); // modulate sample void ampmodem_modulate(ampmodem _fm, float _x, liquid_float_complex *_y); void ampmodem_modulate_block(ampmodem _q, float * _m, unsigned int _n, liquid_float_complex *_s); // demodulate sample void ampmodem_demodulate(ampmodem _fm, liquid_float_complex _y, float *_x); void ampmodem_demodulate_block(ampmodem _q, liquid_float_complex * _r, unsigned int _n, float * _m); // // MODULE : multichannel // #define FIRPFBCH_NYQUIST 0 #define FIRPFBCH_ROOTNYQUIST 1 #define LIQUID_ANALYZER 0 #define LIQUID_SYNTHESIZER 1 // // Finite impulse response polyphase filterbank channelizer // #define LIQUID_FIRPFBCH_MANGLE_CRCF(name) LIQUID_CONCAT(firpfbch_crcf,name) #define LIQUID_FIRPFBCH_MANGLE_CCCF(name) LIQUID_CONCAT(firpfbch_cccf,name) // Macro: // FIRPFBCH : name-mangling macro // TO : output data type // TC : coefficients data type // TI : input data type #define LIQUID_FIRPFBCH_DEFINE_API(FIRPFBCH,TO,TC,TI) \ typedef struct FIRPFBCH(_s) * FIRPFBCH(); \ \ /* create finite impulse response polyphase filter-bank */ \ /* channelizer object from external coefficients */ \ /* _type : channelizer type, e.g. LIQUID_ANALYZER */ \ /* _M : number of channels */ \ /* _p : number of coefficients for each channel */ \ /* _h : coefficients [size: _M*_p x 1] */ \ FIRPFBCH() FIRPFBCH(_create)(int _type, \ unsigned int _M, \ unsigned int _p, \ TC * _h); \ \ /* create FIR polyphase filterbank channelizer object with */ \ /* prototype filter based on windowed Kaiser design */ \ /* _type : type (LIQUID_ANALYZER | LIQUID_SYNTHESIZER) */ \ /* _M : number of channels */ \ /* _m : filter delay (symbols) */ \ /* _As : stop-band attentuation [dB] */ \ FIRPFBCH() FIRPFBCH(_create_kaiser)(int _type, \ unsigned int _M, \ unsigned int _m, \ float _As); \ \ /* create FIR polyphase filterbank channelizer object with */ \ /* prototype root-Nyquist filter */ \ /* _type : type (LIQUID_ANALYZER | LIQUID_SYNTHESIZER) */ \ /* _M : number of channels */ \ /* _m : filter delay (symbols) */ \ /* _beta : filter excess bandwidth factor, in [0,1] */ \ /* _ftype : filter prototype (rrcos, rkaiser, etc.) */ \ FIRPFBCH() FIRPFBCH(_create_rnyquist)(int _type, \ unsigned int _M, \ unsigned int _m, \ float _beta, \ int _ftype); \ \ /* destroy firpfbch object */ \ void FIRPFBCH(_destroy)(FIRPFBCH() _q); \ \ /* clear/reset firpfbch internal state */ \ void FIRPFBCH(_reset)(FIRPFBCH() _q); \ \ /* print firpfbch internal parameters to stdout */ \ void FIRPFBCH(_print)(FIRPFBCH() _q); \ \ /* execute filterbank as synthesizer on block of samples */ \ /* _q : filterbank channelizer object */ \ /* _x : channelized input, [size: num_channels x 1] */ \ /* _y : output time series, [size: num_channels x 1] */ \ void FIRPFBCH(_synthesizer_execute)(FIRPFBCH() _q, \ TI * _x, \ TO * _y); \ \ /* execute filterbank as analyzer on block of samples */ \ /* _q : filterbank channelizer object */ \ /* _x : input time series, [size: num_channels x 1] */ \ /* _y : channelized output, [size: num_channels x 1] */ \ void FIRPFBCH(_analyzer_execute)(FIRPFBCH() _q, \ TI * _x, \ TO * _y); \ LIQUID_FIRPFBCH_DEFINE_API(LIQUID_FIRPFBCH_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) LIQUID_FIRPFBCH_DEFINE_API(LIQUID_FIRPFBCH_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // // Finite impulse response polyphase filterbank channelizer // with output rate 2 Fs / M // #define LIQUID_FIRPFBCH2_MANGLE_CRCF(name) LIQUID_CONCAT(firpfbch2_crcf,name) // Macro: // FIRPFBCH2 : name-mangling macro // TO : output data type // TC : coefficients data type // TI : input data type #define LIQUID_FIRPFBCH2_DEFINE_API(FIRPFBCH2,TO,TC,TI) \ typedef struct FIRPFBCH2(_s) * FIRPFBCH2(); \ \ /* create firpfbch2 object */ \ /* _type : channelizer type (e.g. LIQUID_ANALYZER) */ \ /* _M : number of channels (must be even) */ \ /* _m : prototype filter semi-lenth, length=2*M*m */ \ /* _h : prototype filter coefficient array */ \ FIRPFBCH2() FIRPFBCH2(_create)(int _type, \ unsigned int _M, \ unsigned int _m, \ TC * _h); \ \ /* create firpfbch2 object using Kaiser window prototype */ \ /* _type : channelizer type (e.g. LIQUID_ANALYZER) */ \ /* _M : number of channels (must be even) */ \ /* _m : prototype filter semi-lenth, length=2*M*m+1 */ \ /* _As : filter stop-band attenuation [dB] */ \ FIRPFBCH2() FIRPFBCH2(_create_kaiser)(int _type, \ unsigned int _M, \ unsigned int _m, \ float _As); \ \ /* destroy firpfbch2 object, freeing internal memory */ \ void FIRPFBCH2(_destroy)(FIRPFBCH2() _q); \ \ /* reset firpfbch2 object internals */ \ void FIRPFBCH2(_reset)(FIRPFBCH2() _q); \ \ /* print firpfbch2 object internals */ \ void FIRPFBCH2(_print)(FIRPFBCH2() _q); \ \ /* execute filterbank channelizer */ \ /* LIQUID_ANALYZER: input: M/2, output: M */ \ /* LIQUID_SYNTHESIZER: input: M, output: M/2 */ \ /* _x : channelizer input */ \ /* _y : channelizer output */ \ void FIRPFBCH2(_execute)(FIRPFBCH2() _q, \ TI * _x, \ TO * _y); \ LIQUID_FIRPFBCH2_DEFINE_API(LIQUID_FIRPFBCH2_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) #define OFDMFRAME_SCTYPE_NULL 0 #define OFDMFRAME_SCTYPE_PILOT 1 #define OFDMFRAME_SCTYPE_DATA 2 // initialize default subcarrier allocation // _M : number of subcarriers // _p : output subcarrier allocation array, [size: _M x 1] void ofdmframe_init_default_sctype(unsigned int _M, unsigned char * _p); // initialize default subcarrier allocation // _M : number of subcarriers // _f0 : lower frequency band, _f0 in [-0.5,0.5] // _f1 : upper frequency band, _f1 in [-0.5,0.5] // _p : output subcarrier allocation array, [size: _M x 1] void ofdmframe_init_sctype_range(unsigned int _M, float _f0, float _f1, unsigned char * _p); // validate subcarrier type (count number of null, pilot, and data // subcarriers in the allocation) // _p : subcarrier allocation array, [size: _M x 1] // _M : number of subcarriers // _M_null : output number of null subcarriers // _M_pilot : output number of pilot subcarriers // _M_data : output number of data subcarriers void ofdmframe_validate_sctype(unsigned char * _p, unsigned int _M, unsigned int * _M_null, unsigned int * _M_pilot, unsigned int * _M_data); // print subcarrier allocation to screen // _p : output subcarrier allocation array, [size: _M x 1] // _M : number of subcarriers void ofdmframe_print_sctype(unsigned char * _p, unsigned int _M); // // OFDM frame (symbol) generator // typedef struct ofdmframegen_s * ofdmframegen; // create OFDM framing generator object // _M : number of subcarriers, >10 typical // _cp_len : cyclic prefix length // _taper_len : taper length (OFDM symbol overlap) // _p : subcarrier allocation (null, pilot, data), [size: _M x 1] ofdmframegen ofdmframegen_create(unsigned int _M, unsigned int _cp_len, unsigned int _taper_len, unsigned char * _p); void ofdmframegen_destroy(ofdmframegen _q); void ofdmframegen_print(ofdmframegen _q); void ofdmframegen_reset(ofdmframegen _q); // write first S0 symbol void ofdmframegen_write_S0a(ofdmframegen _q, liquid_float_complex *_y); // write second S0 symbol void ofdmframegen_write_S0b(ofdmframegen _q, liquid_float_complex *_y); // write S1 symbol void ofdmframegen_write_S1(ofdmframegen _q, liquid_float_complex *_y); // write data symbol void ofdmframegen_writesymbol(ofdmframegen _q, liquid_float_complex * _x, liquid_float_complex *_y); // write tail void ofdmframegen_writetail(ofdmframegen _q, liquid_float_complex * _x); // // OFDM frame (symbol) synchronizer // typedef int (*ofdmframesync_callback)(liquid_float_complex * _y, unsigned char * _p, unsigned int _M, void * _userdata); typedef struct ofdmframesync_s * ofdmframesync; // create OFDM framing synchronizer object // _M : number of subcarriers, >10 typical // _cp_len : cyclic prefix length // _taper_len : taper length (OFDM symbol overlap) // _p : subcarrier allocation (null, pilot, data), [size: _M x 1] // _callback : user-defined callback function // _userdata : user-defined data pointer ofdmframesync ofdmframesync_create(unsigned int _M, unsigned int _cp_len, unsigned int _taper_len, unsigned char * _p, ofdmframesync_callback _callback, void * _userdata); void ofdmframesync_destroy(ofdmframesync _q); void ofdmframesync_print(ofdmframesync _q); void ofdmframesync_reset(ofdmframesync _q); int ofdmframesync_is_frame_open(ofdmframesync _q); void ofdmframesync_execute(ofdmframesync _q, liquid_float_complex * _x, unsigned int _n); // query methods float ofdmframesync_get_rssi(ofdmframesync _q); // received signal strength indication float ofdmframesync_get_cfo(ofdmframesync _q); // carrier offset estimate // debugging void ofdmframesync_debug_enable(ofdmframesync _q); void ofdmframesync_debug_disable(ofdmframesync _q); void ofdmframesync_debug_print(ofdmframesync _q, const char * _filename); // // MODULE : nco (numerically-controlled oscillator) // // oscillator type // LIQUID_NCO : numerically-controlled oscillator (fast) // LIQUID_VCO : "voltage"-controlled oscillator (precise) typedef enum { LIQUID_NCO=0, LIQUID_VCO } liquid_ncotype; #define LIQUID_NCO_MANGLE_FLOAT(name) LIQUID_CONCAT(nco_crcf, name) // large macro // NCO : name-mangling macro // T : primitive data type // TC : input/output data type #define LIQUID_NCO_DEFINE_API(NCO,T,TC) \ typedef struct NCO(_s) * NCO(); \ \ NCO() NCO(_create)(liquid_ncotype _type); \ void NCO(_destroy)(NCO() _q); \ void NCO(_print)(NCO() _q); \ \ /* set phase/frequency to zero, reset pll filter */ \ void NCO(_reset)(NCO() _q); \ \ /* get/set/adjust internal frequency/phase */ \ T NCO(_get_frequency)( NCO() _q); \ void NCO(_set_frequency)( NCO() _q, T _f); \ void NCO(_adjust_frequency)(NCO() _q, T _df); \ T NCO(_get_phase)( NCO() _q); \ void NCO(_set_phase)( NCO() _q, T _phi); \ void NCO(_adjust_phase)( NCO() _q, T _dphi); \ \ /* increment phase by internal phase step (frequency) */ \ void NCO(_step)(NCO() _q); \ \ /* compute trigonometric functions */ \ T NCO(_sin)(NCO() _q); \ T NCO(_cos)(NCO() _q); \ void NCO(_sincos)(NCO() _q, T* _s, T* _c); \ void NCO(_cexpf)(NCO() _q, TC * _y); \ \ /* pll : phase-locked loop */ \ void NCO(_pll_set_bandwidth)(NCO() _q, T _bandwidth); \ void NCO(_pll_step)(NCO() _q, T _dphi); \ \ /* Rotate input sample up by NCO angle (no stepping) */ \ void NCO(_mix_up)(NCO() _q, TC _x, TC *_y); \ \ /* Rotate input sample down by NCO angle (no stepping) */ \ void NCO(_mix_down)(NCO() _q, TC _x, TC *_y); \ \ /* Rotate input vector up by NCO angle (stepping) */ \ /* _q : nco object */ \ /* _x : input vector [size: _N x 1] */ \ /* _y : output vector [size: _N x 1] */ \ /* _N : vector size */ \ void NCO(_mix_block_up)(NCO() _q, \ TC *_x, \ TC *_y, \ unsigned int _N); \ \ /* Rotate input vector down by NCO angle (stepping) */ \ /* _q : nco object */ \ /* _x : input vector [size: _N x 1] */ \ /* _y : output vector [size: _N x 1] */ \ /* _N : vector size */ \ void NCO(_mix_block_down)(NCO() _q, \ TC *_x, \ TC *_y, \ unsigned int _N); \ // Define nco APIs LIQUID_NCO_DEFINE_API(LIQUID_NCO_MANGLE_FLOAT, float, liquid_float_complex) // nco utilities // unwrap phase of array (basic) void liquid_unwrap_phase(float * _theta, unsigned int _n); // unwrap phase of array (advanced) void liquid_unwrap_phase2(float * _theta, unsigned int _n); // // MODULE : optimization // // utility function pointer definition typedef float (*utility_function)(void * _userdata, float * _v, unsigned int _n); // n-dimensional Rosenbrock utility function (minimum at _v = {1,1,1...} // _userdata : user-defined data structure (convenience) // _v : input vector [size: _n x 1] // _n : input vector size float liquid_rosenbrock(void * _userdata, float * _v, unsigned int _n); // n-dimensional inverse Gauss utility function (minimum at _v = {0,0,0...} // _userdata : user-defined data structure (convenience) // _v : input vector [size: _n x 1] // _n : input vector size float liquid_invgauss(void * _userdata, float * _v, unsigned int _n); // n-dimensional multimodal utility function (minimum at _v = {0,0,0...} // _userdata : user-defined data structure (convenience) // _v : input vector [size: _n x 1] // _n : input vector size float liquid_multimodal(void * _userdata, float * _v, unsigned int _n); // n-dimensional spiral utility function (minimum at _v = {0,0,0...} // _userdata : user-defined data structure (convenience) // _v : input vector [size: _n x 1] // _n : input vector size float liquid_spiral(void * _userdata, float * _v, unsigned int _n); // // Gradient search // #define LIQUID_OPTIM_MINIMIZE (0) #define LIQUID_OPTIM_MAXIMIZE (1) typedef struct gradsearch_s * gradsearch; // Create a gradient search object // _userdata : user data object pointer // _v : array of parameters to optimize // _num_parameters : array length (number of parameters to optimize) // _u : utility function pointer // _direction : search direction (e.g. LIQUID_OPTIM_MAXIMIZE) gradsearch gradsearch_create(void * _userdata, float * _v, unsigned int _num_parameters, utility_function _utility, int _direction); // Destroy a gradsearch object void gradsearch_destroy(gradsearch _q); // Prints current status of search void gradsearch_print(gradsearch _q); // Iterate once float gradsearch_step(gradsearch _q); // Execute the search float gradsearch_execute(gradsearch _q, unsigned int _max_iterations, float _target_utility); // quasi-Newton search typedef struct qnsearch_s * qnsearch; // Create a simple qnsearch object; parameters are specified internally // _userdata : userdata // _v : array of parameters to optimize // _num_parameters : array length // _get_utility : utility function pointer // _direction : search direction (e.g. LIQUID_OPTIM_MAXIMIZE) qnsearch qnsearch_create(void * _userdata, float * _v, unsigned int _num_parameters, utility_function _u, int _direction); // Destroy a qnsearch object void qnsearch_destroy(qnsearch _g); // Prints current status of search void qnsearch_print(qnsearch _g); // Resets internal state void qnsearch_reset(qnsearch _g); // Iterate once void qnsearch_step(qnsearch _g); // Execute the search float qnsearch_execute(qnsearch _g, unsigned int _max_iterations, float _target_utility); // // chromosome (for genetic algorithm search) // typedef struct chromosome_s * chromosome; // create a chromosome object, variable bits/trait chromosome chromosome_create(unsigned int * _bits_per_trait, unsigned int _num_traits); // create a chromosome object, all traits same resolution chromosome chromosome_create_basic(unsigned int _num_traits, unsigned int _bits_per_trait); // create a chromosome object, cloning a parent chromosome chromosome_create_clone(chromosome _parent); // copy existing chromosomes' internal traits (all other internal // parameters must be equal) void chromosome_copy(chromosome _parent, chromosome _child); // Destroy a chromosome object void chromosome_destroy(chromosome _c); // get number of traits in chromosome unsigned int chromosome_get_num_traits(chromosome _c); // Print chromosome values to screen (binary representation) void chromosome_print(chromosome _c); // Print chromosome values to screen (floating-point representation) void chromosome_printf(chromosome _c); // clear chromosome (set traits to zero) void chromosome_reset(chromosome _c); // initialize chromosome on integer values void chromosome_init(chromosome _c, unsigned int * _v); // initialize chromosome on floating-point values void chromosome_initf(chromosome _c, float * _v); // Mutates chromosome _c at _index void chromosome_mutate(chromosome _c, unsigned int _index); // Resulting chromosome _c is a crossover of parents _p1 and _p2 at _threshold void chromosome_crossover(chromosome _p1, chromosome _p2, chromosome _c, unsigned int _threshold); // Initializes chromosome to random value void chromosome_init_random(chromosome _c); // Returns integer representation of chromosome unsigned int chromosome_value(chromosome _c, unsigned int _index); // Returns floating-point representation of chromosome float chromosome_valuef(chromosome _c, unsigned int _index); // // genetic algorithm search // typedef struct gasearch_s * gasearch; typedef float (*gasearch_utility)(void * _userdata, chromosome _c); // Create a simple gasearch object; parameters are specified internally // _utility : chromosome fitness utility function // _userdata : user data, void pointer passed to _get_utility() callback // _parent : initial population parent chromosome, governs precision, etc. // _minmax : search direction gasearch gasearch_create(gasearch_utility _u, void * _userdata, chromosome _parent, int _minmax); // Create a gasearch object, specifying search parameters // _utility : chromosome fitness utility function // _userdata : user data, void pointer passed to _get_utility() callback // _parent : initial population parent chromosome, governs precision, etc. // _minmax : search direction // _population_size : number of chromosomes in population // _mutation_rate : probability of mutating chromosomes gasearch gasearch_create_advanced(gasearch_utility _utility, void * _userdata, chromosome _parent, int _minmax, unsigned int _population_size, float _mutation_rate); // Destroy a gasearch object void gasearch_destroy(gasearch _q); // print search parameter internals void gasearch_print(gasearch _q); // set mutation rate void gasearch_set_mutation_rate(gasearch _q, float _mutation_rate); // set population/selection size // _q : ga search object // _population_size : new population size (number of chromosomes) // _selection_size : selection size (number of parents for new generation) void gasearch_set_population_size(gasearch _q, unsigned int _population_size, unsigned int _selection_size); // Execute the search // _q : ga search object // _max_iterations : maximum number of iterations to run before bailing // _target_utility : target utility float gasearch_run(gasearch _q, unsigned int _max_iterations, float _target_utility); // iterate over one evolution of the search algorithm void gasearch_evolve(gasearch _q); // get optimal chromosome // _q : ga search object // _c : output optimal chromosome // _utility_opt : fitness of _c void gasearch_getopt(gasearch _q, chromosome _c, float * _utility_opt); // // MODULE : quantization // float compress_mulaw(float _x, float _mu); float expand_mulaw(float _x, float _mu); void compress_cf_mulaw(liquid_float_complex _x, float _mu, liquid_float_complex * _y); void expand_cf_mulaw(liquid_float_complex _y, float _mu, liquid_float_complex * _x); //float compress_alaw(float _x, float _a); //float expand_alaw(float _x, float _a); // inline quantizer: 'analog' signal in [-1, 1] unsigned int quantize_adc(float _x, unsigned int _num_bits); float quantize_dac(unsigned int _s, unsigned int _num_bits); // structured quantizer typedef enum { LIQUID_COMPANDER_NONE=0, LIQUID_COMPANDER_LINEAR, LIQUID_COMPANDER_MULAW, LIQUID_COMPANDER_ALAW } liquid_compander_type; #define LIQUID_QUANTIZER_MANGLE_FLOAT(name) LIQUID_CONCAT(quantizerf, name) #define LIQUID_QUANTIZER_MANGLE_CFLOAT(name) LIQUID_CONCAT(quantizercf, name) // large macro // QUANTIZER : name-mangling macro // T : data type #define LIQUID_QUANTIZER_DEFINE_API(QUANTIZER,T) \ typedef struct QUANTIZER(_s) * QUANTIZER(); \ QUANTIZER() QUANTIZER(_create)(liquid_compander_type _ctype, \ float _range, \ unsigned int _num_bits); \ void QUANTIZER(_destroy)(QUANTIZER() _q); \ void QUANTIZER(_print)(QUANTIZER() _q); \ void QUANTIZER(_execute_adc)(QUANTIZER() _q, \ T _x, \ unsigned int * _sample); \ void QUANTIZER(_execute_dac)(QUANTIZER() _q, \ unsigned int _sample, \ T * _x); \ LIQUID_QUANTIZER_DEFINE_API(LIQUID_QUANTIZER_MANGLE_FLOAT, float) LIQUID_QUANTIZER_DEFINE_API(LIQUID_QUANTIZER_MANGLE_CFLOAT, liquid_float_complex) // // MODULE : random (number generators) // // Uniform random number generator, (0,1] float randf(); float randf_pdf(float _x); float randf_cdf(float _x); // Gauss random number generator, N(0,1) // f(x) = 1/sqrt(2*pi*sigma^2) * exp{-(x-eta)^2/(2*sigma^2)} // // where // eta = mean // sigma = standard deviation // float randnf(); void awgn(float *_x, float _nstd); void crandnf(liquid_float_complex *_y); void cawgn(liquid_float_complex *_x, float _nstd); float randnf_pdf(float _x, float _eta, float _sig); float randnf_cdf(float _x, float _eta, float _sig); // Exponential // f(x) = lambda exp{ -lambda x } // where // lambda = spread parameter, lambda > 0 // x >= 0 float randexpf(float _lambda); float randexpf_pdf(float _x, float _lambda); float randexpf_cdf(float _x, float _lambda); // Weibull // f(x) = (a/b) (x/b)^(a-1) exp{ -(x/b)^a } // where // a = alpha : shape parameter // b = beta : scaling parameter // g = gamma : location (threshold) parameter // float randweibf(float _alpha, float _beta, float _gamma); float randweibf_pdf(float _x, float _a, float _b, float _g); float randweibf_cdf(float _x, float _a, float _b, float _g); // Gamma // x^(a-1) exp(-x/b) // f(x) = ------------------- // Gamma(a) b^a // where // a = alpha : shape parameter, a > 0 // b = beta : scale parameter, b > 0 // Gamma(z) = regular gamma function // x >= 0 float randgammaf(float _alpha, float _beta); float randgammaf_pdf(float _x, float _alpha, float _beta); float randgammaf_cdf(float _x, float _alpha, float _beta); // Nakagami-m // f(x) = (2/Gamma(m)) (m/omega)^m x^(2m-1) exp{-(m/omega)x^2} // where // m : shape parameter, m >= 0.5 // omega : spread parameter, omega > 0 // Gamma(z): regular complete gamma function // x >= 0 float randnakmf(float _m, float _omega); float randnakmf_pdf(float _x, float _m, float _omega); float randnakmf_cdf(float _x, float _m, float _omega); // Rice-K // f(x) = (x/sigma^2) exp{ -(x^2+s^2)/(2sigma^2) } I0( x s / sigma^2 ) // where // s = sqrt( omega*K/(K+1) ) // sigma = sqrt(0.5 omega/(K+1)) // and // K = shape parameter // omega = spread parameter // I0 = modified Bessel function of the first kind // x >= 0 float randricekf(float _K, float _omega); float randricekf_cdf(float _x, float _K, float _omega); float randricekf_pdf(float _x, float _K, float _omega); // Data scrambler : whiten data sequence void scramble_data(unsigned char * _x, unsigned int _len); void unscramble_data(unsigned char * _x, unsigned int _len); void unscramble_data_soft(unsigned char * _x, unsigned int _len); // // MODULE : sequence // // Binary sequence (generic) typedef struct bsequence_s * bsequence; // Create a binary sequence of a specific length (number of bits) bsequence bsequence_create(unsigned int num_bits); // Free memory in a binary sequence void bsequence_destroy(bsequence _bs); // Clear binary sequence (set to 0's) void bsequence_reset(bsequence _bs); // initialize sequence on external array void bsequence_init(bsequence _bs, unsigned char * _v); // Print sequence to the screen void bsequence_print(bsequence _bs); // Push bit into to back of a binary sequence void bsequence_push(bsequence _bs, unsigned int _bit); // circular shift (left) void bsequence_circshift(bsequence _bs); // Correlate two binary sequences together int bsequence_correlate(bsequence _bs1, bsequence _bs2); // compute the binary addition of two bit sequences void bsequence_add(bsequence _bs1, bsequence _bs2, bsequence _bs3); // compute the binary multiplication of two bit sequences void bsequence_mul(bsequence _bs1, bsequence _bs2, bsequence _bs3); // accumulate the 1's in a binary sequence unsigned int bsequence_accumulate(bsequence _bs); // accessor functions unsigned int bsequence_get_length(bsequence _bs); unsigned int bsequence_index(bsequence _bs, unsigned int _i); // Complementary codes // intialize two sequences to complementary codes. sequences must // be of length at least 8 and a power of 2 (e.g. 8, 16, 32, 64,...) // _a : sequence 'a' (bsequence object) // _b : sequence 'b' (bsequence object) void bsequence_create_ccodes(bsequence _a, bsequence _b); // M-Sequence #define LIQUID_MAX_MSEQUENCE_LENGTH 32767 // default m-sequence generators: g (hex) m n g (oct) g (binary) #define LIQUID_MSEQUENCE_GENPOLY_M2 0x0007 // 2 3 7 111 #define LIQUID_MSEQUENCE_GENPOLY_M3 0x000B // 3 7 13 1011 #define LIQUID_MSEQUENCE_GENPOLY_M4 0x0013 // 4 15 23 10011 #define LIQUID_MSEQUENCE_GENPOLY_M5 0x0025 // 5 31 45 100101 #define LIQUID_MSEQUENCE_GENPOLY_M6 0x0043 // 6 63 103 1000011 #define LIQUID_MSEQUENCE_GENPOLY_M7 0x0089 // 7 127 211 10001001 #define LIQUID_MSEQUENCE_GENPOLY_M8 0x011D // 8 255 435 100101101 #define LIQUID_MSEQUENCE_GENPOLY_M9 0x0211 // 9 511 1021 1000010001 #define LIQUID_MSEQUENCE_GENPOLY_M10 0x0409 // 10 1023 2011 10000001001 #define LIQUID_MSEQUENCE_GENPOLY_M11 0x0805 // 11 2047 4005 100000000101 #define LIQUID_MSEQUENCE_GENPOLY_M12 0x1053 // 12 4095 10123 1000001010011 #define LIQUID_MSEQUENCE_GENPOLY_M13 0x201b // 13 8191 20033 10000000011011 #define LIQUID_MSEQUENCE_GENPOLY_M14 0x402b // 14 16383 40053 100000000101011 #define LIQUID_MSEQUENCE_GENPOLY_M15 0x8003 // 15 32767 100003 1000000000000011 typedef struct msequence_s * msequence; // create a maximal-length sequence (m-sequence) object with // an internal shift register length of _m bits. // _m : generator polynomial length, sequence length is (2^m)-1 // _g : generator polynomial, starting with most-significant bit // _a : initial shift register state, default: 000...001 msequence msequence_create(unsigned int _m, unsigned int _g, unsigned int _a); // create a maximal-length sequence (m-sequence) object from a generator polynomial msequence msequence_create_genpoly(unsigned int _g); // creates a default maximal-length sequence msequence msequence_create_default(unsigned int _m); // destroy an msequence object, freeing all internal memory void msequence_destroy(msequence _m); // prints the sequence's internal state to the screen void msequence_print(msequence _m); // advance msequence on shift register, returning output bit unsigned int msequence_advance(msequence _ms); // generate pseudo-random symbol from shift register by // advancing _bps bits and returning compacted symbol // _ms : m-sequence object // _bps : bits per symbol of output unsigned int msequence_generate_symbol(msequence _ms, unsigned int _bps); // reset msequence shift register to original state, typically '1' void msequence_reset(msequence _ms); // initialize a bsequence object on an msequence object // _bs : bsequence object // _ms : msequence object void bsequence_init_msequence(bsequence _bs, msequence _ms); // get the length of the sequence unsigned int msequence_get_length(msequence _ms); // get the internal state of the sequence unsigned int msequence_get_state(msequence _ms); // set the internal state of the sequence void msequence_set_state(msequence _ms, unsigned int _a); // // MODULE : utility // // pack binary array with symbol(s) // _src : source array [size: _n x 1] // _n : input source array length // _k : bit index to write in _src // _b : number of bits in input symbol // _sym_in : input symbol void liquid_pack_array(unsigned char * _src, unsigned int _n, unsigned int _k, unsigned int _b, unsigned char _sym_in); // unpack symbols from binary array // _src : source array [size: _n x 1] // _n : input source array length // _k : bit index to write in _src // _b : number of bits in output symbol // _sym_out : output symbol void liquid_unpack_array(unsigned char * _src, unsigned int _n, unsigned int _k, unsigned int _b, unsigned char * _sym_out); // pack one-bit symbols into bytes (8-bit symbols) // _sym_in : input symbols array [size: _sym_in_len x 1] // _sym_in_len : number of input symbols // _sym_out : output symbols // _sym_out_len : number of bytes allocated to output symbols array // _num_written : number of output symbols actually written void liquid_pack_bytes(unsigned char * _sym_in, unsigned int _sym_in_len, unsigned char * _sym_out, unsigned int _sym_out_len, unsigned int * _num_written); // unpack 8-bit symbols (full bytes) into one-bit symbols // _sym_in : input symbols array [size: _sym_in_len x 1] // _sym_in_len : number of input symbols // _sym_out : output symbols array // _sym_out_len : number of bytes allocated to output symbols array // _num_written : number of output symbols actually written void liquid_unpack_bytes(unsigned char * _sym_in, unsigned int _sym_in_len, unsigned char * _sym_out, unsigned int _sym_out_len, unsigned int * _num_written); // repack bytes with arbitrary symbol sizes // _sym_in : input symbols array [size: _sym_in_len x 1] // _sym_in_bps : number of bits per input symbol // _sym_in_len : number of input symbols // _sym_out : output symbols array // _sym_out_bps : number of bits per output symbol // _sym_out_len : number of bytes allocated to output symbols array // _num_written : number of output symbols actually written void liquid_repack_bytes(unsigned char * _sym_in, unsigned int _sym_in_bps, unsigned int _sym_in_len, unsigned char * _sym_out, unsigned int _sym_out_bps, unsigned int _sym_out_len, unsigned int * _num_written); // shift array to the left _b bits, filling in zeros // _src : source address [size: _n x 1] // _n : input data array size // _b : number of bits to shift void liquid_lbshift(unsigned char * _src, unsigned int _n, unsigned int _b); // shift array to the right _b bits, filling in zeros // _src : source address [size: _n x 1] // _n : input data array size // _b : number of bits to shift void liquid_rbshift(unsigned char * _src, unsigned int _n, unsigned int _b); // circularly shift array to the left _b bits // _src : source address [size: _n x 1] // _n : input data array size // _b : number of bits to shift void liquid_lbcircshift(unsigned char * _src, unsigned int _n, unsigned int _b); // circularly shift array to the right _b bits // _src : source address [size: _n x 1] // _n : input data array size // _b : number of bits to shift void liquid_rbcircshift(unsigned char * _src, unsigned int _n, unsigned int _b); // shift array to the left _b bytes, filling in zeros // _src : source address [size: _n x 1] // _n : input data array size // _b : number of bytes to shift void liquid_lshift(unsigned char * _src, unsigned int _n, unsigned int _b); // shift array to the right _b bytes, filling in zeros // _src : source address [size: _n x 1] // _n : input data array size // _b : number of bytes to shift void liquid_rshift(unsigned char * _src, unsigned int _n, unsigned int _b); // circular shift array to the left _b bytes // _src : source address [size: _n x 1] // _n : input data array size // _b : number of bytes to shift void liquid_lcircshift(unsigned char * _src, unsigned int _n, unsigned int _b); // circular shift array to the right _b bytes // _src : source address [size: _n x 1] // _n : input data array size // _b : number of bytes to shift void liquid_rcircshift(unsigned char * _src, unsigned int _n, unsigned int _b); // Count the number of ones in an integer unsigned int liquid_count_ones(unsigned int _x); // count number of ones in an integer, modulo 2 unsigned int liquid_count_ones_mod2(unsigned int _x); // compute bindary dot-product between two integers unsigned int liquid_bdotprod(unsigned int _x, unsigned int _y); // Count leading zeros in an integer unsigned int liquid_count_leading_zeros(unsigned int _x); // Most-significant bit index unsigned int liquid_msb_index(unsigned int _x); // Print string of bits to stdout void liquid_print_bitstring(unsigned int _x, unsigned int _n); // reverse byte, word, etc. unsigned char liquid_reverse_byte( unsigned char _x); unsigned int liquid_reverse_uint16(unsigned int _x); unsigned int liquid_reverse_uint24(unsigned int _x); unsigned int liquid_reverse_uint32(unsigned int _x); // // MODULE : vector // #define LIQUID_VECTOR_MANGLE_RF(name) LIQUID_CONCAT(liquid_vectorf, name) #define LIQUID_VECTOR_MANGLE_CF(name) LIQUID_CONCAT(liquid_vectorcf,name) // large macro // VECTOR : name-mangling macro // T : data type // TP : data type (primitive) #define LIQUID_VECTOR_DEFINE_API(VECTOR,T,TP) \ \ /* initialize vector with scalar: x[i] = c (scalar) */ \ void VECTOR(_init)(T _c, \ T * _x, \ unsigned int _n); \ \ /* add each element: z[i] = x[i] + y[i] */ \ void VECTOR(_add)(T * _x, \ T * _y, \ unsigned int _n, \ T * _z); \ /* add scalar to each element: y[i] = x[i] + c */ \ void VECTOR(_addscalar)(T * _x, \ unsigned int _n, \ T _c, \ T * _y); \ \ /* multiply each element: z[i] = x[i] * y[i] */ \ void VECTOR(_mul)(T * _x, \ T * _y, \ unsigned int _n, \ T * _z); \ /* multiply each element with scalar: y[i] = x[i] * c */ \ void VECTOR(_mulscalar)(T * _x, \ unsigned int _n, \ T _c, \ T * _y); \ \ /* compute complex phase rotation: x[i] = exp{j theta[i]} */ \ void VECTOR(_cexpj)(TP * _theta, \ unsigned int _n, \ T * _x); \ /* compute angle of each element: theta[i] = arg{ x[i] } */ \ void VECTOR(_carg)(T * _x, \ unsigned int _n, \ TP * _theta); \ /* compute absolute value of each element: y[i] = |x[i]| */ \ void VECTOR(_abs)(T * _x, \ unsigned int _n, \ TP * _y); \ \ /* compute sum of squares: sum{ |x|^2 } */ \ TP VECTOR(_sumsq)(T * _x, \ unsigned int _n); \ \ /* compute l-2 norm: sqrt{ sum{ |x|^2 } } */ \ TP VECTOR(_norm)(T * _x, \ unsigned int _n); \ \ /* compute l-p norm: { sum{ |x|^p } }^(1/p) */ \ TP VECTOR(_pnorm)(T * _x, \ unsigned int _n, \ TP _p); \ \ /* scale vector elements by l-2 norm: y[i] = x[i]/norm(x) */ \ void VECTOR(_normalize)(T * _x, \ unsigned int _n, \ T * _y); \ LIQUID_VECTOR_DEFINE_API(LIQUID_VECTOR_MANGLE_RF, float, float) LIQUID_VECTOR_DEFINE_API(LIQUID_VECTOR_MANGLE_CF, liquid_float_complex, float) // // mixed types // #if 0 void liquid_vectorf_add(float * _a, float * _b, unsigned int _n, float * _c); #endif #ifdef __cplusplus } //extern "C" #endif // __cplusplus #endif // __LIQUID_H__ liquid-dsp-1.3.1/include/liquid.internal.h000066400000000000000000002156341317124540100204760ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2017 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // liquid.internal.h // // Internal header file for liquid DSP for SDR // // This file includes function declarations which are intended // for internal use // #ifndef __LIQUID_INTERNAL_H__ #define __LIQUID_INTERNAL_H__ // Configuration file #include "config.h" #include #include "liquid.h" #if defined HAVE_FEC_H && defined HAVE_LIBFEC # define LIBFEC_ENABLED 1 #endif // // Debugging macros // #define DEBUG_PRINTF_FLOAT(F,STR,I,V) \ fprintf(F,"%s(%4u) = %12.4e;\n",STR,I+1,V) #define DEBUG_PRINTF_CFLOAT(F,STR,I,V) \ fprintf(F,"%s(%4u) = %12.4e +j*%12.4e;\n",STR,I+1,crealf(V),cimagf(V)) #define PRINTVAL_FLOAT(X,F) printf(#F,crealf(X)); #define PRINTVAL_CFLOAT(X,F) printf(#F "+j*" #F, crealf(X), cimagf(X)); // // MODULE : agc // // // MODULE : audio // // // MODULE : buffer // // // MODULE : dotprod // // // MODULE : fec (forward error-correction) // // checksum / cyclic redundancy check (crc) #define CRC8_POLY 0x07 #define CRC16_POLY 0x8005 #define CRC24_POLY 0x5D6DCB #define CRC32_POLY 0x04C11DB7 unsigned int checksum_generate_key(unsigned char * _msg, unsigned int _msg_len); unsigned int crc8_generate_key(unsigned char * _msg, unsigned int _msg_len); unsigned int crc16_generate_key(unsigned char * _msg, unsigned int _msg_len); unsigned int crc24_generate_key(unsigned char * _msg, unsigned int _msg_len); unsigned int crc32_generate_key(unsigned char * _msg, unsigned int _msg_len); // fec : basic object struct fec_s { // common fec_scheme scheme; //unsigned int dec_msg_len; //unsigned int enc_msg_len; float rate; // lengths: convolutional, Reed-Solomon unsigned int num_dec_bytes; unsigned int num_enc_bytes; // convolutional : internal memory structure unsigned char * enc_bits; void * vp; // decoder object int * poly; // polynomial unsigned int R; // primitive rate, inverted (e.g. R=3 for 1/3) unsigned int K; // constraint length unsigned int P; // puncturing rate (e.g. p=3 for 3/4) int * puncturing_matrix; // viterbi decoder function pointers void*(*create_viterbi)(int); //void (*set_viterbi_polynomial)(int*); int (*init_viterbi)(void*,int); int (*update_viterbi_blk)(void*,unsigned char*,int); int (*chainback_viterbi)(void*,unsigned char*,unsigned int,unsigned int); void (*delete_viterbi)(void*); // Reed-Solomon int symsize; // symbol size (bits per symbol) int genpoly; // generator polynomial int fcs; // int prim; // int nroots; // number of roots in the polynomial //int ntrials; // unsigned int rspad; // number of implicit padded symbols int nn; // 2^symsize - 1 int kk; // nn - nroots void * rs; // Reed-Solomon internal object // Reed-Solomon decoder unsigned int num_blocks; // number of blocks: ceil(dec_msg_len / nn) unsigned int dec_block_len; // number of decoded bytes per block: unsigned int enc_block_len; // number of encoded bytes per block: unsigned int res_block_len; // residual bytes in last block unsigned int pad; // padding for each block unsigned char * tblock; // decoder input sequence [size: 1 x n] int * errlocs; // error locations [size: 1 x n] int * derrlocs; // decoded error locations [size: 1 x n] int erasures; // number of erasures // encode function pointer void (*encode_func)(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_dec, unsigned char * _msg_enc); // decode function pointer void (*decode_func)(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); // decode function pointer (soft decision) void (*decode_soft_func)(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); }; // simple type testing int fec_scheme_is_convolutional(fec_scheme _scheme); int fec_scheme_is_punctured(fec_scheme _scheme); int fec_scheme_is_reedsolomon(fec_scheme _scheme); int fec_scheme_is_hamming(fec_scheme _scheme); int fec_scheme_is_repeat(fec_scheme _scheme); // Pass fec fec_pass_create(void *_opts); void fec_pass_destroy(fec _q); void fec_pass_print(fec _q); void fec_pass_encode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_dec, unsigned char * _msg_enc); void fec_pass_decode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); // Repeat (3) fec fec_rep3_create(void *_opts); void fec_rep3_destroy(fec _q); void fec_rep3_print(fec _q); void fec_rep3_encode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_dec, unsigned char * _msg_enc); void fec_rep3_decode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); void fec_rep3_decode_soft(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); // Repeat (5) fec fec_rep5_create(void *_opts); void fec_rep5_destroy(fec _q); void fec_rep5_print(fec _q); void fec_rep5_encode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_dec, unsigned char * _msg_enc); void fec_rep5_decode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); void fec_rep5_decode_soft(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); // Hamming(7,4) extern unsigned char hamming74_enc_gentab[16]; extern unsigned char hamming74_dec_gentab[128]; fec fec_hamming74_create(void *_opts); void fec_hamming74_destroy(fec _q); void fec_hamming74_print(fec _q); void fec_hamming74_encode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_dec, unsigned char * _msg_enc); void fec_hamming74_decode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); void fec_hamming74_decode_soft(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); // soft decoding of one symbol unsigned char fecsoft_hamming74_decode(unsigned char * _soft_bits); // Hamming(8,4) extern unsigned char hamming84_enc_gentab[16]; extern unsigned char hamming84_dec_gentab[256]; fec fec_hamming84_create(void *_opts); void fec_hamming84_destroy(fec _q); void fec_hamming84_print(fec _q); void fec_hamming84_encode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_dec, unsigned char * _msg_enc); void fec_hamming84_decode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); void fec_hamming84_decode_soft(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); // soft decoding of one symbol unsigned char fecsoft_hamming84_decode(unsigned char * _soft_bits); // Hamming(12,8) unsigned int fec_hamming128_encode_symbol(unsigned int _sym_dec); unsigned int fec_hamming128_decode_symbol(unsigned int _sym_enc); extern unsigned short int hamming128_enc_gentab[256]; // encoding table fec fec_hamming128_create(void *_opts); void fec_hamming128_destroy(fec _q); void fec_hamming128_print(fec _q); void fec_hamming128_encode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_dec, unsigned char * _msg_enc); void fec_hamming128_decode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); void fec_hamming128_decode_soft(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); // soft decoding of one symbol unsigned int fecsoft_hamming128_decode(unsigned char * _soft_bits); extern unsigned char fecsoft_hamming128_n3[256][17]; unsigned int fecsoft_hamming128_decode_n3(unsigned char * _soft_bits); // Hamming(15,11) unsigned int fec_hamming1511_encode_symbol(unsigned int _sym_dec); unsigned int fec_hamming1511_decode_symbol(unsigned int _sym_enc); // Hamming(31,26) unsigned int fec_hamming3126_encode_symbol(unsigned int _sym_dec); unsigned int fec_hamming3126_decode_symbol(unsigned int _sym_enc); // Golay(24,12) unsigned int fec_golay2412_encode_symbol(unsigned int _sym_dec); unsigned int fec_golay2412_decode_symbol(unsigned int _sym_enc); extern unsigned int golay2412_P[12]; extern unsigned int golay2412_Gt[24]; extern unsigned int golay2412_H[12]; // multiply input vector with matrix unsigned int golay2412_matrix_mul(unsigned int _v, unsigned int * _A, unsigned int _n); // search for p[i] such that w(v+p[i]) <= 2, return -1 on fail int golay2412_parity_search(unsigned int _v); fec fec_golay2412_create(void *_opts); void fec_golay2412_destroy(fec _q); void fec_golay2412_print(fec _q); void fec_golay2412_encode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_dec, unsigned char * _msg_enc); void fec_golay2412_decode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); // SEC-DED (22,16) // compute parity on 16-bit input unsigned char fec_secded2216_compute_parity(unsigned char * _m); // compute syndrome on 22-bit input unsigned char fec_secded2216_compute_syndrome(unsigned char * _v); // encode symbol // _sym_dec : decoded symbol [size: 2 x 1] // _sym_enc : encoded symbol [size: 3 x 1], _sym_enc[0] has only 6 bits void fec_secded2216_encode_symbol(unsigned char * _sym_dec, unsigned char * _sym_enc); // decode symbol, returning 0/1/2 for zero/one/multiple errors detected // _sym_enc : encoded symbol [size: 3 x 1], _sym_enc[0] has only 6 bits // _sym_dec : decoded symbol [size: 2 x 1] int fec_secded2216_decode_symbol(unsigned char * _sym_enc, unsigned char * _sym_dec); // estimate error vector, returning 0/1/2 for zero/one/multiple errors detected // _sym_enc : encoded symbol [size: 3 x 1], _sym_enc[0] has only 6 bits // _e_hat : estimated error vector [size: 3 x 1] int fec_secded2216_estimate_ehat(unsigned char * _sym_enc, unsigned char * _e_hat); // parity matrix [6 x 16 bits], [6 x 2 bytes] extern unsigned char secded2216_P[12]; // syndrome vectors of errors with weight exactly equal to 1 extern unsigned char secded2216_syndrome_w1[22]; fec fec_secded2216_create(void *_opts); void fec_secded2216_destroy(fec _q); void fec_secded2216_print(fec _q); void fec_secded2216_encode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_dec, unsigned char * _msg_enc); void fec_secded2216_decode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); // SEC-DED (39,32) // compute parity on 32-bit input unsigned char fec_secded3932_compute_parity(unsigned char * _m); // compute syndrome on 39-bit input unsigned char fec_secded3932_compute_syndrome(unsigned char * _v); // encode symbol // _sym_dec : decoded symbol [size: 4 x 1] // _sym_enc : encoded symbol [size: 5 x 1], _sym_enc[0] has only 7 bits void fec_secded3932_encode_symbol(unsigned char * _sym_dec, unsigned char * _sym_enc); // estimate error vector, returning 0/1/2 for zero/one/multiple errors detected // _sym_enc : encoded symbol [size: 5 x 1], _sym_enc[0] has only 7 bits // _e_hat : estimated error vector [size: 5 x 1] int fec_secded3932_estimate_ehat(unsigned char * _sym_enc, unsigned char * _e_hat); // decode symbol, returning 0/1/2 for zero/one/multiple errors detected // _sym_enc : encoded symbol [size: 5 x 1], _sym_enc[0] has only 7 bits // _sym_dec : decoded symbol [size: 4 x 1] int fec_secded3932_decode_symbol(unsigned char * _sym_enc, unsigned char * _sym_dec); // parity matrix [7 x 32 bits], [7 x 4 bytes] extern unsigned char secded3932_P[28]; // syndrome vectors of errors with weight exactly equal to 1 extern unsigned char secded3932_syndrome_w1[39]; fec fec_secded3932_create(void *_opts); void fec_secded3932_destroy(fec _q); void fec_secded3932_print(fec _q); void fec_secded3932_encode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_dec, unsigned char * _msg_enc); void fec_secded3932_decode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); // SEC-DED (72,64) // compute parity byte on 64-byte input unsigned char fec_secded7264_compute_parity(unsigned char * _v); // compute syndrome on 72-bit input unsigned char fec_secded7264_compute_syndrome(unsigned char * _v); // encode symbol // _sym_dec : input symbol [size: 8 x 1] // _sym_enc : input symbol [size: 9 x 1] void fec_secded7264_encode_symbol(unsigned char * _sym_dec, unsigned char * _sym_enc); // estimate error vector, returning 0/1/2 for zero/one/multiple errors detected // _sym_enc : encoded symbol [size: 9 x 1] // _e_hat : estimated error vector [size: 9 x 1] int fec_secded7264_estimate_ehat(unsigned char * _sym_enc, unsigned char * _e_hat); // decode symbol, returning 0/1/2 for zero/one/multiple errors detected // _sym_enc : input symbol [size: 8 x 1] // _sym_dec : input symbol [size: 9 x 1] int fec_secded7264_decode_symbol(unsigned char * _sym_enc, unsigned char * _sym_dec); extern unsigned char secded7264_P[64]; extern unsigned char secded7264_syndrome_w1[72]; fec fec_secded7264_create(void *_opts); void fec_secded7264_destroy(fec _q); void fec_secded7264_print(fec _q); void fec_secded7264_encode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_dec, unsigned char * _msg_enc); void fec_secded7264_decode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); // Convolutional: r1/2 K=7 // r1/2 K=9 // r1/3 K=9 // r1/6 K=15 // compute encoded message length for block codes // _dec_msg_len : decoded message length (bytes) // _m : input block size (bits) // _k : output block size (bits) unsigned int fec_block_get_enc_msg_len(unsigned int _dec_msg_len, unsigned int _m, unsigned int _k); // compute encoded message length for convolutional codes // _dec_msg_len : decoded message length // _K : constraint length // _p : puncturing rate, r = _p / (_p+1) unsigned int fec_conv_get_enc_msg_len(unsigned int _dec_msg_len, unsigned int _K, unsigned int _p); // convolutional code polynomials extern int fec_conv27_poly[2]; extern int fec_conv29_poly[2]; extern int fec_conv39_poly[3]; extern int fec_conv615_poly[6]; // convolutional code puncturing matrices [R x P] extern int fec_conv27p23_matrix[4]; // [2 x 2] extern int fec_conv27p34_matrix[6]; // [2 x 3] extern int fec_conv27p45_matrix[8]; // [2 x 4] extern int fec_conv27p56_matrix[10]; // [2 x 5] extern int fec_conv27p67_matrix[12]; // [2 x 6] extern int fec_conv27p78_matrix[14]; // [2 x 7] extern int fec_conv29p23_matrix[4]; // [2 x 2] extern int fec_conv29p34_matrix[6]; // [2 x 3] extern int fec_conv29p45_matrix[8]; // [2 x 4] extern int fec_conv29p56_matrix[10]; // [2 x 5] extern int fec_conv29p67_matrix[12]; // [2 x 6] extern int fec_conv29p78_matrix[14]; // [2 x 7] fec fec_conv_create(fec_scheme _fs); void fec_conv_destroy(fec _q); void fec_conv_print(fec _q); void fec_conv_encode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_dec, unsigned char * _msg_enc); void fec_conv_decode_hard(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); void fec_conv_decode_soft(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); void fec_conv_decode(fec _q, unsigned char * _msg_dec); void fec_conv_setlength(fec _q, unsigned int _dec_msg_len); // internal initialization methods (sets r, K, viterbi methods) void fec_conv_init_v27(fec _q); void fec_conv_init_v29(fec _q); void fec_conv_init_v39(fec _q); void fec_conv_init_v615(fec _q); // punctured convolutional codes fec fec_conv_punctured_create(fec_scheme _fs); void fec_conv_punctured_destroy(fec _q); void fec_conv_punctured_print(fec _q); void fec_conv_punctured_encode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_dec, unsigned char * _msg_enc); void fec_conv_punctured_decode_hard(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); void fec_conv_punctured_decode_soft(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); void fec_conv_punctured_setlength(fec _q, unsigned int _dec_msg_len); // internal initialization methods (sets r, K, viterbi methods, // and puncturing matrix) void fec_conv_init_v27p23(fec _q); void fec_conv_init_v27p34(fec _q); void fec_conv_init_v27p45(fec _q); void fec_conv_init_v27p56(fec _q); void fec_conv_init_v27p67(fec _q); void fec_conv_init_v27p78(fec _q); void fec_conv_init_v29p23(fec _q); void fec_conv_init_v29p34(fec _q); void fec_conv_init_v29p45(fec _q); void fec_conv_init_v29p56(fec _q); void fec_conv_init_v29p67(fec _q); void fec_conv_init_v29p78(fec _q); // Reed-Solomon // compute encoded message length for Reed-Solomon codes // _dec_msg_len : decoded message length // _nroots : number of roots in polynomial // _nn : // _kk : unsigned int fec_rs_get_enc_msg_len(unsigned int _dec_msg_len, unsigned int _nroots, unsigned int _nn, unsigned int _kk); fec fec_rs_create(fec_scheme _fs); void fec_rs_destroy(fec _q); void fec_rs_init_p8(fec _q); void fec_rs_setlength(fec _q, unsigned int _dec_msg_len); void fec_rs_encode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_dec, unsigned char * _msg_enc); void fec_rs_decode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec); // phi(x) = -logf( tanhf( x/2 ) ) float sumproduct_phi(float _x); // iterate over the sum-product algorithm: // returns 1 if parity checks, 0 otherwise // _m : rows // _n : cols // _H : sparse binary parity check matrix [size: _m x _n] // _LLR : received signal (soft bits, LLR) [size: _n x 1] // _c_hat : estimated transmitted signal [size: _n x 1] // _max_steps : maximum number of steps before bailing int fec_sumproduct(unsigned int _m, unsigned int _n, smatrixb _H, float * _LLR, unsigned char * _c_hat, unsigned int _max_steps); // sum-product algorithm, returns 1 if parity checks, 0 otherwise // _m : rows // _n : cols // _H : sparse binary parity check matrix [size: _m x _n] // _c_hat : estimated transmitted signal [size: _n x 1] // // internal state arrays // _Lq : [size: _m x _n] // _Lr : [size: _m x _n] // _Lc : [size: _n x 1] // _LQ : [size: _n x 1] // _parity : _H * _c_hat [size: _m x 1] int fec_sumproduct_step(unsigned int _m, unsigned int _n, smatrixb _H, unsigned char * _c_hat, float * _Lq, float * _Lr, float * _Lc, float * _LQ, unsigned char * _parity); // // packetizer // // fec/interleaver plan struct fecintlv_plan { unsigned int dec_msg_len; unsigned int enc_msg_len; // fec codec fec_scheme fs; fec f; // interleaver interleaver q; }; #define PACKETIZER_VERSION (1) // packetizer object struct packetizer_s { unsigned int msg_len; unsigned int packet_len; crc_scheme check; unsigned int crc_length; struct fecintlv_plan * plan; unsigned int plan_len; // buffers (ping-pong) unsigned int buffer_len; unsigned char * buffer_0; unsigned char * buffer_1; }; // // MODULE : fft (fast discrete Fourier transform) // // fast fourier transform method typedef enum { LIQUID_FFT_METHOD_UNKNOWN=0, // unknown method LIQUID_FFT_METHOD_RADIX2, // Radix-2 (decimation in time) LIQUID_FFT_METHOD_MIXED_RADIX, // Cooley-Tukey mixed-radix FFT (decimation in time) LIQUID_FFT_METHOD_RADER, // Rader's method for FFTs of prime length LIQUID_FFT_METHOD_RADER2, // Rader's method for FFTs of prime length (alternate) LIQUID_FFT_METHOD_DFT, // regular discrete Fourier transform } liquid_fft_method; // Macro : FFT (internal) // FFT : name-mangling macro // T : primitive data type // TC : primitive data type (complex) #define LIQUID_FFT_DEFINE_INTERNAL_API(FFT,T,TC) \ \ /* print plan recursively */ \ void FFT(_print_plan_recursive)(FFT(plan) _q, \ unsigned int _level); \ \ /* type definitions for create/destroy/execute functions */ \ typedef FFT(plan)(FFT(_create_t)) (unsigned int _nfft, \ TC * _x, \ TC * _y, \ int _dir, \ int _flags); \ typedef void (FFT(_destroy_t))(FFT(plan) _q); \ typedef void (FFT(_execute_t))(FFT(plan) _q); \ \ /* FFT create methods */ \ FFT(_create_t) FFT(_create_plan_dft); \ FFT(_create_t) FFT(_create_plan_radix2); \ FFT(_create_t) FFT(_create_plan_mixed_radix); \ FFT(_create_t) FFT(_create_plan_rader); \ FFT(_create_t) FFT(_create_plan_rader2); \ \ /* FFT destroy methods */ \ FFT(_destroy_t) FFT(_destroy_plan_dft); \ FFT(_destroy_t) FFT(_destroy_plan_radix2); \ FFT(_destroy_t) FFT(_destroy_plan_mixed_radix); \ FFT(_destroy_t) FFT(_destroy_plan_rader); \ FFT(_destroy_t) FFT(_destroy_plan_rader2); \ \ /* FFT execute methods */ \ FFT(_execute_t) FFT(_execute_dft); \ FFT(_execute_t) FFT(_execute_radix2); \ FFT(_execute_t) FFT(_execute_mixed_radix); \ FFT(_execute_t) FFT(_execute_rader); \ FFT(_execute_t) FFT(_execute_rader2); \ \ /* specific codelets for small DFTs */ \ FFT(_execute_t) FFT(_execute_dft_2); \ FFT(_execute_t) FFT(_execute_dft_3); \ FFT(_execute_t) FFT(_execute_dft_4); \ FFT(_execute_t) FFT(_execute_dft_5); \ FFT(_execute_t) FFT(_execute_dft_6); \ FFT(_execute_t) FFT(_execute_dft_7); \ FFT(_execute_t) FFT(_execute_dft_8); \ FFT(_execute_t) FFT(_execute_dft_16); \ \ /* additional methods */ \ unsigned int FFT(_estimate_mixed_radix)(unsigned int _nfft); \ \ /* discrete cosine transform (DCT) prototypes */ \ void FFT(_execute_REDFT00)(FFT(plan) _q); /* DCT-I */ \ void FFT(_execute_REDFT10)(FFT(plan) _q); /* DCT-II */ \ void FFT(_execute_REDFT01)(FFT(plan) _q); /* DCT-III */ \ void FFT(_execute_REDFT11)(FFT(plan) _q); /* DCT-IV */ \ \ /* discrete sine transform (DST) prototypes */ \ void FFT(_execute_RODFT00)(FFT(plan) _q); /* DST-I */ \ void FFT(_execute_RODFT10)(FFT(plan) _q); /* DST-II */ \ void FFT(_execute_RODFT01)(FFT(plan) _q); /* DST-III */ \ void FFT(_execute_RODFT11)(FFT(plan) _q); /* DST-IV */ \ \ /* destroy real-to-real one-dimensional plan */ \ void FFT(_destroy_plan_r2r_1d)(FFT(plan) _q); \ \ /* print real-to-real one-dimensional plan */ \ void FFT(_print_plan_r2r_1d)(FFT(plan) _q); \ // determine best FFT method based on size liquid_fft_method liquid_fft_estimate_method(unsigned int _nfft); // is input radix-2? int fft_is_radix2(unsigned int _n); // miscellaneous functions unsigned int fft_reverse_index(unsigned int _i, unsigned int _n); LIQUID_FFT_DEFINE_INTERNAL_API(LIQUID_FFT_MANGLE_FLOAT, float, liquid_float_complex) // Use fftw library if installed (and not overridden with configuration), // otherwise use internal (less efficient) fft library. #if HAVE_FFTW3_H && !defined LIQUID_FFTOVERRIDE # include # define FFT_PLAN fftwf_plan # define FFT_CREATE_PLAN fftwf_plan_dft_1d # define FFT_DESTROY_PLAN fftwf_destroy_plan # define FFT_EXECUTE fftwf_execute # define FFT_DIR_FORWARD FFTW_FORWARD # define FFT_DIR_BACKWARD FFTW_BACKWARD # define FFT_METHOD FFTW_ESTIMATE #else # define FFT_PLAN fftplan # define FFT_CREATE_PLAN fft_create_plan # define FFT_DESTROY_PLAN fft_destroy_plan # define FFT_EXECUTE fft_execute # define FFT_DIR_FORWARD LIQUID_FFT_FORWARD # define FFT_DIR_BACKWARD LIQUID_FFT_BACKWARD # define FFT_METHOD 0 #endif // // MODULE : filter // // esimate required filter length given transition bandwidth and // stop-band attenuation (algorithm from [Vaidyanathan:1993]) // _df : transition bandwidth (0 < _df < 0.5) // _As : stop-band attenuation [dB] (As > 0) float estimate_req_filter_len_Kaiser(float _df, float _As); // esimate required filter length given transition bandwidth and // stop-band attenuation (algorithm from [Herrmann:1973]) // _df : transition bandwidth (0 < _df < 0.5) // _As : stop-band attenuation [dB] (As > 0) float estimate_req_filter_len_Herrmann(float _df, float _As); // fir_farrow #define LIQUID_FIRFARROW_DEFINE_INTERNAL_API(FIRFARROW,TO,TC,TI) \ void FIRFARROW(_genpoly)(FIRFARROW() _q); LIQUID_FIRFARROW_DEFINE_INTERNAL_API(LIQUID_FIRFARROW_MANGLE_RRRF, float, float, float) LIQUID_FIRFARROW_DEFINE_INTERNAL_API(LIQUID_FIRFARROW_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) // // iirfiltsos : infinite impulse respone filter (second-order sections) // #define LIQUID_IIRFILTSOS_MANGLE_RRRF(name) LIQUID_CONCAT(iirfiltsos_rrrf,name) #define LIQUID_IIRFILTSOS_MANGLE_CRCF(name) LIQUID_CONCAT(iirfiltsos_crcf,name) #define LIQUID_IIRFILTSOS_MANGLE_CCCF(name) LIQUID_CONCAT(iirfiltsos_cccf,name) #define LIQUID_IIRFILTSOS_DEFINE_INTERNAL_API(IIRFILTSOS,TO,TC,TI) \ typedef struct IIRFILTSOS(_s) * IIRFILTSOS(); \ \ /* create 2nd-order infinite impulse reponse filter */ \ /* _b : feed-forward coefficients [size: _3 x 1] */ \ /* _a : feed-back coefficients [size: _3 x 1] */ \ IIRFILTSOS() IIRFILTSOS(_create)(TC * _b, \ TC * _a); \ \ /* explicitly set 2nd-order IIR filter coefficients */ \ /* _q : iirfiltsos object */ \ /* _b : feed-forward coefficients [size: _3 x 1] */ \ /* _a : feed-back coefficients [size: _3 x 1] */ \ void IIRFILTSOS(_set_coefficients)(IIRFILTSOS() _q, \ TC * _b, \ TC * _a); \ \ /* destroy iirfiltsos object, freeing all internal memory */ \ void IIRFILTSOS(_destroy)(IIRFILTSOS() _q); \ \ /* print iirfiltsos object properties to stdout */ \ void IIRFILTSOS(_print)(IIRFILTSOS() _q); \ \ /* clear/reset iirfiltsos object internals */ \ void IIRFILTSOS(_reset)(IIRFILTSOS() _q); \ \ /* compute filter output */ \ /* _q : iirfiltsos object */ \ /* _x : input sample */ \ /* _y : output sample pointer */ \ void IIRFILTSOS(_execute)(IIRFILTSOS() _q, \ TI _x, \ TO * _y); \ \ /* compute filter output, direct-form I method */ \ /* _q : iirfiltsos object */ \ /* _x : input sample */ \ /* _y : output sample pointer */ \ void IIRFILTSOS(_execute_df1)(IIRFILTSOS() _q, \ TI _x, \ TO * _y); \ \ /* compute filter output, direct-form II method */ \ /* _q : iirfiltsos object */ \ /* _x : input sample */ \ /* _y : output sample pointer */ \ void IIRFILTSOS(_execute_df2)(IIRFILTSOS() _q, \ TI _x, \ TO * _y); \ \ /* compute and return group delay of filter object */ \ /* _q : filter object */ \ /* _fc : frequency to evaluate */ \ float IIRFILTSOS(_groupdelay)(IIRFILTSOS() _q, \ float _fc); \ LIQUID_IIRFILTSOS_DEFINE_INTERNAL_API(LIQUID_IIRFILTSOS_MANGLE_RRRF, float, float, float) LIQUID_IIRFILTSOS_DEFINE_INTERNAL_API(LIQUID_IIRFILTSOS_MANGLE_CRCF, liquid_float_complex, float, liquid_float_complex) LIQUID_IIRFILTSOS_DEFINE_INTERNAL_API(LIQUID_IIRFILTSOS_MANGLE_CCCF, liquid_float_complex, liquid_float_complex, liquid_float_complex) // firdes : finite impulse response filter design // Find approximate bandwidth adjustment factor rho based on // filter delay and desired excess bandwdith factor. // // _m : filter delay (symbols) // _beta : filter excess bandwidth factor (0,1) float rkaiser_approximate_rho(unsigned int _m, float _beta); // Design frequency-shifted root-Nyquist filter based on // the Kaiser-windowed sinc using the bisection method // // _k : filter over-sampling rate (samples/symbol) // _m : filter delay (symbols) // _beta : filter excess bandwidth factor (0,1) // _dt : filter fractional sample delay // _h : resulting filter [size: 2*_k*_m+1] // _rho : transition bandwidth adjustment, 0 < _rho < 1 void liquid_firdes_rkaiser_bisection(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h, float * _rho); // Design frequency-shifted root-Nyquist filter based on // the Kaiser-windowed sinc using the quadratic method. // // _k : filter over-sampling rate (samples/symbol) // _m : filter delay (symbols) // _beta : filter excess bandwidth factor (0,1) // _dt : filter fractional sample delay // _h : resulting filter [size: 2*_k*_m+1] // _rho : transition bandwidth adjustment, 0 < _rho < 1 void liquid_firdes_rkaiser_quadratic(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h, float * _rho); // compute filter coefficients and determine resulting ISI // // _k : filter over-sampling rate (samples/symbol) // _m : filter delay (symbols) // _beta : filter excess bandwidth factor (0,1) // _dt : filter fractional sample delay // _rho : transition bandwidth adjustment, 0 < _rho < 1 // _h : filter buffer [size: 2*_k*_m+1] float liquid_firdes_rkaiser_internal_isi(unsigned int _k, unsigned int _m, float _beta, float _dt, float _rho, float * _h); // Design flipped Nyquist/root-Nyquist filters void liquid_firdes_fnyquist(liquid_firfilt_type _type, int _root, unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h); // flipped exponential frequency response void liquid_firdes_fexp_freqresponse(unsigned int _k, unsigned int _m, float _beta, float * _H); // flipped hyperbolic secant frequency response void liquid_firdes_fsech_freqresponse(unsigned int _k, unsigned int _m, float _beta, float * _H); // flipped hyperbolic secant frequency response void liquid_firdes_farcsech_freqresponse(unsigned int _k, unsigned int _m, float _beta, float * _H); // iirdes : infinite impulse response filter design // Sorts array _z of complex numbers into complex conjugate pairs to // within a tolerance. Conjugate pairs are ordered by increasing real // component with the negative imaginary element first. All pure-real // elements are placed at the end of the array. // // Example: // v: liquid_cplxpair(v): // 10 + j*3 -3 - j*4 // 5 + j*0 3 + j*4 // -3 + j*4 10 - j*3 // 10 - j*3 10 + j*3 // 3 + j*0 3 + j*0 // -3 + j*4 5 + j*0 // // _z : complex array (size _n) // _n : number of elements in _z // _tol : tolerance for finding complex pairs // _p : resulting pairs, pure real values of _z at end void liquid_cplxpair(float complex * _z, unsigned int _n, float _tol, float complex * _p); // post-process cleanup used with liquid_cplxpair // // once pairs have been identified and ordered, this method // will clean up the result by ensuring the following: // * pairs are perfect conjugates // * pairs have negative imaginary component first // * pairs are ordered by increasing real component // * pure-real elements are ordered by increasing value // // _p : pre-processed complex array [size: _n x 1] // _n : array length // _num_pairs : number of complex conjugate pairs void liquid_cplxpair_cleanup(float complex * _p, unsigned int _n, unsigned int _num_pairs); // Jacobian elliptic functions (src/filter/src/ellip.c) // Landen transformation (_n iterations) void landenf(float _k, unsigned int _n, float * _v); // compute elliptic integral K(k) for _n recursions void ellipkf(float _k, unsigned int _n, float * _K, float * _Kp); // elliptic degree float ellipdegf(float _N, float _k1, unsigned int _n); // elliptic cd() function (_n recursions) float complex ellip_cdf(float complex _u, float _k, unsigned int _n); // elliptic inverse cd() function (_n recursions) float complex ellip_acdf(float complex _u, float _k, unsigned int _n); // elliptic sn() function (_n recursions) float complex ellip_snf(float complex _u, float _k, unsigned int _n); // elliptic inverse sn() function (_n recursions) float complex ellip_asnf(float complex _u, float _k, unsigned int _n); // // MODULE : framing // // // bpacket // #define BPACKET_VERSION (101+PACKETIZER_VERSION) // generator void bpacketgen_compute_packet_len(bpacketgen _q); void bpacketgen_assemble_pnsequence(bpacketgen _q); void bpacketgen_assemble_header(bpacketgen _q); // synchronizer void bpacketsync_assemble_pnsequence(bpacketsync _q); void bpacketsync_execute_seekpn(bpacketsync _q, unsigned char _bit); void bpacketsync_execute_rxheader(bpacketsync _q, unsigned char _bit); void bpacketsync_execute_rxpayload(bpacketsync _q, unsigned char _bit); void bpacketsync_decode_header(bpacketsync _q); void bpacketsync_decode_payload(bpacketsync _q); void bpacketsync_reconfig(bpacketsync _q); // // flexframe // // flexframe protocol #define FLEXFRAME_PROTOCOL (101+PACKETIZER_VERSION) // header description // NOTE: The flexframe header can be improved with crc24, secded7264, v29 // which also generates a 54-byte frame. Improves header decoding // by about 1 dB (99% probability of decoding with SNR = -1 dB); // however this requires that the 'libfec' libraries are installed. #define FLEXFRAME_H_USER (14) // user-defined array #define FLEXFRAME_H_DEC (FLEXFRAME_H_USER+6) // decoded length #define FLEXFRAME_H_CRC (LIQUID_CRC_32) // header CRC #define FLEXFRAME_H_FEC0 (LIQUID_FEC_SECDED7264) // header FEC (inner) #define FLEXFRAME_H_FEC1 (LIQUID_FEC_HAMMING84) // header FEC (outer) // // gmskframe // #define GMSKFRAME_VERSION (3+PACKETIZER_VERSION) // header description #define GMSKFRAME_H_USER (8) // user-defined array #define GMSKFRAME_H_DEC (GMSKFRAME_H_USER+5) // decoded length #define GMSKFRAME_H_CRC (LIQUID_CRC_32) // header CRC #define GMSKFRAME_H_FEC (LIQUID_FEC_HAMMING128) // header FEC #define GMSKFRAME_H_ENC (26) // encoded length (bytes) #define GMSKFRAME_H_SYM (208) // number of encoded bits // // ofdmflexframe // #define OFDMFLEXFRAME_PROTOCOL (104+PACKETIZER_VERSION) // header description #define OFDMFLEXFRAME_H_USER (8) // user-defined array #define OFDMFLEXFRAME_H_DEC (OFDMFLEXFRAME_H_USER+6) // decoded length #define OFDMFLEXFRAME_H_CRC (LIQUID_CRC_32) // header CRC #define OFDMFLEXFRAME_H_FEC (LIQUID_FEC_GOLAY2412) // header FEC #define OFDMFLEXFRAME_H_ENC (36) // encoded length #define OFDMFLEXFRAME_H_MOD (LIQUID_MODEM_BPSK) // modulation scheme #define OFDMFLEXFRAME_H_BPS (1) // modulation depth #define OFDMFLEXFRAME_H_SYM (288) // number of symbols // // MODULE : math // // // basic trigonometric functions // float liquid_sinf(float _x); float liquid_cosf(float _x); float liquid_tanf(float _x); void liquid_sincosf(float _x, float * _sinf, float * _cosf); float liquid_expf(float _x); float liquid_logf(float _x); // // complex math operations // // complex square root float complex liquid_csqrtf(float complex _z); // complex exponent, logarithm float complex liquid_cexpf(float complex _z); float complex liquid_clogf(float complex _z); // complex arcsin, arccos, arctan float complex liquid_casinf(float complex _z); float complex liquid_cacosf(float complex _z); float complex liquid_catanf(float complex _z); // faster approximation to arg{*} float liquid_cargf_approx(float complex _z); // internal trig helper functions // complex rotation vector: cexpf(_Complex_I*THETA) #define liquid_cexpjf(THETA) (cosf(THETA) + _Complex_I*sinf(THETA)) // // MODULE : matrix // // large macro // MATRIX : name-mangling macro // T : data type #define LIQUID_MATRIX_DEFINE_INTERNAL_API(MATRIX,T) \ T MATRIX(_det2x2)(T * _x, \ unsigned int _rx, \ unsigned int _cx); LIQUID_MATRIX_DEFINE_INTERNAL_API(LIQUID_MATRIX_MANGLE_FLOAT, float) LIQUID_MATRIX_DEFINE_INTERNAL_API(LIQUID_MATRIX_MANGLE_DOUBLE, double) LIQUID_MATRIX_DEFINE_INTERNAL_API(LIQUID_MATRIX_MANGLE_CFLOAT, liquid_float_complex) LIQUID_MATRIX_DEFINE_INTERNAL_API(LIQUID_MATRIX_MANGLE_CDOUBLE, liquid_double_complex) // sparse 'alist' matrix type (similar to MacKay, Davey Lafferty convention) // large macro // SMATRIX : name-mangling macro // T : primitive data type #define LIQUID_SMATRIX_DEFINE_INTERNAL_API(SMATRIX,T) \ \ void SMATRIX(_reset_max_mlist)(SMATRIX() _q); \ void SMATRIX(_reset_max_nlist)(SMATRIX() _q); \ LIQUID_SMATRIX_DEFINE_INTERNAL_API(LIQUID_SMATRIX_MANGLE_BOOL, unsigned char) LIQUID_SMATRIX_DEFINE_INTERNAL_API(LIQUID_SMATRIX_MANGLE_FLOAT, float) LIQUID_SMATRIX_DEFINE_INTERNAL_API(LIQUID_SMATRIX_MANGLE_INT, short int) // search for index placement in list unsigned short int smatrix_indexsearch(unsigned short int * _list, unsigned int _num_elements, unsigned short int _value); // // MODULE : modem // // 'Square' QAM #define QAM4_ALPHA (1./sqrt(2)) #define QAM8_ALPHA (1./sqrt(6)) #define QAM16_ALPHA (1./sqrt(10)) #define QAM32_ALPHA (1./sqrt(20)) #define QAM64_ALPHA (1./sqrt(42)) #define QAM128_ALPHA (1./sqrt(82)) #define QAM256_ALPHA (1./sqrt(170)) #define QAM1024_ALPHA (1./sqrt(682)) #define QAM4096_ALPHA (1./sqrt(2730)) // Rectangular QAM #define RQAM4_ALPHA QAM4_ALPHA #define RQAM8_ALPHA QAM8_ALPHA #define RQAM16_ALPHA QAM16_ALPHA #define RQAM32_ALPHA (1./sqrt(26)) #define RQAM64_ALPHA QAM64_ALPHA #define RQAM128_ALPHA (1./sqrt(106)) #define RQAM256_ALPHA QAM256_ALPHA #define RQAM512_ALPHA (1./sqrt(426)) #define RQAM1024_ALPHA QAM1024_ALPHA #define RQAM2048_ALPHA (1./sqrt(1706)) #define RQAM4096_ALPHA QAM4096_ALPHA // ASK #define ASK2_ALPHA (1.) #define ASK4_ALPHA (1./sqrt(5)) #define ASK8_ALPHA (1./sqrt(21)) #define ASK16_ALPHA (1./sqrt(85)) #define ASK32_ALPHA (1./sqrt(341)) #define ASK64_ALPHA (1./sqrt(1365)) #define ASK128_ALPHA (1./sqrt(5461)) #define ASK256_ALPHA (1./sqrt(21845)) // Macro : MODEM // MODEM : name-mangling macro // T : primitive data type // TC : primitive data type (complex) #define LIQUID_MODEM_DEFINE_INTERNAL_API(MODEM,T,TC) \ \ /* initialize a generic modem object */ \ void MODEM(_init)(MODEM() _q, unsigned int _bits_per_symbol); \ \ /* initialize symbol map for fast modulation */ \ void MODEM(_init_map)(MODEM() _q); \ \ /* generic modem create routines */ \ MODEM() MODEM(_create_ask)( unsigned int _bits_per_symbol); \ MODEM() MODEM(_create_qam)( unsigned int _bits_per_symbol); \ MODEM() MODEM(_create_psk)( unsigned int _bits_per_symbol); \ MODEM() MODEM(_create_dpsk)(unsigned int _bits_per_symbol); \ MODEM() MODEM(_create_apsk)(unsigned int _bits_per_symbol); \ MODEM() MODEM(_create_arb)( unsigned int _bits_per_symbol); \ \ /* Initialize arbitrary modem constellation */ \ void MODEM(_arb_init)(MODEM() _q, \ TC * _symbol_map, \ unsigned int _len); \ \ /* Initialize arb modem constellation from external file */ \ void MODEM(_arb_init_file)(MODEM() _q, char * _filename); \ \ /* specific modem create routines */ \ MODEM() MODEM(_create_bpsk)(void); \ MODEM() MODEM(_create_qpsk)(void); \ MODEM() MODEM(_create_ook)(void); \ MODEM() MODEM(_create_sqam32)(void); \ MODEM() MODEM(_create_sqam128)(void); \ MODEM() MODEM(_create_V29)(void); \ MODEM() MODEM(_create_arb16opt)(void); \ MODEM() MODEM(_create_arb32opt)(void); \ MODEM() MODEM(_create_arb64opt)(void); \ MODEM() MODEM(_create_arb128opt)(void); \ MODEM() MODEM(_create_arb256opt)(void); \ MODEM() MODEM(_create_arb64vt)(void); \ \ /* Scale arbitrary modem energy to unity */ \ void MODEM(_arb_scale)(MODEM() _q); \ \ /* Balance I/Q */ \ void MODEM(_arb_balance_iq)(MODEM() _q); \ \ /* modulate using symbol map (look-up table) */ \ void MODEM(_modulate_map)(MODEM() _q, \ unsigned int _sym_in, \ TC * _y); \ \ /* modem modulate routines */ \ void MODEM(_modulate_ask) ( MODEM(), unsigned int, TC *); \ void MODEM(_modulate_qam) ( MODEM(), unsigned int, TC *); \ void MODEM(_modulate_psk) ( MODEM(), unsigned int, TC *); \ void MODEM(_modulate_dpsk) ( MODEM(), unsigned int, TC *); \ void MODEM(_modulate_arb) ( MODEM(), unsigned int, TC *); \ void MODEM(_modulate_apsk) ( MODEM(), unsigned int, TC *); \ void MODEM(_modulate_bpsk) ( MODEM(), unsigned int, TC *); \ void MODEM(_modulate_qpsk) ( MODEM(), unsigned int, TC *); \ void MODEM(_modulate_ook) ( MODEM(), unsigned int, TC *); \ void MODEM(_modulate_sqam32) ( MODEM(), unsigned int, TC *); \ void MODEM(_modulate_sqam128) ( MODEM(), unsigned int, TC *); \ \ /* modem demodulate routines */ \ void MODEM(_demodulate_ask) ( MODEM(), TC, unsigned int *); \ void MODEM(_demodulate_qam) ( MODEM(), TC, unsigned int *); \ void MODEM(_demodulate_psk) ( MODEM(), TC, unsigned int *); \ void MODEM(_demodulate_dpsk) ( MODEM(), TC, unsigned int *); \ void MODEM(_demodulate_arb) ( MODEM(), TC, unsigned int *); \ void MODEM(_demodulate_apsk) ( MODEM(), TC, unsigned int *); \ void MODEM(_demodulate_bpsk) ( MODEM(), TC, unsigned int *); \ void MODEM(_demodulate_qpsk) ( MODEM(), TC, unsigned int *); \ void MODEM(_demodulate_ook) ( MODEM(), TC, unsigned int *); \ void MODEM(_demodulate_sqam32) ( MODEM(), TC, unsigned int *); \ void MODEM(_demodulate_sqam128)( MODEM(), TC, unsigned int *); \ \ /* modem demodulate (soft) routines */ \ void MODEM(_demodulate_soft_bpsk)(MODEM() _q, \ TC _x, \ unsigned int * _sym_out, \ unsigned char * _soft_bits); \ void MODEM(_demodulate_soft_qpsk)(MODEM() _q, \ TC _x, \ unsigned int * _sym_out, \ unsigned char * _soft_bits); \ void MODEM(_demodulate_soft_arb)( MODEM() _q, \ TC _x, \ unsigned int * _sym_out, \ unsigned char * _soft_bits); \ \ /* generate soft demodulation look-up table */ \ void MODEM(_demodsoft_gentab)(MODEM() _q, \ unsigned int _p); \ \ /* generic soft demodulation routine using nearest-neighbors */ \ /* look-up table */ \ void MODEM(_demodulate_soft_table)(MODEM() _q, \ TC _x, \ unsigned int * _sym_out, \ unsigned char * _soft_bits); \ \ /* Demodulate a linear symbol constellation using dynamic */ \ /* threshold calculation */ \ /* _v : input value */ \ /* _m : bits per symbol */ \ /* _alpha : scaling factor */ \ /* _s : demodulated symbol */ \ /* _res : residual */ \ void MODEM(_demodulate_linear_array)(T _v, \ unsigned int _m, \ T _alpha, \ unsigned int * _s, \ T * _res); \ \ /* Demodulate a linear symbol constellation using */ \ /* refereneced lookup table */ \ /* _v : input value */ \ /* _m : bits per symbol */ \ /* _ref : array of thresholds */ \ /* _s : demodulated symbol */ \ /* _res : residual */ \ void MODEM(_demodulate_linear_array_ref)(T _v, \ unsigned int _m, \ T * _ref, \ unsigned int * _s, \ T * _res); \ // define internal modem APIs LIQUID_MODEM_DEFINE_INTERNAL_API(LIQUID_MODEM_MANGLE_FLOAT,float,float complex) // APSK constants (container for apsk structure definitions) struct liquid_apsk_s { modulation_scheme scheme; // APSK modulation scheme unsigned int num_levels; // number of rings unsigned int * p; // number of symbols per ring float * r; // radius of each ring float * phi; // phase offset of each ring float * r_slicer; // radius slicer unsigned char * map; // symbol mapping }; extern struct liquid_apsk_s liquid_apsk4; extern struct liquid_apsk_s liquid_apsk8; extern struct liquid_apsk_s liquid_apsk16; extern struct liquid_apsk_s liquid_apsk32; extern struct liquid_apsk_s liquid_apsk64; extern struct liquid_apsk_s liquid_apsk128; extern struct liquid_apsk_s liquid_apsk256; // 'square' 32-QAM (first quadrant) extern const float complex modem_arb_sqam32[8]; // 'square' 128-QAM (first quadrant) extern const float complex modem_arb_sqam128[32]; // V.29 star constellation extern const float complex modem_arb_V29[16]; // Virginia Tech logo extern const float complex modem_arb_vt64[64]; // optimal QAM constellations extern const float complex modem_arb16opt[16]; extern const float complex modem_arb32opt[32]; extern const float complex modem_arb64opt[64]; extern const float complex modem_arb128opt[128]; extern const float complex modem_arb256opt[256]; // // MODULE : multichannel // // ofdm frame (common) // generate short sequence symbols // _p : subcarrier allocation array // _M : total number of subcarriers // _S0 : output symbol (freq) // _s0 : output symbol (time) // _M_S0 : total number of enabled subcarriers in S0 void ofdmframe_init_S0(unsigned char * _p, unsigned int _M, float complex * _S0, float complex * _s0, unsigned int * _M_S0); // generate long sequence symbols // _p : subcarrier allocation array // _M : total number of subcarriers // _S1 : output symbol (freq) // _s1 : output symbol (time) // _M_S1 : total number of enabled subcarriers in S1 void ofdmframe_init_S1(unsigned char * _p, unsigned int _M, float complex * _S1, float complex * _s1, unsigned int * _M_S1); // generate symbol (add cyclic prefix/postfix, overlap) void ofdmframegen_gensymbol(ofdmframegen _q, float complex * _buffer); void ofdmframesync_cpcorrelate(ofdmframesync _q); void ofdmframesync_findrxypeak(ofdmframesync _q); void ofdmframesync_rxpayload(ofdmframesync _q); void ofdmframesync_execute_seekplcp(ofdmframesync _q); void ofdmframesync_execute_S0a(ofdmframesync _q); void ofdmframesync_execute_S0b(ofdmframesync _q); void ofdmframesync_execute_S1( ofdmframesync _q); void ofdmframesync_execute_rxsymbols(ofdmframesync _q); void ofdmframesync_S0_metrics(ofdmframesync _q, float complex * _G, float complex * _s_hat); // estimate short sequence gain // _q : ofdmframesync object // _x : input array (time) // _G : output gain (freq) void ofdmframesync_estimate_gain_S0(ofdmframesync _q, float complex * _x, float complex * _G); // estimate long sequence gain // _q : ofdmframesync object // _x : input array (time) // _G : output gain (freq) void ofdmframesync_estimate_gain_S1(ofdmframesync _q, float complex * _x, float complex * _G); // estimate complex equalizer gain from G0 and G1 // _q : ofdmframesync object // _ntaps : number of time-domain taps for smoothing void ofdmframesync_estimate_eqgain(ofdmframesync _q, unsigned int _ntaps); // estimate complex equalizer gain from G0 and G1 using polynomial fit // _q : ofdmframesync object // _order : polynomial order void ofdmframesync_estimate_eqgain_poly(ofdmframesync _q, unsigned int _order); // recover symbol, correcting for gain, pilot phase, etc. void ofdmframesync_rxsymbol(ofdmframesync _q); // // MODULE : nco (numerically-controlled oscillator) // // Numerically-controlled oscillator, floating point phase precision #define LIQUID_NCO_DEFINE_INTERNAL_API(NCO,T,TC) \ \ /* constrain phase/frequency to be in [-pi,pi) */ \ void NCO(_constrain_phase)(NCO() _q); \ void NCO(_constrain_frequency)(NCO() _q); \ \ /* compute trigonometric functions for nco/vco type */ \ void NCO(_compute_sincos_nco)(NCO() _q); \ void NCO(_compute_sincos_vco)(NCO() _q); \ \ /* reset internal phase-locked loop filter */ \ void NCO(_pll_reset)(NCO() _q); \ // Define nco internal APIs LIQUID_NCO_DEFINE_INTERNAL_API(LIQUID_NCO_MANGLE_FLOAT, float, float complex) // // MODULE : optim (non-linear optimization) // // optimization threshold switch // _u0 : first utility // _u1 : second utility // _minimize : minimize flag // // returns: // (_u0 > _u1) if (_minimize == 1) // (_u0 < _u1) otherwise int optim_threshold_switch(float _u0, float _u1, int _minimize); // compute the gradient of a function at a particular point // _utility : user-defined function // _userdata : user-defined data object // _x : operating point, [size: _n x 1] // _n : dimensionality of search // _delta : step value for which to compute gradient // _gradient : resulting gradient void gradsearch_gradient(utility_function _utility, void * _userdata, float * _x, unsigned int _n, float _delta, float * _gradient); // execute line search; loosely solve: // // min|max phi(alpha) := f(_x - alpha*_p) // // and return best guess at alpha that achieves this // // _utility : user-defined function // _userdata : user-defined data object // _direction : search direction (e.g. LIQUID_OPTIM_MINIMIZE) // _n : dimensionality of search // _x : operating point, [size: _n x 1] // _p : normalized gradient, [size: _n x 1] // _alpha : initial step size float gradsearch_linesearch(utility_function _utility, void * _userdata, int _direction, unsigned int _n, float * _x, float * _p, float _alpha); // normalize vector, returning its l2-norm float gradsearch_norm(float * _v, unsigned int _n); // quasi-Newton search object struct qnsearch_s { float* v; // vector to optimize (externally allocated) unsigned int num_parameters; // number of parameters to optimize [n] float gamma; // nominal stepsize float delta; // differential used to compute (estimate) derivative float dgamma; // decremental gamma parameter float gamma_hat; // step size (decreases each epoch) float* v_prime; // temporary vector array float* dv; // parameter step vector float * B; // approximate Hessian matrix inverse [n x n] float * H; // Hessian matrix float* p; // search direction float* gradient; // gradient approximation float* gradient0; // gradient approximation (previous step) // External utility function. utility_function get_utility; float utility; // current utility void * userdata; // userdata pointer passed to utility callback int minimize; // minimize/maximimze utility (search direction) }; // compute gradient(x_k) void qnsearch_compute_gradient(qnsearch _q); // compute the norm of the gradient(x_k) void qnsearch_normalize_gradient(qnsearch _q); // compute Hessian (estimate) void qnsearch_compute_Hessian(qnsearch _q); // compute the updated inverse hessian matrix using the Broyden, Fletcher, // Goldfarb & Shanno method (BFGS) void qnsearch_update_hessian_bfgs(qnsearch _q); // Chromosome structure used in genetic algorithm searches struct chromosome_s { unsigned int num_traits; // number of represented traits unsigned int * bits_per_trait; // bits to represent each trait unsigned long * max_value; // maximum representable integer value unsigned long * traits; // chromosome data unsigned int num_bits; // total number of bits }; struct gasearch_s { chromosome * population; // population of chromosomes unsigned int population_size; // size of the population unsigned int selection_size; // number of float mutation_rate; // rate of mutation unsigned int num_parameters; // number of parameters to optimize unsigned int bits_per_chromosome; // total number of bits in each chromosome float *utility; // utility array unsigned int *rank; // rank indices of chromosomes (best to worst) chromosome c; // copy of best chromosome, optimal solution float utility_opt; // optimum utility (fitness of best solution) // External utility function. // // The success of a GA search algorithm is contingent upon the // design of a good utility function. It should meet the following // criteria: // - monotonically increasing (never flat) // - efficient to compute // - maps the [0,1] bounded output vector to desired range // - for multiple objectives, utility should be high \em only when // all objectives are met (multiplicative, not additive) gasearch_utility get_utility; // utility function pointer void * userdata; // object to optimize int minimize; // minimize/maximize utility (search direction) }; // // gasearch internal methods // // evaluate fitness of entire population void gasearch_evaluate(gasearch _q); // crossover population void gasearch_crossover(gasearch _q); // mutate population void gasearch_mutate(gasearch _q); // rank population by fitness void gasearch_rank(gasearch _q); // sort values by index // _v : input values [size: _len x 1] // _rank : output rank array (indices) [size: _len x 1] // _len : length of input array // _descending : descending/ascending void optim_sort(float *_v, unsigned int * _rank, unsigned int _len, int _descending); // // MODULE : random // #define randf_inline() ((float) rand() / (float) RAND_MAX) float complex icrandnf(); // generate x ~ Gamma(delta,1) float randgammaf_delta(float _delta); // data scrambler masks #define LIQUID_SCRAMBLE_MASK0 (0xb4) #define LIQUID_SCRAMBLE_MASK1 (0x6a) #define LIQUID_SCRAMBLE_MASK2 (0x8b) #define LIQUID_SCRAMBLE_MASK3 (0xc5) // // MODULE : sequence // // maximal-length sequence struct msequence_s { unsigned int m; // length generator polynomial, shift register unsigned int g; // generator polynomial unsigned int a; // initial shift register state, default: 1 unsigned int n; // length of sequence, n = (2^m)-1 unsigned int v; // shift register unsigned int b; // return bit }; // Default msequence generator objects extern struct msequence_s msequence_default[16]; // // MODULE : utility // // number of ones in a byte // 0 0000 0000 : 0 // 1 0000 0001 : 1 // 2 0000 0010 : 1 // 3 0000 0011 : 2 // 4 0000 0100 : 1 // ... // 126 0111 1110 : 6 // 127 0111 1111 : 7 // 128 1000 0000 : 1 // 129 1000 0001 : 2 // ... // 253 1111 1101 : 7 // 254 1111 1110 : 7 // 255 1111 1111 : 8 extern const unsigned char liquid_c_ones[256]; // Count the number of ones in an integer, inline insertion #define liquid_count_ones_uint16(x) ( \ liquid_c_ones[ (x) & 0xff ] + \ liquid_c_ones[ ((x)>>8) & 0xff ]) #define liquid_count_ones_uint24(x) ( \ liquid_c_ones[ (x) & 0xff ] + \ liquid_c_ones[ ((x)>> 8) & 0xff ] + \ liquid_c_ones[ ((x)>>16) & 0xff ]) #define liquid_count_ones_uint32(x) ( \ liquid_c_ones[ (x) & 0xff ] + \ liquid_c_ones[ ((x)>> 8) & 0xff ] + \ liquid_c_ones[ ((x)>>16) & 0xff ] + \ liquid_c_ones[ ((x)>>24) & 0xff ]) // number of ones in a byte, modulo 2 // 0 0000 0000 : 0 // 1 0000 0001 : 1 // 2 0000 0010 : 1 // 3 0000 0011 : 0 // 4 0000 0100 : 1 // ... // 126 0111 1110 : 0 // 127 0111 1111 : 1 // 128 1000 0000 : 1 // 129 1000 0001 : 0 // ... // 253 1111 1101 : 1 // 254 1111 1110 : 1 // 255 1111 1111 : 0 extern const unsigned char liquid_c_ones_mod2[256]; // Count the number of ones in an integer modulo 2, inline insertion #define liquid_count_ones_mod2_uint16(x) (( \ liquid_c_ones_mod2[ (x) & 0xff ] + \ liquid_c_ones_mod2[ ((x)>>8) & 0xff ]) % 2) #define liquid_count_ones_mod2_uint32(x) (( \ liquid_c_ones_mod2[ (x) & 0xff ] + \ liquid_c_ones_mod2[ ((x)>> 8) & 0xff ] + \ liquid_c_ones_mod2[ ((x)>>16) & 0xff ] + \ liquid_c_ones_mod2[ ((x)>>24) & 0xff ]) % 2) // compute binary dot-products (inline pre-processor macros) #define liquid_bdotprod_uint8(x,y) liquid_c_ones_mod2[(x)&(y)] #define liquid_bdotprod_uint16(x,y) liquid_count_ones_mod2_uint16((x)&(y)) #define liquid_bdotprod_uint32(x,y) liquid_count_ones_mod2_uint32((x)&(y)) // number of leading zeros in byte extern unsigned int liquid_c_leading_zeros[256]; // byte reversal and manipulation extern const unsigned char liquid_reverse_byte_gentab[256]; #endif // __LIQUID_INTERNAL_H__ liquid-dsp-1.3.1/makefile.in000066400000000000000000001523771317124540100157110ustar00rootroot00000000000000# Copyright (c) 2007 - 2016 Joseph Gaeddert # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # # Makefile for liquid-dsp libraries # # Targets: # all : dynamic shared-library object (e.g. libliquid.so) # install : install the dynamic shared library object and # header file(s) # uninstall : uninstall the library and header file(s) # clean : clean all targets (bench, check, examples, etc) # distclean : removes everything except the originally distributed files # check : build and run autotest program # bench : build and run benchmarking program # examples : build all examples # sandbox : build all sandbox examples # world : build absolutely everything (but don't install) # # clean-modules : clean all modules # clean-examples : clean examples programs # clean-sandbox : clean sandbox programs # clean-check : clean autotest program # clean-bench : clean benchmark program # # autoconf initialization macros NAME := @PACKAGE_NAME@ VERSION := @PACKAGE_VERSION@ BUGREPORT := @PACKAGE_BUGREPORT@ # paths srcdir := @srcdir@ libdir := @libdir@ prefix := @prefix@ exec_prefix := @exec_prefix@ include_dirs := . include # programs CC := @CC@ MV := mv -f RM := rm -f SED := @SED@ GREP := @GREP@ AR := @AR@ RANLIB := @RANLIB@ # flags INCLUDE_CFLAGS = $(addprefix -I,$(include_dirs)) CONFIG_CFLAGS = @CFLAGS@ @DEBUG_MSG_OPTION@ @ARCH_OPTION@ CPPFLAGS = @CPPFLAGS@ $(INCLUDE_CFLAGS) CFLAGS = $(CONFIG_CFLAGS) -Wall -fPIC LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ ARFLAGS = r PATHSEP = / # # liquid headers # headers_install := liquid.h headers := $(headers_install) liquid.internal.h include_headers := $(addprefix include/,$(headers)) ## ## liquid-dsp modules ## all: # additional targets to clean extra_clean := # additional autotest objects autotest_extra_obj := # additional benchmark objects benchmark_extra_obj := # # MODULE : agc - automatic gain control # # object files agc_objects = \ src/agc/src/agc_crcf.o \ src/agc/src/agc_rrrf.o \ # explicit targets and dependencies src/agc/src/agc_crcf.o : %.o : %.c src/agc/src/agc.c $(include_headers) src/agc/src/agc_rrrf.o : %.o : %.c src/agc/src/agc.c $(include_headers) # autotests agc_autotests := \ src/agc/tests/agc_crcf_autotest.c \ # benchmarks agc_benchmarks := \ src/agc/bench/agc_crcf_benchmark.c \ # # MODULE : audio # # described below audio_objects := \ src/audio/src/cvsd.o \ src/cvsd/src/cvsd.o : %.o : %.c $(include_headers) audio_autotests := \ src/audio/tests/cvsd_autotest.c \ audio_benchmarks := \ src/audio/bench/cvsd_benchmark.c \ # # MODULE : buffer # buffer_objects := \ src/buffer/src/bufferf.o \ src/buffer/src/buffercf.o \ buffer_includes := \ src/buffer/src/cbuffer.c \ src/buffer/src/wdelay.c \ src/buffer/src/window.c \ src/buffer/src/bufferf.o : %.o : %.c $(include_headers) $(buffer_includes) src/buffer/src/buffercf.o : %.o : %.c $(include_headers) $(buffer_includes) buffer_autotests := \ src/buffer/tests/cbuffer_autotest.c \ src/buffer/tests/wdelay_autotest.c \ src/buffer/tests/window_autotest.c \ # src/buffer/tests/sbuffer_autotest.c buffer_benchmarks := \ src/buffer/bench/cbuffercf_benchmark.c \ src/buffer/bench/window_push_benchmark.c \ src/buffer/bench/window_read_benchmark.c \ # # MODULE : channel # channel_objects := \ src/channel/src/channel_cccf.o \ channel_includes := \ src/channel/src/channel.c \ src/channel/src/tvmpch.c \ src/channel/src/channel_cccf.o : %.o : %.c $(include_headers) $(channel_includes) channel_autotests := \ #src/channel/tests/channel_cccf_autotest.c channel_benchmarks := \ #src/channel/bench/channel_cccf_benchmark.c # # MODULE : dotprod # dotprod_objects := \ @MLIBS_DOTPROD@ \ src/dotprod/src/dotprod_cccf.o : %.o : %.c $(include_headers) src/dotprod/src/dotprod.c src/dotprod/src/dotprod_crcf.o : %.o : %.c $(include_headers) src/dotprod/src/dotprod.c src/dotprod/src/dotprod_rrrf.o : %.o : %.c $(include_headers) src/dotprod/src/dotprod.c src/dotprod/src/sumsq.o : %.o : %.c $(include_headers) # specific machine architectures # AltiVec src/dotprod/src/dotprod_rrrf.av.o : %.o : %.c $(include_headers) # MMX/SSE2 src/dotprod/src/dotprod_rrrf.mmx.o : %.o : %.c $(include_headers) src/dotprod/src/dotprod_crcf.mmx.o : %.o : %.c $(include_headers) src/dotprod/src/dotprod_cccf.mmx.o : %.o : %.c $(include_headers) src/dotprod/src/sumsq.mmx.o : %.o : %.c $(include_headers) # SSE4.1/2 src/dotprod/src/dotprod_rrrf.sse4.o : %.o : %.c $(include_headers) # ARM Neon src/dotprod/src/dotprod_rrrf.neon.o : %.o : %.c $(include_headers) src/dotprod/src/dotprod_crcf.neon.o : %.o : %.c $(include_headers) src/dotprod/src/dotprod_cccf.neon.o : %.o : %.c $(include_headers) dotprod_autotests := \ src/dotprod/tests/dotprod_rrrf_autotest.c \ src/dotprod/tests/dotprod_crcf_autotest.c \ src/dotprod/tests/dotprod_cccf_autotest.c \ src/dotprod/tests/sumsqf_autotest.c \ src/dotprod/tests/sumsqcf_autotest.c \ dotprod_benchmarks := \ src/dotprod/bench/dotprod_cccf_benchmark.c \ src/dotprod/bench/dotprod_crcf_benchmark.c \ src/dotprod/bench/dotprod_rrrf_benchmark.c \ src/dotprod/bench/sumsqf_benchmark.c \ src/dotprod/bench/sumsqcf_benchmark.c \ # # MODULE : equalization # equalization_objects := \ src/equalization/src/equalizer_cccf.o \ src/equalization/src/equalizer_rrrf.o \ $(equalization_objects) : %.o : %.c $(include_headers) src/equalization/src/eqlms.c src/equalization/src/eqrls.c # autotests equalization_autotests := \ src/equalization/tests/eqlms_cccf_autotest.c \ src/equalization/tests/eqrls_rrrf_autotest.c \ # benchmarks equalization_benchmarks := \ src/equalization/bench/eqlms_cccf_benchmark.c \ src/equalization/bench/eqrls_cccf_benchmark.c \ # # MODULE : fec - forward error-correction # fec_objects := \ src/fec/src/crc.o \ src/fec/src/fec.o \ src/fec/src/fec_conv.o \ src/fec/src/fec_conv_poly.o \ src/fec/src/fec_conv_pmatrix.o \ src/fec/src/fec_conv_punctured.o \ src/fec/src/fec_golay2412.o \ src/fec/src/fec_hamming74.o \ src/fec/src/fec_hamming84.o \ src/fec/src/fec_hamming128.o \ src/fec/src/fec_hamming1511.o \ src/fec/src/fec_hamming3126.o \ src/fec/src/fec_hamming128_gentab.o \ src/fec/src/fec_pass.o \ src/fec/src/fec_rep3.o \ src/fec/src/fec_rep5.o \ src/fec/src/fec_rs.o \ src/fec/src/fec_secded2216.o \ src/fec/src/fec_secded3932.o \ src/fec/src/fec_secded7264.o \ src/fec/src/interleaver.o \ src/fec/src/packetizer.o \ src/fec/src/sumproduct.o \ # list explicit targets and dependencies here $(fec_objects) : %.o : %.c $(include_headers) # autotests fec_autotests := \ src/fec/tests/crc_autotest.c \ src/fec/tests/fec_autotest.c \ src/fec/tests/fec_soft_autotest.c \ src/fec/tests/fec_golay2412_autotest.c \ src/fec/tests/fec_hamming74_autotest.c \ src/fec/tests/fec_hamming84_autotest.c \ src/fec/tests/fec_hamming128_autotest.c \ src/fec/tests/fec_hamming1511_autotest.c \ src/fec/tests/fec_hamming3126_autotest.c \ src/fec/tests/fec_reedsolomon_autotest.c \ src/fec/tests/fec_rep3_autotest.c \ src/fec/tests/fec_rep5_autotest.c \ src/fec/tests/fec_secded2216_autotest.c \ src/fec/tests/fec_secded3932_autotest.c \ src/fec/tests/fec_secded7264_autotest.c \ src/fec/tests/interleaver_autotest.c \ src/fec/tests/packetizer_autotest.c \ # benchmarks fec_benchmarks := \ src/fec/bench/crc_benchmark.c \ src/fec/bench/fec_encode_benchmark.c \ src/fec/bench/fec_decode_benchmark.c \ src/fec/bench/fecsoft_decode_benchmark.c \ src/fec/bench/sumproduct_benchmark.c \ src/fec/bench/interleaver_benchmark.c \ src/fec/bench/packetizer_decode_benchmark.c \ # # MODULE : fft - fast Fourier transforms, discrete sine/cosine transforms, etc. # fft_objects := \ src/fft/src/fftf.o \ src/fft/src/spgramcf.o \ src/fft/src/spgramf.o \ src/fft/src/fft_utilities.o \ # explicit targets and dependencies fft_includes := \ src/fft/src/fft_common.c \ src/fft/src/fft_dft.c \ src/fft/src/fft_radix2.c \ src/fft/src/fft_mixed_radix.c \ src/fft/src/fft_rader.c \ src/fft/src/fft_rader2.c \ src/fft/src/fft_r2r_1d.c \ src/fft/src/fftf.o : %.o : %.c $(include_headers) $(fft_includes) src/fft/src/asgram.o : %.o : %.c $(include_headers) src/fft/src/dct.o : %.o : %.c $(include_headers) src/fft/src/fftf.o : %.o : %.c $(include_headers) src/fft/src/fft_utilities.o : %.o : %.c $(include_headers) src/fft/src/mdct.o : %.o : %.c $(include_headers) src/fft/src/spgramcf.o : %.o : %.c $(include_headers) src/fft/src/asgram.c src/fft/src/spgram.c src/fft/src/spwaterfall.c src/fft/src/spgramf.o : %.o : %.c $(include_headers) src/fft/src/asgram.c src/fft/src/spgram.c src/fft/src/spwaterfall.c # fft autotest scripts fft_autotests := \ src/fft/tests/fft_small_autotest.c \ src/fft/tests/fft_radix2_autotest.c \ src/fft/tests/fft_composite_autotest.c \ src/fft/tests/fft_prime_autotest.c \ src/fft/tests/fft_r2r_autotest.c \ src/fft/tests/fft_shift_autotest.c \ # additional autotest objects autotest_extra_obj += \ src/fft/tests/fft_runtest.o \ src/fft/tests/data/fft_data_2.o \ src/fft/tests/data/fft_data_3.o \ src/fft/tests/data/fft_data_4.o \ src/fft/tests/data/fft_data_5.o \ src/fft/tests/data/fft_data_6.o \ src/fft/tests/data/fft_data_7.o \ src/fft/tests/data/fft_data_8.o \ src/fft/tests/data/fft_data_9.o \ src/fft/tests/data/fft_data_10.o \ src/fft/tests/data/fft_data_16.o \ src/fft/tests/data/fft_data_17.o \ src/fft/tests/data/fft_data_20.o \ src/fft/tests/data/fft_data_21.o \ src/fft/tests/data/fft_data_22.o \ src/fft/tests/data/fft_data_24.o \ src/fft/tests/data/fft_data_26.o \ src/fft/tests/data/fft_data_30.o \ src/fft/tests/data/fft_data_32.o \ src/fft/tests/data/fft_data_35.o \ src/fft/tests/data/fft_data_36.o \ src/fft/tests/data/fft_data_43.o \ src/fft/tests/data/fft_data_48.o \ src/fft/tests/data/fft_data_63.o \ src/fft/tests/data/fft_data_64.o \ src/fft/tests/data/fft_data_79.o \ src/fft/tests/data/fft_data_92.o \ src/fft/tests/data/fft_data_96.o \ src/fft/tests/data/fft_data_120.o \ src/fft/tests/data/fft_data_130.o \ src/fft/tests/data/fft_data_157.o \ src/fft/tests/data/fft_data_192.o \ src/fft/tests/data/fft_data_317.o \ src/fft/tests/data/fft_data_509.o \ src/fft/tests/data/fft_r2rdata_8.o \ src/fft/tests/data/fft_r2rdata_27.o \ src/fft/tests/data/fft_r2rdata_32.o \ # fft benchmark scripts fft_benchmarks := \ src/fft/bench/fft_composite_benchmark.c \ src/fft/bench/fft_prime_benchmark.c \ src/fft/bench/fft_radix2_benchmark.c \ src/fft/bench/fft_r2r_benchmark.c \ # additional benchmark objects benchmark_extra_obj := \ src/fft/bench/fft_runbench.o \ # # MODULE : filter # filter_objects := \ src/filter/src/bessel.o \ src/filter/src/butter.o \ src/filter/src/cheby1.o \ src/filter/src/cheby2.o \ src/filter/src/ellip.o \ src/filter/src/filter_rrrf.o \ src/filter/src/filter_crcf.o \ src/filter/src/filter_cccf.o \ src/filter/src/firdes.o \ src/filter/src/firdespm.o \ src/filter/src/fnyquist.o \ src/filter/src/gmsk.o \ src/filter/src/group_delay.o \ src/filter/src/hM3.o \ src/filter/src/iirdes.pll.o \ src/filter/src/iirdes.o \ src/filter/src/lpc.o \ src/filter/src/rcos.o \ src/filter/src/rkaiser.o \ src/filter/src/rrcos.o \ # list explicit targets and dependencies here filter_includes := \ src/filter/src/autocorr.c \ src/filter/src/fftfilt.c \ src/filter/src/firdecim.c \ src/filter/src/firfarrow.c \ src/filter/src/firfilt.c \ src/filter/src/firhilb.c \ src/filter/src/firinterp.c \ src/filter/src/firpfb.c \ src/filter/src/iirdecim.c \ src/filter/src/iirfilt.c \ src/filter/src/iirfiltsos.c \ src/filter/src/iirinterp.c \ src/filter/src/msresamp.c \ src/filter/src/msresamp2.c \ src/filter/src/resamp.c \ src/filter/src/resamp2.c \ src/filter/src/symsync.c \ src/filter/src/bessel.o : %.o : %.c $(include_headers) src/filter/src/bessel.o : %.o : %.c $(include_headers) src/filter/src/butter.o : %.o : %.c $(include_headers) src/filter/src/cheby1.o : %.o : %.c $(include_headers) src/filter/src/cheby2.o : %.o : %.c $(include_headers) src/filter/src/ellip.o : %.o : %.c $(include_headers) src/filter/src/filter_rrrf.o : %.o : %.c $(include_headers) $(filter_includes) src/filter/src/filter_crcf.o : %.o : %.c $(include_headers) $(filter_includes) src/filter/src/filter_cccf.o : %.o : %.c $(include_headers) $(filter_includes) src/filter/src/firdes.o : %.o : %.c $(include_headers) src/filter/src/firdespm.o : %.o : %.c $(include_headers) src/filter/src/group_delay.o : %.o : %.c $(include_headers) src/filter/src/hM3.o : %.o : %.c $(include_headers) src/filter/src/iirdes.pll.o : %.o : %.c $(include_headers) src/filter/src/iirdes.o : %.o : %.c $(include_headers) src/filter/src/lpc.o : %.o : %.c $(include_headers) src/filter/src/rcos.o : %.o : %.c $(include_headers) src/filter/src/rkaiser.o : %.o : %.c $(include_headers) src/filter/src/rrcos.o : %.o : %.c $(include_headers) filter_autotests := \ src/filter/tests/fftfilt_xxxf_autotest.c \ src/filter/tests/filter_crosscorr_autotest.c \ src/filter/tests/firdecim_xxxf_autotest.c \ src/filter/tests/firdes_autotest.c \ src/filter/tests/firdespm_autotest.c \ src/filter/tests/firfilt_xxxf_autotest.c \ src/filter/tests/firhilb_autotest.c \ src/filter/tests/firinterp_autotest.c \ src/filter/tests/firpfb_autotest.c \ src/filter/tests/groupdelay_autotest.c \ src/filter/tests/iirdes_autotest.c \ src/filter/tests/iirfilt_xxxf_autotest.c \ src/filter/tests/iirfiltsos_rrrf_autotest.c \ src/filter/tests/msresamp_crcf_autotest.c \ src/filter/tests/resamp_crcf_autotest.c \ src/filter/tests/resamp2_crcf_autotest.c \ src/filter/tests/symsync_crcf_autotest.c \ src/filter/tests/symsync_rrrf_autotest.c \ # additional autotest objects autotest_extra_obj += \ src/filter/tests/fftfilt_runtest.o \ \ src/filter/tests/data/fftfilt_rrrf_data_h4x256.o \ src/filter/tests/data/fftfilt_crcf_data_h4x256.o \ src/filter/tests/data/fftfilt_cccf_data_h4x256.o \ \ src/filter/tests/data/fftfilt_rrrf_data_h7x256.o \ src/filter/tests/data/fftfilt_crcf_data_h7x256.o \ src/filter/tests/data/fftfilt_cccf_data_h7x256.o \ \ src/filter/tests/data/fftfilt_rrrf_data_h13x256.o \ src/filter/tests/data/fftfilt_crcf_data_h13x256.o \ src/filter/tests/data/fftfilt_cccf_data_h13x256.o \ \ src/filter/tests/data/fftfilt_rrrf_data_h23x256.o \ src/filter/tests/data/fftfilt_crcf_data_h23x256.o \ src/filter/tests/data/fftfilt_cccf_data_h23x256.o \ \ src/filter/tests/firdecim_runtest.o \ \ src/filter/tests/data/firdecim_rrrf_data_M2h4x20.o \ src/filter/tests/data/firdecim_crcf_data_M2h4x20.o \ src/filter/tests/data/firdecim_cccf_data_M2h4x20.o \ \ src/filter/tests/data/firdecim_rrrf_data_M3h7x30.o \ src/filter/tests/data/firdecim_crcf_data_M3h7x30.o \ src/filter/tests/data/firdecim_cccf_data_M3h7x30.o \ \ src/filter/tests/data/firdecim_rrrf_data_M4h13x40.o \ src/filter/tests/data/firdecim_crcf_data_M4h13x40.o \ src/filter/tests/data/firdecim_cccf_data_M4h13x40.o \ \ src/filter/tests/data/firdecim_rrrf_data_M5h23x50.o \ src/filter/tests/data/firdecim_crcf_data_M5h23x50.o \ src/filter/tests/data/firdecim_cccf_data_M5h23x50.o \ \ src/filter/tests/firfilt_runtest.o \ \ src/filter/tests/data/firfilt_rrrf_data_h4x8.o \ src/filter/tests/data/firfilt_crcf_data_h4x8.o \ src/filter/tests/data/firfilt_cccf_data_h4x8.o \ \ src/filter/tests/data/firfilt_rrrf_data_h7x16.o \ src/filter/tests/data/firfilt_crcf_data_h7x16.o \ src/filter/tests/data/firfilt_cccf_data_h7x16.o \ \ src/filter/tests/data/firfilt_rrrf_data_h13x32.o \ src/filter/tests/data/firfilt_crcf_data_h13x32.o \ src/filter/tests/data/firfilt_cccf_data_h13x32.o \ \ src/filter/tests/data/firfilt_rrrf_data_h23x64.o \ src/filter/tests/data/firfilt_crcf_data_h23x64.o \ src/filter/tests/data/firfilt_cccf_data_h23x64.o \ \ src/filter/tests/iirfilt_runtest.o \ \ src/filter/tests/data/iirfilt_rrrf_data_h3x64.o \ src/filter/tests/data/iirfilt_crcf_data_h3x64.o \ src/filter/tests/data/iirfilt_cccf_data_h3x64.o \ \ src/filter/tests/data/iirfilt_rrrf_data_h5x64.o \ src/filter/tests/data/iirfilt_crcf_data_h5x64.o \ src/filter/tests/data/iirfilt_cccf_data_h5x64.o \ \ src/filter/tests/data/iirfilt_rrrf_data_h7x64.o \ src/filter/tests/data/iirfilt_crcf_data_h7x64.o \ src/filter/tests/data/iirfilt_cccf_data_h7x64.o \ filter_benchmarks := \ src/filter/bench/fftfilt_crcf_benchmark.c \ src/filter/bench/firdecim_crcf_benchmark.c \ src/filter/bench/firhilb_benchmark.c \ src/filter/bench/firinterp_crcf_benchmark.c \ src/filter/bench/firfilt_crcf_benchmark.c \ src/filter/bench/iirdecim_crcf_benchmark.c \ src/filter/bench/iirfilt_crcf_benchmark.c \ src/filter/bench/iirinterp_crcf_benchmark.c \ src/filter/bench/resamp_crcf_benchmark.c \ src/filter/bench/resamp2_crcf_benchmark.c \ src/filter/bench/symsync_crcf_benchmark.c \ # # MODULE : framing # framing_objects := \ src/framing/src/bpacketgen.o \ src/framing/src/bpacketsync.o \ src/framing/src/bpresync_cccf.o \ src/framing/src/bsync_rrrf.o \ src/framing/src/bsync_crcf.o \ src/framing/src/bsync_cccf.o \ src/framing/src/detector_cccf.o \ src/framing/src/framedatastats.o \ src/framing/src/framesyncstats.o \ src/framing/src/framegen64.o \ src/framing/src/framesync64.o \ src/framing/src/flexframegen.o \ src/framing/src/flexframesync.o \ src/framing/src/gmskframegen.o \ src/framing/src/gmskframesync.o \ src/framing/src/msourcecf.o \ src/framing/src/ofdmflexframegen.o \ src/framing/src/ofdmflexframesync.o \ src/framing/src/presync_cccf.o \ src/framing/src/symstreamcf.o \ src/framing/src/symtrack_cccf.o \ src/framing/src/qdetector_cccf.o \ src/framing/src/qpacketmodem.o \ src/framing/src/qpilotgen.o \ src/framing/src/qpilotsync.o \ # list explicit targets and dependencies here src/framing/src/bpacketgen.o : %.o : %.c $(include_headers) src/framing/src/bpacketsync.o : %.o : %.c $(include_headers) src/framing/src/bpresync_cccf.o : %.o : %.c $(include_headers) src/framing/src/bpresync.c src/framing/src/bsync_rrrf.o : %.o : %.c $(include_headers) src/framing/src/bsync.c src/framing/src/bsync_crcf.o : %.o : %.c $(include_headers) src/framing/src/bsync.c src/framing/src/bsync_cccf.o : %.o : %.c $(include_headers) src/framing/src/bsync.c src/framing/src/detector_cccf.o : %.o : %.c $(include_headers) src/framing/src/framedatastats.o : %.o : %.c $(include_headers) src/framing/src/framesyncstats.o : %.o : %.c $(include_headers) src/framing/src/framegen64.o : %.o : %.c $(include_headers) src/framing/src/framesync64.o : %.o : %.c $(include_headers) src/framing/src/flexframegen.o : %.o : %.c $(include_headers) src/framing/src/flexframesync.o : %.o : %.c $(include_headers) src/framing/src/msourcecf.o : %.o : %.c $(include_headers) src/framing/src/msource.c src/framing/src/ofdmflexframegen.o : %.o : %.c $(include_headers) src/framing/src/ofdmflexframesync.o : %.o : %.c $(include_headers) src/framing/src/presync_cccf.o : %.o : %.c $(include_headers) src/framing/src/presync.c src/framing/src/qpacketmodem.o : %.o : %.c $(include_headers) src/framing/src/symstreamcf.o : %.o : %.c $(include_headers) src/framing/src/symstream.c src/framing/src/symtrack_cccf.o : %.o : %.c $(include_headers) src/framing/src/symtrack.c framing_autotests := \ src/framing/tests/bpacketsync_autotest.c \ src/framing/tests/bsync_autotest.c \ src/framing/tests/detector_autotest.c \ src/framing/tests/flexframesync_autotest.c \ src/framing/tests/framesync64_autotest.c \ src/framing/tests/qdetector_cccf_autotest.c \ src/framing/tests/qpacketmodem_autotest.c \ src/framing/tests/qpilotsync_autotest.c \ framing_benchmarks := \ src/framing/bench/presync_benchmark.c \ src/framing/bench/bpacketsync_benchmark.c \ src/framing/bench/bpresync_benchmark.c \ src/framing/bench/bsync_benchmark.c \ src/framing/bench/detector_benchmark.c \ src/framing/bench/flexframesync_benchmark.c \ src/framing/bench/framesync64_benchmark.c \ src/framing/bench/gmskframesync_benchmark.c \ src/framing/bench/qdetector_benchmark.c \ # # MODULE : math # math_objects := \ src/math/src/poly.o \ src/math/src/polyc.o \ src/math/src/polyf.o \ src/math/src/polycf.o \ src/math/src/math.o \ src/math/src/math.bessel.o \ src/math/src/math.gamma.o \ src/math/src/math.complex.o \ src/math/src/math.trig.o \ src/math/src/modular_arithmetic.o \ src/math/src/windows.o \ poly_includes := \ src/math/src/poly.common.c \ src/math/src/poly.expand.c \ src/math/src/poly.findroots.c \ src/math/src/poly.lagrange.c \ src/math/src/poly.o : %.o : %.c $(include_headers) $(poly_includes) src/math/src/polyc.o : %.o : %.c $(include_headers) $(poly_includes) src/math/src/polyf.o : %.o : %.c $(include_headers) $(poly_includes) src/math/src/polycf.o : %.o : %.c $(include_headers) $(poly_includes) src/math/src/math.o : %.o : %.c $(include_headers) src/math/src/math.bessel.o : %.o : %.c $(include_headers) src/math/src/math.gamma.o : %.o : %.c $(include_headers) src/math/src/math.complex.o : %.o : %.c $(include_headers) src/math/src/math.trig.o : %.o : %.c $(include_headers) src/math/src/modular_arithmetic.o : %.o : %.c $(include_headers) src/math/src/windows.o : %.o : %.c $(include_headers) math_autotests := \ src/math/tests/kbd_autotest.c \ src/math/tests/math_autotest.c \ src/math/tests/math_bessel_autotest.c \ src/math/tests/math_gamma_autotest.c \ src/math/tests/math_complex_autotest.c \ src/math/tests/polynomial_autotest.c \ math_benchmarks := \ src/math/bench/polyfit_benchmark.c \ # # MODULE : matrix # matrix_objects := \ src/matrix/src/matrix.o \ src/matrix/src/matrixf.o \ src/matrix/src/matrixc.o \ src/matrix/src/matrixcf.o \ src/matrix/src/smatrix.common.o \ src/matrix/src/smatrixb.o \ src/matrix/src/smatrixf.o \ src/matrix/src/smatrixi.o \ matrix_includes := \ src/matrix/src/matrix.base.c \ src/matrix/src/matrix.cgsolve.c \ src/matrix/src/matrix.chol.c \ src/matrix/src/matrix.gramschmidt.c \ src/matrix/src/matrix.inv.c \ src/matrix/src/matrix.linsolve.c \ src/matrix/src/matrix.ludecomp.c \ src/matrix/src/matrix.qrdecomp.c \ src/matrix/src/matrix.math.c \ src/matrix/src/matrix.o : %.o : %.c $(include_headers) $(matrix_includes) src/matrix/src/matrixc.o : %.o : %.c $(include_headers) $(matrix_includes) src/matrix/src/matrixf.o : %.o : %.c $(include_headers) $(matrix_includes) src/matrix/src/matrixcf.o : %.o : %.c $(include_headers) $(matrix_includes) src/matrix/src/smatrixb.o : %.o : %.c $(include_headers) src/matrix/src/smatrix.c src/matrix/src/smatrixf.o : %.o : %.c $(include_headers) src/matrix/src/smatrix.c src/matrix/src/smatrixi.o : %.o : %.c $(include_headers) src/matrix/src/smatrix.c # matrix autotest scripts matrix_autotests := \ src/matrix/tests/matrixcf_autotest.c \ src/matrix/tests/matrixf_autotest.c \ src/matrix/tests/smatrixb_autotest.c \ src/matrix/tests/smatrixf_autotest.c \ src/matrix/tests/smatrixi_autotest.c \ # additional autotest objects autotest_extra_obj += \ src/matrix/tests/data/matrixf_data_add.o \ src/matrix/tests/data/matrixf_data_aug.o \ src/matrix/tests/data/matrixf_data_cgsolve.o \ src/matrix/tests/data/matrixf_data_chol.o \ src/matrix/tests/data/matrixf_data_gramschmidt.o \ src/matrix/tests/data/matrixf_data_inv.o \ src/matrix/tests/data/matrixf_data_linsolve.o \ src/matrix/tests/data/matrixf_data_ludecomp.o \ src/matrix/tests/data/matrixf_data_mul.o \ src/matrix/tests/data/matrixf_data_qrdecomp.o \ src/matrix/tests/data/matrixf_data_transmul.o \ \ src/matrix/tests/data/matrixcf_data_add.o \ src/matrix/tests/data/matrixcf_data_aug.o \ src/matrix/tests/data/matrixcf_data_chol.o \ src/matrix/tests/data/matrixcf_data_inv.o \ src/matrix/tests/data/matrixcf_data_linsolve.o \ src/matrix/tests/data/matrixcf_data_ludecomp.o \ src/matrix/tests/data/matrixcf_data_mul.o \ src/matrix/tests/data/matrixcf_data_qrdecomp.o \ src/matrix/tests/data/matrixcf_data_transmul.o \ matrix_benchmarks := \ src/matrix/bench/matrixf_inv_benchmark.c \ src/matrix/bench/matrixf_linsolve_benchmark.c \ src/matrix/bench/matrixf_mul_benchmark.c \ src/matrix/bench/smatrixf_mul_benchmark.c \ # # MODULE : modem # modem_objects := \ src/modem/src/ampmodem.o \ src/modem/src/cpfskdem.o \ src/modem/src/cpfskmod.o \ src/modem/src/fskdem.o \ src/modem/src/fskmod.o \ src/modem/src/gmskdem.o \ src/modem/src/gmskmod.o \ src/modem/src/modemf.o \ src/modem/src/modem_utilities.o \ src/modem/src/modem_apsk_const.o \ src/modem/src/modem_arb_const.o \ # explicit targets and dependencies modem_includes := \ src/modem/src/freqdem.c \ src/modem/src/freqmod.c \ src/modem/src/modem_common.c \ src/modem/src/modem_psk.c \ src/modem/src/modem_dpsk.c \ src/modem/src/modem_ask.c \ src/modem/src/modem_qam.c \ src/modem/src/modem_apsk.c \ src/modem/src/modem_bpsk.c \ src/modem/src/modem_qpsk.c \ src/modem/src/modem_ook.c \ src/modem/src/modem_sqam32.c \ src/modem/src/modem_sqam128.c \ src/modem/src/modem_arb.c \ #src/modem/src/modem_demod_soft_const.c src/modem/src/modemf.o : %.o : %.c $(include_headers) $(modem_includes) src/modem/src/gmskmod.o : %.o : %.c $(include_headers) src/modem/src/gmskdem.o : %.o : %.c $(include_headers) src/modem/src/ampmodem.o : %.o : %.c $(include_headers) src/modem/src/freqmodem.o : %.o : %.c $(include_headers) src/modem/src/modem_utilities.o : %.o : %.c $(include_headers) src/modem/src/modem_apsk_const.o : %.o : %.c $(include_headers) src/modem/src/modem_arb_const.o : %.o : %.c $(include_headers) modem_autotests := \ src/modem/tests/cpfskmodem_autotest.c \ src/modem/tests/freqmodem_autotest.c \ src/modem/tests/fskmodem_autotest.c \ src/modem/tests/modem_autotest.c \ src/modem/tests/modem_demodsoft_autotest.c \ src/modem/tests/modem_demodstats_autotest.c \ modem_benchmarks := \ src/modem/bench/freqdem_benchmark.c \ src/modem/bench/freqmod_benchmark.c \ src/modem/bench/fskdem_benchmark.c \ src/modem/bench/fskmod_benchmark.c \ src/modem/bench/gmskmodem_benchmark.c \ src/modem/bench/modem_modulate_benchmark.c \ src/modem/bench/modem_demodulate_benchmark.c \ src/modem/bench/modem_demodsoft_benchmark.c \ # # MODULE : multichannel # multichannel_objects := \ src/multichannel/src/firpfbch_crcf.o \ src/multichannel/src/firpfbch_cccf.o \ src/multichannel/src/ofdmframe.common.o \ src/multichannel/src/ofdmframegen.o \ src/multichannel/src/ofdmframesync.o \ $(multichannel_objects) : %.o : %.c $(include_headers) # list explicit targets and dependencies here multichannel_includes := \ src/multichannel/src/firpfbch.c \ src/multichannel/src/firpfbch2.c \ src/multichannel/src/firpfbch_crcf.o : %.o : %.c $(include_headers) $(multichannel_includes) src/multichannel/src/firpfbch_cccf.o : %.o : %.c $(include_headers) $(multichannel_includes) # autotests multichannel_autotests := \ src/multichannel/tests/firpfbch2_crcf_autotest.c \ src/multichannel/tests/firpfbch_crcf_synthesizer_autotest.c \ src/multichannel/tests/firpfbch_crcf_analyzer_autotest.c \ src/multichannel/tests/ofdmframesync_autotest.c \ # benchmarks multichannel_benchmarks := \ src/multichannel/bench/firpfbch_crcf_benchmark.c \ src/multichannel/bench/firpfbch2_crcf_benchmark.c \ src/multichannel/bench/ofdmframesync_acquire_benchmark.c \ src/multichannel/bench/ofdmframesync_rxsymbol_benchmark.c \ # # MODULE : nco - numerically-controlled oscillator # nco_objects := \ src/nco/src/nco_crcf.o \ src/nco/src/nco.utilities.o \ src/nco/src/nco_crcf.o : %.o : %.c $(include_headers) src/nco/src/nco.c src/nco/src/nco.utilities.o : %.o : %.c $(include_headers) # autotests nco_autotests := \ src/nco/tests/nco_crcf_frequency_autotest.c \ src/nco/tests/nco_crcf_phase_autotest.c \ src/nco/tests/nco_crcf_pll_autotest.c \ src/nco/tests/unwrap_phase_autotest.c \ # additional autotest objects autotest_extra_obj += \ src/nco/tests/data/nco_sincos_fsqrt1_2.o \ src/nco/tests/data/nco_sincos_fsqrt1_3.o \ src/nco/tests/data/nco_sincos_fsqrt1_5.o \ src/nco/tests/data/nco_sincos_fsqrt1_7.o \ # benchmarks nco_benchmarks := \ src/nco/bench/nco_benchmark.c \ src/nco/bench/vco_benchmark.c \ # # MODULE : optim - optimization # optim_objects := \ src/optim/src/chromosome.o \ src/optim/src/gasearch.o \ src/optim/src/gradsearch.o \ src/optim/src/optim.common.o \ src/optim/src/qnsearch.o \ src/optim/src/utilities.o \ $(optim_objects) : %.o : %.c $(include_headers) # autotests optim_autotests := \ src/optim/tests/gradsearch_autotest.c \ # benchmarks optim_benchmarks := # # MODULE : quantization # quantization_objects := \ src/quantization/src/compand.o \ src/quantization/src/quantizercf.o \ src/quantization/src/quantizerf.o \ src/quantization/src/quantizer.inline.o \ src/quantization/src/compand.o : %.o : %.c $(include_headers) src/quantization/src/quantizercf.o : %.o : %.c $(include_headers) src/quantization/src/quantizer.c src/quantization/src/quantizerf.o : %.o : %.c $(include_headers) src/quantization/src/quantizer.c src/quantization/src/quantizer.inline.o : %.o : %.c $(include_headers) # autotests quantization_autotests := \ src/quantization/tests/compand_autotest.c \ src/quantization/tests/quantize_autotest.c \ # benchmarks quantization_benchmarks := \ src/quantization/bench/quantizer_benchmark.c \ src/quantization/bench/compander_benchmark.c \ # # MODULE : random # random_objects := \ src/random/src/rand.o \ src/random/src/randn.o \ src/random/src/randexp.o \ src/random/src/randweib.o \ src/random/src/randgamma.o \ src/random/src/randnakm.o \ src/random/src/randricek.o \ src/random/src/scramble.o \ $(random_objects) : %.o : %.c $(include_headers) # autotests random_autotests := \ src/random/tests/scramble_autotest.c \ # src/random/tests/random_autotest.c # benchmarks random_benchmarks := \ src/random/bench/random_benchmark.c \ # # MODULE : sequence # sequence_objects := \ src/sequence/src/bsequence.o \ src/sequence/src/msequence.o \ $(sequence_objects) : %.o : %.c $(include_headers) # autotests sequence_autotests := \ src/sequence/tests/bsequence_autotest.c \ src/sequence/tests/complementary_codes_autotest.c \ src/sequence/tests/msequence_autotest.c \ # benchmarks sequence_benchmarks := \ src/sequence/bench/bsequence_benchmark.c \ # # MODULE : utility # utility_objects := \ src/utility/src/bshift_array.o \ src/utility/src/byte_utilities.o \ src/utility/src/msb_index.o \ src/utility/src/pack_bytes.o \ src/utility/src/shift_array.o \ $(utility_objects) : %.o : %.c $(include_headers) # autotests utility_autotests := \ src/utility/tests/bshift_array_autotest.c \ src/utility/tests/count_bits_autotest.c \ src/utility/tests/pack_bytes_autotest.c \ src/utility/tests/shift_array_autotest.c \ # benchmarks utility_benchmarks := # # MODULE : vector # # main objects list vector_objects := \ @MLIBS_VECTOR@ \ # portable builds src/vector/src/vectorf_add.port.o : %.o : %.c $(include_headers) src/vector/src/vector_add.c src/vector/src/vectorf_norm.port.o : %.o : %.c $(include_headers) src/vector/src/vector_norm.c src/vector/src/vectorf_mul.port.o : %.o : %.c $(include_headers) src/vector/src/vector_mul.c src/vector/src/vectorf_trig.port.o : %.o : %.c $(include_headers) src/vector/src/vector_trig.c src/vector/src/vectorcf_add.port.o : %.o : %.c $(include_headers) src/vector/src/vector_add.c src/vector/src/vectorcf_norm.port.o : %.o : %.c $(include_headers) src/vector/src/vector_norm.c src/vector/src/vectorcf_mul.port.o : %.o : %.c $(include_headers) src/vector/src/vector_mul.c src/vector/src/vectorcf_trig.port.o : %.o : %.c $(include_headers) src/vector/src/vector_trig.c # builds for specific architectures # ... # vector autotest scripts vector_autotests := # additional autotest objects autotest_extra_obj += # vector benchmark scripts vector_benchmarks := # Target collection # # Information about targets for each module is collected # in these variables objects := \ src/libliquid.o \ $(agc_objects) \ $(audio_objects) \ $(buffer_objects) \ $(channel_objects) \ $(dotprod_objects) \ $(equalization_objects) \ $(fec_objects) \ $(fft_objects) \ $(filter_objects) \ $(framing_objects) \ $(math_objects) \ $(matrix_objects) \ $(modem_objects) \ $(multichannel_objects) \ $(nco_objects) \ $(optim_objects) \ $(quantization_objects) \ $(random_objects) \ $(sequence_objects) \ $(utility_objects) \ $(vector_objects) \ autotest_sources := \ autotest/null_autotest.c \ $(agc_autotests) \ $(audio_autotests) \ $(buffer_autotests) \ $(channel_autotests) \ $(dotprod_autotests) \ $(equalization_autotests) \ $(fec_autotests) \ $(fft_autotests) \ $(filter_autotests) \ $(framing_autotests) \ $(math_autotests) \ $(matrix_autotests) \ $(modem_autotests) \ $(multichannel_autotests) \ $(nco_autotests) \ $(optim_autotests) \ $(quantization_autotests) \ $(random_autotests) \ $(sequence_autotests) \ $(utility_autotests) \ $(vector_autotests) \ benchmark_sources := \ bench/null_benchmark.c \ $(agc_benchmarks) \ $(audio_benchmarks) \ $(buffer_benchmarks) \ $(channel_benchmarks) \ $(dotprod_benchmarks) \ $(equalization_benchmarks) \ $(fec_benchmarks) \ $(fft_benchmarks) \ $(filter_benchmarks) \ $(framing_benchmarks) \ $(math_benchmarks) \ $(matrix_benchmarks) \ $(modem_benchmarks) \ $(multichannel_benchmarks) \ $(nco_benchmarks) \ $(optim_benchmarks) \ $(quantization_benchmarks) \ $(random_benchmarks) \ $(sequence_benchmarks) \ $(utility_benchmarks) \ $(vector_benchmarks) \ ## ## TARGET : all - build shared library (default) ## .PHONY: all # Shared library SHARED_LIB = @SH_LIB@ # liquid library definition libliquid.a: $(objects) $(AR) $(ARFLAGS) $@ $^ $(RANLIB) $@ # darwin # # gcc -dynamiclib -install_name libliquid.dylib -o libliquid.dylib libmodem.a libutility.a libliquid.dylib: $(objects) $(CC) -dynamiclib -install_name $@ -o $@ $^ $(LDFLAGS) $(LIBS) # linux, et al libliquid.so: libliquid.a $(CC) $(CFLAGS) $(LDFLAGS) -shared -Xlinker -soname=$@ -o $@ -Wl,-whole-archive $^ -Wl,-no-whole-archive $(LIBS) all: libliquid.a $(SHARED_LIB) ## ## TARGET : help - print list of targets ## # look for all occurences of '## TARGET : ' and print rest of line to screen help: @echo "Targets for liquid-dsp makefile:" @$(GREP) -E "^## TARGET : " [Mm]akefile | $(SED) 's/## TARGET : / /' ## ## TARGET : install - installs the libraries and header files in the host system ## install: all @echo "installing..." @echo "" mkdir -p $(DESTDIR)$(exec_prefix)$(libdir) mkdir -p $(DESTDIR)$(prefix)/include/liquid install -m 644 -p $(SHARED_LIB) libliquid.a $(DESTDIR)$(exec_prefix)$(libdir) install -m 644 -p $(addprefix include/,$(headers_install)) $(DESTDIR)$(prefix)/include/liquid @echo "" @echo "---------------------------------------------------------" @echo " liquid-dsp was successfully installed. " @echo "" @echo " On some machines (e.g. Linux) you should rebind your" @echo " libraries by running 'ldconfig' to make the shared" @echo " object available. You might also need to modify your" @echo " LD_LIBRARY_PATH environment variable to include the" @echo " directory $(DESTDIR)$(exec_prefix)" @echo "" @echo " Please report bugs to $(BUGREPORT)" @echo "---------------------------------------------------------" @echo "" ## ## TARGET : uninstall - uninstalls the libraries and header files in the host system ## uninstall: @echo "uninstalling..." $(RM) $(addprefix $(DESTDIR)$(prefix)/include/liquid/, $(headers_install)) $(RM) $(DESTDIR)$(exec_prefix)$(libdir)/libliquid.a $(RM) $(DESTDIR)$(exec_prefix)$(libdir)/$(SHARED_LIB) @echo "done." ## ## autoscript ## autoscript : scripts/autoscript scripts/autoscript.o scripts/main.o : %.o : %.c $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< scripts/autoscript : scripts/autoscript.o scripts/main.o $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) clean-autoscript : $(RM) scripts/autoscript.o scripts/main.o scripts/autoscript ## ## TARGET : check - build and run autotest scripts ## # Autotests are used to check the validity and accuracy of the # DSP libraries. .PHONY: autotest autotest_prog = xautotest # run the autotest generator script to create autotest_include.h autotest_include.h : scripts/autoscript $(autotest_sources) $(include_headers) ./scripts/autoscript $(PATHSEP) autotest $(autotest_sources) > $@ # autotest objects # NOTE: by default, gcc compiles any file with a '.h' extension as a 'pre-compiled # header' so we need to explicity tell it to compile as a c source file with # the '-x c' flag autotest_obj = $(patsubst %.c,%.o,$(autotest_sources)) $(autotest_obj) : %.o : %.c $(include_headers) $(CC) $(CPPFLAGS) $(CFLAGS) $< -c -o $@ # additional autotest objects $(autotest_extra_obj) : %.o : %.c $(include_headers) # compile the autotest internal library functions without linking autotest/autotestlib.o : autotest/autotestlib.c autotest/autotest.h $(CC) $(CPPFLAGS) $(CFLAGS) $< -c -o $@ # compile the autotest program without linking $(autotest_prog).o : autotest/autotest.c autotest/autotest.h autotest_include.h $(CC) $(CPPFLAGS) $(CFLAGS) $< -c -o $@ # link the autotest program with the objects # NOTE: linked libraries must come _after_ the target program $(autotest_prog): $(autotest_prog).o $(autotest_obj) $(autotest_extra_obj) autotest/autotestlib.o libliquid.a $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS) # run the autotest program check: $(autotest_prog) ./$(autotest_prog) -v # let 'make test' be an alias for 'make check' test: check # clean the generated files clean-check: $(RM) autotest_include.h $(autotest_prog).o $(autotest_prog) $(RM) autotest/autotestlib.o $(RM) $(autotest_obj) $(RM) $(autotest_extra_obj) ## ## TARGET : bench - build and run all benchmarks ## # Benchmarks measure the relative speed of the DSP algorithms running # on the target platform. .PHONY: bench bench_prog = benchmark BENCH_CPPFLAGS = $(CPPFLAGS) BENCH_CFLAGS = -Wall $(CFLAGS) BENCH_LDFLAGS = $(LDFLAGS) BENCH_LIBS = $(LIBS) # run the benchmark generator script to create benchmark_include.h benchmark_include.h : scripts/autoscript $(benchmark_sources) $(include_headers) ./scripts/autoscript $(PATHSEP) benchmark $(benchmark_sources) > $@ # benchmark objects # NOTE: by default, gcc compiles any file with a '.h' extension as a 'pre-compiled # header' so we need to explicity tell it to compile as a c source file with # the '-x c' flag benchmark_obj = $(patsubst %.c,%.o,$(benchmark_sources)) $(benchmark_obj) : %.o : %.c $(include_headers) $(CC) $(BENCH_CPPFLAGS) $(BENCH_CFLAGS) $< -c -o $@ # additional benchmark objects $(benchmark_extra_obj) : %.o : %.c $(include_headers) # compile the benchmark program without linking $(bench_prog).o: bench/bench.c benchmark_include.h bench/bench.c $(CC) $(BENCH_CPPFLAGS) $(BENCH_CFLAGS) $< -c -o $(bench_prog).o # link the benchmark program with the library objects # NOTE: linked libraries must come _after_ the target program $(bench_prog): $(bench_prog).o $(benchmark_obj) $(benchmark_extra_obj) libliquid.a $(CC) $(BENCH_CFLAGS) $(BENCH_LDFLAGS) $^ -o $(bench_prog) $(BENCH_LIBS) # run the benchmark program bench: $(bench_prog) ./$(bench_prog) # benchmark compare script scripts/benchmark_compare : % : %.c $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) # fftbench program bench/fftbench.o : %.o : %.c $(CC) $(BENCH_CPPFLAGS) $(BENCH_CFLAGS) $< -c -o $@ bench/fftbench : % : %.o libliquid.a $(CC) $(BENCH_CFLAGS) $(BENCH_LDFLAGS) $^ -o $@ $(BENCH_LIBS) # clean up the generated files clean-bench: $(RM) benchmark_include.h $(bench_prog).o $(bench_prog) $(RM) scripts/benchmark_compare $(RM) $(benchmark_obj) $(RM) $(benchmark_extra_obj) $(RM) bench/fftbench.o $(RM) bench/fftbench ## ## TARGET : examples - build all examples binaries ## .PHONY: examples example_programs := \ examples/agc_crcf_example \ examples/agc_crcf_squelch_example \ examples/agc_crcf_qpsk_example \ examples/agc_rrrf_example \ examples/ampmodem_example \ examples/asgramcf_example \ examples/asgramf_example \ examples/autocorr_cccf_example \ examples/bpacketsync_example \ examples/bpresync_example \ examples/bsequence_example \ examples/cbufferf_example \ examples/cgsolve_example \ examples/channel_cccf_example \ examples/chromosome_example \ examples/compand_example \ examples/compand_cf_example \ examples/complementary_codes_example \ examples/conversion_example \ examples/crc_example \ examples/cpfskmodem_example \ examples/cpfskmodem_psd_example \ examples/cvsd_example \ examples/detector_cccf_example \ examples/dotprod_rrrf_example \ examples/dotprod_cccf_example \ examples/eqlms_cccf_block_example \ examples/eqlms_cccf_blind_example \ examples/eqlms_cccf_decisiondirected_example \ examples/eqlms_cccf_example \ examples/eqrls_cccf_example \ examples/fec_example \ examples/fec_soft_example \ examples/fft_example \ examples/fftfilt_crcf_example \ examples/firdecim_crcf_example \ examples/firfarrow_rrrf_example \ examples/firfilt_cccf_example \ examples/firfilt_crcf_example \ examples/firfilt_rrrf_example \ examples/firdes_kaiser_example \ examples/firdespm_callback_example \ examples/firdespm_example \ examples/firdespm_lowpass_example \ examples/firhilb_example \ examples/firhilb_decim_example \ examples/firhilb_interp_example \ examples/firpfbch2_crcf_example \ examples/firinterp_crcf_example \ examples/firpfbch_crcf_example \ examples/firpfbch_crcf_analysis_example \ examples/firpfbch_crcf_synthesis_example \ examples/flexframesync_example \ examples/flexframesync_reconfig_example \ examples/framesync64_example \ examples/freqmodem_example \ examples/fskmodem_example \ examples/gasearch_example \ examples/gasearch_knapsack_example \ examples/gmskframesync_example \ examples/gmskmodem_example \ examples/gradsearch_datafit_example \ examples/gradsearch_example \ examples/interleaver_example \ examples/interleaver_soft_example \ examples/interleaver_scatterplot_example \ examples/iirdes_example \ examples/iirdes_analog_example \ examples/iirdes_pll_example \ examples/iirdecim_crcf_example \ examples/iirfilt_cccf_example \ examples/iirfilt_crcf_example \ examples/iirfilt_crcf_dcblocker_example \ examples/iirinterp_crcf_example \ examples/kbd_window_example \ examples/lpc_example \ examples/libliquid_example \ examples/matched_filter_example \ examples/math_lngamma_example \ examples/math_primitive_root_example \ examples/modem_arb_example \ examples/modem_example \ examples/modem_soft_example \ examples/modular_arithmetic_example \ examples/msequence_example \ examples/msourcecf_example \ examples/msresamp_crcf_example \ examples/msresamp2_crcf_example \ examples/nco_example \ examples/nco_pll_example \ examples/nco_pll_modem_example \ examples/nyquist_filter_example \ examples/ofdmflexframesync_example \ examples/ofdmframesync_example \ examples/packetizer_example \ examples/packetizer_soft_example \ examples/pll_example \ examples/polyfit_example \ examples/polyfit_lagrange_example \ examples/poly_findroots_example \ examples/qdetector_cccf_example \ examples/qpacketmodem_performance_example \ examples/qpacketmodem_example \ examples/qpilotsync_example \ examples/qnsearch_example \ examples/quantize_example \ examples/random_histogram_example \ examples/repack_bytes_example \ examples/resamp_crcf_example \ examples/resamp2_cccf_example \ examples/resamp2_crcf_example \ examples/resamp2_crcf_decim_example \ examples/resamp2_crcf_filter_example \ examples/resamp2_crcf_interp_example \ examples/ricek_channel_example \ examples/scramble_example \ examples/smatrix_example \ examples/spgramcf_example \ examples/spgramcf_waterfall_example \ examples/spgramf_example \ examples/spwaterfallcf_example \ examples/symsync_crcf_example \ examples/symsync_crcf_full_example \ examples/symsync_crcf_kaiser_example \ examples/symstreamcf_example \ examples/symtrack_cccf_example \ examples/wdelayf_example \ examples/windowf_example \ # examples/metadata_example # examples/ofdmframegen_example # examples/gmskframe_example # examples/fading_generator_example example_objects = $(patsubst %,%.o,$(example_programs)) examples: $(example_programs) # NOTE: linked libraries must come _after_ the target program $(example_objects): %.o : %.c $(example_programs): % : %.o libliquid.a $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS) # clean examples clean-examples: $(RM) examples/*.o $(RM) $(example_programs) ## ## TARGET : sandbox - build all sandbox binaries ## # NOTE: sandbox _requires_ fftw3 to build .PHONY: sandbox sandbox_programs = \ sandbox/bpresync_test \ sandbox/cpmodem_test \ sandbox/count_ones_gentab \ sandbox/crc_gentab \ sandbox/ellip_func_test \ sandbox/ellip_test \ sandbox/eqlms_cccf_test \ sandbox/fecsoft_ber_test \ sandbox/fec_g2412product_test \ sandbox/fec_golay2412_test \ sandbox/fec_golay_test \ sandbox/fec_hamming3126_example \ sandbox/fec_hamming128_test \ sandbox/fec_hamming128_gentab \ sandbox/fec_hamming128_example \ sandbox/fec_hamming74_gentab \ sandbox/fec_hamming84_gentab \ sandbox/fec_hamming_test \ sandbox/fec_ldpc_test \ sandbox/fec_rep3_test \ sandbox/fec_rep5_test \ sandbox/fec_secded2216_test \ sandbox/fec_secded3932_test \ sandbox/fec_secded7264_test \ sandbox/fec_spc2216_test \ sandbox/fec_secded_punctured_test \ sandbox/fecsoft_conv_test \ sandbox/fecsoft_hamming128_gentab \ sandbox/fecsoft_ldpc_test \ sandbox/fec_sumproduct_test \ sandbox/fskmodem_test \ sandbox/fft_dual_radix_test \ sandbox/fft_mixed_radix_test \ sandbox/fft_recursive_plan_test \ sandbox/fft_recursive_test \ sandbox/fft_rader_prime_test \ sandbox/fft_rader_prime_radix2_test \ sandbox/fft_r2r_test \ sandbox/firdes_energy_test \ sandbox/firdes_fexp_test \ sandbox/firdes_gmskrx_test \ sandbox/firdes_length_test \ sandbox/firfarrow_rrrf_test \ sandbox/firpfbch_analysis_alignment_test \ sandbox/firpfbch2_analysis_equivalence_test \ sandbox/firpfbch2_test \ sandbox/firpfbch_analysis_equivalence_test \ sandbox/firpfbch_synthesis_equivalence_test \ sandbox/gmskmodem_test \ sandbox/gmskmodem_coherent_test \ sandbox/gmskmodem_equalizer_test \ sandbox/householder_test \ sandbox/iirdes_example \ sandbox/iirfilt_intdiff_test \ sandbox/levinson_test \ sandbox/matched_filter_test \ sandbox/matched_filter_cfo_test \ sandbox/math_lngamma_test \ sandbox/math_cacosf_test \ sandbox/math_casinf_test \ sandbox/math_catanf_test \ sandbox/math_cexpf_test \ sandbox/math_clogf_test \ sandbox/math_csqrtf_test \ sandbox/matrix_test \ sandbox/minsearch_test \ sandbox/minsearch2_test \ sandbox/matrix_eig_test \ sandbox/modem_demodulate_arb_gentab \ sandbox/modem_demodulate_soft_test \ sandbox/modem_demodulate_soft_gentab \ sandbox/mskmodem_test \ sandbox/msresamp_crcf_test \ sandbox/ofdmoqam_firpfbch_test \ sandbox/ofdm_ber_test \ sandbox/ofdmframe_papr_test \ sandbox/ofdmframesync_cfo_test \ sandbox/pll_design_test \ sandbox/predemod_sync_test \ sandbox/quasinewton_test \ sandbox/recursive_qpsk_test \ sandbox/resamp2_crcf_filterbank_test \ sandbox/resamp2_crcf_interp_recreate_test \ sandbox/reverse_byte_gentab \ sandbox/rkaiser2_test \ sandbox/shadowing_test \ sandbox/simplex_test \ sandbox/symsync_crcf_test \ sandbox/symsync_eqlms_test \ sandbox/svd_test \ sandbox/thiran_allpass_iir_test \ sandbox/vectorcf_test \ # sandbox/packetizer_persistent_ber_test # firpfbch_analysis_test # sandbox/ofdmoqam_firpfbch_cfo_test # sandbox/mdct_test # sandbox/fct_test sandbox_objects = $(patsubst %,%.o,$(sandbox_programs)) sandbox: $(sandbox_programs) SANDBOX_LDFLAGS = $(LDFLAGS) -lfftw3f # NOTE: linked libraries must come _after_ the target program $(sandbox_objects): %.o : %.c $(sandbox_programs): % : %.o libliquid.a $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) $(LIBS) # clean sandbox clean-sandbox: $(RM) sandbox/*.o $(RM) $(sandbox_programs) ## ## TARGET : world - build absolutely everything ## world : all check bench examples sandbox ## ## TARGET : clean - clean build (objects, dependencies, libraries, etc.) ## .PHONY: clean clean-modules: @echo "cleaning modules..." $(RM) src/agc/src/*.o src/agc/bench/*.o src/agc/tests/*.o $(RM) src/audio/src/*.o src/audio/bench/*.o src/audio/tests/*.o $(RM) src/buffer/src/*.o src/buffer/bench/*.o src/buffer/tests/*.o $(RM) src/channel/src/*.o src/channel/bench/*.o src/channel/tests/*.o $(RM) src/dotprod/src/*.o src/dotprod/bench/*.o src/dotprod/tests/*.o $(RM) src/equalization/src/*.o src/equalization/bench/*.o src/equalization/tests/*.o $(RM) src/fec/src/*.o src/fec/bench/*.o src/fec/tests/*.o $(RM) src/fft/src/*.o src/fft/bench/*.o src/fft/tests/*.o $(RM) src/filter/src/*.o src/filter/bench/*.o src/filter/tests/*.o $(RM) src/framing/src/*.o src/framing/bench/*.o src/framing/tests/*.o $(RM) src/math/src/*.o src/math/bench/*.o src/math/tests/*.o $(RM) src/matrix/src/*.o src/matrix/bench/*.o src/matrix/tests/*.o $(RM) src/modem/src/*.o src/modem/bench/*.o src/modem/tests/*.o $(RM) src/multichannel/src/*.o src/multichannel/bench/*.o src/multichannel/tests/*.o $(RM) src/nco/src/*.o src/nco/bench/*.o src/nco/tests/*.o $(RM) src/optim/src/*.o src/optim/bench/*.o src/optim/tests/*.o $(RM) src/quantization/src/*.o src/quantization/bench/*.o src/quantization/tests/*.o $(RM) src/random/src/*.o src/random/bench/*.o src/random/tests/*.o $(RM) src/sequence/src/*.o src/sequence/bench/*.o src/sequence/tests/*.o $(RM) src/utility/src/*.o src/utility/bench/*.o src/utility/tests/*.o $(RM) src/vector/src/*.o src/vector/bench/*.o src/vector/tests/*.o $(RM) src/libliquid.o clean: clean-modules clean-autoscript clean-check clean-bench clean-examples clean-sandbox $(RM) $(extra_clean) $(RM) libliquid.a $(RM) $(SHARED_LIB) ## ## TARGET : distclean - removes everything except the originally distributed files ## distclean: clean @echo "cleaning distribution..." $(RM) octave-core *.m $(RM) configure config.h config.h.in config.h.in~ config.log config.status $(RM) -r autom4te.cache $(RM) aclocal.m4 $(RM) makefile liquid-dsp-1.3.1/sandbox/000077500000000000000000000000001317124540100152235ustar00rootroot00000000000000liquid-dsp-1.3.1/sandbox/README.md000066400000000000000000000007301317124540100165020ustar00rootroot00000000000000 liquid-dsp sandbox ================== This directory is the sandbox for prototyping DSP processing elements in liquid. It contains a number of scripts which are used for testing and prototyping certain signal processing algorithms. Its primary function is to validate functional correctness without adding unnecessary code to the main project files. All the programs in this directory can be build by invoking 'make' from the root directory, viz. $ make sandbox liquid-dsp-1.3.1/sandbox/bpresync_test.c000066400000000000000000000216131317124540100202560ustar00rootroot00000000000000// // bpresync_test.c // // This example demonstrates the binary pre-demodulator synchronizer. A random // binary sequence is generated, modulated with BPSK, and then interpolated. // The resulting sequence is used to generate a bpresync object which in turn // is used to detect a signal in the presence of carrier frequency and timing // offsets and additive white Gauss noise. // #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "bpresync_test.m" // print usage/help message void usage() { printf("bpresync_test -- test binary pre-demodulation synchronization\n"); printf(" h : print usage/help\n"); printf(" v : increase output verbosity\n"); printf(" q : decrease output verbosity\n"); printf(" k : samples/symbol, default: 2\n"); printf(" n : number of data symbols, default: 64\n"); printf(" F : carrier frequency offset, default: 0.02\n"); printf(" S : SNR [dB], default: 20\n"); printf(" t : number of trials, default: 1000\n"); } void bpresync_test(bpresync_cccf _q, float complex * _x, unsigned int _n, float _SNRdB, float _dphi_max, float * _rxy_max, float * _dphi_err, float * _delay_err, unsigned int _num_trials, unsigned int _verbosity); int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int k=2; // filter samples/symbol unsigned int num_sync_symbols = 64; // number of synchronization symbols float SNRdB = 20.0f; // signal-to-noise ratio [dB] float dphi_max = 0.02f; // maximum carrier frequency offset unsigned int num_trials = 1000; // number of trials to run int verbosity = 1; // verbosity level int dopt; while ((dopt = getopt(argc,argv,"hvqk:n:F:S:t:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'v': verbosity++; break; case 'q': verbosity--; break; case 'k': k = atoi(optarg); break; case 'n': num_sync_symbols = atoi(optarg); break; case 'F': dphi_max = atof(optarg); break; case 'S': SNRdB = atof(optarg); break; case 't': num_trials = atoi(optarg); break; default: exit(1); } } unsigned int i; // arrays float complex seq[k*num_sync_symbols]; // synchronization pattern (samples) float rxy_max[num_trials]; float dphi_err[num_trials]; float delay_err[num_trials]; // generate synchronization pattern (BPSK) and interpolate unsigned int n=0; for (i=0; i _rxy_max[t] ) { _rxy_max[t] = cabsf(rxy); _dphi_err[t] = dphi_est - dphi; _delay_err[t] = (float)i - (float)(_n + delay + (h_len-1)/2) + 1.0f + dt; } } if (_verbosity == 0) { // do nothing } else if (_verbosity == 1) { // print progress bar if ( (t%100)==0 || t==_num_trials-1 ) { float percent = (float)(t+1) / (float)_num_trials; unsigned int bars = (unsigned int) (percent*60); printf("["); for (i=0; i<60; i++) printf("%c", i < bars ? '#' : ' '); printf("] %5.1f%%\r", percent*100); fflush(stdout); } } else { // print every trial printf(" %6u: rxy_max=%12.8f, dphi-err=%12.8f, delay-err=%12.8f\n", t, _rxy_max[t], _dphi_err[t], _delay_err[t]); } } // destroy Farrow filter firfarrow_crcf_destroy(fdelay); } liquid-dsp-1.3.1/sandbox/count_ones_gentab.c000066400000000000000000000047371317124540100210760ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // generate tables for counting ones in a byte // #include #include // slow implementation counting ones in a byte unsigned int count_ones(unsigned char _x) { unsigned int n=0; unsigned int i; for (i=0; i<8; i++) n += (_x >> i) & 0x01; return n; } int main() { unsigned int i; printf("// auto-generated file (do not edit)\n"); printf("\n"); printf("// number of ones in a byte\n"); printf("unsigned const char liquid_c_ones[256] = {\n "); for (i=0; i<256; i++) { // unsigned int n = count_ones((unsigned char)i); // print results printf("%1u", n); if ( i != 255 ) { printf(","); if ( ((i+1)%16)==0 ) printf("\n "); else printf(" "); } } printf("};\n\n"); // do the same modulo 2 printf("// number of ones in a byte modulo 2\n"); printf("unsigned const char liquid_c_ones_mod2[256] = {\n "); for (i=0; i<256; i++) { // unsigned int n = count_ones((unsigned char)i); // print results printf("%1u", n % 2); if ( i != 255 ) { printf(","); if ( ((i+1)%16)==0 ) printf("\n "); else printf(" "); } } printf("};\n\n"); return 0; } liquid-dsp-1.3.1/sandbox/cpmodem_test.c000066400000000000000000000115571317124540100200630ustar00rootroot00000000000000// // cpmodem_test.c // // This example demonstrates how the use the nco/pll object // (numerically-controlled oscillator with phase-locked loop) interface for // tracking to a complex sinusoid. The loop bandwidth, phase offset, and // other parameter can be specified via the command-line interface. // // SEE ALSO: nco_example.c // nco_pll_modem_example.c // #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "cpmodem_test.m" // print usage/help message void usage() { printf("cpmodem_test [options]\n"); printf(" h : print usage\n"); printf(" m : bits per symbol, default: 2\n"); printf(" n : number of symbols, default: 20\n"); printf(" p : phase offset (radians), default: pi/4\n"); printf(" f : frequency offset (radians), default: 0.3\n"); } int main(int argc, char*argv[]) { srand( time(NULL) ); // parameters float phase_offset = M_PI / 4.0f; float frequency_offset = 0.1f; unsigned int m = 2; // bits per symbol unsigned int num_symbols=20; // number of iterations int dopt; while ((dopt = getopt(argc,argv,"uhm:n:p:f:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'm': m = atoi(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 'p': phase_offset = atof(optarg); break; case 'f': frequency_offset= atof(optarg); break; default: exit(1); } } // derived values unsigned int M = 1< #include // generator polynomial #define CRC32_POLY 0xEDB88320 // 0x04C11DB7 int main() { unsigned int crc; unsigned int mask; unsigned int crcpoly = CRC32_POLY; unsigned int crc_gentab[256]; // generate table unsigned int i, j; for (i=0; i<256; i++) { crc = i; for (j=0; j<8; j++) { mask = -(crc & 0x01); crc = (crc >> 1) ^ (crcpoly & mask); } crc_gentab[i] = crc; } printf("\n"); printf("unsigned char crc_gentab[%u] = {\n ", 256); for (i=0; i<256; i++) { printf("0x%.2x", crc_gentab[i]); if (i==255) printf("};\n"); else if (((i+1)%8)==0) printf(",\n "); else printf(", "); } // test it... return 0; } liquid-dsp-1.3.1/sandbox/ellip_func_test.c000066400000000000000000000015651317124540100205550ustar00rootroot00000000000000// // ellip_func_test.c // // gcc -I. -I./include -lm libliquid.a ellip_func_test.c -o ellip_func_test // #include #include #include "include/liquid.h" #include "src/filter/src/ellip.c" int main() { float complex u = 0.7f; float k = 0.8f; unsigned int n=7; float complex cd = ellip_cdf(u,k,n); float complex sn = ellip_snf(u,k,n); printf("u : %12.8f + j*%12.8f\n", crealf(u), cimagf(u)); printf("k : %12.8f\n", k); printf("cd : %12.8f + j*%12.8f\n", crealf(cd), cimagf(cd)); printf("sn : %12.8f + j*%12.8f\n", crealf(sn), cimagf(sn)); printf("\n"); float complex acd = ellip_acdf(cd,k,n); float complex asn = ellip_asnf(sn,k,n); printf("acd : %12.8f + j*%12.8f\n", crealf(acd), cimagf(acd)); printf("asn : %12.8f + j*%12.8f\n", crealf(asn), cimagf(asn)); printf("done.\n"); return 0; } liquid-dsp-1.3.1/sandbox/ellip_test.c000066400000000000000000000050201317124540100175300ustar00rootroot00000000000000// // elliptest.c // // gcc -I. -I./include -lm libliquid.a elliptest.c -o elliptest // #include #include #include "include/liquid.h" #include "src/filter/src/ellip.c" int main() { // filter specifications float fp = 4.0f; float fs = 4.5f; float Gp = 0.95f; float Gs = 0.05f; unsigned int n=7; // number of iterations float Wp = 2*M_PI*fp; float Ws = 2*M_PI*fs; // ripples passband, stopband float ep = sqrtf(1.0f/(Gp*Gp) - 1.0f); float es = sqrtf(1.0f/(Gs*Gs) - 1.0f); printf("ep, es : %12.8f, %12.8f\n", ep, es); float k = Wp/Ws; // 0.8889f; float k1 = ep/es; // 0.0165f; float K, Kp; float K1, K1p; ellipkf(k, n, &K, &Kp); // K = 2.23533416, Kp = 1.66463780 ellipkf(k1,n, &K1, &K1p); // K1 = 1.57090271, K1p = 5.49361753 printf("K, Kp : %12.8f, %12.8f\n", K, Kp); printf("K1, K1p : %12.8f, %12.8f\n", K1, K1p); float Nexact = (K1p/K1)/(Kp/K); // 4.69604063 float N = ceilf(Nexact); // 5 printf("N (exact) : %12.8f\n", Nexact); printf("N : %12.8f\n", N); k = ellipdegf(N,k1,n); // 0.91427171 printf("k : %12.8f\n", k); float fs_new = fp/k; // 4.37506723 printf("fs_new : %12.8f\n", fs_new); unsigned int L = (unsigned int)(floorf(N/2.0f)); // 2 //unsigned int r = ((unsigned int)N) % 2; float u[L]; unsigned int i; for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "eqlms_cccf_test.m" int main() { // options unsigned int k=2; // samples/symbol unsigned int m=3; float beta = 0.3f; //float dt = 0.4f; // timing offset unsigned int num_symbols = 256; unsigned int hc_len=1; // channel impulse response length unsigned int p=13; // equalizer filter length float mu = 0.05f; // TODO : validate input // derived values unsigned int num_samples = k*num_symbols; // data arrays float complex s[num_symbols]; // original QPSK symbols float complex x[num_samples]; // interpolated samples float complex y[num_samples]; // received samples float complex z[num_samples]; // recovered samples // generate data sequence unsigned int i; for (i=0; i 0.0f ? 1.0f : -1.0f) + (cimagf(d_hat) > 0.0f ? 1.0f : -1.0f) * _Complex_I; // compute error float complex alpha = d_prime - d_hat; // compute signal energy float ex2 = 1.414f; // update weighting vector for (j=0; j #include #include #include "liquid.h" int main() { unsigned int n=16; float x[n]; // time-domain 'signal' float y[n]; // fft(x) float z[n]; // ifft(y) unsigned int i; for (i=0; i #include #include #include #include "liquid.internal.h" #define DEBUG (0) typedef struct g2412p_s * g2412p; g2412p g2412p_create (); void g2412p_destroy (g2412p _q); void g2412p_print (g2412p _q); void g2412p_encode (g2412p _q, unsigned char * _msg_org, unsigned char * _msg_enc); void g2412p_decode (g2412p _q, unsigned char * _msg_rec, unsigned char * _msg_dec); int g2412p_iterate (g2412p _q); int g2412p_step (g2412p _q); void g2412p_load_row(g2412p _q, unsigned int _row); void g2412p_save_row(g2412p _q, unsigned int _row); void g2412p_load_col(g2412p _q, unsigned int _col); void g2412p_save_col(g2412p _q, unsigned int _col); // pack 24-value soft-bit message into integer unsigned int g2412p_pack_symbol(unsigned char * _msg_soft); // unpack 24-bit integer into soft array void g2412p_unpack_symbol(unsigned int _msg_hard, unsigned char * _msg_soft); unsigned int liquid_hard_decision(unsigned char _soft_bit); void print_bitstring(unsigned int _x, unsigned int _n) { unsigned int i; printf(" "); for (i=0; i<_n; i++) printf("%1u ", (_x >> (_n-i-1)) & 1); printf("\n"); } int main(int argc, char*argv[]) { unsigned int i; unsigned int j; unsigned char msg_org[144]; unsigned char msg_enc[576]; unsigned char msg_rec[576]; unsigned char msg_dec[144]; // create object to handle encoding/decoding g2412p q = g2412p_create(); // initialize input array unsigned char p = 0x01; for (i=0; i<144; i++) { //msg_org[i] = i % 2; msg_org[i] = p & 1; p = ((p << 1) & 0xfe) | liquid_bdotprod(p,0xad); msg_org[i] = 0; } #if DEBUG // print original message printf("msg_org:\n"); for (i=0; i<12; i++) { printf("%3u: ", i); for (j=0; j<12; j++) printf("%2u", msg_org[12*i+j]); printf("\n"); } #endif // encode message g2412p_encode(q, msg_org, msg_enc); #if DEBUG // print encoded message printf("msg_enc:\n"); for (i=0; i<24; i++) { printf("%3u: ", i); for (j=0; j<24; j++) printf("%2u", msg_enc[24*i+j]); printf("\n"); } #endif #if 0 // corrupt message for (i=0; i<576; i++) msg_rec[i] = msg_enc[i] ? LIQUID_SOFTBIT_1 : LIQUID_SOFTBIT_0; msg_rec[ 0] = 255 - msg_rec[ 0]; msg_rec[ 24] = 255 - msg_rec[ 24]; msg_rec[ 48] = 255 - msg_rec[ 48]; msg_rec[ 72] = 255 - msg_rec[ 72]; msg_rec[ 96] = 255 - msg_rec[ 96]; msg_rec[120] = 255 - msg_rec[120]; #else // modulate, add noise, demodulate soft float SNRdB = -4.0f; float nstd = powf(10.0f, -SNRdB/20.0f); modem mod = modem_create(LIQUID_MODEM_BPSK); for (i=0; i<576; i++) { float complex v; unsigned int s; modem_modulate(mod, msg_enc[i], &v); v += nstd*(randnf() + randnf()*_Complex_I) * M_SQRT1_2; modem_demodulate_soft(mod, v, &s, &msg_rec[i]); } modem_destroy(mod); #endif // decode message g2412p_decode(q, msg_rec, msg_dec); // print decoded message printf("msg_org:\n"); for (i=0; i<12; i++) { printf("%3u: ", i); for (j=0; j<12; j++) printf("%2u", msg_dec[12*i+j]); printf("\n"); } // count errors unsigned int num_errors = 0; for (i=0; i<144; i++) num_errors += (msg_dec[i] & 1) == (msg_org[i] & 1) ? 0 : 1; printf("bit errors: %u / %u\n", num_errors, 144); // clean up allocated objects g2412p_destroy(q); printf("done\n"); return 0; } struct g2412p_s { unsigned char msg_buf[576]; // 24 x 24 message array unsigned char reg0[24]; // 24 value register unsigned int r; unsigned int d; }; g2412p g2412p_create() { g2412p q = (g2412p) malloc( sizeof(struct g2412p_s) ); return q; } void g2412p_destroy(g2412p _q) { // free main object memory free(_q); } void g2412p_print(g2412p _q) { unsigned int i; #if 1 unsigned int j; printf("msg_buf:\n"); for (i=0; i<24; i++) { if (i==12) printf("------\n"); printf("%2u:", i); for (j=0; j<24; j++) printf(" %s%3u", j==12 ? ":" : "", _q->msg_buf[24*i+j]); printf("\n"); } #else for (i=0; i<576; i++) printf(" %3u%s", _q->msg_buf[i], ((i+1)%24)==0 ? "\n" : ""); #endif } void g2412p_encode(g2412p _q, unsigned char * _msg_org, unsigned char * _msg_enc) { unsigned int r; unsigned int c; // encode rows #if DEBUG printf("rows:\n"); #endif for (r=0; r<12; r++) { unsigned int sym_org = 0; for (c=0; c<12; c++) { sym_org <<= 1; sym_org |= _msg_org[12*r+c] ? 1 : 0; } unsigned int sym_enc = fec_golay2412_encode_symbol(sym_org); // make systematic (swap upper and lower 12 bit chunks) sym_enc = ((sym_enc >> 12) & 0xfff) | ((sym_enc << 12) & 0xfff000); #if DEBUG printf(" %2u: 0x%.3x > 0x%.6x\n", r, sym_org, sym_enc); #endif // for (c=0; c<24; c++) { unsigned int bit = (sym_enc >> (24-c-1)) & 1; _msg_enc[24*r+c] = bit; } } // encode columns #if DEBUG printf("cols:\n"); #endif for (c=0; c<24; c++) { unsigned int sym_org = 0; for (r=0; r<12; r++) { sym_org <<= 1; sym_org |= _msg_enc[c+24*r] ? 1 : 0; } unsigned int sym_enc = fec_golay2412_encode_symbol(sym_org); // make systematic (swap upper and lower 12 bit chunks) sym_enc = ((sym_enc >> 12) & 0xfff) | ((sym_enc << 12) & 0xfff000); #if DEBUG printf(" %2u: 0x%.3x > 0x%.6x\n", c, sym_org, sym_enc); #endif // append only parity bits (no need to overwrite original bits) for (r=12; r<24; r++) { unsigned int bit = (sym_enc >> (24-r-1)) & 1; _msg_enc[c+24*r] = bit; } } } void g2412p_decode(g2412p _q, unsigned char * _msg_rec, unsigned char * _msg_dec) { unsigned int i; // copy received message to internal buffer memmove(_q->msg_buf, _msg_rec, 576*sizeof(unsigned char)); // print #if DEBUG g2412p_print(_q); #endif #if 1 // iterate // while... for (i=0; i<30; i++) { int rc = g2412p_iterate(_q); if (rc == 0) break; } printf("steps: %u\n", i); #endif // print #if DEBUG g2412p_print(_q); #endif // copy resulting output #if 0 for (i=0; i<12; i++) memmove(&_msg_dec[24*i], &_q->msg_buf[12*i], 12*sizeof(unsigned char)); #else unsigned int r; unsigned int c; unsigned int n = 0; for (r=0; r<12; r++) { for (c=0; c<12; c++) { _msg_dec[n++] = _q->msg_buf[24*r+c] > LIQUID_SOFTBIT_ERASURE ? 1 : 0; } } #endif } // run single iteration int g2412p_iterate(g2412p _q) { unsigned int i; int rc = 0; // decode columns for (i=0; i<24; i++) { g2412p_load_col (_q, i); rc += g2412p_step (_q ); g2412p_save_col (_q, i); } // decode rows for (i=0; i<12; i++) { g2412p_load_row (_q, i); rc += g2412p_step (_q ); g2412p_save_row (_q, i); } return rc; } // int g2412p_step(g2412p _q) { // TODO: determine if parity check passed // run hard-decision decoding unsigned int sym_rec = 0; unsigned int i; for (i=0; i<24; i++) { sym_rec <<= 1; sym_rec |= _q->reg0[i] > 127 ? 1 : 0; } // flip... //printf(" 0x%.6x > ", sym_rec); sym_rec = ((sym_rec >> 12) & 0xfff) | ((sym_rec << 12) & 0xfff000); // decode to 12-bit symbol unsigned int sym_dec = fec_golay2412_decode_symbol(sym_rec); // re-encode 24-bit symbol unsigned int sym_enc = fec_golay2412_encode_symbol(sym_dec); int rc = (sym_rec == sym_enc) ? 0 : 1; // flip... sym_enc = ((sym_enc >> 12) & 0xfff) | ((sym_enc << 12) & 0xfff000); //printf("0x%.6x\n", sym_enc); // update register // TODO: this is the crux of the algorithm and should be adjusted to // produce maximum performance. float alpha = 0.9f; // percentage of old value to retain float beta = 1.0f - alpha; // percentage of new value to retain for (i=0; i<24; i++) { //int v = (int)(_q->reg0[i]) + ((sym_enc >> i) & 1 ? 16 : -16); int p = (sym_enc >> (24-i-1)) & 1 ? LIQUID_SOFTBIT_1 : LIQUID_SOFTBIT_0; int v = ((int)(alpha*_q->reg0[i]) + beta*p); if (v < 0) _q->reg0[i] = 0; else if (v > 255) _q->reg0[i] = 255; else _q->reg0[i] = (unsigned char)v; } return rc; } // load 24-bit row into register void g2412p_load_row(g2412p _q, unsigned int _row) { //memmove(_q->reg0, &_q->msg_buf[_row*24], 24*sizeof(unsigned char)); unsigned int c; for (c=0; c<24; c++) _q->reg0[c] = _q->msg_buf[24*_row + c]; } void g2412p_save_row(g2412p _q, unsigned int _row) { //memmove(&_q->msg_buf[_row*24], _q->reg0, 24*sizeof(unsigned char)); unsigned int c; for (c=0; c<24; c++) _q->msg_buf[24*_row + c] = _q->reg0[c]; } void g2412p_load_col(g2412p _q, unsigned int _col) { unsigned int r; for (r=0; r<24; r++) _q->reg0[r] = _q->msg_buf[24*r + _col]; } void g2412p_save_col(g2412p _q, unsigned int _col) { unsigned int r; for (r=0; r<24; r++) _q->msg_buf[24*r + _col] = _q->reg0[r]; } // pack 24-value soft-bit message into integer unsigned int g2412p_pack_symbol(unsigned char * _msg_soft) { unsigned int i; unsigned int sym = 0; for (i=0; i<24; i++) { sym <<= 1; sym |= liquid_hard_decision(_msg_soft[i]); } return sym; } // unpack 24-bit integer into soft array void g2412p_unpack_symbol(unsigned int _msg_hard, unsigned char * _msg_soft) { unsigned int i; for (i=0; i<24; i++) { _msg_soft[i] = _msg_hard & 1 ? LIQUID_SOFTBIT_1 : LIQUID_SOFTBIT_0; _msg_hard >>= 1; } } unsigned int liquid_hard_decision(unsigned char _soft_bit) { return _soft_bit > LIQUID_SOFTBIT_ERASURE ? LIQUID_SOFTBIT_1 : LIQUID_SOFTBIT_0; } liquid-dsp-1.3.1/sandbox/fec_golay2412_test.c000066400000000000000000000252141317124540100206730ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Golay(24,12) code test // #include #include #include #include "liquid.internal.h" #define DEBUG_FEC_GOLAY 1 // P matrix [12 x 12] unsigned char P[144] = { 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}; // generator matrix [12 x 24] unsigned char G[288]; void golay_init_G(); // parity check matrix [12 x 24] unsigned char H[288]; void golay_init_H(); unsigned int fec_golay2412_encode_symbol(unsigned int _sym_dec) { // validate input if (_sym_dec >= (1<<11)) { fprintf(stderr,"error, fec_golay2412_encode(), input symbol too large\n"); exit(1); } return 0; } unsigned int fec_golay2412_decode_symbol(unsigned int _sym_enc) { // validate input if (_sym_enc >= (1<<15)) { fprintf(stderr,"error, fec_golay2412_decode(), input symbol too large\n"); exit(1); } return 0; } void print_bitstring(unsigned int _x, unsigned int _n) { unsigned int i; for (i=0; i<_n; i++) printf("%1u", (_x >> (_n-i-1)) & 1); } void matrix2_print(unsigned char * _x, unsigned int _m, unsigned int _n) { unsigned int i; unsigned int j; for (i=0; i<_m; i++) { printf(" "); for (j=0; j<_n; j++) printf("%c ", _x[i*_n+j] ? '1' : '0'); printf("\n"); } } // multiply two matrices modulo 2 void matrix2_mul(unsigned char * _x, unsigned int _mx, unsigned int _nx, unsigned char * _y, unsigned int _my, unsigned int _ny, unsigned char * _z, unsigned int _mz, unsigned int _nz) { // ensure lengths are valid if (_mz != _mx || _nz != _ny || _nx != _my ) { fprintf(stderr,"error: matrix2_mul(), invalid dimensions\n"); exit(1); } unsigned int r, c, i; for (r=0; r<_mz; r++) { for (c=0; c<_nz; c++) { unsigned int sum = 0; for (i=0; i<_nx; i++) { sum += matrix_access(_x,_mx,_nx,r,i) * matrix_access(_y,_my,_ny,i,c); } matrix_access(_z,_mz,_nz,r,c) = sum % 2; } } } unsigned int vector_weight(unsigned char * _x, unsigned int _n) { unsigned int w = 0; unsigned int i; for (i=0; i<_n; i++) w += _x[i] ? 1 : 0; return w; } int main(int argc, char*argv[]) { // initialize matrices golay_init_G(); golay_init_H(); printf("P:\n"); matrix2_print(P,12,12); printf("G:\n"); matrix2_print(G,12,24); printf("H:\n"); matrix2_print(H,12,24); unsigned int i; // error vector unsigned char err[24] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}; // arrays unsigned char m[12]; // original message unsigned char v[24]; // encoded/transmitted message unsigned char e[24]; // error vector unsigned char r[24]; // received vector unsigned char s[12]; // syndrome vector unsigned char e_hat[24];// estimated error vector unsigned char v_hat[24];// estimated transmitted message unsigned char m_hat[24];// estimated original message // compute (random) original message for (i=0; i<12; i++) m[i] = rand() % 2; printf("m (original message):\n"); matrix2_print(m,1,12); // compute encoded/transmitted message: v = m*G matrix2_mul(m,1,12, G,12,24, v,1,24); printf("v (encoded/transmitted message):\n"); matrix2_print(v,1,24); #if 0 // generate random error vector unsigned int e0 = rand() % 24; for (i=0; i<24; i++) e[i] = (i==e0) ? 1 : 0; #else // use pre-determined error vector for (i=0; i<24; i++) e[i] = err[i]; #endif printf("e (error vector):\n"); matrix2_print(e,1,24); #if 0 // from Lin & Costello, p. 128, // error locations at indices: 3, 10, 23 r[ 0] = 1; r[ 1] = 0; r[ 2] = 0; r[ 3] = 0; r[ 4] = 0; r[ 5] = 0; r[ 6] = 1; r[ 7] = 1; r[ 8] = 0; r[ 9] = 1; r[10] = 0; r[11] = 0; r[12] = 1; r[13] = 1; r[14] = 0; r[15] = 0; r[16] = 0; r[17] = 0; r[18] = 0; r[19] = 0; r[20] = 0; r[21] = 0; r[22] = 0; r[23] = 1; #else // compute received vector: r = v + e for (i=0; i<24; i++) r[i] = (v[i] + e[i]) % 2; printf("r (received vector):\n"); matrix2_print(r,1,24); #endif // compute syndrome vector, s = r*H^T = ( H*r^T )^T matrix2_mul(H,12,24, r,24,1, s,12,1); printf("s (syndrome vector):\n"); matrix2_print(s,1,12); // compute weight of s unsigned int ws = vector_weight(s,12); printf("w(s) = %u\n", ws); // step 2: if (ws <= 3) { printf(" w(s) <= 3: estimating error vector as [s, 0(12)]\n"); // set e_hat = [s 0(12)] for (i=0; i<24; i++) e_hat[i] = i < 12 ? s[i] : 0; } else { // step 3: search for p[i] s.t. w(s+p[i]) <= 2 printf(" searching for w(s + p_i) <= 2...\n"); unsigned int j; unsigned char spj[12]; int flag3 = 0; unsigned int p3_index = 0; for (j=0; j<12; j++) { for (i=0; i<12; i++) spj[i] = (s[i] + P[12*j+i]) % 2; unsigned int wj = vector_weight(spj,12); printf(" w(s + p[%2u]) = %2u%s\n", j, wj, wj <= 2 ? " *" : ""); if (wj <= 2) { flag3 = 1; p3_index = j; break; } } if (flag3) { // vector found! printf(" w(s + p[%2u]) <= 2: estimating error vector as [s+p[%2u],u[%2u]]\n", p3_index, p3_index, p3_index); for (i=0; i<12; i++) e_hat[i] = (s[i] + P[12*p3_index + i]) % 2; for (i=0; i<12; i++) e_hat[i+12] = (i == p3_index) ? 1 : 0; } else { // step 4: compute s*P unsigned char sP[12]; matrix2_mul(s,1,12, P,12,12, sP,1,12); printf("s*P:\n"); matrix2_print(sP,1,12); unsigned int wsP = vector_weight(sP,12); printf("w(s*P) = %u\n", wsP); if (wsP == 2 || wsP == 3) { // step 5: set e = [0, s*P] printf(" w(s*P) in [2,3]: estimating error vector as [0(12), s*P]\n"); for (i=0; i<24; i++) e_hat[i] = i < 12 ? 0 : sP[i-12]; } else { // step 6: search for p[i] s.t. w(s*P + p[i]) == 2... printf(" searching for w(s*P + p_i) == 2...\n"); unsigned int j; unsigned char sPpj[12]; int flag6 = 0; unsigned int p6_index = 0; for (j=0; j<12; j++) { for (i=0; i<12; i++) sPpj[i] = (sP[i] + P[12*j + i]) % 2; unsigned int wj = vector_weight(sPpj,12); printf(" w(s*P + p[%2u]) = %2u%s\n", j, wj, wj == 2 ? " *" : ""); if (wj == 2) { flag6 = 1; p6_index = j; break; } } if (flag6) { // vector found! printf(" w(s*P + p[%2u]) == 2: estimating error vector as [u[%2u],s*P+p[%2u]]\n", p6_index, p6_index, p6_index); for (i=0; i<12; i++) e_hat[i] = (i == p6_index) ? 1 : 0; for (i=0; i<12; i++) e_hat[i+12] = (sP[i] + P[12*p6_index+i]) % 2; } else { // step 7: decoding error printf(" **** decoding error\n"); } } } } // step 8: compute estimated transmitted message: v_hat = r + e_hat printf("e-hat (estimated error vector):\n"); matrix2_print(e_hat,1,24); for (i=0; i<24; i++) v_hat[i] = (r[i] + e_hat[i]) % 2; printf("v-hat (estimated transmitted vector):\n"); matrix2_print(v_hat,1,24); matrix2_print(v, 1,24); // compute errors between v, v_hat unsigned int num_errors_v = 0; for (i=0; i<24; i++) num_errors_v += v[i] == v_hat[i] ? 0 : 1; printf("\n"); printf("decoding errors (encoded) : %2u / 24\n", num_errors_v); // compute estimated original message: (last 12 bits of encoded message) for (i=0; i<12; i++) m_hat[i] = v_hat[i+12]; // compute errors between m, m_hat unsigned int num_errors_m = 0; for (i=0; i<12; i++) num_errors_m += m[i] == m_hat[i] ? 0 : 1; printf("decoding errors (original) : %2u / 12\n", num_errors_m); return 0; } // initialize generator matrix as G = [P I_12] void golay_init_G() { unsigned int i; unsigned int j; for (i=0; i<12; i++) { for (j=0; j<12; j++) G[i*24 + j] = P[i*12 + j]; for (j=0; j<12; j++) G[i*24 + j + 12] = (i==j) ? 1 : 0; } } // initialize generator matrix as H = [I_12 P] void golay_init_H() { unsigned int i; unsigned int j; for (i=0; i<12; i++) { for (j=0; j<12; j++) H[i*24+j] = (i==j) ? 1 : 0; for (j=0; j<12; j++) H[i*24 + j + 12] = P[i*12 + j]; } } liquid-dsp-1.3.1/sandbox/fec_golay_test.c000066400000000000000000000164441317124540100203670ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Golay(24,12) code test // #include #include #include #include "liquid.internal.h" #define DEBUG_FEC_GOLAY 1 // P matrix [12 x 12] unsigned int P[12] = { 0x08ed, 0x01db, 0x03b5, 0x0769, 0x0ed1, 0x0da3, 0x0b47, 0x068f, 0x0d1d, 0x0a3b, 0x0477, 0x0ffe}; #if 0 // generator matrix [12 x 24] unsigned int G[12] = { 0x008ed800, 0x001db400, 0x003b5200, 0x00769100, 0x00ed1080, 0x00da3040, 0x00b47020, 0x0068f010, 0x00d1d008, 0x00a3b004, 0x00477002, 0x00ffe001}; #endif // generator matrix transposed [24 x 12] unsigned int Gt[24] = { 0x08ed, 0x01db, 0x03b5, 0x0769, 0x0ed1, 0x0da3, 0x0b47, 0x068f, 0x0d1d, 0x0a3b, 0x0477, 0x0ffe, 0x0800, 0x0400, 0x0200, 0x0100, 0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001}; // parity check matrix [12 x 24] unsigned int H[12] = { 0x008008ed, 0x004001db, 0x002003b5, 0x00100769, 0x00080ed1, 0x00040da3, 0x00020b47, 0x0001068f, 0x00008d1d, 0x00004a3b, 0x00002477, 0x00001ffe}; void print_bitstring(unsigned int _x, unsigned int _n) { unsigned int i; printf(" "); for (i=0; i<_n; i++) printf("%1u ", (_x >> (_n-i-1)) & 1); printf("\n"); } int main(int argc, char*argv[]) { unsigned int i; // error vector // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 unsigned int err = 0x00000d00; // original message // 1 0 1 1 1 1 0 0 1 1 0 1 unsigned int m = 0x0bcd; // derived values unsigned int v; // encoded/transmitted message unsigned int e; // error vector unsigned int r; // received vector unsigned int s; // syndrome vector unsigned int e_hat; // estimated error vector unsigned int v_hat; // estimated transmitted message unsigned int m_hat; // estimated original message // original message printf("m (original message):\n"); print_bitstring(m,12); // compute encoded/transmitted message: v = m*G v = 0; for (i=0; i<24; i++) { v <<= 1; v |= liquid_count_ones_mod2(Gt[i] & m); } printf("v (encoded/transmitted message):\n"); print_bitstring(v,24); // use pre-determined error vector e = err; printf("e (error vector):\n"); print_bitstring(e,24); // compute received vector: r = v + e r = v ^ e; printf("r (received vector):\n"); print_bitstring(r,24); // compute syndrome vector, s = r*H^T = ( H*r^T )^T s = 0; for (i=0; i<12; i++) { s <<= 1; s |= liquid_count_ones_mod2(H[i] & r); } printf("s (syndrome vector):\n"); print_bitstring(s,12); // compute weight of s unsigned int ws = liquid_count_ones(s); printf("w(s) = %u\n", ws); // step 2: e_hat = 0; if (ws <= 3) { printf(" w(s) <= 3: estimating error vector as [s, 0(12)]\n"); // set e_hat = [s 0(12)] e_hat = s << 12; } else { // step 3: search for p[i] s.t. w(s+p[i]) <= 2 printf(" searching for w(s + p_i) <= 2...\n"); unsigned int j; unsigned int spj; int flag3 = 0; unsigned int p3_index = 0; for (j=0; j<12; j++) { spj = s ^ P[j]; unsigned int wj = liquid_count_ones(spj); printf(" w(s + p[%2u]) = %2u%s\n", j, wj, wj <= 2 ? " *" : ""); if (wj <= 2) { flag3 = 1; p3_index = j; break; } } if (flag3) { // vector found! printf(" w(s + p[%2u]) <= 2: estimating error vector as [s+p[%2u],u[%2u]]\n", p3_index, p3_index, p3_index); // NOTE : uj = 1 << (12-j-1) e_hat = ((s ^ P[p3_index]) << 12) | (1 << (11-p3_index)); } else { // step 4: compute s*P unsigned int sP = 0; for (i=0; i<12; i++) { sP <<= 1; sP |= liquid_count_ones_mod2(s & P[i]); } printf("s*P:\n"); print_bitstring(sP,12); unsigned int wsP = liquid_count_ones(sP); printf("w(s*P) = %u\n", wsP); if (wsP == 2 || wsP == 3) { // step 5: set e = [0, s*P] printf(" w(s*P) in [2,3]: estimating error vector as [0(12), s*P]\n"); e_hat = sP; } else { // step 6: search for p[i] s.t. w(s*P + p[i]) == 2... printf(" searching for w(s*P + p_i) == 2...\n"); unsigned int j; unsigned int sPpj; int flag6 = 0; unsigned int p6_index = 0; for (j=0; j<12; j++) { sPpj = sP ^ P[j]; unsigned int wj = liquid_count_ones(sPpj); printf(" w(s*P + p[%2u]) = %2u%s\n", j, wj, wj == 2 ? " *" : ""); if (wj == 2) { flag6 = 1; p6_index = j; break; } } if (flag6) { // vector found! printf(" w(s*P + p[%2u]) == 2: estimating error vector as [u[%2u],s*P+p[%2u]]\n", p6_index, p6_index, p6_index); // NOTE : uj = 1 << (12-j-1) // [ uj << 1 2 ] [ sP + p[j] ] e_hat = (1 << (23-p6_index)) | (sP ^ P[p6_index]); } else { // step 7: decoding error printf(" **** decoding error\n"); } } } } // step 8: compute estimated transmitted message: v_hat = r + e_hat printf("e-hat (estimated error vector):\n"); print_bitstring(e_hat,24); v_hat = r ^ e_hat; printf("v-hat (estimated transmitted vector):\n"); print_bitstring(v_hat,24); print_bitstring(v, 24); // compute errors between v, v_hat printf("decoding errors (encoded) : %2u / 24\n", count_bit_errors(v, v_hat)); // compute estimated original message: (last 12 bits of encoded message) m_hat = v_hat & ((1<<12)-1); // compute errors between m, m_hat printf("decoding errors (original) : %2u / 12\n", count_bit_errors(m, m_hat)); return 0; } liquid-dsp-1.3.1/sandbox/fec_hamming128_example.c000066400000000000000000000021771317124540100216010ustar00rootroot00000000000000// // Hamming(12,8) example // #include #include #include "liquid.internal.h" void print_bitstring(unsigned int _x, unsigned int _n) { unsigned int i; for (i=0; i<_n; i++) printf("%1u", (_x >> (_n-i-1)) & 1); } int main(int argc, char*argv[]) { // original symbol unsigned int sym_org = 139; // encoded symbol unsigned int sym_enc = fec_hamming128_encode_symbol(sym_org); // received symbol unsigned int n=7; // index of bit to corrupt unsigned int sym_rec = sym_enc ^ (1<<(12-n)); // decoded symbol unsigned int sym_dec = fec_hamming128_decode_symbol(sym_rec); // print results printf(" sym org : "); print_bitstring(sym_org, 8); printf("\n"); printf(" sym enc : "); print_bitstring(sym_enc, 12); printf("\n"); printf(" sym rec : "); print_bitstring(sym_rec, 12); printf("\n"); printf(" sym dec : "); print_bitstring(sym_dec, 8); printf("\n"); // print number of bit errors printf(" bit errors : %u\n", count_bit_errors(sym_org, sym_dec)); return 0; } liquid-dsp-1.3.1/sandbox/fec_hamming128_gentab.c000066400000000000000000000033011317124540100213740ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // 2/3-rate (12,8) Hamming code encoding table generator // #include #include #include "liquid.internal.h" int main() { unsigned int i; unsigned int c; printf("unsigned short int hamming128_enc_gentab[256] = {\n "); for (i=0; i<256; i++) { // encode symbol c = fec_hamming128_encode_symbol(i); // print result printf("0x%.4x", c); if (i != 255) printf(", "); else printf("};"); if ( ((i+1)%8) == 0) printf("\n "); } printf("\n"); return 0; } liquid-dsp-1.3.1/sandbox/fec_hamming128_test.c000066400000000000000000000067521317124540100211300ustar00rootroot00000000000000// // Hamming(12,8) code test // // Tests syndrome decoding // #include #include #include "liquid.internal.h" void print_bitstring(unsigned int _x, unsigned int _n) { unsigned int i; for (i=0; i<_n; i++) printf("%1u", (_x >> (_n-i-1)) & 1); } unsigned char hamming128_P[4] = { 0xda, // 1101 1010 0xb6, // 1011 0110 0x71, // 0111 0001 0x0f}; // 0000 1111 int main(int argc, char*argv[]) { // ... unsigned int sym_org = 0x21; // original symbol unsigned int sym_enc; // encoded symbol unsigned int e = 0x001; // error vector unsigned int sym_rec; // received symbol unsigned int sym_dec; // decoded symbol unsigned int i; // encode symbol unsigned int p0 = liquid_c_ones[sym_org & hamming128_P[0]] & 0x01; unsigned int p1 = liquid_c_ones[sym_org & hamming128_P[1]] & 0x01; unsigned int p2 = liquid_c_ones[sym_org & hamming128_P[2]] & 0x01; unsigned int p3 = liquid_c_ones[sym_org & hamming128_P[3]] & 0x01; unsigned int parity = (p0 << 3) | (p1 << 2) | (p2 << 1) | (p3 << 0); sym_enc = (parity << 8) | sym_org; // received symbol (add error) sym_rec = sym_enc ^ e; // // decode symbol // sym_dec = sym_rec & 0xff; unsigned int e_hat = 0x000; // compute syndrome vector; s = r*H^T = ( H*r^T )^T unsigned int s = 0x0; // 4 bits resolution for (i=0; i<4; i++) { s <<= 1; unsigned int p = ( (sym_rec & (1<<(12-i-1))) ? 1 : 0 ) + liquid_c_ones[sym_rec & hamming128_P[i]]; s |= p & 0x01; } // compute weight of s unsigned int ws = liquid_count_ones(s); printf(" syndrome : "); print_bitstring(s, 4); printf(" (%u)\n", ws); if (ws == 0) { printf("no errors detected\n"); } else { // estimate error location unsigned int e_test = 0x001; int syndrome_match = 0; // TODO : these can be pre-computed unsigned int n; for (n=0; n<12; n++) { // compute syndrome unsigned int s_hat = 0; for (i=0; i<4; i++) { s_hat <<= 1; unsigned int p = ( (e_test & (1<<(12-i-1))) ? 1 : 0 ) + liquid_c_ones[e_test & hamming128_P[i]]; s_hat |= p & 0x01; } // print results //printf("e_test:"); print_bitstring(e_test, 72); printf(" %2u e = ", n); print_bitstring(e_test,12); printf(" s = "); print_bitstring(s_hat,4); if (s == s_hat) printf(" *"); printf("\n"); if (s == s_hat) { e_hat = e_test; syndrome_match = 1; } // shift e_test e_test <<= 1; } // apply error correction and return if (syndrome_match) sym_dec = (sym_rec ^ e_hat) & 0xff; } // print results printf(" sym org : "); print_bitstring(sym_org, 8); printf("\n"); printf(" sym enc : "); print_bitstring(sym_enc, 12); printf("\n"); printf(" sym rec : "); print_bitstring(sym_rec, 12); printf("\n"); printf(" sym dec : "); print_bitstring(sym_dec, 8); printf("\n"); // print number of bit errors printf(" bit errors : %u\n", count_bit_errors(sym_org, sym_dec)); return 0; } liquid-dsp-1.3.1/sandbox/fec_hamming3126_example.c000066400000000000000000000302061317124540100216540ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Hamming code parity check matrix // // bit position 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 // encoded bits P1 P2 1 P4 2 3 4 P8 5 6 7 8 9 10 11 P16 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 P32 27 28 29 30 31 32 // // parity bit P1 x . x . x . x . x . x . x . x . x . x . x . x . x . x . x . x . // coverage P2 . x x . . x x . . x x . . x x . . x x . . x x . . x x . . x x . // P4 . . . x x x x . . . . x x x x . . . . x x x x . . . . x x x x . // P8 . . . . . . . x x x x x x x x . . . . . . . . x x x x x x x x . // P16 . . . . . . . . . . . . . . . x x x x x x x x x x x x x x x x . // P32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . x #include #include #include #include "liquid.internal.h" #define DEBUG_FEC_HAMMING 1 #if 0 // // (12,8) Hamming code // // parity bit coverage mask for encoder (collapsed version of figure // above, stripping out parity bits P1, P2, P4, P8 and only including // data bits 1:8) // // bit position 3 5 6 7 9 10 11 12 // // parity bit P1 x x . x x . x . = 1101 1010 // coverage P2 x . x x . x x . = 1011 0110 // P4 . x x x . . . x = 0111 0001 // P8 . . . . x x x x = 0000 1111 #define HAMMING_M1 0xda // 1101 1010 #define HAMMING_M2 0xb6 // 1011 0110 #define HAMMING_M4 0x71 // 0111 0001 #define HAMMING_M8 0x0f // 0000 1111 // parity bit coverage mask for decoder; used to compute syndromes // for decoding a received message (see first figure, above). #define HAMMING_S1 0x0aaa // .... 1010 1010 1010 #define HAMMING_S2 0x0666 // .... 0110 0110 0110 #define HAMMING_S4 0x01e1 // .... 0001 1110 0001 #define HAMMING_S8 0x001f // .... 0000 0001 1111 #endif #if 0 // // (15,11) Hamming code // // parity bit coverage mask for encoder (collapsed version of figure // above, stripping out parity bits P1, P2, P4, P8 and only including // data bits 1:11) // // parity bit P1 x x . x x . x . x . x = .110 1101 0101 // coverage P2 x . x x . x x . . x x = .101 1011 0011 // P4 . x x x . . . x x x x = .011 1000 1111 // P8 . . . . x x x x x x x = .000 0111 1111 #define HAMMING_M1 0x0d65 // .110 1101 0101 #define HAMMING_M2 0x05b3 // .101 1011 0011 #define HAMMING_M4 0x038f // .011 1000 1111 #define HAMMING_M8 0x007f // .000 0111 1111 // parity bit coverage mask for decoder; used to compute syndromes // for decoding a received message (see first figure, above). #define HAMMING_S1 0x5555 // .101 0101 0101 0101 #define HAMMING_S2 0x3333 // .011 0011 0011 0011 #define HAMMING_S4 0x0f0f // .000 1111 0000 1111 #define HAMMING_S8 0x00ff // .000 0000 1111 1111 #endif // // (31,26) Hamming code // // parity bit coverage mask for encoder (collapsed version of figure // above, stripping out parity bits P1, P2, P4, P8, P16 and only including // data bits 1:26) // // bit position 3 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 // * * * * * * // parity bit P1 x x . x x . x . x . x x . x . x . x . x . x . x . x = ..11 0110 1010 1101 0101 0101 0101 // coverage P2 x . x x . x x . . x x . x x . . x x . . x x . . x x = ..10 1101 1001 1011 0011 0011 0011 // P4 . x x x . . . x x x x . . . x x x x . . . . x x x x = ..01 1100 0111 1000 1111 0000 1111 // P8 . . . . x x x x x x x . . . . . . . x x x x x x x x = ..00 0011 1111 1000 0000 1111 1111 // P16 . . . . . . . . . . . x x x x x x x x x x x x x x x = ..00 0000 0000 0111 1111 1111 1111 #define HAMMING_M1 0x036AD555 // ..11 0110 1010 1101 0101 0101 0101 #define HAMMING_M2 0x02D9B333 // ..10 1101 1001 1011 0011 0011 0011 #define HAMMING_M4 0x01C78F0F // ..01 1100 0111 1000 1111 0000 1111 #define HAMMING_M8 0x003F80FF // ..00 0011 1111 1000 0000 1111 1111 #define HAMMING_M16 0x00007FFF // ..00 0000 0000 0111 1111 1111 1111 // bit position 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 // * * * * * * * // parity bit P1 x . x . x . x . x . x . x . x . x . x . x . x . x . x . x . x = .101 0101 0101 0101 0101 0101 0101 0101 // coverage P2 . x x . . x x . . x x . . x x . . x x . . x x . . x x . . x x = .011 0011 0011 0011 0011 0011 0011 0011 // P4 . . . x x x x . . . . x x x x . . . . x x x x . . . . x x x x = .000 1111 0000 1111 0000 1111 0000 1111 // P8 . . . . . . . x x x x x x x x . . . . . . . . x x x x x x x x = .000 0000 1111 1111 0000 0000 1111 1111 // P16 . . . . . . . . . . . . . . . x x x x x x x x x x x x x x x x = .000 0000 0000 0000 1111 1111 1111 1111 // // parity bit coverage mask for decoder; used to compute syndromes // for decoding a received message (see figure, above). #define HAMMING_S1 0x55555555 // .101 0101 0101 0101 0101 0101 0101 0101 #define HAMMING_S2 0x33333333 // .011 0011 0011 0011 0011 0011 0011 0011 #define HAMMING_S4 0x0f0f0f0f // .000 1111 0000 1111 0000 1111 0000 1111 #define HAMMING_S8 0x00ff00ff // .000 0000 1111 1111 0000 0000 1111 1111 #define HAMMING_S16 0x0000ffff // .000 0000 0000 0000 1111 1111 1111 1111 unsigned int fec_hamming_encode_symbol(unsigned int _sym_dec) { // validate input if (_sym_dec >= (1<<26)) { fprintf(stderr,"error, fec_hamming_encode(), input symbol too large\n"); exit(1); } // compute parity bits unsigned int p1 = liquid_bdotprod_uint32(_sym_dec, HAMMING_M1); unsigned int p2 = liquid_bdotprod_uint32(_sym_dec, HAMMING_M2); unsigned int p4 = liquid_bdotprod_uint32(_sym_dec, HAMMING_M4); unsigned int p8 = liquid_bdotprod_uint32(_sym_dec, HAMMING_M8); unsigned int p16 = liquid_bdotprod_uint32(_sym_dec, HAMMING_M16); #if DEBUG_FEC_HAMMING printf("parity bits (p1,p2,p4,p8,p16) : (%1u,%1u,%1u,%1u,%1u)\n", p1, p2, p4, p8, p16); #endif // encode symbol by inserting parity bits with data bits to // make a 31-bit symbol unsigned int sym_enc = ((_sym_dec & 0x00007fff) << 0) | // ..00 0000 0000 0111 1111 1111 1111 ((_sym_dec & 0x003F8000) << 1) | // ..00 0011 1111 1000 0000 0000 0000 ((_sym_dec & 0x01C00000) << 2) | // ..01 1100 0000 0000 0000 0000 0000 ((_sym_dec & 0x02000000) << 3) | // ..10 0000 0000 0000 0000 0000 0000 ( p1 << 30 ) | // 30 = 31 - 1 (position of P1) ( p2 << 29 ) | // 29 = 31 - 2 (position of P2) ( p4 << 27 ) | // 27 = 31 - 4 (position of P4) ( p8 << 23 ) | // 23 = 31 - 8 (position of P8) ( p16 << 15 ); // 15 = 31 - 16 (position of P16) return sym_enc; } unsigned int fec_hamming_decode_symbol(unsigned int _sym_enc) { // validate input if (_sym_enc >= (1<<31)) { fprintf(stderr,"error, fec_hamming_decode(), input symbol too large\n"); exit(1); } // compute syndrome bits unsigned int s1 = liquid_bdotprod_uint32(_sym_enc, HAMMING_S1); unsigned int s2 = liquid_bdotprod_uint32(_sym_enc, HAMMING_S2); unsigned int s4 = liquid_bdotprod_uint32(_sym_enc, HAMMING_S4); unsigned int s8 = liquid_bdotprod_uint32(_sym_enc, HAMMING_S8); unsigned int s16 = liquid_bdotprod_uint32(_sym_enc, HAMMING_S16); // index unsigned int z = (s16<<4) | (s8<<3) | (s4<<2) | (s2<<1) | s1; #if DEBUG_FEC_HAMMING printf("syndrome bits (s1,s2,s4,s8,16) : (%1u,%1u,%1u,%1u,%1u)\n", s1, s2, s4, s8, s16); printf("syndrome z : %u\n", z); #endif // flip bit at this position if (z) { if (z > 31) { // if this happens there are likely too many errors // to correct; just pass without trying to do anything fprintf(stderr,"warning, fec_hamming_decode_symbol(), syndrome index exceeds maximum\n"); } else { //printf("error detected!\n"); _sym_enc ^= 1 << (31-z); } } // strip data bits from encoded symbol with parity bits unsigned int sym_dec = ((_sym_enc & 0x00007fff) ) | // .000 0000 0000 0000 0111 1111 1111 1111 ((_sym_enc & 0x007f0000) >> 1) | // .000 0000 0111 1111 0000 0000 0000 0000 ((_sym_enc & 0x07000000) >> 2) | // .000 0111 0000 0000 0000 0000 0000 0000 ((_sym_enc & 0x10000000) >> 3); // .001 0000 0000 0000 0000 0000 0000 0000 return sym_dec; } // // Hamming(31,26) example // void print_bitstring(unsigned int _x, unsigned int _n) { unsigned int i; for (i=0; i<_n; i++) printf("%1u", (_x >> (_n-i-1)) & 1); } int main(int argc, char*argv[]) { // original symbol unsigned int sym_org = 28236851; // ..01 1010 1110 1101 1100 0011 0011 // encoded symbol unsigned int sym_enc = fec_hamming_encode_symbol(sym_org); // received symbol unsigned int n=7; // index of bit to corrupt unsigned int sym_rec = sym_enc ^ (1<<(31-n)); // decoded symbol unsigned int sym_dec = fec_hamming_decode_symbol(sym_rec); // print results printf(" sym org : "); print_bitstring(sym_org, 26); printf("\n"); printf(" sym enc : "); print_bitstring(sym_enc, 31); printf("\n"); printf(" sym rec : "); print_bitstring(sym_rec, 31); printf("\n"); printf(" sym dec : "); print_bitstring(sym_dec, 26); printf("\n"); // print number of bit errors printf(" bit errors : %u\n", count_bit_errors(sym_org, sym_dec)); return 0; } liquid-dsp-1.3.1/sandbox/fec_hamming74_gentab.c000066400000000000000000000125221317124540100213210ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // 1/2-rate (7,4) Hamming code table generator // #include #include // generator matrices // encoding matrix #define HAMMING74_G0 0x0d // 1101 #define HAMMING74_G1 0x0b // 1011 #define HAMMING74_G2 0x08 // 1000 #define HAMMING74_G3 0x07 // 0111 #define HAMMING74_G4 0x04 // 0100 #define HAMMING74_G5 0x02 // 0010 #define HAMMING74_G6 0x01 // 0001 // syndrome matrix #define HAMMING74_H0 0x55 // .101 0101 #define HAMMING74_H1 0x33 // .011 0011 #define HAMMING74_H2 0x0f // .000 1111 // decoding matrix #define HAMMING74_R0 0x10 // .001 0000 #define HAMMING74_R1 0x04 // .000 0100 #define HAMMING74_R2 0x02 // .000 0010 #define HAMMING74_R3 0x01 // .000 0001 unsigned int count_ones(unsigned int _x); unsigned int hamming74_enc_symbol(unsigned int _p); unsigned int hamming74_dec_symbol(unsigned int _x); int main() { unsigned int n = 16; unsigned int k = 128; // generate encoding table unsigned int enc_gentab[n]; unsigned int p; for (p=0; p>= 1; } return num_ones; } unsigned int hamming74_enc_symbol(unsigned int _p) { unsigned int x0 = count_ones(_p & HAMMING74_G0) % 2; unsigned int x1 = count_ones(_p & HAMMING74_G1) % 2; unsigned int x2 = count_ones(_p & HAMMING74_G2) % 2; unsigned int x3 = count_ones(_p & HAMMING74_G3) % 2; unsigned int x4 = count_ones(_p & HAMMING74_G4) % 2; unsigned int x5 = count_ones(_p & HAMMING74_G5) % 2; unsigned int x6 = count_ones(_p & HAMMING74_G6) % 2; unsigned int x = (x0 << 6) | (x1 << 5) | (x2 << 4) | (x3 << 3) | (x4 << 2) | (x5 << 1) | (x6 ); return x; } unsigned int hamming74_dec_symbol(unsigned int _r) { // compute syndromes unsigned int z0 = count_ones(_r & HAMMING74_H0) % 2; unsigned int z1 = count_ones(_r & HAMMING74_H1) % 2; unsigned int z2 = count_ones(_r & HAMMING74_H2) % 2; unsigned int z = (z0 << 0) | (z1 << 1) | (z2 << 2); unsigned int r_hat = _r; if (z) { // error detected: flip appropriate bit of // received symbol r_hat ^= 1 << (7-z); } // decode unsigned int p0 = count_ones(r_hat & HAMMING74_R0) % 2; unsigned int p1 = count_ones(r_hat & HAMMING74_R1) % 2; unsigned int p2 = count_ones(r_hat & HAMMING74_R2) % 2; unsigned int p3 = count_ones(r_hat & HAMMING74_R3) % 2; unsigned int p = (p0 << 3) | (p1 << 2) | (p2 << 1) | (p3 << 0); return p; } liquid-dsp-1.3.1/sandbox/fec_hamming84_gentab.c000066400000000000000000000131751317124540100213270ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // 1/2-rate (8,4) Hamming code table generator // #include #include // generator matrices // encoding matrix #define HAMMING84_G0 0x0d // 1101 #define HAMMING84_G1 0x0b // 1011 #define HAMMING84_G2 0x08 // 1000 #define HAMMING84_G3 0x07 // 0111 #define HAMMING84_G4 0x04 // 0100 #define HAMMING84_G5 0x02 // 0010 #define HAMMING84_G6 0x01 // 0001 #define HAMMING84_G7 0x0e // 1110 // syndrome matrix #define HAMMING84_H0 0xaa // 1010 1010 #define HAMMING84_H1 0x66 // 0110 0110 #define HAMMING84_H2 0x1e // 0001 1110 #define HAMMING84_H3 0xff // 1111 1111 // decoding matrix #define HAMMING84_R0 0x20 // 0010 0000 #define HAMMING84_R1 0x08 // 0000 1000 #define HAMMING84_R2 0x04 // 0000 0100 #define HAMMING84_R3 0x02 // 0000 0010 unsigned int count_ones(unsigned int _x); unsigned int hamming84_enc_symbol(unsigned int _p); unsigned int hamming84_dec_symbol(unsigned int _x); int main() { unsigned int n = 16; unsigned int k = 256; // generate encoding table unsigned int enc_gentab[n]; unsigned int p; for (p=0; p>= 1; } return num_ones; } unsigned int hamming84_enc_symbol(unsigned int _p) { unsigned int x0 = count_ones(_p & HAMMING84_G0) % 2; unsigned int x1 = count_ones(_p & HAMMING84_G1) % 2; unsigned int x2 = count_ones(_p & HAMMING84_G2) % 2; unsigned int x3 = count_ones(_p & HAMMING84_G3) % 2; unsigned int x4 = count_ones(_p & HAMMING84_G4) % 2; unsigned int x5 = count_ones(_p & HAMMING84_G5) % 2; unsigned int x6 = count_ones(_p & HAMMING84_G6) % 2; unsigned int x7 = count_ones(_p & HAMMING84_G7) % 2; unsigned int x = (x0 << 7) | (x1 << 6) | (x2 << 5) | (x3 << 4) | (x4 << 3) | (x5 << 2) | (x6 << 1) | (x7 ); return x; } unsigned int hamming84_dec_symbol(unsigned int _r) { // compute syndromes unsigned int z0 = count_ones(_r & HAMMING84_H0) % 2; unsigned int z1 = count_ones(_r & HAMMING84_H1) % 2; unsigned int z2 = count_ones(_r & HAMMING84_H2) % 2; unsigned int z = (z0 << 0) | (z1 << 1) | (z2 << 2); unsigned int r_hat = _r; if (z) { // error detected: flip appropriate bit of // received symbol r_hat ^= 1 << (8-z); } #if 0 // check extra parity bit unsigned int z3 = count_ones(r_hat & HAMMING84_H3) % 2; if (z3) printf("decoding error!\n"); #endif // decode unsigned int p0 = count_ones(r_hat & HAMMING84_R0) % 2; unsigned int p1 = count_ones(r_hat & HAMMING84_R1) % 2; unsigned int p2 = count_ones(r_hat & HAMMING84_R2) % 2; unsigned int p3 = count_ones(r_hat & HAMMING84_R3) % 2; unsigned int p = (p0 << 3) | (p1 << 2) | (p2 << 1) | (p3 << 0); return p; } liquid-dsp-1.3.1/sandbox/fec_hamming_test.c000066400000000000000000000205561317124540100206730ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Hamming code parity check matrix // // bit position 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 // encoded bits P1 P2 1 P4 2 3 4 P8 5 6 7 8 9 10 11 P16 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 P32 27 28 29 30 31 32 // // parity bit P1 x . x . x . x . x . x . x . x . x . x . x . x . x . x . x . x . // coverage P2 . x x . . x x . . x x . . x x . . x x . . x x . . x x . . x x . // P4 . . . x x x x . . . . x x x x . . . . x x x x . . . . x x x x . // P8 . . . . . . . x x x x x x x x . . . . . . . . x x x x x x x x . // P16 . . . . . . . . . . . . . . . x x x x x x x x x x x x x x x x . // P32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . x #include #include #include #include "liquid.internal.h" #define DEBUG_FEC_HAMMING 1 #if 0 // parity bit coverage mask for encoder (collapsed version of figure // above, stripping out parity bits P1, P2, P4, P8 and only including // data bits 1:8) // // bit position 3 5 6 7 9 10 11 12 // // parity bit P1 x x . x x . x . = 1101 1010 // coverage P2 x . x x . x x . = 1011 0110 // P4 . x x x . . . x = 0111 0001 // P8 . . . . x x x x = 0000 1111 #define HAMMING_M1 0xda // 1101 1010 #define HAMMING_M2 0xb6 // 1011 0110 #define HAMMING_M4 0x71 // 0111 0001 #define HAMMING_M8 0x0f // 0000 1111 // parity bit coverage mask for decoder; used to compute syndromes // for decoding a received message (see first figure, above). #define HAMMING_S1 0x0aaa // .... 1010 1010 1010 #define HAMMING_S2 0x0666 // .... 0110 0110 0110 #define HAMMING_S4 0x01e1 // .... 0001 1110 0001 #define HAMMING_S8 0x001f // .... 0000 0001 1111 #endif // // Hamming(15,11) // // parity bit coverage mask for encoder (collapsed version of figure // above, stripping out parity bits P1, P2, P4, P8 and only including // data bits 1:11) // // parity bit P1 x x . x x . x . x . x = .110 1101 0101 // coverage P2 x . x x . x x . . x x = .101 1011 0011 // P4 . x x x . . . x x x x = .011 1000 1111 // P8 . . . . x x x x x x x = .000 0111 1111 #define HAMMING_M1 0x06d5 // .110 1101 0101 #define HAMMING_M2 0x05b3 // .101 1011 0011 #define HAMMING_M4 0x038f // .011 1000 1111 #define HAMMING_M8 0x007f // .000 0111 1111 // parity bit coverage mask for decoder; used to compute syndromes // for decoding a received message (see first figure, above). #define HAMMING_S1 0x5555 // .101 0101 0101 0101 #define HAMMING_S2 0x3333 // .011 0011 0011 0011 #define HAMMING_S4 0x0f0f // .000 1111 0000 1111 #define HAMMING_S8 0x00ff // .000 0000 1111 1111 unsigned int fec_hamming_encode_symbol(unsigned int _sym_dec) { // validate input if (_sym_dec >= (1<<11)) { fprintf(stderr,"error, fec_hamming_encode(), input symbol too large\n"); exit(1); } // compute parity bits unsigned int p1 = liquid_bdotprod_uint16(_sym_dec, HAMMING_M1); unsigned int p2 = liquid_bdotprod_uint16(_sym_dec, HAMMING_M2); unsigned int p4 = liquid_bdotprod_uint16(_sym_dec, HAMMING_M4); unsigned int p8 = liquid_bdotprod_uint16(_sym_dec, HAMMING_M8); #if DEBUG_FEC_HAMMING printf("parity bits (p1,p2,p4,p8) : (%1u,%1u,%1u,%1u)\n", p1, p2, p4, p8); #endif // encode symbol by inserting parity bits with data bits to // make a 15-bit symbol unsigned int sym_enc = ((_sym_dec & 0x007f) << 0) | ((_sym_dec & 0x0380) << 1) | ((_sym_dec & 0x0400) << 2) | ( p1 << 14 ) | ( p2 << 13 ) | ( p4 << 11 ) | ( p8 << 7 ); return sym_enc; } unsigned int fec_hamming_decode_symbol(unsigned int _sym_enc) { // validate input if (_sym_enc >= (1<<15)) { fprintf(stderr,"error, fec_hamming_decode(), input symbol too large\n"); exit(1); } // compute syndrome bits unsigned int s1 = liquid_bdotprod_uint16(_sym_enc, HAMMING_S1); unsigned int s2 = liquid_bdotprod_uint16(_sym_enc, HAMMING_S2); unsigned int s4 = liquid_bdotprod_uint16(_sym_enc, HAMMING_S4); unsigned int s8 = liquid_bdotprod_uint16(_sym_enc, HAMMING_S8); // index unsigned int z = (s8<<3) | (s4<<2) | (s2<<1) | s1; #if DEBUG_FEC_HAMMING printf("syndrome bits (s1,s2,s4,s8) : (%1u,%1u,%1u,%1u)\n", s1, s2, s4, s8); printf("syndrome z : %u\n", z); #endif // flip bit at this position if (z) { if (z > 15) { // if this happens there are likely too many errors // to correct; just pass without trying to do anything fprintf(stderr,"warning, fec_hamming_decode_symbol(), syndrome index exceeds maximum\n"); } else { //printf("error detected!\n"); _sym_enc ^= 1 << (15-z); } } // strip data bits (x) from encoded symbol with parity bits (.) // symbol: [..x. xxx. xxxx] // 0000 0000 1111 > 0x000f // 0000 1110 0000 > 0x00e0 // 0010 0000 0000 > 0x0200 // // symbol: [ -..x .xxx .xxx xxxx] // -000 0000 0xxx xxxx > 0x007f // -000 0111 0000 0000 > 0x0700 // -001 0000 0000 0000 > 0x1000 unsigned int sym_dec = ((_sym_enc & 0x007f) ) | ((_sym_enc & 0x0700) >> 1) | ((_sym_enc & 0x1000) >> 2); return sym_dec; } // // Hamming(12,8) example // void print_bitstring(unsigned int _x, unsigned int _n) { unsigned int i; for (i=0; i<_n; i++) printf("%1u", (_x >> (_n-i-1)) & 1); } int main(int argc, char*argv[]) { // original symbol unsigned int sym_org = 1377; // 10101100001 // encoded symbol unsigned int sym_enc = fec_hamming_encode_symbol(sym_org); // received symbol unsigned int n=7; // index of bit to corrupt unsigned int sym_rec = sym_enc ^ (1<<(15-n)); // decoded symbol unsigned int sym_dec = fec_hamming_decode_symbol(sym_rec); // print results printf(" sym org : "); print_bitstring(sym_org, 11); printf("\n"); printf(" sym enc : "); print_bitstring(sym_enc, 15); printf("\n"); printf(" sym rec : "); print_bitstring(sym_rec, 15); printf("\n"); printf(" sym dec : "); print_bitstring(sym_dec, 11); printf("\n"); // print number of bit errors printf(" bit errors : %u\n", count_bit_errors(sym_org, sym_dec)); return 0; } liquid-dsp-1.3.1/sandbox/fec_ldpc_test.c000066400000000000000000000111211317124540100201610ustar00rootroot00000000000000// // fec_ldpc_test.c // // Test soft demodulation of LDPC code // #include #include #include #define DEBUG_LDPC_TEST (0) #if DEBUG_LDPC_TEST #include #endif // float phi(float _x) { return -logf(tanhf(_x/2.0f + 1e-12)); } int main(int argc, char*argv[]) { // parity check matrix unsigned char H[32] = { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1}; // transmitted codeword unsigned char c[8] = { 1, 0, 1, 0, 1, 1, 1, 1}; // received message float y[8] = { 0.2, 0.2, -0.9, 0.6, 0.5, -1.1, -0.4, -1.2}; // noise standard deviation float sigma = sqrtf(0.5f); unsigned int max_iterations = 10; unsigned int n = 8; unsigned int m = 4; // internal variables unsigned int num_iterations = 0; float Lq[m*n]; float Lr[m*n]; float Lc[n]; float LQ[n]; unsigned char c_hat[n]; unsigned char parity[m]; unsigned int i; unsigned int j; unsigned int ip; unsigned int jp; float alpha_prod; float phi_sum; int parity_pass; int continue_running = 1; // initialize Lq with log-likelihood values for (i=0; i 0.0f ? 1.0f : -1.0f; float beta = fabsf(Lq[j*n+ip]); phi_sum += phi(beta); alpha_prod *= alpha; } } Lr[j*n+i] = alpha_prod * phi(phi_sum); } } #if DEBUG_LDPC_TEST // print Lq matrixf_print(Lq,m,n); // print Lr matrixf_print(Lr,m,n); #endif // compute next iteration of Lq for (i=0; i #include "liquid.h" int main() { unsigned char s0, s1, s2, r, r_hat; unsigned int errors = 0; for (s0=0; s0<2; s0++) { for (s1=0; s1<2; s1++) { for (s2=0; s2<2; s2++) { r = (s0 + s1 + s2) < 2 ? 0 : 1; //r_hat = (!s0 & s1 & s2) | (s0 & !(!s1 & !s2)); r_hat = (s1 & s2) | (s0 & s1) | (s0 & s2); int error_found = (s0 ^ s1) | (s0 ^ s2) | (s1 ^ s2); errors += r != r_hat; printf("%2u %2u %2u %2u (%2u) %2u\n", s0, s1, s2, r, r_hat, error_found); } } } printf("errors : %u\n", errors); return 0; } liquid-dsp-1.3.1/sandbox/fec_rep5_test.c000066400000000000000000000022761317124540100201250ustar00rootroot00000000000000// // // #include #include "liquid.h" int main() { unsigned char s0, s1, s2, s3, s4, r, r_hat; unsigned int errors = 0; for (s0=0; s0<2; s0++) { for (s1=0; s1<2; s1++) { for (s2=0; s2<2; s2++) { for (s3=0; s3<2; s3++) { for (s4=0; s4<2; s4++) { r = (s0 + s1 + s2 + s3 + s4) < 3 ? 0 : 1; r_hat = (s0 & s1) | (s0 & s2) | (s0 & s3) | (s0 & s4) | (s1 & s2) | (s1 & s3) | (s1 & s4) | (s2 & s3) | (s2 & s4) | (s3 & s4); r_hat = (s0 & s1 & s2) | (s0 & s1 & s3) | (s0 & s1 & s4) | (s0 & s2 & s3) | (s0 & s2 & s4) | (s0 & s3 & s4) | (s1 & s2 & s3) | (s1 & s2 & s4) | (s1 & s3 & s4) | (s2 & s3 & s4); int error_found = 0; errors += r != r_hat; printf("%2u %2u %2u %2u %2u %2u (%2u) %c %2u\n", s0, s1, s2, s3, s4, r, r_hat, r==r_hat ? ' ' : '*', error_found); } } } } } printf("errors : %u\n", errors); return 0; } liquid-dsp-1.3.1/sandbox/fec_secded2216_test.c000066400000000000000000000166331317124540100210160ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // (22,16) code test (SEC-DED) // #include #include #include #include #include "liquid.internal.h" #define DEBUG_FEC_SECDED 1 // P matrix [6 x 16 bits], [6 x 2 bytes] // 1001 1001 0011 1100 : // 0011 1110 1000 1010 : // 1110 1110 0110 0000 : // 1110 0001 1101 0001 : // 0001 0011 1100 0111 : // 0100 0100 0011 1111 : unsigned char P[12] = { 0x99, 0x3c, 0x3e, 0x8a, 0xee, 0x60, 0xe1, 0xd1, 0x13, 0xc7, 0x44, 0x3f}; void print_bitstring_short(unsigned char _x, unsigned char _n) { unsigned int i; for (i=0; i<_n; i++) printf("%1u", (_x >> (_n-i-1)) & 1); } void print_bitstring(unsigned char * _x, unsigned char _n) { unsigned int i; // compute number of elements in _x div_t d = div(_n, 8); unsigned int N = d.quot + (d.rem ? 1 : 0); // print leader printf(" "); if (d.rem == 0) printf(" "); for (i=0; i<8-d.rem-1; i++) printf(" "); // print bitstring for (i=0; i #include #include #include #include "liquid.internal.h" #define DEBUG_FEC_SECDED 1 // P matrix [7 x 32 bits], [7 x 4 bytes] // 1000 1010 1000 0010 0000 1111 0001 1011 // 0001 0000 0001 1111 0111 0001 0110 0001 // 0001 0110 1111 0000 1001 0010 1010 0110 // 1111 1111 0000 0001 1010 0100 0100 0100 // 0110 1100 1111 1111 0000 1000 0000 1000 // 0010 0001 0010 0100 1111 1111 1001 0000 // 1100 0001 0100 1000 0100 0000 1111 1111 unsigned char P[28] = { 0x8a, 0x82, 0x0f, 0x1b, 0x10, 0x1f, 0x71, 0x61, 0x16, 0xf0, 0x92, 0xa6, 0xff, 0x01, 0xa4, 0x44, 0x6c, 0xff, 0x08, 0x08, 0x21, 0x24, 0xff, 0x90, 0xc1, 0x48, 0x40, 0xff}; void print_bitstring_short(unsigned char _x, unsigned char _n) { unsigned int i; for (i=0; i<_n; i++) printf("%1u", (_x >> (_n-i-1)) & 1); } void print_bitstring(unsigned char * _x, unsigned char _n) { unsigned int i; // compute number of elements in _x div_t d = div(_n, 8); unsigned int N = d.quot + (d.rem ? 1 : 0); // print leader printf(" "); if (d.rem == 0) printf(" "); for (i=0; i<8-d.rem-1; i++) printf(" "); // print bitstring for (i=0; i #include #include #include #include "liquid.internal.h" #define DEBUG_FEC_SECDED 1 // P matrix [8 x 64] // 11111111 00001111 00001111 00001100 01101000 10001000 10001000 10000000 : // 11110000 11111111 00000000 11110011 01100100 01000100 01000100 01000000 : // 00110000 11110000 11111111 00001111 00000010 00100010 00100010 00100110 : // 11001111 00000000 11110000 11111111 00000001 00010001 00010001 00010110 : // 01101000 10001000 10001000 10000000 11111111 00001111 00000000 11110011 : // 01100100 01000100 01000100 01000000 11110000 11111111 00001111 00001100 : // 00000010 00100010 00100010 00100110 11001111 00000000 11111111 00001111 : // 00000001 00010001 00010001 00010110 00110000 11110000 11110000 11111111 : unsigned char P[64] = { 0xFF, 0x0F, 0x0F, 0x0C, 0x68, 0x88, 0x88, 0x80, 0xF0, 0xFF, 0x00, 0xF3, 0x64, 0x44, 0x44, 0x40, 0x30, 0xF0, 0xFF, 0x0F, 0x02, 0x22, 0x22, 0x26, 0xCF, 0x00, 0xF0, 0xFF, 0x01, 0x11, 0x11, 0x16, 0x68, 0x88, 0x88, 0x80, 0xFF, 0x0F, 0x00, 0xF3, 0x64, 0x44, 0x44, 0x40, 0xF0, 0xFF, 0x0F, 0x0C, 0x02, 0x22, 0x22, 0x26, 0xCF, 0x00, 0xFF, 0x0F, 0x01, 0x11, 0x11, 0x16, 0x30, 0xF0, 0xF0, 0xFF}; void print_bitstring_short(unsigned char _x, unsigned char _n) { unsigned int i; for (i=0; i<_n; i++) printf("%1u", (_x >> (_n-i-1)) & 1); } void print_bitstring(unsigned char * _x, unsigned char _n) { unsigned int i; // compute number of elements in _x div_t d = div(_n, 8); unsigned int N = d.quot + (d.rem ? 1 : 0); // print leader printf(" "); if (d.rem == 0) printf(" "); for (i=0; i<8-d.rem-1; i++) printf(" "); // print bitstring for (i=0; i #include #include #include #include #include "liquid.internal.h" #define OUTPUT_FILENAME "fec_secded_punctured_test.m" void usage() { printf("Usage: fec_secded_punctured_test\n"); printf(" h : print usage/help\n"); printf(" p : input rate, [1:8], default: 4\n"); printf(" s : SNR start [dB], default: -5\n"); printf(" x : SNR max [dB], default: 5\n"); printf(" n : number of SNR steps, default: 21\n"); printf(" t : number of trials, default: 1000\n"); } // encode symbol void secded7264_encode_symbol_punctured(unsigned char * _sym_dec, unsigned char * _sym_enc, unsigned int _p); // decode symbol void secded7264_decode_symbol_punctured(unsigned char * _sym_enc, unsigned char * _sym_dec, unsigned int _p); int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int p = 4; // input size: p in [1,8] float SNRdB_min = 0.0f; // minimum SNR float SNRdB_max = 10.0f; // maximum SNR unsigned int num_steps = 21; // number of steps unsigned int num_trials = 80000; // get command-line options int dopt; while((dopt = getopt(argc,argv,"hp:s:x:n:t:")) != EOF){ switch (dopt) { case 'h': usage(); return 0; case 'p': p = atoi(optarg); break; case 's': SNRdB_min = atof(optarg); break; case 'x': SNRdB_max = atof(optarg); break; case 'n': num_steps = atoi(optarg); break; case 't': num_trials = atoi(optarg); break; default: printf("error: %s, unknown option\n", argv[0]); exit(-1); } } // validate input if (p < 1 || p >8) { fprintf(stderr,"error: %s, p must be in [1,8]\n", argv[0]); exit(1); } else if (SNRdB_max <= SNRdB_min) { fprintf(stderr,"error: %s, invalid SNR range\n", argv[0]); exit(1); } else if (num_steps < 1) { fprintf(stderr,"error: %s, must have at least 1 SNR step\n", argv[0]); exit(1); } // derived values unsigned int n = p*8; // decoded message length (bits) unsigned int k = (p+1)*8; // encoded message length (bits) float rate = (float)n / (float)k; float SNRdB_step = (SNRdB_max - SNRdB_min) / (num_steps-1); unsigned int i; // arrays unsigned char m[p]; // original message [64 x 1] unsigned char v[p+1]; // encoded/transmitted message float complex y[k]; // received message with noise unsigned char r[p+1]; // received vector (hard decision) unsigned char m_hat[p]; // estimated original message #if 0 // test it out for (i=0; i 0 ) ? 0x80 : 0x00; r[i] |= ( crealf(y[8*i+1]) > 0 ) ? 0x40 : 0x00; r[i] |= ( crealf(y[8*i+2]) > 0 ) ? 0x20 : 0x00; r[i] |= ( crealf(y[8*i+3]) > 0 ) ? 0x10 : 0x00; r[i] |= ( crealf(y[8*i+4]) > 0 ) ? 0x08 : 0x00; r[i] |= ( crealf(y[8*i+5]) > 0 ) ? 0x04 : 0x00; r[i] |= ( crealf(y[8*i+6]) > 0 ) ? 0x02 : 0x00; r[i] |= ( crealf(y[8*i+7]) > 0 ) ? 0x01 : 0x00; } // decode secded7264_decode_symbol_punctured(r,m_hat,p); // compute errors in decoded message signal num_bit_errors[s] += count_bit_errors_array(m,m_hat,p); } // print results for this SNR step printf(" %8.3f %8.3f [%8u] %8u %12.4e %12.4e\n", SNRdB, SNRdB - 10*log10f(rate), n*num_trials, num_bit_errors[s], (float)(num_bit_errors[s]) / (float)(num_trials*n), 0.5f*erfcf(1.0f/sigma)); } // // export output file // FILE * fid = fopen(OUTPUT_FILENAME, "w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"\n\n"); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); fprintf(fid,"n = %u;\n", n); fprintf(fid,"k = %u;\n", k); fprintf(fid,"r = n / k;\n"); fprintf(fid,"num_steps = %u;\n", num_steps); fprintf(fid,"num_trials = %u;\n", num_trials); fprintf(fid,"num_bit_trials = num_trials*n;\n"); for (i=0; i #include #include #include #include #include #include "liquid.internal.h" #define DEBUG_SPC2216 0 #define OUTPUT_FILENAME "spc2216_ber_test.m" // encode message // _msg_org : original message [size: 32 bytes] // _msg_enc : encoded message [size: 61 bytes] void spc2216_encode(unsigned char * _msg_org, unsigned char * _msg_enc); // decode message // _msg_rec : received message [size: 61 bytes] // _msg_dec : decoded message [size: 32 bytes] void spc2216_decode(unsigned char * _msg_rec, unsigned char * _msg_dec); // pack message // _m : input message [size: 32 bytes] // _pr : row parities [size: 16 bytes, @ 6 bits] // _pc : col parities [size: 22 bytes, @ 6 bits] // _v : output message [size: 61 bytes] void spc2216_pack(unsigned char * _m, unsigned char * _pr, unsigned char * _pc, unsigned char * _v); // unpack message // _v : input message [size: 61 bytes] // _pr : row parities [size: 16 bytes, @ 6 bits] // _pc : col parities [size: 22 bytes, @ 6 bits] // _m : output message [size: 32 bytes] void spc2216_unpack(unsigned char * _v, unsigned char * _pr, unsigned char * _pc, unsigned char * _m); // transpose square message block (generic) // _m : input message block [size: _n x _n bits, _n*_n/8 bytes] // _n : matrix dimension (must be divisble by 8) void spc2216_transpose_block(unsigned char * _m, unsigned int _n, unsigned char * _mT); // transpose message block and row parities // _m : message block [size: 16 x 16 bits, 32 bytes] // _pr : row parities [size: 16 x 6 bits, 16 bytes] // _w : transposed array [size: 22 x 16 bits, 44 bytes] void spc2216_transpose_row(unsigned char * _m, unsigned char * _pr, unsigned char * _w); // transpose message block and row parities (reverse) // _w : transposed array [size: 22 x 16 bits, 44 bytes] // _m : message block [size: 16 x 16 bits, 32 bytes] // _pr : row parities [size: 16 x 6 bits, 16 bytes] void spc2216_transpose_col(unsigned char * _w, unsigned char * _m, unsigned char * _pr); // print decoded block void spc2216_print_decoded(unsigned char * _m); // print encoded block void spc2216_print_encoded(unsigned char * _v); // print unpacked block void spc2216_print_unpacked(unsigned char * _m, unsigned char * _pr, unsigned char * _pc); // decode message (soft bits) // _msg_rec : received soft message [size: 488 soft bits] // _msg_dec_hard : decoded hard message [size: 32 bytes] void spc2216_decode_soft(unsigned char * _msg_rec, unsigned char * _msg_dec_hard); // decode soft symbol // _msg_rec : received soft bits [size: 22 soft bits] // _msg_dec : decoded soft bits [size: 22 soft bits] // _msg_dec_hard : decoded hard bits [size: 32 bytes] int spc2216_decode_sym_soft(unsigned char * _msg_rec, unsigned char * _msg_dec); void print_bitstring(unsigned char _x, unsigned char _n) { unsigned int i; for (i=0; i<_n; i++) printf("%2s", ((_x >> (_n-i-1)) & 1) ? "1" : "."); } int main(int argc, char*argv[]) { srand(time(NULL)); unsigned int i; // error vector unsigned char e[61]; #if 0 for (i=0; i<61; i++) e[i] = (rand() % 8) == 0 ? 1 << rand() % 7 : 0; #else memset(e, 0x00, 61); e[3] = 0x08; #endif // original message [16 x 16 bits], 32 bytes unsigned char m[32]; // derived values unsigned char v[61]; // encoded/transmitted message unsigned char r[61]; // received vector unsigned char m_hat[32];// estimated original message // generate random transmitted message #if 0 for (i=0; i<32; i++) m[i] = rand() & 0xff; #else for (i=0; i<32; i++) { if (i < 16 && (i%2)==0) m[i] = 0xff >> (i/2); //1 << 7-(i/2); else if (i >= 16 && (i%2)==1) m[i] = 1 << (7-((i-16-1)/2)); else m[i] = 0x00; } #endif printf("m (original message):\n"); spc2216_print_decoded(m); // encode spc2216_encode(m, v); printf("v (encoded message):\n"); spc2216_print_encoded(v); printf("e (error message):\n"); spc2216_print_encoded(e); // add errors for (i=0; i<61; i++) r[i] = v[i] ^ e[i]; printf("r (received message):\n"); spc2216_print_encoded(r); // decode spc2216_decode(r, m_hat); // compute errors between m, m_hat unsigned int num_errors_decoded = count_bit_errors_array(m, m_hat, 32); printf("decoding errors (original) : %2u / 256\n", num_errors_decoded); // // test soft decoding // #if 1 unsigned char msg_rec_soft[8*61]; unsigned char soft0 = 64; unsigned char soft1 = 192; // modulate with BPSK for (i=0; i<61; i++) { msg_rec_soft[8*i+0] = (r[i] & 0x80) ? soft1 : soft0; msg_rec_soft[8*i+1] = (r[i] & 0x40) ? soft1 : soft0; msg_rec_soft[8*i+2] = (r[i] & 0x20) ? soft1 : soft0; msg_rec_soft[8*i+3] = (r[i] & 0x10) ? soft1 : soft0; msg_rec_soft[8*i+4] = (r[i] & 0x08) ? soft1 : soft0; msg_rec_soft[8*i+5] = (r[i] & 0x04) ? soft1 : soft0; msg_rec_soft[8*i+6] = (r[i] & 0x02) ? soft1 : soft0; msg_rec_soft[8*i+7] = (r[i] & 0x01) ? soft1 : soft0; } // add 'noise'... for (i=0; i<6*61; i++) { int LLR = msg_rec_soft[i] + 30*randnf(); if (LLR < 0) LLR = 0; if (LLR > 255) LLR = 255; msg_rec_soft[i] = LLR; } // test soft-decision decoding memset(m_hat, 0x00, 32); spc2216_decode_soft(msg_rec_soft, m_hat); // compute errors between m, m_hat num_errors_decoded = count_bit_errors_array(m, m_hat, 32); printf("soft decoding errors (original) : %2u / 256\n", num_errors_decoded); #else // 1 1 . . 1 1 |. . 1 1 1 1 1 1 . . . . . . . . unsigned char msg_rec_soft[22] = { 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, }; // add noise for (i=0; i<22; i++) { int bit = msg_rec_soft[i] > 128 ? 192 : 64; bit += 30*randnf(); if (bit < 0) bit = 0; if (bit > 255) bit = 255; msg_rec_soft[i] = (unsigned char)bit; } int rc = spc2216_decode_sym_soft(msg_rec_soft, m_hat); #endif // // run SNR trials // float SNRdB_min = -1.0f; // signal-to-noise ratio (minimum) float SNRdB_max = 7.0f; // signal-to-noise ratio (maximum) unsigned int num_snr = 33; // number of SNR steps unsigned int num_trials=10000; // number of trials // arrays float complex sym_rec[8*61]; // received BPSK symbols unsigned int bit_errors_hard[num_snr]; unsigned int bit_errors_soft[num_snr]; unsigned int n_enc = 61; unsigned char msg_org[32]; unsigned char msg_enc[61]; unsigned char msg_cor[61]; // corrupted message (hard bits) unsigned char msg_LLR[8*61]; // corrupted message (soft-bit log-likelihood ratio) unsigned char msg_dec_hard[32]; unsigned char msg_dec_soft[32]; // set up parameters float SNRdB_step = (SNRdB_max - SNRdB_min) / (num_snr-1); printf(" %8s %8s [%8s] %8s %12s %8s %12s %12s\n", "SNR [dB]", "Eb/N0", "trials", "hard", "(hard BER)", "soft", "(soft BER)", "uncoded"); unsigned int s; for (s=0; s 0.0f ? 0x80 : 0x00; msg_cor[i] |= crealf(sym_rec[8*i+1]) > 0.0f ? 0x40 : 0x00; msg_cor[i] |= crealf(sym_rec[8*i+2]) > 0.0f ? 0x20 : 0x00; msg_cor[i] |= crealf(sym_rec[8*i+3]) > 0.0f ? 0x10 : 0x00; msg_cor[i] |= crealf(sym_rec[8*i+4]) > 0.0f ? 0x08 : 0x00; msg_cor[i] |= crealf(sym_rec[8*i+5]) > 0.0f ? 0x04 : 0x00; msg_cor[i] |= crealf(sym_rec[8*i+6]) > 0.0f ? 0x02 : 0x00; msg_cor[i] |= crealf(sym_rec[8*i+7]) > 0.0f ? 0x01 : 0x00; } spc2216_decode(msg_cor, msg_dec_hard); // convert to approximate LLR (soft decoding) for (i=0; i<8*n_enc; i++) { int LLR = (int)( 256*(crealf(sym_rec[i])*0.5f + 0.5f) ); if (LLR < 0) LLR = 0; if (LLR > 255) LLR = 255; msg_LLR[i] = (unsigned char) LLR; } spc2216_decode_soft(msg_LLR, msg_dec_soft); // tabulate results bit_errors_hard[s] += count_bit_errors_array(msg_org, msg_dec_hard, 32); bit_errors_soft[s] += count_bit_errors_array(msg_org, msg_dec_soft, 32); } // print results for this SNR step float rate = 32. / 61.; // true rate printf(" %8.3f %8.3f [%8u] %8u %12.4e %8u %12.4e %12.4e\n", SNRdB, SNRdB - 10*log10f(rate), 8*32*num_trials, bit_errors_hard[s], (float)(bit_errors_hard[s]) / (float)(num_trials*32*8), bit_errors_soft[s], (float)(bit_errors_soft[s]) / (float)(num_trials*32*8), 0.5f*erfcf(1.0f/nstd)); } // // export output file // FILE * fid = fopen(OUTPUT_FILENAME, "w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"\n\n"); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); fprintf(fid,"n = %u; %% frame size [bytes]\n", 32); fprintf(fid,"k = %u; %% encoded frame size [bytes]\n", 61); fprintf(fid,"r = n / k; %% true rate\n"); fprintf(fid,"num_snr = %u;\n", num_snr); fprintf(fid,"num_trials = %u;\n", num_trials); fprintf(fid,"num_bit_trials = num_trials*n*8;\n"); fprintf(fid,"bit_errors_hard = zeros(1,num_snr);\n"); fprintf(fid,"bit_errors_soft = zeros(1,num_snr);\n"); for (i=0; i> (6-j-1)) & 0x01) ? "1" : "."); if (i==15) printf(" "); } printf("\n"); } } // decode message (soft bits) // _msg_rec : received soft message [size: 488 soft bits] // _msg_dec_hard : decoded hard message [size: 32 bytes] void spc2216_decode_soft(unsigned char * _msg_rec, unsigned char * _msg_dec_hard) { unsigned char w[256]; // 256 = 16 x 16 bits unsigned char parity_row[96]; // 96 = 16 rows @ 6 bits unsigned char parity_col[132]; // 132 = 22 cols @ 6 bits // unpack encoded soft bits: memmove(w, _msg_rec, 256); memmove(parity_row, &_msg_rec[256], 96); memmove(parity_col, &_msg_rec[256+96], 132); unsigned int i; unsigned int j; #if 0 // print... for (i=0; i<16; i++) { printf(" "); for (j=0; j<16; j++) printf("%2s", w[16*i+j] > 128 ? "1" : "."); printf(" |"); for (j=0; j<6; j++) printf("%2s", parity_row[6*i+j] > 128 ? "1" : "."); printf("\n"); } printf(" ---------------------------------+-------------\n"); for (i=0; i<6; i++) { printf(" "); for (j=0; j<22; j++) printf("%2s", parity_col[6*j + i] > 128 ? "1" : "."); printf("\n"); } #endif // unsigned char sym_rec[22]; // encoded 22-bit message unsigned char sym_dec[22]; // decoded 22-bit message int syndrome_flag; // TODO : run multiple iterations... unsigned int n; for (n=0; n<6; n++) { #if DEBUG_SPC2216 printf("\n"); // print soft values for (i=0; i<16; i++) { for (j=0; j<16; j++) printf("%3u ", w[16*i+j]); printf("\n"); } #endif // compute syndromes on columns and run soft decoder //printf("columns (w):\n"); for (i=0; i<16; i++) { // extract encoded symbol for (j=0; j<6; j++) sym_rec[j ] = parity_col[j + 6*i]; for (j=0; j<16; j++) sym_rec[j+6] = w[16*j + i]; // run soft decoder syndrome_flag = spc2216_decode_sym_soft(sym_rec, sym_dec); // replace decoded symbol for (j=0; j<6; j++) parity_col[j + 6*i] = sym_dec[j]; for (j=0; j<16; j++) w[16*j + i] = sym_dec[j+6]; } // compute syndromes on row parities and run soft decoder //printf("row parities:\n"); for (i=0; i<6; i++) { // extract encoded symbol for (j=0; j<6; j++) sym_rec[j ] = parity_col[j + 6*(i+16)]; for (j=0; j<16; j++) sym_rec[j+6] = parity_row[6*j + i]; // run soft decoder syndrome_flag = spc2216_decode_sym_soft(sym_rec, sym_dec); // replace decoded symbol for (j=0; j<6; j++) parity_col[j + 6*(i+16)] = sym_rec[j]; for (j=0; j<16; j++) parity_row[6*j + i] = sym_rec[j+6]; } #if DEBUG_SPC2216 printf("...\n"); // print soft values for (i=0; i<16; i++) { for (j=0; j<16; j++) printf("%3u ", w[16*i+j]); printf("\n"); } #endif // compute syndromes on rows and run soft decoder //printf("rows:\n"); unsigned int num_errors = 0; for (i=0; i<16; i++) { // extract encoded symbol for (j=0; j<6; j++) sym_rec[j ] = parity_row[6*i + j]; for (j=0; j<16; j++) sym_rec[j+6] = w[16*i + j]; // run soft decoder syndrome_flag = spc2216_decode_sym_soft(sym_rec, sym_dec); num_errors += syndrome_flag == 0 ? 0 : 1; // replace decoded symbol for (j=0; j<6; j++) parity_row[6*i + j] = sym_rec[j]; for (j=0; j<16; j++) w[16*i + j] = sym_rec[j+6]; } //printf("%3u, detected %u soft decoding errors\n", n, num_errors); if (num_errors == 0) break; } // hard-decision decoding for (i=0; i<16; i++) { _msg_dec_hard[2*i+0] = 0; _msg_dec_hard[2*i+0] |= w[16*i+ 0] > 128 ? 0x80 : 0; _msg_dec_hard[2*i+0] |= w[16*i+ 1] > 128 ? 0x40 : 0; _msg_dec_hard[2*i+0] |= w[16*i+ 2] > 128 ? 0x20 : 0; _msg_dec_hard[2*i+0] |= w[16*i+ 3] > 128 ? 0x10 : 0; _msg_dec_hard[2*i+0] |= w[16*i+ 4] > 128 ? 0x08 : 0; _msg_dec_hard[2*i+0] |= w[16*i+ 5] > 128 ? 0x04 : 0; _msg_dec_hard[2*i+0] |= w[16*i+ 6] > 128 ? 0x02 : 0; _msg_dec_hard[2*i+0] |= w[16*i+ 7] > 128 ? 0x01 : 0; _msg_dec_hard[2*i+1] = 0; _msg_dec_hard[2*i+1] |= w[16*i+ 8] > 128 ? 0x80 : 0; _msg_dec_hard[2*i+1] |= w[16*i+ 9] > 128 ? 0x40 : 0; _msg_dec_hard[2*i+1] |= w[16*i+10] > 128 ? 0x20 : 0; _msg_dec_hard[2*i+1] |= w[16*i+11] > 128 ? 0x10 : 0; _msg_dec_hard[2*i+1] |= w[16*i+12] > 128 ? 0x08 : 0; _msg_dec_hard[2*i+1] |= w[16*i+13] > 128 ? 0x04 : 0; _msg_dec_hard[2*i+1] |= w[16*i+14] > 128 ? 0x02 : 0; _msg_dec_hard[2*i+1] |= w[16*i+15] > 128 ? 0x01 : 0; } // print decoded block //spc2216_print_decoded(_msg_dec_hard); } // decode soft symbol // _msg_rec : received soft bits [size: 22 soft bits] // _msg_dec : decoded soft bits [size: 22 soft bits] // return value: syndrome flag int spc2216_decode_sym_soft(unsigned char * _msg_rec, unsigned char * _msg_dec) { // pack... unsigned char sym_enc[3] = {0, 0, 0}; unsigned char e_hat[3]; unsigned int i; #if DEBUG_SPC2216 printf(" msg_rec:"); for (i=0; i<22; i++) printf("%3u,", _msg_rec[i]); printf("\n"); #endif for (i=0; i<6; i++) { sym_enc[0] <<= 1; sym_enc[0] |= _msg_rec[i] > 128 ? 1 : 0; } for (i=0; i<8; i++) { sym_enc[1] <<= 1; sym_enc[2] <<= 1; sym_enc[1] |= _msg_rec[ 6 + i] > 128 ? 1 : 0; sym_enc[2] |= _msg_rec[14 + i] > 128 ? 1 : 0; } int syndrome_flag = fec_secded2216_estimate_ehat(sym_enc, e_hat); #if DEBUG_SPC2216 if (syndrome_flag == 0) { printf(" (no errors detected)\n"); } else if (syndrome_flag == 1) { printf(" (one error detected and corrected!)\n"); } else { printf(" (multiple errors detected)\n"); } printf(" input : "); print_bitstring(sym_enc[0], 6); printf("|"); print_bitstring(sym_enc[1], 8); print_bitstring(sym_enc[2], 8); printf("\n"); #endif // apply error vector estimate to appropriate arrays sym_enc[0] ^= e_hat[0]; sym_enc[1] ^= e_hat[1]; sym_enc[2] ^= e_hat[2]; #if DEBUG_SPC2216 printf(" output : "); print_bitstring(sym_enc[0], 6); printf("|"); print_bitstring(sym_enc[1], 8); print_bitstring(sym_enc[2], 8); printf("\n"); #endif // unpack... unsigned char sym_dec_soft[22]; for (i=0; i<6; i++) { sym_dec_soft[i] = sym_enc[0] & (1 << (6-i-1)) ? 255 : 0; } for (i=0; i<8; i++) { sym_dec_soft[ 6 + i] = sym_enc[1] & (1 << (8-i-1)) ? 255 : 0; sym_dec_soft[14 + i] = sym_enc[2] & (1 << (8-i-1)) ? 255 : 0; } // combine... for (i=0; i<22; i++) { int delta = (int)sym_dec_soft[i] - 128; //_msg_dec[i] = 0.5*_msg_rec[i] + 0.5*sym_dec_soft[i]; int bit = _msg_rec[i] + 0.2*delta; if (bit < 0) bit = 0; if (bit > 255) bit = 255; _msg_dec[i] = (unsigned char) bit; } #if DEBUG_SPC2216 printf(" msg_dec:"); for (i=0; i<22; i++) printf("%3u,", _msg_dec[i]); printf("\n"); #endif return syndrome_flag; } liquid-dsp-1.3.1/sandbox/fec_sumproduct_test.c000066400000000000000000000031341317124540100214510ustar00rootroot00000000000000// // fec_sumproduct_test.c // // Test soft decoding of LDPC codes using internal sum-product // algorithm. // #include #include #include #include "liquid.internal.h" int main(int argc, char*argv[]) { // parity check matrix unsigned char Hb[32] = { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1}; // convert H to sparse matrix smatrixb H = smatrixb_create_array(Hb, 4, 8); // transmitted codeword unsigned char c[8] = { 1, 0, 1, 0, 1, 1, 1, 1}; // received message float y[8] = {0.2, 0.2, -0.9, 0.6, 0.5, -1.1, -0.4, -1.2}; unsigned int i; // noise standard deviation float sigma = sqrtf(0.5f); unsigned int m = 4; unsigned int n = 8; // convert received signal to LLR float LLR[n]; for (i=0; i #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "fecsoft_ber_test.m" void usage() { printf("fec_ber\n"); printf(" Simulates soft decoding\n"); printf("options:\n"); printf(" u/h : print usage/help\n"); printf(" s : SNR start [dB], default: -2\n"); printf(" x : SNR max [dB], default: 13\n"); printf(" n : number of SNR steps, default: 16\n"); printf(" t : number of trials, default: 800\n"); printf(" f : frame size, default: 64\n"); printf(" c : coding scheme, (h74 default):\n"); liquid_print_fec_schemes(); } int main(int argc, char *argv[]) { // set initial seed to random srand(time(NULL)); // options unsigned int n = 64; // frame size (bytes) float SNRdB_min = -2.0f; // signal-to-noise ratio (minimum) float SNRdB_max = 13.0f; // signal-to-noise ratio (maximum) unsigned int num_snr = 16; // number of SNR steps unsigned int num_trials=800; // number of trials fec_scheme fs = LIQUID_FEC_HAMMING74; // error-correcting scheme // get command-line options int dopt; while((dopt = getopt(argc,argv,"uhs:x:n:t:f:c:")) != EOF){ switch (dopt) { case 'h': case 'u': usage(); return 0; case 's': SNRdB_min = atof(optarg); break; case 'x': SNRdB_max = atof(optarg); break; case 'n': num_snr = atoi(optarg); break; case 't': num_trials = atoi(optarg); break; case 'f': n = atoi(optarg); break; case 'c': fs = liquid_getopt_str2fec(optarg); if (fs == LIQUID_FEC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported fec scheme \"%s\"\n\n",optarg); exit(1); } break; default: exit(1); } } unsigned int i; // create arrays unsigned int n_enc = fec_get_enc_msg_length(fs,n); printf("dec msg len : %u\n", n); printf("enc msg len : %u\n", n_enc); float rate = (float)n / (float)n_enc; unsigned char msg_org[n]; // original data message unsigned char msg_enc[n_enc]; // encoded data message float complex sym_rec[8*n_enc]; // received BPSK symbols unsigned char msg_cor_soft[8*n_enc]; // corrupted data message (soft bits) unsigned char msg_cor_hard[n_enc]; // corrupted data message (hard bits) unsigned char msg_dec_soft[n]; // decoded data message (soft bits) unsigned char msg_dec_hard[n]; // decoded data message (soft bits) // create object fec q = fec_create(fs,NULL); fec_print(q); unsigned int bit_errors_soft[num_snr]; unsigned int bit_errors_hard[num_snr]; // // set up parameters // float SNRdB_step = (SNRdB_max - SNRdB_min) / (num_snr-1); // // start trials // printf(" %8s %8s [%8s] %8s %12s %8s %12s %12s\n", "SNR [dB]", "Eb/N0", "trials", "soft", "(BER)", "hard", "(BER)", "uncoded"); unsigned int s; for (s=0; s 255) soft_bit = 255; if (soft_bit < 0) soft_bit = 0; msg_cor_soft[i] = (unsigned char)(soft_bit); } // convert to hard bits (hard decoding) for (i=0; i 0.0f ? 0x80 : 0x00; msg_cor_hard[i] |= crealf(sym_rec[8*i+1]) > 0.0f ? 0x40 : 0x00; msg_cor_hard[i] |= crealf(sym_rec[8*i+2]) > 0.0f ? 0x20 : 0x00; msg_cor_hard[i] |= crealf(sym_rec[8*i+3]) > 0.0f ? 0x10 : 0x00; msg_cor_hard[i] |= crealf(sym_rec[8*i+4]) > 0.0f ? 0x08 : 0x00; msg_cor_hard[i] |= crealf(sym_rec[8*i+5]) > 0.0f ? 0x04 : 0x00; msg_cor_hard[i] |= crealf(sym_rec[8*i+6]) > 0.0f ? 0x02 : 0x00; msg_cor_hard[i] |= crealf(sym_rec[8*i+7]) > 0.0f ? 0x01 : 0x00; } // decode fec_decode( q, n, msg_cor_hard, msg_dec_hard); fec_decode_soft(q, n, msg_cor_soft, msg_dec_soft); // tabulate results bit_errors_soft[s] += count_bit_errors_array(msg_org, msg_dec_soft, n); bit_errors_hard[s] += count_bit_errors_array(msg_org, msg_dec_hard, n); } // print results for this SNR step printf(" %8.3f %8.3f [%8u] %8u %12.4e %8u %12.4e %12.4e\n", SNRdB, SNRdB - 10*log10f(rate), 8*n*num_trials, bit_errors_soft[s], (float)(bit_errors_soft[s]) / (float)(num_trials*n*8), bit_errors_hard[s], (float)(bit_errors_hard[s]) / (float)(num_trials*n*8), 0.5f*erfcf(1.0f/nstd)); } // clean up objects fec_destroy(q); // // export output file // FILE * fid = fopen(OUTPUT_FILENAME, "w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"\n\n"); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); fprintf(fid,"n = %u; %% frame size [bytes]\n", n); fprintf(fid,"k = %u; %% encoded frame size [bytes]\n", n_enc); fprintf(fid,"r = n / k; %% true rate\n"); fprintf(fid,"num_snr = %u;\n", num_snr); fprintf(fid,"num_trials = %u;\n", num_trials); fprintf(fid,"num_bit_trials = num_trials*n*8;\n"); for (i=0; i #include #include #include #include #include #include "liquid.internal.h" #define OUTPUT_FILENAME "fecsoft_conv_test.m" void usage() { printf("fecsoft_conv_test\n"); printf(" Simulates soft decoding of convoluational codes\n"); printf("options:\n"); printf(" u/h : print usage/help\n"); printf(" s : SNR start [dB], default: -5\n"); printf(" x : SNR max [dB], default: 5\n"); printf(" n : number of SNR steps, default: 21\n"); printf(" t : number of trials, default: 1000\n"); printf(" c : convoluational coding scheme: v27, v29, v39, v615, punctured\n"); } int main(int argc, char *argv[]) { // set initial seed to random srand(time(NULL)); // options fec_scheme fs = LIQUID_FEC_CONV_V27; // convolutional FEC scheme unsigned int n = 64; // original message length float SNRdB_min = -5.0f; // signal-to-noise ratio (minimum) float SNRdB_max = 5.0f; // signal-to-noise ratio (maximum) unsigned int num_snr = 21; // number of SNR steps unsigned int num_trials=100; // number of trials // get command-line options int dopt; while((dopt = getopt(argc,argv,"uhs:x:n:t:c:")) != EOF){ switch (dopt) { case 'h': case 'u': usage(); return 0; case 's': SNRdB_min = atof(optarg); break; case 'x': SNRdB_max = atof(optarg); break; case 'n': num_snr = atoi(optarg); break; case 't': num_trials = atoi(optarg); break; case 'c': fs = liquid_getopt_str2fec(optarg); if (fs == LIQUID_FEC_UNKNOWN ) { fprintf(stderr,"error: %s, unknown/unsupported fec scheme \"%s\"\n\n",argv[0], optarg); exit(1); } else if ( !fec_scheme_is_convolutional(fs) ) { fprintf(stderr,"error: %s, input fec scheme '%s' is not convolutional\n\n",argv[0], optarg); exit(1); } break; default: exit(1); } } unsigned int i; // derived values unsigned int k = fec_get_enc_msg_length(fs, n); // encoded message length // create forward error-correction object fec q = fec_create(fs, NULL); fec_print(q); // // data arrays // #if 0 unsigned int sym_org; // original symbol float complex sym_enc[7]; // encoded symbol float complex sym_rec[7]; // received symbol #endif unsigned char msg_org[n]; // original message unsigned char msg_enc[k]; // encoded message float complex mod_sym[8*k]; // modulated symbols unsigned char msg_rec_soft[8*k]; // received 'soft' bits unsigned char msg_rec_hard[8*k]; // received 'hard' bits unsigned char msg_dec_soft[n]; // soft-decision decoding unsigned char msg_dec_hard[n]; // hard-decision decoding unsigned int bit_errors_soft[num_snr]; unsigned int bit_errors_hard[num_snr]; // // set up parameters // float SNRdB_step = (SNRdB_max - SNRdB_min) / (num_snr-1); // // start trials // #if 0 // test sym_org = 13; fecsoft_hamming74_encode(sym_org, sym_enc); fecsoft_hamming74_decode(sym_enc, &sym_dec_soft); exit(1); #endif printf(" %8s [%6s] %6s %6s\n", "SNR [dB]", "trials", "soft", "hard"); unsigned int s; for (s=0; s> 7) & 0x01) ? 1.0f : -1.0f; mod_sym[8*i+1] = ((msg_enc[i] >> 6) & 0x01) ? 1.0f : -1.0f; mod_sym[8*i+2] = ((msg_enc[i] >> 5) & 0x01) ? 1.0f : -1.0f; mod_sym[8*i+3] = ((msg_enc[i] >> 4) & 0x01) ? 1.0f : -1.0f; mod_sym[8*i+4] = ((msg_enc[i] >> 3) & 0x01) ? 1.0f : -1.0f; mod_sym[8*i+5] = ((msg_enc[i] >> 2) & 0x01) ? 1.0f : -1.0f; mod_sym[8*i+6] = ((msg_enc[i] >> 1) & 0x01) ? 1.0f : -1.0f; mod_sym[8*i+7] = ((msg_enc[i] ) & 0x01) ? 1.0f : -1.0f; } // add noise for (i=0; i<8*k; i++) mod_sym[i] += nstd*randnf()*cexpf(_Complex_I*2*M_PI*randf()); // 'demodulate' hard/soft for (i=0; i<8*k; i++) { // hard decision msg_rec_hard[i] = ( crealf(mod_sym[i]) > 0.0f ) ? LIQUID_SOFTBIT_1 : LIQUID_SOFTBIT_0; // soft decision #if 0 float soft_bit = (255*( 0.5f + 0.5f*tanhf(crealf(mod_sym[i])) )); if (soft_bit < 0) msg_rec_soft[i] = 0; else if (soft_bit > 255) msg_rec_soft[i] = 255; else msg_rec_soft[i] = (unsigned char) soft_bit; #else msg_rec_soft[i] = (unsigned char)(255*( 0.5f + 0.5f*tanhf(crealf(mod_sym[i])) )); #endif //printf(" hard : %3u, soft : %3u\n", msg_rec_hard[i], msg_rec_soft[i]); } // decode using 'soft' algorithm if ( fec_scheme_is_punctured(fs) ) { fec_conv_punctured_decode_soft(q, n, msg_rec_hard, msg_dec_hard); fec_conv_punctured_decode_soft(q, n, msg_rec_soft, msg_dec_soft); } else { fec_conv_decode_soft(q, n, msg_rec_hard, msg_dec_hard); fec_conv_decode_soft(q, n, msg_rec_soft, msg_dec_soft); } // count bit errors and tabulate results bit_errors_hard[s] += count_bit_errors_array(msg_org, msg_dec_hard, n); bit_errors_soft[s] += count_bit_errors_array(msg_org, msg_dec_soft, n); } // print results for this SNR step printf(" %8.3f [%6u] %6u %6u\n", SNRdB, 8*n*num_trials, bit_errors_soft[s], bit_errors_hard[s]); } // destroy forward error-correction object fec_destroy(q); // // export output file // FILE * fid = fopen(OUTPUT_FILENAME, "w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"\n\n"); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); fprintf(fid,"n = %u;\n", n); fprintf(fid,"k = %u;\n", k); fprintf(fid,"num_trials = %u;\n", num_trials); fprintf(fid,"total_bits = %u;\n", 8*n*num_trials); fprintf(fid,"num_snr = %u;\n", num_snr); fprintf(fid,"num_trials = %u;\n", num_trials); for (i=0; i #include #include "liquid.internal.h" int main() { // find the 17 symbols with a hamming distance of exactly 3 unsigned int sym_org; // original symbol unsigned int sym_enc; // encoded symbol unsigned int n3; // counter for symbols with a Hamming distance 3 unsigned char sym3[17]; // ... unsigned int i; printf("unsigned char fecsoft_hamming128_neighbors[256][17] = {\n"); for (sym_org=0; sym_org<256; sym_org++) { // printf(" {"); // reset counter n3=0; // encode symbol sym_enc = fec_hamming128_encode_symbol(sym_org); // look at all possible symbols... for (i=0; i<256; i++) { unsigned int sym_test = fec_hamming128_encode_symbol(i); // compute number of bit differences... unsigned int d = count_bit_errors(sym_enc, sym_test); // if (d==3) { if (n3 == 17) { fprintf(stderr,"error: expected no more than 17 symbols of distance 3\n"); exit(1); } sym3[n3++] = i; } // print results... //printf(" %3u : %3u\n", i, d); } //printf(" %3u : n3 =%3u\n", sym_org, n3); if (n3 != 17) { fprintf(stderr,"error: expected exactly 17 symbols of distance 3\n"); exit(1); } // print line for (i=0; i<17; i++) { printf("0x%.2x", sym3[i]); if (i != 16) printf(", "); } printf("}"); if (sym_org != 255) printf(",\n"); else printf("};\n"); } return 0; } liquid-dsp-1.3.1/sandbox/fecsoft_ldpc_test.c000066400000000000000000000134021317124540100210610ustar00rootroot00000000000000// // fecsoft_ldpc_test.c // // Test soft decoding using the sum-product // algorithm (see sandbox/ldpc_test.c) // // The generator and parity check matrices can be generated from // the 16 x 16 matrix P. Each row of P is a circular shift of the // generator polynomial p = [ 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0] // such that P^T = P and // G = [I(16) P ]^T // H = [P^T I(16)] #include #include #include #include #include "liquid.internal.h" #define OUTPUT_FILENAME "fecsoft_ldpc_test.m" int main(int argc, char*argv[]) { // initialize random seed srand(time(NULL)); float SNRdB_min = -2.0f; float SNRdB_max = 6.0f; unsigned int num_steps = 19; unsigned int num_trials = 2000; unsigned int max_iterations = 5; unsigned int m = 16; // rows in H unsigned int n = 32; // cols in H // initial generator polynomial // TODO : find 'optimal' generator polynomial unsigned char p[] = {1,0,0,0, 0,1,0,0, 0,0,0,1, 0,0,0,0}; // generator matrix [n x m] unsigned char Gs[n*m]; // parity check matrix [m x n] unsigned char Hs[m*n]; unsigned int i; unsigned int j; // init generator and parity check matrices for (i=0; i #include #include #include #include #include #define DEBUG 0 #define DFT_FORWARD (-1) #define DFT_REVERSE ( 1) // print usage/help message void usage() { printf("fft_mixed_radix_test -- test mixed-radix DFTs, compare to slow DFT method\n"); printf("options (default values in []):\n"); printf(" u/h : print usage/help\n"); printf(" p : stride (freq)\n"); printf(" q : stride (time)\n"); } // super slow DFT, but functionally correct void dft_run(unsigned int _nfft, float complex * _x, float complex * _y, int _dir, int _flags); int main(int argc, char*argv[]) { // transform size: p*q unsigned int p = 5; unsigned int q = 3; int dopt; while ((dopt = getopt(argc,argv,"uhp:q:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'p': p = atoi(optarg); break; case 'q': q = atoi(optarg); break; default: exit(1); } } // transform size unsigned int n = p*q; // validate input if ( n == 0 ) { fprintf(stderr,"error: input transform size must be at least 2\n"); exit(1); } unsigned int i; unsigned int k; // create and initialize data arrays float complex x[n]; float complex y[n]; float complex y_test[n]; for (i=0; i %12.6f + j%12.6f\n", crealf(t0[k]), cimagf(t0[k]), crealf(t1[k]), cimagf(t1[k])); #endif } // multipy by twiddle factors // NOTE: this can be combined with previous step printf("multiplying twiddles...\n"); for (i=0; i %12.6f + j%12.6f\n", crealf(t0[k]), cimagf(t0[k]), crealf(t1[k]), cimagf(t1[k])); #endif } // transpose results for (i=0; i #include #include #include #include #include #define DEBUG 0 #define DFT_FORWARD (-1) #define DFT_REVERSE ( 1) #define MAX_FACTORS (40) // print usage/help message void usage() { printf("fft_mixed_radix_test -- test mixed-radix DFTs, compare to slow DFT method\n"); printf("options (default values in []):\n"); printf(" h : print usage/help\n"); printf(" n : fft size\n"); } // super slow DFT, but functionally correct void dft_run(unsigned int _nfft, float complex * _x, float complex * _y, int _dir, int _flags); // FFT mixed-radix butterfly // _x : input/output buffer pointer [size: _nfft x 1] // _twiddle : pre-computed twiddle factors [size: _nfft x 1] // _nfft : original FFT size // _stride : output stride // _m : number of FFTs to compute // _p : generic (small) FFT size // // NOTES : the butterfly decimates in time, storing the output as // contiguous samples in the same buffer. void fftmr_bfly(float complex * _x, float complex * _twiddle, unsigned int _nfft, unsigned int _stride, unsigned int _m, unsigned int _p) { #if DEBUG printf(" bfly: stride=%3u, m=%3u, p=%3u\n", _stride, _m, _p); #endif // create temporary buffer the size of the FFT float complex * x_tmp = (float complex *) malloc(_p*sizeof(float complex)); unsigned int i; unsigned int k; unsigned int n; for (n=0; n<_m; n++) { #if DEBUG printf(" u=%u\n", n); #endif // copy input to temporary buffer for (i=0; i<_p; i++) x_tmp[i] = _x[n + i*_m]; // compute DFT, applying appropriate twiddle factors unsigned int twiddle_base = n; for (i=0; i<_p; i++) { #if DEBUG printf(" ----\n"); #endif float complex y = x_tmp[0]; unsigned int twiddle_index = 0; for (k=1; k<_p; k++) { twiddle_index = (twiddle_index + _stride*twiddle_base) % _nfft; #if DEBUG printf(" twiddle_index = %3u > %12.8f + j%12.8f, %12.8f + j%12.8f\n", twiddle_index, crealf(_twiddle[twiddle_index]), cimagf(_twiddle[twiddle_index]), crealf(x_tmp[k]), cimagf(x_tmp[k])); #endif y += x_tmp[k] * _twiddle[twiddle_index]; } // increment twiddle twiddle base twiddle_base += _m; // store output _x[n + i*_m] = y; #if DEBUG printf(" y = %12.6f + j%12.6f\n", crealf(y), cimagf(y)); #endif } } // free temporary buffer free(x_tmp); } // FFT mixed-radix recursive function... // _x : constant input pointer [size: _nfft x 1] // _y : output pointer // _twiddle : pre-computed twiddle factors [size: _nfft x 1] // _nfft : original FFT size // _xoffset : input buffer offset // _xstride : input buffer stride // _m_vect : array of radix values [size: num_factors x 1] // _p_vect : array of DFT values [size: num_factors x 1] void fftmr_cycle(float complex * _x, float complex * _y, float complex * _twiddle, unsigned int _nfft, unsigned int _xoffset, unsigned int _xstride, unsigned int * _m_vect, unsigned int * _p_vect) { // de-reference factors and pop values off the top unsigned int m = _m_vect[0]; // radix unsigned int p = _p_vect[0]; // DFT size // increment factor pointers _m_vect++; _p_vect++; #if DEBUG printf("fftmr_cycle: offset=%3u, stride=%3u, p=%3u, m=%3u\n", _xoffset, _xstride, p, m); #endif unsigned int i; if ( m == 1 ) { // copy data to output buffer for (i=0; i 1 && num_factors < MAX_FACTORS); // NOTE: this is extremely unlikely as the worst case is // nfft=2^MAX_FACTORS in which case we will probably run out // of memory first if (num_factors == MAX_FACTORS) { fprintf(stderr,"error: could not factor %u with %u factors\n", nfft, MAX_FACTORS); exit(1); } printf("factors of %u:\n", nfft); for (i=0; i #include #include #include #include #include #include "liquid.internal.h" #ifdef HAVE_FFTW3_H # include #else # warning "fftw3.h not installed; this sandbox program won't run" #endif // print usage/help message void usage() { printf("fft_r2r_test -- test real ffts, compare to fftw3\n"); printf("options (default values in []):\n"); printf(" u/h : print usage/help\n"); printf(" n : number of points\n"); } int main(int argc, char*argv[]) { #ifdef HAVE_FFTW3_H unsigned int n = 32; // transform size unsigned int d = 4; // number of elements to print each line int dopt; while ((dopt = getopt(argc,argv,"uhn:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'n': n = atoi(optarg); break; default: exit(1); } } // validate input if ( n < 2 ) { fprintf(stderr,"error: input transform size must be at least 2\n"); exit(1); } // create and initialize data arrays float x[n]; float y[n]; unsigned int i; for (i=0; i #include #include #include #include #include #define DEBUG 0 #define DFT_FORWARD (-1) #define DFT_REVERSE ( 1) #define MAX_FACTORS (40) // print usage/help message void usage() { printf("fft_rader_prime_radix2_test -- test Rader's alternate prime FFT\n"); printf(" algorithm, compare to slow DFT method\n"); printf("options (default values in []):\n"); printf(" h : print usage/help\n"); printf(" n : fft size (must be prime and greater than 2)\n"); } // super slow DFT, but functionally correct void dft_run(unsigned int _nfft, float complex * _x, float complex * _y, int _dir, int _flags); // determine if number is prime (slow, simple method) int is_prime(unsigned int _n); // find smallest primitive root of _n (assuming _n is prime) unsigned int primitive_root(unsigned int _n); // compute c = base^exp (mod n) unsigned int modpow(unsigned int _base, unsigned int _exp, unsigned int _n); int main(int argc, char*argv[]) { // transform size (must be prime) unsigned int nfft = 17; int dopt; while ((dopt = getopt(argc,argv,"uhn:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': nfft = atoi(optarg); break; default: exit(1); } } // validate input if ( nfft <= 2 || !is_prime(nfft)) { fprintf(stderr,"error: %s, input transform size must be prime and greater than two\n", argv[0]); exit(1); } unsigned int i; // create and initialize data arrays float complex * x = (float complex *) malloc(nfft * sizeof(float complex)); float complex * y = (float complex *) malloc(nfft * sizeof(float complex)); float complex * y_test = (float complex *) malloc(nfft * sizeof(float complex)); if (x == NULL || y == NULL || y_test == NULL) { fprintf(stderr,"error: %s, not enough memory for allocation\n", argv[0]); exit(1); } for (i=0; i 0) { nfft_prime >>= 1; m++; } nfft_prime = 1 << m; printf("nfft_prime = %u\n", nfft_prime); #else // compute larger FFT length greater than 2*nfft-4 // NOTE: while any length greater than 2*nfft-4 will work, use // nfft_prime as smallest 'simple' FFT (mostly small factors) // // score(n) = n / sum(factors(n).^2) float gamma_max = 0.0f; // score unsigned int nfft_prime_opt = 0; for (i=1; i<=10 + nfft/4; i++) { unsigned int n_hat = 2*nfft - 4 + i; // compute factors printf("%3u : ", n_hat); unsigned int k; unsigned int num_factors = 0; unsigned int m = n_hat; float gamma = 0.0f; do { for (k=2; k<=m; k++) { if ( (m % k) == 0) { printf("%-4u", k); m /= k; num_factors++; gamma += k*k; break; } } } while (m > 1); for (k=12; k>num_factors; k--) printf(" "); // compute score: //float gamma = (float)n_hat / (float)num_factors; //float gamma = 1e3f * (float)num_factors / (float)n_hat; gamma = (float)n_hat / gamma; printf(" score : %12.8f%s\n", gamma, gamma > gamma_max ? " *" : ""); if (gamma > gamma_max) { gamma_max = gamma; nfft_prime_opt = n_hat; } } printf("best nfft_prime : %u\n", nfft_prime_opt); unsigned int nfft_prime = nfft_prime_opt; #endif // compute DFT of sequence { exp(-j*2*pi*g^i/nfft }, size: nfft_prime // NOTE: R[0] = -1, |R[k]| = sqrt(nfft) for k != 0 // NOTE: R can be pre-computed float complex * r = (float complex*)malloc((nfft_prime)*sizeof(float complex)); float complex * R = (float complex*)malloc((nfft_prime)*sizeof(float complex)); for (i=0; i 1 && num_unique_factors < MAX_FACTORS); #if 0 // print unique factors printf("found %u unique factors of n-1 = %u\n", num_unique_factors, _n-1); for (k=0; k #include #include #include #include #include #define DEBUG 0 #define DFT_FORWARD (-1) #define DFT_REVERSE ( 1) #define MAX_FACTORS (40) // print usage/help message void usage() { printf("fft_rader_prime_test -- test Rader's prime FFT algorithm, compare to slow DFT method\n"); printf("options (default values in []):\n"); printf(" h : print usage/help\n"); printf(" n : fft size (must be prime and greater than 2)\n"); } // super slow DFT, but functionally correct void dft_run(unsigned int _nfft, float complex * _x, float complex * _y, int _dir, int _flags); // determine if number is prime (slow, simple method) int is_prime(unsigned int _n); // find smallest primitive root of _n (assuming _n is prime) unsigned int primitive_root(unsigned int _n); // compute c = base^exp (mod n) unsigned int modpow(unsigned int _base, unsigned int _exp, unsigned int _n); int main(int argc, char*argv[]) { // transform size (must be prime) unsigned int nfft = 17; int dopt; while ((dopt = getopt(argc,argv,"uhn:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': nfft = atoi(optarg); break; default: exit(1); } } // validate input if ( nfft <= 2 || !is_prime(nfft)) { fprintf(stderr,"error: %s, input transform size must be prime and greater than two\n", argv[0]); exit(1); } unsigned int i; // create and initialize data arrays float complex * x = (float complex *) malloc(nfft * sizeof(float complex)); float complex * y = (float complex *) malloc(nfft * sizeof(float complex)); float complex * y_test = (float complex *) malloc(nfft * sizeof(float complex)); if (x == NULL || y == NULL || y_test == NULL) { fprintf(stderr,"error: %s, not enough memory for allocation\n", argv[0]); exit(1); } for (i=0; i 1 && num_unique_factors < MAX_FACTORS); #if 0 // print unique factors printf("found %u unique factors of n-1 = %u\n", num_unique_factors, _n-1); for (k=0; k #include #include #include #include #include #include "liquid.internal.h" // print usage/help message void usage() { printf("fft_recursive_plan_test -- test planning FFTs\n"); printf("options (default values in []):\n"); printf(" h : print help\n"); printf(" n : input fft size\n"); } // print fft plan // _nfft : input fft size // _level : level void liquid_fft_plan(unsigned int _nfft, unsigned int _level); int main(int argc, char*argv[]) { // options unsigned int nfft = 124; int dopt; while ((dopt = getopt(argc,argv,"hn:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': nfft = atoi(optarg); break; default: exit(1); } } // validate input if ( nfft == 0 ) { fprintf(stderr,"error: input transform size must be at least 2\n"); exit(1); } // print the FFT plan liquid_fft_plan(nfft, 0); printf("done.\n"); return 0; } // print fft plan // _nfft : input fft size // _level : level void liquid_fft_plan(unsigned int _nfft, unsigned int _level) { if (_nfft == 0) { // invalid length fprintf(stderr,"error: liquid_fft_estimate_method(), fft size must be > 0\n"); exit(1); } // print appropriate spacing unsigned int i; for (i=0; i<_level; i++) printf(" "); // print fft size printf("%u, ", _nfft); if (_nfft < 8) { // use simple DFT codelet printf("codelet\n"); return; } else if (fft_is_radix2(_nfft)) { // transform is of the form 2^m printf("radix-2\n"); return; } else if (liquid_is_prime(_nfft)) { // compute prime factors of _nfft-1 unsigned int factors[LIQUID_MAX_FACTORS]; unsigned int num_factors=0; liquid_factor(_nfft-1,factors,&num_factors); if (num_factors > 2) { // use Rader's algorithm (type I) for size _nfft-1 printf("Rader's algorithm, Type I > %u\n", _nfft-1); liquid_fft_plan(_nfft-1, _level+1); return; } else { // use Rader's algorithm (type II) for radix-2 // nfft_prime = 2 ^ nextpow2(2*nfft - 4) unsigned int nfft_prime = 1 << liquid_nextpow2(2*_nfft-4); printf("Rader's algorithm, Type II > %u\n", nfft_prime); liquid_fft_plan(nfft_prime, _level+1); return; } } // use Cooley-Tukey algorithm printf("Cooley-Tukey\n"); // compute prime factors of _nfft unsigned int factors[LIQUID_MAX_FACTORS]; unsigned int num_factors=0; liquid_factor(_nfft,factors,&num_factors); for (i=0; i #include #include #include #include #include #include "liquid.h" #define DEBUG 0 #define DFT_FORWARD (-1) #define DFT_REVERSE ( 1) // print usage/help message void usage() { printf("fft_recursive_test -- test recursive mixed-radix DFTs, compare to slow DFT method\n"); printf("options (default values in []):\n"); printf(" h : print help\n"); printf(" n : fft size, default: 30\n"); } // recursive FFT algorithm void fft_recursion(unsigned int _nfft, float complex * _x, float complex * _y, int _dir); // super slow DFT, but functionally correct void dft_run(unsigned int _nfft, float complex * _x, float complex * _y, int _dir); int main(int argc, char*argv[]) { // transform size unsigned int nfft = 30; int dopt; while ((dopt = getopt(argc,argv,"hn:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': nfft = atoi(optarg); break; default: exit(1); } } // validate input if ( nfft < 2 ) { fprintf(stderr,"error: %s, input transform size must be at least 2\n", argv[0]); exit(1); } unsigned int i; // create and initialize data arrays float complex x[nfft]; float complex y[nfft]; float complex y_test[nfft]; for (i=0; i #include #include #include "liquid.h" // print usage/help message void usage() { printf("firdes_energy_test:\n"); printf(" u/h : print usage/help\n"); printf(" f : filter cutoff frequency, 0 < f < 0.5, default: 0.2\n"); printf(" t : filter transition bandwidth, 0 < t < 0.5, default: 0.1\n"); printf(" s : filter stop-band attenuation [dB], 0 < s, default: 60\n"); printf(" m : fractional sample delay, -0.5 < m < 0.5, default: 0\n"); } int main(int argc, char*argv[]) { // options float fc=0.2f; // filter cutoff frequency float ft=0.1f; // filter transition float As=60.0f; // stop-band attenuation [dB] float mu=0.0f; // fractional timing offset int dopt; while ((dopt = getopt(argc,argv,"uhf:t:s:m:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'f': fc = atof(optarg); break; case 't': ft = atof(optarg); break; case 's': As = atof(optarg); break; case 'm': mu = atof(optarg); break; default: exit(1); } } // derived values unsigned int h_len = estimate_req_filter_len(ft,As); printf("h_len : %u\n", h_len); printf("filter design parameters\n"); printf(" cutoff frequency : %8.4f\n", fc); printf(" transition bandwidth : %8.4f\n", ft); printf(" stop-band attenuation [dB] : %8.4f\n", As); printf(" fractional sample offset : %8.4f\n", mu); printf(" filter length : %u\n", h_len); // generate the filter unsigned int i; float h[h_len]; liquid_firdes_kaiser(h_len,fc,As,mu,h); // print coefficients for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "firdes_fexp_test.m" // print usage/help message void usage() { printf("Usage: sandbox/firdes_fexp_test [OPTION]\n"); printf("Run example fexp receive filter design\n"); printf("\n"); printf(" u/h : print usage/help\n"); printf(" k : filter samples/symbol, k >= 2, default: 4\n"); printf(" m : filter delay (symbols), m >= 1, default: 3\n"); printf(" b : filter excess bandwidth factor, 0 < b < 1, default: 0.3\n"); } float firdes_freqresponse_fexp(float _f, unsigned int _k, float _beta); int main(int argc, char*argv[]) { // options unsigned int k=4; // filter samples/symbol unsigned int m=3; // filter delay [symbols] float beta = 0.3f; // filter excess bandwidth factor // read properties from command line int dopt; while ((dopt = getopt(argc,argv,"uhk:m:b:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; default: exit(1); } } // validate input if (k < 2) { fprintf(stderr,"error: %s, k must be at least 2\n", argv[0]); exit(1); } else if (m < 1) { fprintf(stderr,"error: %s, m must be at least 1\n", argv[0]); exit(1); } else if (beta <= 0.0f || beta >= 1.0f) { fprintf(stderr,"error: %s, beta must be in (0,1)\n", argv[0]); exit(1); } unsigned int i; // derived values unsigned int h_len = 2*k*m+1; // filter length // arrays float ht[h_len]; // transmit filter coefficients float hr[h_len]; // recieve filter coefficients // // start of filter design procedure // float H_prime[h_len]; // frequency response of Nyquist filter float complex h_tx[h_len]; // impulse response of square-root Nyquist filter float complex H_tx[h_len]; // frequency response of square-root Nyquist filter // compute frequency response of Nyquist filter for (i=0; i 0.5f) f = f - 1.0f; H_prime[i] = firdes_freqresponse_fexp(f,k,beta); } // compute square-root response, copy to fft input for (i=0; i f0 && f < f2) { // transition band float B = 0.5f/(float)_k; float gamma = logf(2.0f)/(_beta*B); if ( f < f1) { return expf(gamma*(B*(1-_beta) - f)); } else { return 1.0f - expf(gamma*(f - (1+_beta)*B)); } } else { return 0.0f; } return 0.0f; } liquid-dsp-1.3.1/sandbox/firdes_gmskrx_test.c000066400000000000000000000210741317124540100213010ustar00rootroot00000000000000// // firdes_gmskrx_test.c : test synthesis of GMSK receive filter // #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "firdes_gmskrx_test.m" // print usage/help message void usage() { printf("Usage: sandbox/firdes_gmskrx_test [OPTION]\n"); printf("Run example GMSK receive filter design\n"); printf("\n"); printf(" u/h : print usage/help\n"); printf(" k : filter samples/symbol, k >= 2, default: 4\n"); printf(" m : filter delay (symbols), m >= 1, default: 3\n"); printf(" b : filter excess bandwidth factor, 0 < b < 1, default: 0.3\n"); } int main(int argc, char*argv[]) { // options unsigned int k=4; // samples/symbol unsigned int m=3; // filter delay [symbols] float BT = 0.3f; // bandwidth-time product // read properties from command line int dopt; while ((dopt = getopt(argc,argv,"uhk:m:b:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': BT = atof(optarg); break; default: exit(1); } } // validate input if (k < 2) { fprintf(stderr,"error: %s, k must be at least 2\n", argv[0]); exit(1); } else if (m < 1) { fprintf(stderr,"error: %s, m must be at least 1\n", argv[0]); exit(1); } else if (BT <= 0.0f || BT >= 1.0f) { fprintf(stderr,"error: %s, BT must be in (0,1)\n", argv[0]); exit(1); } unsigned int i; // derived values unsigned int h_len = 2*k*m+1; // filter length // arrays float ht[h_len]; // transmit filter coefficients float hr[h_len]; // recieve filter coefficients // design transmit filter liquid_firdes_gmsktx(k,m,BT,0.0f,ht); // print results to screen printf("gmsk transmit filter:\n"); for (i=0; i #include #include #include "liquid.internal.h" #define OUTPUT_FILENAME "firdes_length_test.m" // print usage/help message void usage() { printf("firdes_length_test:\n"); printf(" u/h : print usage/help\n"); printf(" t : filter transition bandwidth, 0 < t < 0.5, default: 0.1\n"); printf(" a : filter attenuation (minimum) [dB], default: 20\n"); printf(" A : filter attenuation (maximum) [dB], default: 100\n"); printf(" n : number of steps, default: 41\n"); } int main(int argc, char*argv[]) { // options float ft=0.1f; // filter transition float As_min = 20.0f; float As_max = 100.0f; unsigned int num_As = 41; // number of steps int dopt; while ((dopt = getopt(argc,argv,"uht:a:A:n:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 't': ft = atof(optarg); break; case 'a': As_min = atof(optarg); break; case 'A': As_max = atof(optarg); break; case 'n': num_As = atoi(optarg); break; default: exit(1); } } // validate input if (As_min <= 0.0f || As_max <= 0.0f) { fprintf(stderr,"error: %s, attenuation must be greater than zero\n", argv[0]); exit(1); } else if (As_max <= As_min) { fprintf(stderr,"error: %s, minimum attenuation cannot exceed maximum\n", argv[0]); exit(1); } else if (num_As < 2) { fprintf(stderr,"error: %s, must have at least 2 steps", argv[0]); exit(1); } // derived values float As_step = (As_max - As_min) / (float)(num_As - 1); // output to file FILE*fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n\n"); fprintf(fid,"num_steps = %u;\n", num_As); fprintf(fid,"As=zeros(1,num_steps);\n"); fprintf(fid,"n_Kaiser=zeros(1,num_steps);\n"); fprintf(fid,"n_Herrmann=zeros(1,num_steps);\n"); unsigned int i; for (i=0; i #include "liquid.h" #define OUTPUT_FILENAME "firfarrow_rrrf_test.m" int main() { // options unsigned int h_len=19; // filter length unsigned int p=5; // polynomial order float fc=0.45f; // filter cutoff float As=60.0f; // stop-band attenuation [dB] unsigned int m=9; // number of delays to evaluate // coefficients array float h[h_len]; float tao = ((float)h_len-1)/2.0f; // nominal filter delay firfarrow_rrrf f = firfarrow_rrrf_create(h_len, p, fc, As); FILE*fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\nclose all;\n\n"); fprintf(fid,"m = %u;\n", m); fprintf(fid,"h_len = %u;\n", h_len); fprintf(fid,"h = zeros(%u,%u);\n", m, h_len); fprintf(fid,"mu = zeros(1,%u);\n", m); fprintf(fid,"tao = %12.8f;\n", tao); unsigned int i, j; float mu_vect[m]; for (i=0; i #include #include #include #include #include "liquid.internal.h" // print debug status #define DEBUG 0 // use pseudo-random coefficients; this is useful for determining // functional correctness (no symmetry in filter) #define RANDOM_COEFFICIENTS 0 int main(int argc, char*argv[]) { // options unsigned int num_channels=6; // number of channels (must be even) unsigned int m=4; // filter delay unsigned int num_symbols=4*m; // number of symbols // validate input if (num_channels%2) { fprintf(stderr,"error: %s, number of channels must be even\n", argv[0]); exit(1); } // derived values unsigned int num_samples = num_channels * num_symbols; unsigned int i; unsigned int j; // // ANALYSIS FILTERBANK // // generate filter // NOTE : these coefficients can be random; the purpose of this // exercise is to demonstrate mathematical equivalence unsigned int h_len = 2*m*num_channels+1; float h[h_len]; #if RANDOM_COEFFICIENTS // testing: set filter coefficients to random values unsigned int s0 = 1; unsigned int p0 = 524287; // large prime number unsigned int g0 = 1031; // another large prime number for (i=0; i beta = 8.00000 (6 channels, m=4) liquid_firdes_kaiser(h_len, 1.0f/(float)num_channels, 81.29528f, 0.0f, h); #endif // normalize float hsum = 0.0f; for (i=0; i beta = 8.00000 (6 channels, m=4) liquid_firdes_kaiser(f_len, 0.5f/(float)num_channels, 81.29528f, 0.0f, f); #endif // normalize float fsum = 0.0f; for (i=0; i #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "firpfbch_analysis_sync_test.m" // forward declaration of internal methods void firpfbch_crcf_analyzer_push(firpfbch_crcf _q, float complex _x); void firpfbch_crcf_analyzer_run(firpfbch_crcf _q, unsigned int _k, float complex * _X); int main() { // options unsigned int num_channels=4; // must be even number unsigned int num_symbols=12; // number of symbols unsigned int m=3; // filter delay (symbols) float beta = 0.9f; // filter excess bandwidth factor unsigned int delay = 3; // initial sampling delay int ftype = LIQUID_FIRFILT_ARKAISER; // derived values unsigned int num_frames = num_symbols + 2*m; // compensate for filter delay unsigned int num_samples = num_channels * num_frames; // total number of samples // data arrays float complex x[num_samples]; float complex Y0[num_frames][num_channels]; float complex Y1[num_frames][num_channels]; // create analyzer objects firpfbch_crcf ca0 = firpfbch_crcf_create_rnyquist(LIQUID_ANALYZER, num_channels, m, beta, ftype); firpfbch_crcf ca1 = firpfbch_crcf_create_rnyquist(LIQUID_ANALYZER, num_channels, m, beta, ftype); unsigned int i; unsigned int j; // generate random input sequence for (i=0; i #include #include #include "liquid.internal.h" #define DEBUG 1 int main() { // options unsigned int num_channels=4; // number of channels unsigned int m=5; // filter delay unsigned int num_symbols=12; // number of symbols // derived values unsigned int num_samples = num_channels * num_symbols; unsigned int i; unsigned int j; // generate filter // NOTE : these coefficients can be random; the purpose of this // exercise is to demonstrate mathematical equivalence unsigned int h_len = 2*m*num_channels; float h[h_len]; for (i=0; i #include #include "liquid.internal.h" int main() { // options unsigned int num_channels=8; // number of channels unsigned int m=2; // filter delay float As=60; // stop-band attenuation [dB] unsigned int num_symbols=8; // number of symbols // create filterbank objects firpfbch ca0 = firpfbch_create(num_channels, m, As, 0, FIRPFBCH_NYQUIST, 0); firpfbch ca1 = firpfbch_create(num_channels, m, As, 0, FIRPFBCH_NYQUIST, 0); unsigned int i, j; float complex x[num_channels]; // time-domain input float complex y0[num_channels]; // channelized output float complex y1[num_channels]; // channelized output #if 0 // push samples channelizer 1 float complex x_hat; for (i=0; i #include #include #include "liquid.internal.h" #define DEBUG 1 int main() { // options unsigned int num_channels=4; // number of channels unsigned int m=3; // filter delay unsigned int num_symbols=5; // number of symbols // derived values unsigned int num_samples = num_channels * num_symbols; unsigned int i; unsigned int j; // generate filter // NOTE : these coefficients can be random; the purpose of this // exercise is to demonstrate mathematical equivalence unsigned int h_len = 2*m*num_channels; float h[h_len]; for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "fskmodem_test.m" // print usage/help message void usage() { printf("fskmodem_example -- frequency-shift keying test\n"); printf("options:\n"); printf(" h : print help\n"); printf(" m : bits/symbol, default: 1\n"); printf(" k : samples/symbol, default: 2*2^m\n"); printf(" b : signal bandwidth default: 0.2\n"); printf(" n : number of data symbols, default: 80\n"); printf(" s : SNR [dB], default: 40\n"); printf(" F : carrier frequency offset, default: 0\n"); printf(" P : carrier phase offset, default: 0\n"); printf(" T : fractional symbol offset, default: 0\n"); } int main(int argc, char*argv[]) { // options unsigned int m = 3; // number of bits/symbol unsigned int k = 0; // filter samples/symbol unsigned int num_symbols = 200; // number of data symbols float SNRdB = 40.0f; // signal-to-noise ratio [dB] float cfo = 0.0f; // carrier frequency offset float cpo = 0.0f; // carrier phase offset float tau = 0.0f; // fractional symbol timing offset float bandwidth = 0.20; // frequency spacing int dopt; while ((dopt = getopt(argc,argv,"hm:k:b:n:s:F:P:T:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'm': m = atoi(optarg); break; case 'k': k = atoi(optarg); break; case 'b': bandwidth = atof(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'F': cfo = atof(optarg); break; case 'P': cpo = atof(optarg); break; case 'T': tau = atof(optarg); break; default: exit(1); } } unsigned int i; unsigned int j; // derived values if (k == 0) k = 2 << m; // set samples per symbol if not otherwise specified unsigned int num_samples = k*num_symbols; unsigned int M = 1 << m; float nstd = powf(10.0f, -SNRdB/20.0f); float M2 = 0.5f*(float)(M-1); // validate input if (k < M) { fprintf(stderr,"errors: %s, samples/symbol must be at least modulation size (M=%u)\n", __FILE__,M); exit(1); } else if (k > 2048) { fprintf(stderr,"errors: %s, samples/symbol exceeds maximum (2048)\n", __FILE__); exit(1); } else if (M > 1024) { fprintf(stderr,"errors: %s, modulation size (M=%u) exceeds maximum (1024)\n", __FILE__, M); exit(1); } else if (bandwidth <= 0.0f || bandwidth >= 0.5f) { fprintf(stderr,"errors: %s, bandwidht must be in (0,0.5)\n", __FILE__); exit(1); } // compute demodulation FFT size such that FFT output bin frequencies are // as close to modulated frequencies as possible unsigned int K = 0; // demodulation FFT size float df = bandwidth / M2; // frequency spacing float err_min = 1e9f; unsigned int K_min = k; // minimum FFT size unsigned int K_max = k*4 < 16 ? 16 : k*4; // maximum FFT size unsigned int K_hat; for (K_hat=K_min; K_hat<=K_max; K_hat++) { // compute candidate FFT size float v = 0.5f*df * (float)K_hat; // bin spacing float err = fabsf( roundf(v) - v ); // fractional bin spacing // print results printf(" K_hat = %4u : v = %12.8f, err=%12.8f %s\n", K_hat, v, err, err < err_min ? "*" : ""); // save best result if (K_hat==K_min || err < err_min) { K = K_hat; err_min = err; } // perfect match; no need to continue searching if (err < 1e-6f) break; } // arrays unsigned int sym_in[num_symbols]; // input symbols float complex x[num_samples]; // transmitted signal float complex y[num_samples]; // received signal unsigned int sym_out[num_symbols]; // output symbols // determine demodulation mapping between tones and frequency bins // TODO: use gray coding unsigned int demod_map[M]; for (i=0; i vmax) { s_opt = s; vmax =v; } } // save best result sym_out[j++] = s_opt; } } // destroy fft object fft_destroy_plan(fft); #endif // count errors unsigned int num_symbol_errors = 0; for (i=0; i 10) num_symbols = 10; num_samples = k*num_symbols; FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); fprintf(fid,"k = %u;\n", k); fprintf(fid,"M = %u;\n", M); fprintf(fid,"num_symbols = %u;\n", num_symbols); fprintf(fid,"num_samples = %u;\n", num_samples); fprintf(fid,"nfft = %u;\n", nfft); fprintf(fid,"x = zeros(1,num_samples);\n"); fprintf(fid,"y = zeros(1,num_samples);\n"); for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "gmskmodem_coherent_test.m" // print usage/help message void usage() { printf("gmskmodem_coherent_test -- coherent GMSK demodulation example\n"); printf("options:\n"); printf(" h : print help\n"); printf(" k : samples/symbol, default: 8\n"); printf(" m : filter delay (symbols), default: 3\n"); printf(" b : filter roll-off, default: 0.3\n"); printf(" n : number of data symbols, default: 80\n"); printf(" s : SNR [dB], default: 40\n"); } int main(int argc, char*argv[]) { // options unsigned int k = 8; // filter samples/symbol unsigned int m = 3; // filter delay (symbols) float beta = 0.25f; // GMSK bandwidth-time factor unsigned int num_symbols = 80; // number of data symbols float SNRdB = 40.0f; // signal-to-noise ratio [dB] int dopt; while ((dopt = getopt(argc,argv,"hk:m:b:n:s:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; default: exit(1); } } unsigned int i; // derived values unsigned int num_samples = k*num_symbols; float nstd = powf(10.0f, -SNRdB/20.0f); // arrays unsigned int sym_in [num_symbols]; // input symbols float complex x [num_samples]; // transmitted signal float complex y [num_samples]; // received signal float complex z [num_samples]; // received signal unsigned int sym_out[num_symbols]; // output symbols // create modem objects gmskmod mod = gmskmod_create(k, m, beta); // generate message signal for (i=0; i #include #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "gmskmodem_equalizer_test.m" // print usage/help message void usage() { printf("Usage: gmskmodem_equalizer_test [OPTION]\n"); printf(" h : print help\n"); printf(" n : number of symbols, default: 500\n"); printf(" k : samples/symbol, default: 2\n"); printf(" m : filter semi-length (symbols), default: 4\n"); printf(" b : filter excess bandwidth factor, default: 0.3\n"); printf(" p : equalizer semi-length (symbols), default: 3\n"); printf(" u : equalizer learning rate, default; 0.05\n"); } int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int num_symbols = 1200; // number of symbols to observe unsigned int k = 2; // matched filter samples/symbol unsigned int m = 3; // matched filter delay (symbols) float beta = 0.30f; // GMSK bandwidth-time factor unsigned int p = 3; // equalizer length (symbols, hp_len = 2*k*p+1) float mu = 0.10f; // learning rate unsigned int nfft = 1200; // spectrum estimate FFT size int dopt; while ((dopt = getopt(argc,argv,"hn:k:m:b:p:u:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': num_symbols = atoi(optarg); break; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'p': p = atoi(optarg); break; case 'u': mu = atof(optarg); break; default: exit(1); } } // validate input if (num_symbols == 0) { fprintf(stderr,"error: %s, number of symbols must be greater than zero\n", argv[0]); exit(1); } else if (k < 2) { fprintf(stderr,"error: %s, samples/symbol must be at least 2\n", argv[0]); exit(1); } else if (m == 0) { fprintf(stderr,"error: %s, filter semi-length must be at least 1 symbol\n", argv[0]); exit(1); } else if (beta < 0.0f || beta > 1.0f) { fprintf(stderr,"error: %s, filter excess bandwidth must be in [0,1]\n", argv[0]); exit(1); } else if (p == 0) { fprintf(stderr,"error: %s, equalizer semi-length must be at least 1 symbol\n", argv[0]); exit(1); } else if (mu < 0.0f || mu > 1.0f) { fprintf(stderr,"error: %s, equalizer learning rate must be in [0,1]\n", argv[0]); exit(1); } // derived values unsigned int hm_len = 2*k*m+1; // matched filter length unsigned int hp_len = 2*k*p+1; // equalizer filter length unsigned int num_samples = k*num_symbols; // bookkeeping variables float complex x[num_samples]; // interpolated time series float complex y[num_samples]; // equalized output float hm[hm_len]; // matched filter response float complex hp[hp_len]; // equalizer filter coefficients unsigned int i; // generate matched filter response liquid_firdes_prototype(LIQUID_FIRFILT_GMSKTX, k, m, beta, 0.0f, hm); // create the modem objects modem demod = modem_create(LIQUID_MODEM_QPSK); gmskmod gmod = gmskmod_create(k,m,beta); for (i=0; i #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "gmskmodem_test.m" // print usage/help message void usage() { printf("gmskmodem_test -- Gaussian minimum-shift keying modem example\n"); printf("options (default values in <>):\n"); printf(" u/h : print usage/help\n"); printf(" k : samples/symbol <4>\n"); printf(" m : filter delay [symbols], <3>\n"); printf(" n : number of data symbols <32>\n"); printf(" b : bandwidth-time product, 0 <= b <= 1, <0.3>\n"); printf(" s : SNR [dB] <30>\n"); } int main(int argc, char*argv[]) { // options unsigned int k=4; // filter samples/symbol unsigned int m=3; // filter delay (symbols) float BT=0.5f; // bandwidth-time product unsigned int num_data_symbols = 32; // number of data symbols float SNRdB = 30.0f; // signal-to-noise ratio [dB] int dopt; while ((dopt = getopt(argc,argv,"uhk:m:n:b:s:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'n': num_data_symbols = atoi(optarg); break; case 'b': BT = atof(optarg); break; case 's': SNRdB = atof(optarg); break; default: exit(1); } } unsigned int i; // validate input if (BT <= 0.0f || BT >= 1.0f) { fprintf(stderr,"error: %s, bandwidth-time product must be in (0,1)\n", argv[0]); exit(1); } // derived values unsigned int num_symbols = num_data_symbols + 2*m; unsigned int num_samples = k*num_symbols; unsigned int h_len = 2*k*m+1; float nstd = powf(10.0f, -SNRdB/20.0f); // arrays unsigned char sym_in[num_symbols]; // input symbols float phi[num_samples]; // transmitted phase float complex x[num_samples]; // transmitted signal float complex y[num_samples]; // received signal float phi_hat[num_samples]; // received phase float phi_prime[num_samples]; // matched-filter output unsigned char sym_out[num_symbols]; // output symbols // create transmit/receive interpolator/decimator #if 0 float ht[h_len]; // transmit filter coefficients liquid_firdes_gmsktx(k,m,BT,0.0f,ht); firfilt_rrrf ft = firfilt_rrrf_create(ht,h_len); #else firinterp_rrrf interp_tx = firinterp_rrrf_create_prototype(LIQUID_FIRFILT_GMSKTX,k,m,BT,0); #endif float hr[h_len]; // receive filter coefficients liquid_firdes_gmskrx(k,m,BT,0.0f,hr); firfilt_rrrf decim_rx = firfilt_rrrf_create(hr,h_len); // generate symbols and interpolate float theta = 0.0f; float k_inv = 1.0f / (float)k; for (i=0; i 0.0f ? 1 : 0; printf("%3u : %12.8f (%1u)", n, phi_prime[i], sym_out[n]); if (n >= 2*m) printf(" (%1u)\n", sym_in[n-2*m]); else printf("\n"); n++; } } // compute number of errors unsigned int num_errors = 0; for (i=0; i #include #include #include #include "liquid.h" #define DEBUG 1 int main() { unsigned int i; unsigned int j; unsigned int k; #if 0 // problem definition float A[40] = { 22, 10, 2, 3, 7, 14, 7, 10, 0, 8, -1, 13, -1, -11, 3, -3, -2, 13, -2, 4, 9, 8, 1, -2, 4, 9, 1, -7, 5, -1, 2, -6, 6, 5, 1, 4, 5, 0, -2, 2}; unsigned int m = 8; unsigned int n = 5; #else unsigned int m=8; unsigned int n=5; float A[m*n]; // make random matrix unsigned int t; for (t=0; tk float ck = 1.0 / (2*sk*a0_kk/fabs(a0_kk)*xk); // TODO : use copysign for (i=k+1; i m] float a1_kk1 = matrix_access(A1,m,n,k,k+1); betak = -tk * a1_kk1 / fabs(a1_kk1); // TODO : use copysign #if DEBUG printf(" tk : %12.8f\n", tk); printf(" betak : %12.8f\n", betak); printf(" A1[k,k+1] : %12.8f\n", a1_kk1); #endif // TODO : check dimension size if ( (k+1)==n ) { fprintf(stderr,"warning: maximum dimension exceeded\n"); // copy and exit memmove(A0, A1, m*n*sizeof(float)); break; } if (tk == 0) { for (j=0; j m] float yk1 = (tk == 0) ? 0.0 : sqrt( 0.5*(1 + fabs(a1_kk1)/tk) ); yj[k+1] = yk1; // compute y_j(k) for j > k+1 float dk = 1.0 / (2*tk*a1_kk1/fabs(a1_kk1)*yk1); #if DEBUG printf("dk : %12.8f\n", dk); #endif for (j=k+2; j #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "iirdes_example.m" // print usage/help message void usage() { printf("iirdes_example -- infinite impulse response filter design\n"); printf("options (default values in []):\n"); printf(" u/h : print usage/help\n"); printf(" t : filter type: [butter], cheby1, cheby2, ellip, bessel\n"); printf(" b : filter transformation: [LP], HP, BP, BS\n"); printf(" n : filter order, n > 0 [5]\n"); printf(" r : passband ripple in dB (cheby1, ellip), r > 0 [1.0]\n"); printf(" s : stopband attenuation in dB (cheby2, ellip), s > 0 [60.0]\n"); printf(" f : passband cut-off, 0 < f < 0.5 [0.2]\n"); printf(" c : center frequency (BP, BS cases), 0 < c < 0.5 [0.25]\n"); printf(" o : format [sos], tf\n"); printf(" sos : second-order sections form\n"); printf(" tf : regular transfer function form (potentially\n"); printf(" unstable for large orders\n"); } int main(int argc, char*argv[]) { // options unsigned int n=5; // filter order float fc = 0.20f; // cutoff frequency (low-pass prototype) float f0 = 0.25f; // center frequency (band-pass, band-stop) float As = 60.0f; // stopband attenuation [dB] float ripple = 1.0f; // passband ripple [dB] // filter type liquid_iirdes_filtertype ftype = LIQUID_IIRDES_BUTTER; // band type liquid_iirdes_bandtype btype = LIQUID_IIRDES_LOWPASS; // output format: second-order sections or transfer function liquid_iirdes_format format = LIQUID_IIRDES_SOS; int dopt; while ((dopt = getopt(argc,argv,"uht:b:n:r:s:f:c:o:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 't': if (strcmp(optarg,"butter")==0) { ftype = LIQUID_IIRDES_BUTTER; } else if (strcmp(optarg,"cheby1")==0) { ftype = LIQUID_IIRDES_CHEBY1; } else if (strcmp(optarg,"cheby2")==0) { ftype = LIQUID_IIRDES_CHEBY2; } else if (strcmp(optarg,"ellip")==0) { ftype = LIQUID_IIRDES_ELLIP; } else if (strcmp(optarg,"bessel")==0) { ftype = LIQUID_IIRDES_BESSEL; } else { fprintf(stderr,"error: iirdes_example, unknown filter type \"%s\"\n", optarg); usage(); exit(1); } break; case 'b': if (strcmp(optarg,"LP")==0) { btype = LIQUID_IIRDES_LOWPASS; } else if (strcmp(optarg,"HP")==0) { btype = LIQUID_IIRDES_HIGHPASS; } else if (strcmp(optarg,"BP")==0) { btype = LIQUID_IIRDES_BANDPASS; } else if (strcmp(optarg,"BS")==0) { btype = LIQUID_IIRDES_BANDSTOP; } else { fprintf(stderr,"error: iirdes_example, unknown band type \"%s\"\n", optarg); usage(); exit(1); } break; case 'n': n = atoi(optarg); break; case 'r': ripple = atof(optarg); break; case 's': As = atof(optarg); break; case 'f': fc = atof(optarg); break; case 'c': f0 = atof(optarg); break; case 'o': if (strcmp(optarg,"sos")==0) { format = LIQUID_IIRDES_SOS; } else if (strcmp(optarg,"tf")==0) { format = LIQUID_IIRDES_TF; } else { fprintf(stderr,"error: iirdes_example, unknown output format \"%s\"\n", optarg); usage(); exit(1); } break; default: exit(1); } } // validate input if (fc <= 0 || fc >= 0.5) { fprintf(stderr,"error: %s, cutoff frequency out of range\n", argv[0]); usage(); exit(1); } else if (f0 < 0 || f0 > 0.5) { fprintf(stderr,"error: %s, center frequency out of range\n", argv[0]); usage(); exit(1); } else if (ripple <= 0) { fprintf(stderr,"error: %s, pass-band ripple out of range\n", argv[0]); usage(); exit(1); } else if (As <= 0) { fprintf(stderr,"error: %s, stop-band ripple out of range\n", argv[0]); usage(); exit(1); } // number of analaog poles/zeros unsigned int npa = n; unsigned int nza; // analog poles/zeros/gain float complex pa[n]; float complex za[n]; float complex ka; float complex k0; unsigned int r = n%2; unsigned int L = (n-r)/2; unsigned int i; // specific filter variables float epsilon, Gp, Gs, ep, es; switch (ftype) { case LIQUID_IIRDES_BUTTER: printf("Butterworth filter design:\n"); nza = 0; k0 = 1.0f; butter_azpkf(n,za,pa,&ka); break; case LIQUID_IIRDES_CHEBY1: printf("Cheby-I filter design:\n"); nza = 0; epsilon = sqrtf( powf(10.0f, ripple / 10.0f) - 1.0f ); k0 = r ? 1.0f : 1.0f / sqrtf(1.0f + epsilon*epsilon); cheby1_azpkf(n,epsilon,za,pa,&ka); break; case LIQUID_IIRDES_CHEBY2: printf("Cheby-II filter design:\n"); nza = 2*L; epsilon = powf(10.0f, -As/20.0f); k0 = 1.0f; cheby2_azpkf(n,epsilon,za,pa,&ka); break; case LIQUID_IIRDES_ELLIP: printf("elliptic filter design:\n"); nza = 2*L; Gp = powf(10.0f, -ripple / 20.0f); Gs = powf(10.0f, -As / 20.0f); printf(" Gp = %12.8f\n", Gp); printf(" Gs = %12.8f\n", Gs); // epsilon values ep = sqrtf(1.0f/(Gp*Gp) - 1.0f); es = sqrtf(1.0f/(Gs*Gs) - 1.0f); k0 = r ? 1.0f : 1.0f / sqrtf(1.0f + ep*ep); ellip_azpkf(n,ep,es,za,pa,&ka); break; case LIQUID_IIRDES_BESSEL: printf("Bessel filter design:\n"); bessel_azpkf(n,za,pa,&ka); k0 = 1.0f; nza = 0; break; default: fprintf(stderr,"error: iirdes_example: unknown filter type\n"); exit(1); } printf("poles (analog):\n"); for (i=0; i 2*n r = 0; L = n; n = 2*n; } fprintf(fid,"n=%u;\n", n); fprintf(fid,"r=%u;\n", r); fprintf(fid,"L=%u;\n", L); fprintf(fid,"nfft=1024;\n"); // print digital z/p/k fprintf(fid,"zd = zeros(1,n);\n"); fprintf(fid,"pd = zeros(1,n);\n"); for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "iirfilt_intdiff_test.m" int main(int argc, char*argv[]) { // options unsigned int num_samples = 801; // // integrator digital zeros/poles/gain, [Pintelon:1990] Table II // // zeros, digital, integrator float complex zdi[8] = { 1.175839 * -1.0f, 3.371020 * cexpf(_Complex_I * M_PI / 180.0f * -125.1125f), 3.371020 * cexpf(_Complex_I * M_PI / 180.0f * 125.1125f), 4.549710 * cexpf(_Complex_I * M_PI / 180.0f * -80.96404f), 4.549710 * cexpf(_Complex_I * M_PI / 180.0f * 80.96404f), 5.223966 * cexpf(_Complex_I * M_PI / 180.0f * -40.09347f), 5.223966 * cexpf(_Complex_I * M_PI / 180.0f * 40.09347f), 5.443743,}; // poles, digital, integrator float complex pdi[8] = { 0.5805235f * -1.0f, 0.2332021f * cexpf(_Complex_I * M_PI / 180.0f * -114.0968f), 0.2332021f * cexpf(_Complex_I * M_PI / 180.0f * 114.0968f), 0.1814755f * cexpf(_Complex_I * M_PI / 180.0f * -66.33969f), 0.1814755f * cexpf(_Complex_I * M_PI / 180.0f * 66.33969f), 0.1641457f * cexpf(_Complex_I * M_PI / 180.0f * -21.89539f), 0.1641457f * cexpf(_Complex_I * M_PI / 180.0f * 21.89539f), 1.0f,}; // gain, digital, integrator float complex kdi = -1.89213380759321e-05f; #if 1 // second-order sections // allocate 12 values for 4 second-order sections each with // 2 roots (order 8), e.g. (1 + r0 z^-1)(1 + r1 z^-1) float Bi[12]; float Ai[12]; iirdes_dzpk2sosf(zdi, pdi, 8, kdi, Bi, Ai); // create integrator iirfilt_crcf integrator = iirfilt_crcf_create_sos(Bi,Ai,4); #else // regular transfer function form // 9 = order + 1 float bi[9]; float ai[9]; iirdes_dzpk2tff(zdi, pdi, 8, kdi, bi, ai); iirfilt_crcf integrator = iirfilt_crcf_create(bi,9,ai,9); #endif // // differentiator digital zeros/poles/gain, [Pintelon:1990] Table IV // // zeros, digital, differentiator float complex zdd[8] = { 1.702575f * -1.0f, 5.877385f * cexpf(_Complex_I * M_PI / 180.0f * -221.4063f), 5.877385f * cexpf(_Complex_I * M_PI / 180.0f * 221.4063f), 4.197421f * cexpf(_Complex_I * M_PI / 180.0f * -144.5972f), 4.197421f * cexpf(_Complex_I * M_PI / 180.0f * 144.5972f), 5.350284f * cexpf(_Complex_I * M_PI / 180.0f * -66.88802f), 5.350284f * cexpf(_Complex_I * M_PI / 180.0f * 66.88802f), 1.0f,}; // poles, digital, differentiator float complex pdd[8] = { 0.8476936f * -1.0f, 0.2990781f * cexpf(_Complex_I * M_PI / 180.0f * -125.5188f), 0.2990781f * cexpf(_Complex_I * M_PI / 180.0f * 125.5188f), 0.2232427f * cexpf(_Complex_I * M_PI / 180.0f * -81.52326f), 0.2232427f * cexpf(_Complex_I * M_PI / 180.0f * 81.52326f), 0.1958670f * cexpf(_Complex_I * M_PI / 180.0f * -40.51510f), 0.1958670f * cexpf(_Complex_I * M_PI / 180.0f * 40.51510f), 0.1886088f,}; // gain, digital, differentiator float complex kdd = 2.09049284907492e-05f; #if 1 // second-order sections // allocate 12 values for 4 second-order sections each with // 2 roots (order 8), e.g. (1 + r0 z^-1)(1 + r1 z^-1) float Bd[12]; float Ad[12]; iirdes_dzpk2sosf(zdd, pdd, 8, kdd, Bd, Ad); // create differentiator iirfilt_crcf differentiator = iirfilt_crcf_create_sos(Bd,Ad,4); #else // regular transfer function form // 9 = order + 1 float bd[9]; float ad[9]; iirdes_dzpk2tff(zdd, pdd, 8, kdd, bd, ad); iirfilt_crcf differentiator = iirfilt_crcf_create(bd,9,ad,9); #endif // allocate arrays float complex x[num_samples]; float complex y[num_samples]; float complex z[num_samples]; float tmin = 0.0f; float tmax = 1.0f; float dt = (tmax-tmin)/(float)(num_samples-1); unsigned int i; for (i=0; i #include #include #include #include "liquid.internal.h" int main() { unsigned int p=10; // derived values float r[p+1]; float a_matrixinv[p+1]; float a_levinson[p+1]; unsigned int i; unsigned int j; for (i=0; ij) ? (i-j) : (j-i)]; // abs(i-j) } // invert matrix (using Gauss-Jordan elimination) matrixf_inv(R,p,p); float rt[p]; float a_hat[p]; for (i=0; i #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "matched_filter_cfo_test.m" // print usage/help message void usage() { printf("matched_filter_cfo_test options:\n"); printf(" u/h : print usage/help\n"); printf(" t : filter type: [rrcos], rkaiser, arkaiser, hM3\n"); printf(" k : filter samples/symbol, k >= 2, default: 2\n"); printf(" m : filter delay (symbols), m >= 1, default: 3\n"); printf(" b : filter excess bandwidth factor, 0 < b < 1, default: 0.5\n"); printf(" n : number of symbols, default: 16\n"); printf(" P : carrier phase offset, default: 0\n"); printf(" F : carrier frequency offset, default: 0.8\n"); printf(" c : compensate for carrier frequency offset in matched filter? default: no\n"); } int main(int argc, char*argv[]) { // options unsigned int k=2; // samples/symbol unsigned int m=4; // symbol delay float beta=0.3f; // excess bandwidth factor float phi = 0.0f; // carrier phase offset float dphi = 0.8f; // carrier frequency offset unsigned int num_symbols=128; int cfo_compensation=0; // compensate for carrier offset in matched filter? enum { FILTER_RRCOS=0, FILTER_RKAISER, FILTER_ARKAISER, FILTER_hM3 } ftype = 0; // filter prototype int dopt; while ((dopt = getopt(argc,argv,"uht:k:m:b:n:P:F:c")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 't': if (strcmp(optarg,"rrcos")==0) { ftype = FILTER_RRCOS; } else if (strcmp(optarg,"rkaiser")==0) { ftype = FILTER_RKAISER; } else if (strcmp(optarg,"arkaiser")==0) { ftype = FILTER_ARKAISER; } else if (strcmp(optarg,"hM3")==0) { ftype = FILTER_hM3; } else { fprintf(stderr,"error: %s, unknown filter type '%s'\n", argv[0], optarg); exit(1); } break; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 'P': phi = atof(optarg); break; case 'F': dphi = atof(optarg); break; case 'c': cfo_compensation=1; break; default: exit(1); } } if (k < 2) { fprintf(stderr,"error: %s, k must be at least 2\n", argv[0]); exit(1); } else if (m < 1) { fprintf(stderr,"error: %s, m must be at least 1\n", argv[0]); exit(1); } else if (beta <= 0.0f || beta >= 1.0f) { fprintf(stderr,"error: %s, beta must be in (0,1)\n", argv[0]); exit(1); } // initialize objects unsigned int h_len = 2*k*m+1; float h[h_len]; switch (ftype) { case FILTER_RRCOS: liquid_firdes_rrcos(k,m,beta,0,h); break; case FILTER_RKAISER: liquid_firdes_rkaiser(k,m,beta,0,h); break; case FILTER_ARKAISER: liquid_firdes_arkaiser(k,m,beta,0,h); break; case FILTER_hM3: liquid_firdes_hM3(k,m,beta,0,h); break; default: // should never get to this point fprintf(stderr,"error: %s, invalid filter type\n", argv[0]); exit(1); } // derived values unsigned int num_samples = num_symbols*k; // generate receive filter coefficients (reverse of transmit) float complex gc[h_len]; unsigned int i; for (i=0; i=2*m) printf(" *\n"); else printf("\n"); #endif } // clean up objects firinterp_crcf_destroy(interp); firdecim_cccf_destroy(decim); FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"k = %u;\n", k); fprintf(fid,"m = %u;\n", m); fprintf(fid,"beta = %12.8f;\n", beta); fprintf(fid,"num_symbols = %u;\n", num_symbols); fprintf(fid,"num_samples = k*num_symbols;\n"); fprintf(fid,"y = zeros(1,num_samples);\n"); for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "matched_filter_test.m" // print usage/help message void usage() { printf("matched_filter_test options:\n"); printf(" u/h : print usage/help\n"); printf(" k : filter samples/symbol, k >= 2, default: 4\n"); printf(" m : filter delay (symbols), m >= 1, default: 2\n"); printf(" b : filter excess bandwidth factor, 0 < b < 1, default: 0.9\n"); } int main(int argc, char*argv[]) { // options unsigned int k=4; // samples/symbol unsigned int m=2; // symbol delay float beta=0.9f; // excess bandwidth factor int dopt; while ((dopt = getopt(argc,argv,"uhk:m:b:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; default: exit(1); } } if (k < 2) { fprintf(stderr,"error: %s, k must be at least 2\n", argv[0]); exit(1); } else if (m < 1) { fprintf(stderr,"error: %s, m must be at least 1\n", argv[0]); exit(1); } else if (beta <= 0.0f || beta >= 1.0f) { fprintf(stderr,"error: %s, beta must be in (0,1)\n", argv[0]); exit(1); } // design filter unsigned int h_len = 2*k*m+1; float h[h_len]; liquid_firdes_rrcos(k,m,beta,0,h); // truncate filter to be of length 2*k*m unsigned int g_len = 2*k*m; // generate receive filter coefficients (reverse of transmit) float g[g_len]; unsigned int i; for (i=0; i #include #include #include #define sandbox_randf() ((float) rand() / (float) RAND_MAX) float complex sandbox_cacosf(float complex _z) { // return based on quadrant int sign_i = crealf(_z) > 0; int sign_q = cimagf(_z) > 0; if (sign_i == sign_q) { return - _Complex_I*clogf(_z + csqrtf(_z*_z - 1.0f)); } else { return - _Complex_I*clogf(_z - csqrtf(_z*_z - 1.0f)); } // should never get to this state return 0.0f; } int main() { unsigned int n=32; // number of tests unsigned int d=2; // number items per line // data arrays float complex z[n]; float complex test[n]; float complex err_max = 0.0f; unsigned int i; for (i=0; i cabsf(err_max) ) err_max = err; } printf("maximum error: %12.4e;\n", cabsf(err_max)); // // print autotest lines // printf("\n"); printf(" float complex z[%u] = {\n ", n); for (i=0; i #include #include #include #define sandbox_randf() ((float) rand() / (float) RAND_MAX) float complex sandbox_cacosf(float complex _z) { // return based on quadrant int sign_i = crealf(_z) > 0; int sign_q = cimagf(_z) > 0; if (sign_i == sign_q) { return - _Complex_I*clogf(_z + csqrtf(_z*_z - 1.0f)); } else { return - _Complex_I*clogf(_z - csqrtf(_z*_z - 1.0f)); } // should never get to this state return 0.0f; } float complex sandbox_casinf(float complex _z) { return 0.5f*M_PI - sandbox_cacosf(_z); } int main() { unsigned int n=32; // number of tests unsigned int d=2; // number items per line // data arrays float complex z[n]; float complex test[n]; float complex err_max = 0.0f; unsigned int i; for (i=0; i cabsf(err_max) ) err_max = err; } printf("maximum error: %12.4e;\n", cabsf(err_max)); // // print autotest lines // printf("\n"); printf(" float complex z[%u] = {\n ", n); for (i=0; i #include #include #include #define sandbox_randf() ((float) rand() / (float) RAND_MAX) float complex sandbox_catanf(float complex _z) { return 0.5f*_Complex_I*clogf( (1.0f-_Complex_I*_z)/(1.0f+_Complex_I*_z) ); } int main() { unsigned int n=32; // number of tests unsigned int d=2; // number items per line // data arrays float complex z[n]; float complex test[n]; float complex err_max = 0.0f; unsigned int i; for (i=0; i cabsf(err_max) ) err_max = err; } printf("maximum error: %12.4e;\n", cabsf(err_max)); // // print autotest lines // printf("\n"); printf(" float complex z[%u] = {\n ", n); for (i=0; i #include #include #include #define sandbox_randf() ((float) rand() / (float) RAND_MAX) float complex sandbox_cexpf(float complex _z) { float r = expf( crealf(_z) ); float complex re = cosf( cimagf(_z) ); float complex im = sinf( cimagf(_z) ); return r*(re + _Complex_I*im); } int main() { unsigned int n=32; // number of tests unsigned int d=2; // number items per line // data arrays float complex z[n]; float complex test[n]; unsigned int i; float complex err_max = 0.0f; for (i=0; i cabsf(err_max) ) err_max = err; } printf("maximum error: %12.4e;\n", cabsf(err_max)); // // print autotest lines // printf("\n"); printf(" float complex z[%u] = {\n ", n); for (i=0; i #include #include #include #define sandbox_randf() ((float) rand() / (float) RAND_MAX) float complex sandbox_clogf(float complex _z) { return logf(cabsf(_z)) + _Complex_I*cargf(_z); } int main() { unsigned int n=32; // number of tests unsigned int d=2; // number items per line // data arrays float complex z[n]; float complex test[n]; unsigned int i; float complex err_max = 0.0f; for (i=0; i cabsf(err_max) ) err_max = err; } printf("maximum error: %12.4e;\n", cabsf(err_max)); // // print autotest lines // printf("\n"); printf(" float complex z[%u] = {\n ", n); for (i=0; i #include #include #include #define sandbox_randf() ((float) rand() / (float) RAND_MAX) float complex sandbox_csqrtf(float complex _z) { float r = cabsf(_z); // magnitude of _z float a = crealf(_z); // real component of _z float re = sqrtf(0.5f*(r+a)); // real component of return value float im = sqrtf(0.5f*(r-a)); // imag component of return value // return value, retaining sign of imaginary component return cimagf(_z) > 0 ? re + _Complex_I*im : re - _Complex_I*im; } int main() { unsigned int n=32; // number of tests unsigned int d=2; // number of items per line // data arrays float complex z[n]; float complex test[n]; float complex err_max = 0.0f; unsigned int i; for (i=0; i cabsf(err_max) ) err_max = err; } printf("maximum error: %12.4e;\n", cabsf(err_max)); // // print autotest lines // printf("\n"); printf(" float complex z[%u] = {\n ", n); for (i=0; i #include #include #include "liquid.h" float z[41] = { 0.00100000, 0.00125890, 0.00158490, 0.00199530, 0.00251190, 0.00316230, 0.00398110, 0.00501190, 0.00630960, 0.00794330, 0.01000000, 0.01258900, 0.01584900, 0.01995300, 0.02511900, 0.03162300, 0.03981100, 0.05011900, 0.06309600, 0.07943300, 0.10000000, 0.12589000, 0.15849000, 0.19953000, 0.25119000, 0.31623000, 0.39811000, 0.50119000, 0.63096000, 0.79433000, 1.00000000, 1.25890000, 1.58490000, 1.99530000, 2.51190000, 3.16230000, 3.98110000, 5.01190000, 6.30960000, 7.94330000, 10.00000000}; float lngamma_test[41] = { 6.90720000, 6.67680000, 6.44630000, 6.21580000, 5.98530000, 5.75460000, 5.52390000, 5.29310000, 5.06210000, 4.83090000, 4.59950000, 4.36780000, 4.13570000, 3.90320000, 3.67010000, 3.43640000, 3.20190000, 2.96640000, 2.72990000, 2.49200000, 2.25270000, 2.01200000, 1.76980000, 1.52660000, 1.28300000, 1.04050000, 0.80154000, 0.57004000, 0.35224000, 0.15757000, 0.00000000, -0.10025000, -0.11440000, -0.00199580, 0.29308000, 0.84799000, 1.76800000, 3.19600000, 5.32420000, 8.41110000, 12.80200000}; float sandbox_lngammaf(float _z, float * _v) { float v0 = _v[0]; float v1 = _v[1]; // z = 10.^[-3:0.1:1]; // t0 = log(gamma(z)); // t1 = (1+z-0.5).*log(1+z) - (1+z) + 0.5*log(2*pi) - log(z) + 0.0405*(1-tanh(0.5*log(z))); // float g_hat = (0.5f+_z)*logf(1.0f+_z) - (1.0f+_z) + 0.5f*logf(2*M_PI) - logf(_z) + v0*(1.0f - tanhf(v1*logf(_z))); return g_hat; } // gradient search curve-fit error float gserror(void * _userdata, float * _v, unsigned int _n) { // compute error float rmse = 0.0f; unsigned int i; for (i=0; i<41; i++) { float g = sandbox_lngammaf(z[i], _v); float e = g - lngamma_test[i]; rmse += e*e; } return sqrtf(rmse / 41.0f); } int main() { unsigned int num_iterations = 1000; // number of iterations to run float v[2] = {0.0405f, 0.5f}; // gradsearch gs = gradsearch_create(NULL,v,2,gserror,LIQUID_OPTIM_MINIMIZE); // execute search one iteration at a time unsigned int i; float rmse; for (i=0; i #include #include "liquid.h" int main() { unsigned int num_iterations=8; #if 0 unsigned int n=4; float A[16] = { 1,2,3,4, 5,5,7,8, 6,4,8,7, 1,0,3,1}; #else unsigned int n=3; float A[9] = { 1.0f, 1.0f, 1.0f, 1.0f, 2.0f, 1.0f, 1.0f, 1.0f, 2.0f}; #endif float eig[n]; float A0[n*n]; float Q[n*n], R[n*n]; memmove(A0, A, n*n*sizeof(float)); printf("\n"); printf("testing Q/R decomposition [Gram-Schmidt]\n"); matrixf_qrdecomp_gramschmidt(A,n,n,Q,R); //matrixf_print(Q,n,n); //matrixf_print(R,n,n); unsigned int k; for (k=0; k #include #include #include "liquid.h" int main() { float x[6] = { 1, 2, 3, 4, 5, 6}; float y[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9}; float z[6]; // compute z = x * y printf("z = x * y :\n"); matrixf_mul(x,2,3,y,3,3,z,2,3); matrixf_print(z,2,3); /* // compute z = y * x' matrixf_transpose(x); printf("x' : \n"); matrixf_print(x); matrixf_transpose(z); matrixf_multiply(y,x,z); printf("z = y * x' :\n"); matrixf_print(z); matrixf_destroy(x); matrixf_destroy(y); matrixf_destroy(z); */ float s[16] = { 1,2,3,4, 5,5,7,8, 6,4,8,7, 1,0,3,1}; float s_inv[16]; memmove(s_inv,s,16*sizeof(float)); matrixf_inv(s_inv,4,4); float i4[16]; matrixf_mul(s,4,4,s_inv,4,4,i4,4,4); printf("\ns:\n"); matrixf_print(s,4,4); printf("\ninv(s):\n"); matrixf_print(s_inv,4,4); printf("\ns*inv(s):\n"); matrixf_print(i4,4,4); printf("\n"); float det = matrixf_det(s,4,4); printf("det(s) = %12.8f\n", det); #if 0 // pivot test (matrix inversion) float t[32] = { 1,2,3,4, 1,0,0,0, 5,5,7,8, 0,1,0,0, 6,4,8,7, 0,0,1,0, 1,0,3,1, 0,0,0,1}; unsigned int i; for (i=0; i<4; i++) { matrixf_pivot(t,4,8,i,i); matrixf_print(t,4,8); } unsigned int j; for (i=0; i<4; i++) { float v = matrix_access(t,4,8,i,i); for (j=0; j<8; j++) matrix_access(t,4,8,i,j) /= v; } matrixf_print(t,4,8); #endif printf("\n"); printf("testing L/U decomposition [Crout's method]\n"); float L[16], U[16], P[16]; matrixf_ludecomp_crout(s,4,4,L,U,P); matrixf_print(L,4,4); matrixf_print(U,4,4); printf("\n"); printf("testing L/U decomposition [Doolittle's method]\n"); matrixf_ludecomp_doolittle(s,4,4,L,U,P); matrixf_print(L,4,4); matrixf_print(U,4,4); printf("\n\n"); float X[16] = { 0.84382, -2.38304, 1.43061, -1.66604, 3.99475, 0.88066, 4.69373, 0.44563, 7.28072, -2.06608, 0.67074, 9.80657, 6.07741, -3.93099, 1.22826, -0.42142}; float Y[16]; printf("\nX:\n"); matrixf_print(X,4,4); // swaprows memmove(Y,X,16*sizeof(float)); matrixf_swaprows(Y,4,4,0,2); printf("\nmatrixf_swaprows(X,4,4,0,2):\n"); matrixf_print(Y,4,4); // pivot test memmove(Y,X,16*sizeof(float)); matrixf_pivot(Y,4,4,1,2); printf("\nmatrixf_pivot(X,4,4,1,2):\n"); matrixf_print(Y,4,4); // inverse test memmove(Y,X,16*sizeof(float)); matrixf_inv(Y,4,4); printf("\nmatrixf_inv(X,4,4):\n"); matrixf_print(Y,4,4); // determinant test float D = matrixf_det(X,4,4); printf("\nmatrixf_det(X,4) = %12.8f\n", D); // L/U decomp (Crout's method) matrixf_ludecomp_crout(X,4,4,L,U,P); printf("\nmatrixf_ludecomp_crout(X,4,4,L,U,P)\n"); printf("L:\n"); matrixf_print(L,4,4); printf("U:\n"); matrixf_print(U,4,4); // L/U decomp (Doolittle's method) matrixf_ludecomp_doolittle(X,4,4,L,U,P); printf("\nmatrixf_ludecomp_doolittle(X,4,4,L,U,P)\n"); printf("L:\n"); matrixf_print(L,4,4); printf("U:\n"); matrixf_print(U,4,4); printf("\n"); printf("testing Q/R decomposition [Gram-Schmidt]\n"); float Q[16], R[16]; matrixf_qrdecomp_gramschmidt(X,4,4,Q,R); matrixf_print(Q,4,4); matrixf_print(R,4,4); /* float b[4] = { 0.91489, 0.71789, 1.06553, -0.81707}; */ float Xb[20] = { 0.84382, -2.38304, 1.43061, -1.66604, 0.91489, 3.99475, 0.88066, 4.69373, 0.44563, 0.71789, 7.28072, -2.06608, 0.67074, 9.80657, 1.06553, 6.07741, -3.93099, 1.22826, -0.42142, -0.81707}; printf("\n[X b] =\n"); matrixf_print(Xb,4,5); matrixf_gjelim(Xb,4,5); printf("\nmatrixf_gjelim(Xb,4,5)\n"); matrixf_print(Xb,4,5); // compute a*a' float a[20] = { -0.24655, -1.78843, 0.39477, 0.43735, -1.08998, -0.42751, 0.62496, 1.43802, 0.19814, 0.78155, -0.35658, -0.81875, -1.09984, 1.87006, -0.94191, 0.39553, -2.02036, 1.17393, 1.54591, 1.29663}; printf("\na =\n"); matrixf_print(a,4,5); printf("\n\n"); printf("computing a*a'\n"); float aaT[16]; matrixf_mul_transpose(a,4,5,aaT); matrixf_print(aaT,4,4); printf("\n\n"); printf("computing a'*a\n"); float aTa[25]; matrixf_transpose_mul(a,4,5,aTa); matrixf_print(aTa,5,5); printf("\n"); printf("testing Gram-Schmidt\n"); float Xgs[12] = { 1., 2., 1., 0., 2., 0., 2., 3., 1., 1., 1., 0.}; float Ugs[12]; float Ugs_test[12] = { sqrtf(6.)/6., sqrtf(2.)/6., 2./3., 0., 2.*sqrtf(2.)/3.,-1./3., sqrtf(6.)/3., 0., 0., sqrtf(6.)/6., -sqrtf(2.)/6., -2./3.}; matrixf_gramschmidt(Xgs,4,3,Ugs); printf("X:\n"); matrixf_print(Xgs,4,3); printf("normalized X:\n"); matrixf_print(Ugs,4,3); printf("expected:\n"); matrixf_print(Ugs_test,4,3); // // test Cholesky decomposition // printf("\n"); printf("testing Cholesky decomposition\n"); // generate input matrix float complex Lp[9] = { 1.0, 0.0, 0.0, -3.1 + 0.2*_Complex_I, 0.3, 0.0, 1.7 + 0.5*_Complex_I, -0.6 - 0.3*_Complex_I, 2.9}; float complex Ap[9]; matrixcf_mul_transpose(Lp, 3, 3, Ap); float complex Lc[9]; matrixcf_chol(Ap, 3, Lc); printf("Lp:\n"); matrixcf_print(Lp, 3, 3); printf("Ap:\n"); matrixcf_print(Ap, 3, 3); printf("Lc:\n"); matrixcf_print(Lc, 3, 3); printf("done.\n"); return 0; } liquid-dsp-1.3.1/sandbox/mdct_test.c000066400000000000000000000106241317124540100173600ustar00rootroot00000000000000// // mdct_example.c // // Modified discrete cosine transform (MDCT) example. Demonstrates // the functionality and interface for the mdct and imdct routines. // #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "mdct_example.m" int main() { // MDCT options unsigned int num_channels=64; // MDCT size unsigned int num_symbols=16; // filter options unsigned int h_len=21; // filter length float fc=0.01f; // filter cutoff float As=60.0f; // stop-band attenuation [dB] float mu=0.0f; // timing offset // derived values unsigned int i,j; unsigned int num_samples = num_channels*num_symbols; float x[num_samples]; float X[num_samples]; float y[num_samples]; for (i=0; i #include #include #include double function(double _x) { #if 0 // -sin(x) minimum at x = pi/2 double y = 1.0f-sin(_x); #else // exp(-(x-pi/2)^2) double t = _x - M_PI/2; double y = 1-exp(-t*t); #endif return y; } int main() { // options unsigned int num_iterations = 10; double x0; // lower value double x1 = 1.2f; // middle value (initial guess) double x2; // upper value double dx = 2.0f; // step size double gamma = 0.7f;// step size reduction double tol = 1e-6f; // error tolerance // choose x0, x2 x0 = x1 - dx; x2 = x1 + dx; // double y0, y1, y2; double x_hat; double del = 0.0f; unsigned int i; for (i=0; i x1); assert(x1 > x0); // compute minimum // TODO : exploit uniform spacing... double t0 = y0*(x1*x1 - x2*x2) + y1*(x2*x2 - x0*x0) + y2*(x0*x0 - x1*x1); double t1 = y0*(x1 - x2) + y1*(x2 - x0) + y2*(x0 - x1); x_hat = 0.5f * t0 / t1; del = x_hat - x1; // print printf("%4u : %12.8f, e=%12.4e, del: %12.4e\n", i, x_hat, x_hat-M_PI/2, del); // reduce step size dx *= gamma; // x0 = x_hat - dx; x2 = x_hat + dx; if (fabs(del) < tol) break; } printf("estimated minimum : %f (%f)\n", x_hat, M_PI/2); return 0; } liquid-dsp-1.3.1/sandbox/minsearch_test.c000066400000000000000000000035471317124540100204100ustar00rootroot00000000000000// // minsearch.c // // search to find minimum of a function using parabolic // interpolation // #include #include #include #include double function(double _x) { #if 0 // -sin(x) minimum at x = pi/2 double y = 1.0f-sin(_x); #else // exp(-(x-pi/2)^2) double t = _x - M_PI/2; double y = -exp(-t*t); #endif return y; } int main() { // options unsigned int num_iterations = 10; double x0 = 0.3f; // lower value double x1; // middle value (ignored) double x2 = 3.1f; // upper value double tol = 1e-6f; // error tolerance // double y0 = function(x0); double y1; double y2 = function(x2); double x_hat; double del = 0.0f; unsigned int i; for (i=0; i x1); assert(x1 > x0); // compute minimum double t0 = y0*(x1*x1 - x2*x2) + y1*(x2*x2 - x0*x0) + y2*(x0*x0 - x1*x1); double t1 = y0*(x1 - x2) + y1*(x2 - x0) + y2*(x0 - x1); x_hat = 0.5f * t0 / t1; del = x_hat - x1; // print printf("%4u : %12.8f, e=%12.4e\n", i, x_hat, x_hat-M_PI/2); if (x_hat > x1) { // new minimum x0 = x1; y0 = y1; } else { // new maximum x2 = x1; y2 = y1; } if (fabs(del) < tol) break; } printf("estimated minimum : %f (%f)\n", x_hat, M_PI/2); return 0; } liquid-dsp-1.3.1/sandbox/modem_demodulate_arb_gentab.c000066400000000000000000000242171317124540100230450ustar00rootroot00000000000000// // modem_demodulate_arb_gentab.c // // Generate fast demodulation tables for arbitrary modems; use existing // modulation scheme with fast decoding (e.g. 16-QAM) and associate // these constellation points with the arbitrary constellation points. // The goal is to allow the demodulator to first demodulate the // received point using the fast demodulator and then perform a search // over only the set of nearby points. This script computes the look-up // table for these nearby points and stores them as an array of // indices. // #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "modem_demodulate_arb_gentab.m" #define DEBUG 0 // print usage/help message void usage() { printf("sandbox/modem_demodulate_arb_gentab [options]\n"); printf(" u/h : print usage\n"); printf(" m : input modulation scheme (arb64vt default)\n"); printf(" r : reference modulation scheme (qam16 default)\n"); liquid_print_modulation_schemes(); printf(" a : alpha (reference scheme gain), default: 1.0\n"); } // search for nearest constellation points to reference points void modem_arbref_search(float complex * _c, unsigned int _M, float complex * _cref, unsigned int _p, unsigned char * _index, unsigned int _s); // search for nearest constellation points to single reference point void modem_arbref_search_point(float complex * _c, unsigned int _M, float complex _cref, unsigned char * _index, unsigned int _s); // find unassigned constellation points unsigned int modem_arbref_search_unassigned(unsigned char * _index, unsigned int _M, unsigned int _p, unsigned int _s, unsigned char * _assigned); int main(int argc, char*argv[]) { // create mod/demod objects modulation_scheme ms = LIQUID_MODEM_ARB64VT; modulation_scheme mref = LIQUID_MODEM_QAM64; float alpha = 1.0f; int dopt; while ((dopt = getopt(argc,argv,"uhp:m:r:a:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'm': ms = liquid_getopt_str2mod(optarg); if (ms == LIQUID_MODEM_UNKNOWN) { fprintf(stderr,"error: %s, unknown/unsupported modulation scheme '%s'\n", argv[0], optarg); return 1; } break; case 'r': mref = liquid_getopt_str2mod(optarg); if (mref == LIQUID_MODEM_UNKNOWN) { fprintf(stderr,"error: %s, unknown/unsupported modulation scheme '%s'\n", argv[0], optarg); return 1; } break; case 'a': alpha = atof(optarg); break; default: exit(1); } } // validate input unsigned int i; unsigned int j; // initialize reference points modem qref = modem_create(mref); unsigned int kref = modem_get_bps(qref); unsigned int p = 1 << kref; float complex cref[p]; for (i=0; i 0); // print table printf("\n"); printf("unsigned char modem_demodulate_gentab[%u][%u] = {\n", p, s); for (i=0; i _M) { fprintf(stderr,"error: modem_arbref_search(), index size exceeds constellation size\n"); exit(1); } // unsigned int i; for (i=0; i<_p; i++) modem_arbref_search_point(_c, _M, _cref[i], &_index[_s*i], _s); } // search for nearest constellation points to single reference point void modem_arbref_search_point(float complex * _c, unsigned int _M, float complex _cref, unsigned char * _index, unsigned int _s) { #if DEBUG printf("searching neighbors to (%8.3f,%8.3f)\n", crealf(_cref), cimagf(_cref)); #endif // initialize array of selected element flags unsigned char selected[_M]; memset(selected, 0x00, _M); unsigned int i; unsigned int n; for (n=0; n<_s; n++) { int min_found = 0; float d; float dmin = 0.0f; unsigned int index_min = 0; for (i=0; i<_M; i++) { // ignore constellation point if it has already been // selected if (selected[i]==1) continue; // compute distance d = crealf( (_c[i]-_cref)*conjf(_c[i]-_cref) ); if ( d < dmin || !min_found ) { dmin = d; index_min = i; min_found = 1; } } // save minimum index _index[n] = index_min; // flag point as 'selected' selected[index_min] = 1; #if DEBUG printf("%6u (%8.3f,%8.3f)\n", index_min, crealf(_c[index_min]), cimagf(_c[index_min])); #endif } } // find unassigned constellation points unsigned int modem_arbref_search_unassigned(unsigned char * _index, unsigned int _M, unsigned int _p, unsigned int _s, unsigned char * _assigned) { unsigned int num_unassigned = 0; // unsigned int i; for (i=0; i<_M; i++) { // initialized 'assigned' flag to false _assigned[i] = 0; unsigned int j; for (j=0; j<_p; j++) { // see if this constellation point has been assigned // to this reference unsigned int k; for (k=0; k<_s; k++) { if (_index[j*_s+k] == i) _assigned[i] = 1; } } if (!_assigned[i]) num_unassigned++; } return num_unassigned; } liquid-dsp-1.3.1/sandbox/modem_demodulate_soft_gentab.c000066400000000000000000000271671317124540100232630ustar00rootroot00000000000000// // modem_demodulate_soft_gentab.c // // Generates table of nearest symbols and tests soft demodulation // #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "modem_demodulate_soft_gentab.m" #define DEBUG 0 // print a string of bits to the standard output void print_bitstring(unsigned int _x, unsigned int _n) { unsigned int i; for (i=0; i<_n; i++) printf("%1u", (_x >> (_n-i-1)) & 1); } // soft demodulation // _q : demodulator object // _c : constellation table // _cp : nearest neighbor table [size: _p x 1] // _p : size of table // _r : received sample // _s : hard demodulator output // _soft_bits : soft bit ouput (approximate log-likelihood ratio) void modem_demodulate_soft_tab(modem _q, float complex * _c, unsigned int * _cp, unsigned int _p, float complex _r, unsigned int * _s, float * _soft_bits); int main(int argc, char*argv[]) { srand(time(NULL)); // options modulation_scheme ms = LIQUID_MODEM_QAM16; // modulation scheme unsigned int p = 4; // number of 'nearest symbols' float complex e = 0.1f + _Complex_I*0.15f; // error // validate input if (ms == LIQUID_MODEM_UNKNOWN || ms >= LIQUID_MODEM_NUM_SCHEMES) { fprintf(stderr,"error: %s, invalid modulation scheme\n", argv[0]); exit(1); } unsigned int i; unsigned int j; unsigned int k; // derived values unsigned int bps = modulation_types[ms].bps; unsigned int M = 1 << bps; // constellation size // ensure number of nearest symbols is not too large if (p > (M-1)) { fprintf(stderr,"error: requesting too many neighbors\n"); exit(1); } float sig = 0.2f; // noise standard deviation // generate constellation modem q = modem_create(ms); float complex c[M]; // constellation for (i=0; i> (bps-k-1)) & 0x01; //printf("%c", bit ? '1' : '0'); if (bit) bit_1 += t; else bit_0 += t; #if DEBUG printf(" symbol : "); print_bitstring(i,bps); printf(" [%c]", bit ? '1' : '0'); printf(" { %7.4f %7.4f}, d=%7.4f, t=%12.8f\n", crealf(c[i]), cimagf(c[i]), d, t); #endif } soft_bits[k] = logf(bit_1) - logf(bit_0); #if DEBUG printf(" {0 : %12.8f, 1 : %12.8f}\n", bit_0, bit_1); #endif } // // demodulate using internal method // q = modem_create(ms); unsigned int sym_out_tab; float soft_bits_tab[bps]; modem_demodulate_soft_tab(q,c,cp,p,r,&sym_out_tab,soft_bits_tab); modem_destroy(q); // print results printf("\n"); printf(" input symbol : "); print_bitstring(sym_in,bps); printf(" {%12.8f, %12.8f}\n", crealf(c[sym_in]), cimagf(c[sym_in])); printf(" soft bits :\n"); printf(" /----------- LLR -----------\\ /------- min dist --------\\\n"); for (k=0; k> (bps-k-1)) & 0x01); printf("%12.8f > ", soft_bits[k]); int soft_bit = (soft_bits[k]*16 + 127); if (soft_bit > 255) soft_bit = 255; if (soft_bit < 0) soft_bit = 0; printf("%5d > %1u", soft_bit, soft_bit & 0x80 ? 1 : 0); // // print tabular method // printf(" "); printf("%12.8f > ", soft_bits_tab[k]); soft_bit = (soft_bits_tab[k]*16 + 127); if (soft_bit > 255) soft_bit = 255; if (soft_bit < 0) soft_bit = 0; printf("%5d > %1u", soft_bit, soft_bit & 0x80 ? 1 : 0); printf("\n"); } // // export results to file // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n\n"); fprintf(fid,"m = %u;\n", bps); fprintf(fid,"M = %u;\n", 1<> (bps-k-1)) & 0x01; if (bit) dmin_1 = d; else dmin_0 = d; // check symbols in table #if DEBUG printf(" index %2u : ", k); #endif for (i=0; i<_p; i++) { bit = (_cp[(*_s)*_p+i] >> (bps-k-1)) & 0x01; #if DEBUG print_bitstring(_cp[(*_s)*_p+i],bps); printf("[%1u]", bit); #endif // compute distance float complex x_hat = _c[ _cp[(*_s)*_p + i] ]; d = crealf( (_r-x_hat)*conjf(_r-x_hat) ); #if DEBUG printf("(%8.6f) ", d); #endif if (bit) { if (d < dmin_1) dmin_1 = d; } else { if (d < dmin_0) dmin_0 = d; } } #if DEBUG printf("\n"); printf(" dmin_0 : %12.8f\n", dmin_0); printf(" dmin_1 : %12.8f\n", dmin_1); #endif // make assignments #if 0 _soft_bits[k] = logf(expf(-dmin_1/(2.0f*sig*sig))) - logf(expf(-dmin_0/(2.0f*sig*sig))); #else _soft_bits[k] = (-dmin_1/(2.0f*sig*sig)) - (-dmin_0/(2.0f*sig*sig)); #endif } } liquid-dsp-1.3.1/sandbox/modem_demodulate_soft_test.c000066400000000000000000000102631317124540100227670ustar00rootroot00000000000000// // modem_demodulate_soft_test.c // // Tests soft demoulation using log-likelihood ratio // #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "modem_demodulate_soft_test.m" int main() { srand(time(NULL)); // options modulation_scheme ms = LIQUID_MODEM_QAM16; // modulation scheme float complex e = 0.1f + _Complex_I*0.2f; // error unsigned int i; // derived values float sig = 0.2f; // noise standard deviation // generate constellation modem q = modem_create(ms); unsigned int bps = modem_get_bps(q); unsigned int M = 1 << bps; // constellation size float complex c[M]; // constellation for (i=0; i> (bps-k-1)) & 0x01; //printf("%c", bit ? '1' : '0'); if (bit) bit_1 += t; else bit_0 += t; printf(" symbol : "); unsigned int j; for (j=0; j> (bps-j-1)) & 0x01 ? '1' : '0'); printf(" [%c]", bit ? '1' : '0'); printf(" { %7.4f %7.4f}, d=%7.4f, t=%12.8f\n", crealf(c[i]), cimagf(c[i]), d, t); } soft_bits[k] = logf(bit_1) - logf(bit_0); printf(" {0 : %12.8f, 1 : %12.8f}\n", bit_0, bit_1); } // print results printf("\n"); printf(" input symbol : "); for (k=0; k> (bps-k-1)) & 0x01 ? '1' : '0'); printf(" {%12.8f, %12.8f}\n", crealf(c[sym_in]), cimagf(c[sym_in])); printf(" soft bits :\n"); for (k=0; k> (bps-k-1)) & 0x01); printf("%12.8f > ", soft_bits[k]); int soft_bit = (soft_bits[k]*16 + 127); if (soft_bit > 255) soft_bit = 255; if (soft_bit < 0) soft_bit = 0; printf("%5d > %1u\n", soft_bit, soft_bit & 0x80 ? 1 : 0); } // // export results to file // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n\n"); fprintf(fid,"m = %u;\n", bps); fprintf(fid,"M = %u;\n", 1< #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "mskmodem_test.m" // print usage/help message void usage() { printf("mskmodem_test -- minimum-shift keying modem example\n"); printf("options:\n"); printf(" h : print help\n"); printf(" t : filter type: [square], rcos-full, rcos-half, gmsk\n"); printf(" k : samples/symbol, default: 8\n"); printf(" b : bits/symbol, default: 1\n"); printf(" H : modulation index, default: 0.5\n"); printf(" B : filter roll-off, default: 0.35\n"); printf(" n : number of data symbols, default: 20\n"); printf(" s : SNR [dB], default: 80\n"); printf(" F : carrier freq. offset, default: 0.0\n"); printf(" P : carrier phase offset, default: 0.0\n"); printf(" T : fractional symbol offset, default: 0.0\n"); } int main(int argc, char*argv[]) { // options unsigned int k = 8; // filter samples/symbol unsigned int bps= 1; // number of bits/symbol float h = 0.5f; // modulation index (h=1/2 for MSK) unsigned int num_data_symbols = 20; // number of data symbols float SNRdB = 80.0f; // signal-to-noise ratio [dB] float cfo = 0.0f; // carrier frequency offset float cpo = 0.0f; // carrier phase offset float tau = 0.0f; // fractional symbol offset enum { TXFILT_SQUARE=0, TXFILT_RCOS_FULL, TXFILT_RCOS_HALF, TXFILT_GMSK, } tx_filter_type = TXFILT_SQUARE; float gmsk_bt = 0.35f; // GMSK bandwidth-time factor int dopt; while ((dopt = getopt(argc,argv,"ht:k:b:H:B:n:s:F:P:T:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 't': if (strcmp(optarg,"square")==0) { tx_filter_type = TXFILT_SQUARE; } else if (strcmp(optarg,"rcos-full")==0) { tx_filter_type = TXFILT_RCOS_FULL; } else if (strcmp(optarg,"rcos-half")==0) { tx_filter_type = TXFILT_RCOS_HALF; } else if (strcmp(optarg,"gmsk")==0) { tx_filter_type = TXFILT_GMSK; } else { fprintf(stderr,"error: %s, unknown filter type '%s'\n", argv[0], optarg); exit(1); } break; case 'k': k = atoi(optarg); break; case 'b': bps = atoi(optarg); break; case 'H': h = atof(optarg); break; case 'B': gmsk_bt = atof(optarg); break; case 'n': num_data_symbols = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'F': cfo = atof(optarg); break; case 'P': cpo = atof(optarg); break; case 'T': tau = atof(optarg); break; default: exit(1); } } unsigned int i; // derived values unsigned int num_symbols = num_data_symbols; unsigned int num_samples = k*num_symbols; unsigned int M = 1 << bps; // constellation size float nstd = powf(10.0f, -SNRdB/20.0f); // arrays unsigned char sym_in[num_symbols]; // input symbols float phi[num_samples]; // transmitted phase float complex x[num_samples]; // transmitted signal float complex y[num_samples]; // received signal float complex z[num_samples]; // output... //unsigned char sym_out[num_symbols]; // output symbols unsigned int ht_len = 0; unsigned int tx_delay = 0; float * ht = NULL; switch (tx_filter_type) { case TXFILT_SQUARE: // regular MSK ht_len = k; tx_delay = 1; ht = (float*) malloc(ht_len *sizeof(float)); for (i=0; i (%1u)", n, crealf(z[i]), cimagf(z[i]), phi_hat, v, sym_out); if (n >= m+tx_delay) { num_errors += (sym_out == sym_in[n-m-tx_delay]) ? 0 : 1; num_symbols_checked++; printf(" (%1u)\n", sym_in[n-m-tx_delay]); } else { printf("\n"); } n++; } } // print number of errors printf("errors : %3u / %3u\n", num_errors, num_symbols_checked); // destroy objects firinterp_rrrf_destroy(interp_tx); firfilt_crcf_destroy(decim_rx); // compute power spectral density of transmitted signal unsigned int nfft = 1024; float psd[nfft]; spgramcf_estimate_psd(nfft, y, num_samples, psd); // // export results // FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); fprintf(fid,"k = %u;\n", k); fprintf(fid,"h = %f;\n", h); fprintf(fid,"num_symbols = %u;\n", num_symbols); fprintf(fid,"num_samples = %u;\n", num_samples); fprintf(fid,"nfft = %u;\n", nfft); fprintf(fid,"delay = %u; %% receive filter delay\n", tx_delay); fprintf(fid,"x = zeros(1,num_samples);\n"); fprintf(fid,"y = zeros(1,num_samples);\n"); fprintf(fid,"z = zeros(1,num_samples);\n"); fprintf(fid,"phi = zeros(1,num_samples);\n"); for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "msresamp_crcf_test.m" // print usage/help message void usage() { printf("Usage: msresamp_crcf_test [OPTION]\n"); printf(" h : print help\n"); printf(" r : resampling rate (output/input), default: 0.117\n"); printf(" s : stop-band attenuation [dB], default: 60\n"); printf(" n : number of input samples, default: 500\n"); } int main(int argc, char*argv[]) { // options float r=1.2f; // resampling rate (output/input) float As=80.0f; // resampling filter stop-band attenuation [dB] unsigned int nx=400; // number of input samples float fc=0.40f; // complex sinusoid frequency int dopt; while ((dopt = getopt(argc,argv,"hr:s:n:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'r': r = atof(optarg); break; case 's': As = atof(optarg); break; case 'n': nx = atoi(optarg); break; default: exit(1); } } // validate input if (nx == 0) { fprintf(stderr,"error: %s, number of input samples must be greater than zero\n", argv[0]); exit(1); } else if (r <= 0.0f) { fprintf(stderr,"error: %s, resampling rate must be greater than zero\n", argv[0]); exit(1); } else if ( fabsf(log2f(r)) > 10 ) { fprintf(stderr,"error: %s, resampling rate unreasonable\n", argv[0]); exit(1); } unsigned int i; // derived values unsigned int ny_alloc = (unsigned int) (2*(float)nx * r); // allocation for output // allocate memory for arrays float complex x[nx]; float complex y[ny_alloc]; // generate input unsigned int window_len = (3*nx)/4; for (i=0; i1, fx = f/r; fy = f; %% interpolated\n"); fprintf(fid,"else, fx = f; fy = f*r; %% decimated\n"); fprintf(fid,"end;\n"); fprintf(fid,"plot(fx,X,'Color',[0.5 0.5 0.5],fy,Y,'LineWidth',2);\n"); fprintf(fid,"grid on;\n\n"); fprintf(fid,"xlabel('normalized frequency');\n"); fprintf(fid,"ylabel('PSD [dB]');\n"); fprintf(fid,"legend('original','resampled','location','northeast');"); fprintf(fid,"axis([-0.5 0.5 -120 10]);\n"); fprintf(fid,"\n\n"); fprintf(fid,"%% plot time-domain result\n"); fprintf(fid,"tx=[0:(length(x)-1)];\n"); fprintf(fid,"ty=[0:(length(y)-1)]/r-delay;\n"); fprintf(fid,"figure;\n"); fprintf(fid,"subplot(2,1,1);\n"); fprintf(fid," plot(tx,real(x),'-s','Color',[0.5 0.5 0.5],'MarkerSize',1,...\n"); fprintf(fid," ty,real(y),'-s','Color',[0.5 0 0], 'MarkerSize',1);\n"); fprintf(fid," legend('original','resampled','location','northeast');"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('real');\n"); fprintf(fid," grid on;\n\n"); fprintf(fid,"subplot(2,1,2);\n"); fprintf(fid," plot(tx,imag(x),'-s','Color',[0.5 0.5 0.5],'MarkerSize',1,...\n"); fprintf(fid," ty,imag(y),'-s','Color',[0 0.5 0], 'MarkerSize',1);\n"); fprintf(fid," legend('original','resampled','location','northeast');"); fprintf(fid," xlabel('time');\n"); fprintf(fid," ylabel('imag');\n"); fprintf(fid," grid on;\n\n"); fclose(fid); printf("results written to %s\n",OUTPUT_FILENAME); printf("done.\n"); return 0; } liquid-dsp-1.3.1/sandbox/newbench_example.c000066400000000000000000000071031317124540100206740ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Example of a benchmark header // // compile and run: // $ gcc -Wall -I. -I./include -c newbench_example.c -o newbench_example.o // $ gcc newbench_example.o libliquid.a -lm -lfec -lpthread -lc -lfftw3f -o newbench_example // $ ./newbench_example #include #include #include #include #include #include #include "include/liquid.h" double calculate_execution_time(struct rusage _start, struct rusage _finish) { return _finish.ru_utime.tv_sec - _start.ru_utime.tv_sec + 1e-6*(_finish.ru_utime.tv_usec - _start.ru_utime.tv_usec) + _finish.ru_stime.tv_sec - _start.ru_stime.tv_sec + 1e-6*(_finish.ru_stime.tv_usec - _start.ru_stime.tv_usec); } struct decim_crcf_opts { unsigned int n; // filter length unsigned int D; // decimation factor }; void benchmark_decim_crcf( void * _opts, struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { // retrieve options struct decim_crcf_opts * opts = (struct decim_crcf_opts*) _opts; unsigned long int i; // DSP initiazation goes here float h[opts->n]; for (i=0; in; i++) h[i] = 0.0f; decim_crcf decim = decim_crcf_create(opts->D,h,opts->n); float complex x[opts->D]; float complex y; for (i=0; iD; i++) x[i] = 1.0f; getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { // DSP execution goes here decim_crcf_execute(decim,x,&y,opts->D-1); } getrusage(RUSAGE_SELF, _finish); // DSP cleanup goes here decim_crcf_destroy(decim); } void precision_decim_crcf( unsigned int argc, char *argv[], float * _error) { // blah... *_error = 0.0f; } int main() { struct rusage start,finish; unsigned long int num_trials = 1000000; unsigned int n; unsigned int D; double extime; double cpuclock=2.4e9; double cycles_per_trial; struct decim_crcf_opts opts; for (D=2; D<=8; D*=2) { printf("***** D = %u\n",D); for (n=5; n<31; n+=4) { opts.D = D; opts.n = n; benchmark_decim_crcf((void*)(&opts),&start,&finish,&num_trials); extime = calculate_execution_time(start,finish); cycles_per_trial = cpuclock * extime / (double)(num_trials); printf("n : %3u, D : %3u, cycles/trial : %6.2f\n", n,D,cycles_per_trial); } } printf("done.\n"); return 0; } liquid-dsp-1.3.1/sandbox/ofdm_ber_test.c000066400000000000000000000113471317124540100202110ustar00rootroot00000000000000// // ofdm_ber_test.c // #include #include #include #include #include #include #include "liquid.h" void usage() { printf("ofdm_ber_test [options]\n"); printf(" h : print usage\n"); printf(" s : signal-to-noise ratio [dB], default: 6.5\n"); printf(" M : number of subcarriers (must be even), default: 64\n"); printf(" C : cyclic prefix length, default: 16\n"); printf(" m : modulation scheme (bpsk default)\n"); liquid_print_modulation_schemes(); printf(" n : number of OFDM symbols, default: 40\n"); printf(" c : number of channel taps, default: 1\n"); } int main(int argc, char*argv[]) { // set random number generator seed srand(time(NULL)); // options unsigned int M = 64; // number of subcarriers unsigned int cp_len = 16; // cyclic prefix length modulation_scheme ms = LIQUID_MODEM_BPSK; float SNRdB = 6.5f; // signal-to-noise ratio [dB] unsigned int hc_len = 1; // channel impulse response length unsigned int num_symbols = 40; // number of OFDM symbols // get options int dopt; while((dopt = getopt(argc,argv,"hs:M:C:m:n:c:")) != EOF){ switch (dopt) { case 'h': usage(); return 0; case 's': SNRdB = atof(optarg); break; case 'M': M = atoi(optarg); break; case 'C': cp_len = atoi(optarg); break; case 'm': ms = liquid_getopt_str2mod(optarg); if (ms == LIQUID_MODEM_UNKNOWN) { fprintf(stderr,"error: %s, unknown/unsupported mod. scheme: %s\n", argv[0], optarg); exit(-1); } break; case 'n': num_symbols = atoi(optarg); break; case 'c': hc_len = atoi(optarg); break; default: exit(-1); } } unsigned int i; // validate options if (M < 4) { fprintf(stderr,"error: %s, must have at least 4 subcarriers\n", argv[0]); exit(1); } else if (hc_len == 0) { fprintf(stderr,"error: %s, must have at least 1 channel tap\n", argv[0]); exit(1); } // derived values unsigned int symbol_len = M + cp_len; float nstd = powf(10.0f, -SNRdB/20.0f); float fft_gain = 1.0f / sqrtf(M); // 'gain' due to taking FFT // buffers unsigned int sym_in[M]; // input data symbols unsigned int sym_out[M]; // output data symbols float complex x[M]; // time-domain buffer float complex X[M]; // freq-domain buffer float complex buffer[symbol_len]; // // create modulator/demodulator objects modem mod = modem_create(ms); modem demod = modem_create(ms); unsigned int bps = modem_get_bps(mod); // modem bits/symbol // create channel filter (random taps) float complex hc[hc_len]; hc[0] = 1.0f; for (i=1; i #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "ofdmframe_papr_test.m" void usage() { printf("Usage: ofdmframe_papr_test [OPTION]\n"); printf(" h : print help\n"); printf(" M : number of subcarriers (must be even), default: 64\n"); printf(" C : cyclic prefix length, default: 16\n"); printf(" T : taper length, default: 0\n"); printf(" N : number of data symbols, default: 1000\n"); } // compute peak-to-average power ratio // _x : input time series // _n : number of samples float ofdmframe_PAPR(float complex * _x, unsigned int _n); int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int M = 64; // number of subcarriers unsigned int cp_len = 16; // cyclic prefix length unsigned int taper_len = 0; // taper length unsigned int num_symbols = 1000; // number of data symbols modulation_scheme ms = LIQUID_MODEM_QPSK; // get options int dopt; while((dopt = getopt(argc,argv,"hM:C:T:N:")) != EOF){ switch (dopt) { case 'h': usage(); return 0; case 'M': M = atoi(optarg); break; case 'C': cp_len = atoi(optarg); break; case 'T': taper_len = atoi(optarg); break; case 'N': num_symbols = atoi(optarg); break; default: exit(1); } } unsigned int i; // derived values unsigned int frame_len = M + cp_len; // initialize subcarrier allocation unsigned char p[M]; ofdmframe_init_default_sctype(M, p); // create frame generator ofdmframegen fg = ofdmframegen_create(M, cp_len, taper_len, p); ofdmframegen_print(fg); modem mod = modem_create(ms); float complex X[M]; // channelized symbols float complex buffer[frame_len];// output time series float * PAPR = (float*) malloc(num_symbols*sizeof(float)); // histogram display float xmin = -1.29f + 0.70f*log2f(M); float xmax = 8.97f + 0.34f*log2f(M); unsigned int num_bins = 30; float bin_width = (xmax - xmin) / (num_bins); unsigned int hist[num_bins]; for (i=0; i= num_bins) index = num_bins-1; hist[index]++; // save min/max PAPR values if (i==0 || PAPR[i] < PAPR_min) PAPR_min = PAPR[i]; if (i==0 || PAPR[i] > PAPR_max) PAPR_max = PAPR[i]; PAPR_mean += PAPR[i]; } PAPR_mean /= (float)num_symbols; // destroy objects ofdmframegen_destroy(fg); modem_destroy(mod); // print results to screen // find max(hist) unsigned int hist_max = 0; for (i=0; i hist_max ? hist[i] : hist_max; printf("%8s : %6s [%6s]\n", "PAPR[dB]", "count", "prob."); for (i=0; i e_max) ? e : e_max; } e_mean = e_mean / (float)_n; return 10*log10f(e_max / e_mean); } liquid-dsp-1.3.1/sandbox/ofdmframesync_cfo_test.c000066400000000000000000000154701317124540100221210ustar00rootroot00000000000000// // ofdmframesync_cfo_test : test carrier frequency offset estimation // #include #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "ofdmframesync_cfo_test.dat" void usage() { printf("Usage: ofdmframesync_cfo_test [OPTION]\n"); printf(" h : print help\n"); printf(" M : number of subcarriers (must be even), default: 64\n"); printf(" C : cyclic prefix length, default: 16\n"); printf(" T : taper length, default: 4\n"); printf(" S : signal-to-noise ratio [dB], default: 20\n"); printf(" t : number of trials, default: 500\n"); printf(" s : number of steps, default: 21\n"); } static int callback(float complex * _X, unsigned char * _p, unsigned int _M, void * _userdata); int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int M = 64; // number of subcarriers unsigned int cp_len = 16; // cyclic prefix length unsigned int taper_len = 4; // taper length float noise_floor = -30.0f; // noise floor [dB] float SNRdB = 20.0f; // signal-to-noise ratio [dB] unsigned int num_trials = 500; // number of trials to simulate unsigned int num_steps = 21; // number of steps // get options int dopt; while((dopt = getopt(argc,argv,"hM:C:T:S:t:s:")) != EOF){ switch (dopt) { case 'h': usage(); return 0; case 'M': M = atoi(optarg); break; case 'C': cp_len = atoi(optarg); break; case 'T': taper_len = atoi(optarg); break; case 'S': SNRdB = atof(optarg); break; case 't': num_trials= atoi(optarg); break; case 's': num_steps = atoi(optarg); break; default: exit(1); } } unsigned int i; // derived values unsigned int num_symbols = 1; // number of data symbols unsigned int symbol_len = M + cp_len; unsigned int num_samples = (3+num_symbols)*symbol_len; // data symbols float nstd = powf(10.0f, noise_floor/20.0f); float gamma = powf(10.0f, (SNRdB + noise_floor)/20.0f); printf("gamma : %f\n", gamma); // initialize subcarrier allocation unsigned char p[M]; ofdmframe_init_default_sctype(M, p); // create frame generator ofdmframegen fg = ofdmframegen_create(M, cp_len, taper_len, p); ofdmframegen_print(fg); // create frame synchronizer int frame_detected; ofdmframesync fs = ofdmframesync_create(M, cp_len, taper_len, p, callback, (int*)&frame_detected); ofdmframesync_print(fs); float complex X[M]; // channelized symbols float complex frame[num_samples]; // initial frame float complex y[num_samples]; // output time series unsigned int n=0; // generate frame ofdmframegen_write_S0a(fg, &frame[n]); n += symbol_len; ofdmframegen_write_S0b(fg, &frame[n]); n += symbol_len; ofdmframegen_write_S1( fg, &frame[n]); n += symbol_len; // generate single data symbol (random BPSK) for (i=0; i #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "ofdmoqam_firpfbch_cfo_test.m" #define DEBUG 1 int main() { // options unsigned int num_channels=64; // must be even number unsigned int num_symbols=16; // number of symbols unsigned int m=3; // filter delay (symbols) float beta = 0.9f; // filter excess bandwidth factor float phi = 0.0f; // carrier phase offset; float dphi = 0.04f; // carrier frequency offset // number of frames (compensate for filter delay) unsigned int num_frames = num_symbols + 2*m; unsigned int num_samples = num_channels * num_frames; unsigned int i; unsigned int j; // create filter prototype unsigned int h_len = 2*num_channels*m + 1; float h[h_len]; float complex hc[h_len]; float complex gc[h_len]; liquid_firdes_rkaiser(num_channels, m, beta, 0.0f, h); unsigned int g_len = 2*num_channels*m; for (i=0; i #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "ofdmoqam_firpfbch_test.m" int main() { // options unsigned int num_channels=6; // must be even number unsigned int num_symbols=32; // number of symbols unsigned int m=3; // filter delay (symbols) float beta = 0.9f; // filter excess bandwidth factor int ftype = LIQUID_FIRFILT_ARKAISER; // number of frames (compensate for filter delay) unsigned int num_frames = num_symbols + 2*m; unsigned int num_samples = num_channels * num_frames; // create synthesizer/analyzer objects firpfbch_crcf cs0 = firpfbch_crcf_create_rnyquist(LIQUID_SYNTHESIZER, num_channels, m, beta, ftype); firpfbch_crcf cs1 = firpfbch_crcf_create_rnyquist(LIQUID_SYNTHESIZER, num_channels, m, beta, ftype); firpfbch_crcf ca0 = firpfbch_crcf_create_rnyquist(LIQUID_ANALYZER, num_channels, m, beta, ftype); firpfbch_crcf ca1 = firpfbch_crcf_create_rnyquist(LIQUID_ANALYZER, num_channels, m, beta, ftype); FILE*fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\nclose all;\n\n"); fprintf(fid,"num_channels=%u;\n", num_channels); fprintf(fid,"num_symbols=%u;\n", num_symbols); fprintf(fid,"num_samples=%u;\n", num_samples); fprintf(fid,"X = zeros(%u,%u);\n", num_channels, num_frames); fprintf(fid,"y = zeros(1,%u);\n", num_samples); fprintf(fid,"Y = zeros(%u,%u);\n", num_channels, num_frames); unsigned int i, j, n=0; unsigned int k2 = num_channels/2; float complex X[num_channels]; // channelized symbols float complex y[num_channels]; // interpolated time-domain samples float complex Y[num_channels]; // received symbols // temporary buffers float complex X0[num_channels]; float complex X1[num_channels]; float complex y0[num_channels]; float complex y1[num_channels]; float complex y1_prime[num_channels]; for (i=0; i #include #include #include #include #include #include #include "liquid.internal.h" #define OUTPUT_FILENAME "packetizer_persistent_ber_test.m" void usage() { printf("Usage: packetizer_persistent_ber_test\n"); printf(" Simulates persistent decoding (best for small packets, large CRC)\n"); printf("options:\n"); printf(" u/h : print usage/help\n"); printf(" s : SNR min [dB], default: 0\n"); printf(" x : SNR max [dB], default: 8\n"); printf(" n : number of SNR steps, default: 33\n"); printf(" t : number of trials, default: 2000\n"); printf(" f : frame size, default: 20\n"); printf(" v : data integrity check: crc32 default\n"); liquid_print_crc_schemes(); printf(" c : coding scheme (inner), default: h128\n"); printf(" k : coding scheme (outer), default: none\n"); liquid_print_fec_schemes(); } // persistent decoding methods int packetizer_decode_persistent(packetizer _p, unsigned char * _pkt, unsigned char * _msg); int packetizer_decode_persistent2(packetizer _p, unsigned char * _pkt, unsigned char * _msg); int main(int argc, char *argv[]) { // set initial seed to random srand(time(NULL)); // options unsigned int n = 20; // frame size (bytes) float SNRdB_min = 0.0f; // signal-to-noise ratio (minimum) float SNRdB_max = 8.0f; // signal-to-noise ratio (maximum) unsigned int num_snr = 33; // number of SNR steps unsigned int num_trials=2000; // number of trials crc_scheme check = LIQUID_CRC_32; // error-detection scheme fec_scheme fec0 = LIQUID_FEC_HAMMING128;// error-correcting scheme (inner) fec_scheme fec1 = LIQUID_FEC_NONE; // error-correcting scheme (outer) // get command-line options int dopt; while((dopt = getopt(argc,argv,"uhs:x:n:t:f:v:c:k:")) != EOF){ switch (dopt) { case 'h': case 'u': usage(); return 0; case 's': SNRdB_min = atof(optarg); break; case 'x': SNRdB_max = atof(optarg); break; case 'n': num_snr = atoi(optarg); break; case 't': num_trials = atoi(optarg); break; case 'f': n = atoi(optarg); break; case 'v': // data integrity check check = liquid_getopt_str2crc(optarg); if (check == LIQUID_CRC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported CRC scheme \"%s\"\n\n",optarg); exit(1); } break; case 'c': fec0 = liquid_getopt_str2fec(optarg); if (fec0 == LIQUID_FEC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported fec scheme \"%s\"\n\n",optarg); exit(1); } break; case 'k': fec1 = liquid_getopt_str2fec(optarg); if (fec1 == LIQUID_FEC_UNKNOWN) { fprintf(stderr,"error: unknown/unsupported fec scheme \"%s\"\n\n",optarg); exit(1); } break; default: exit(1); } } unsigned int i; // create arrays unsigned int k = packetizer_compute_enc_msg_len(n,check,fec0,fec1); printf("dec msg len : %u\n", n); printf("enc msg len : %u\n", k); float rate = (float)n / (float)k; unsigned char msg_org[n]; // original data message unsigned char msg_enc[k]; // encoded data message float complex sym_rec[8*k]; // received BPSK symbols unsigned char msg_cor[k]; // corrupted data message unsigned char msg_dec_per0[n]; // decoded data message (regular decoding) unsigned char msg_dec_per2[n]; // decoded data message (persistent decoding) // create object packetizer q = packetizer_create(n,check,fec0,fec1); packetizer_print(q); unsigned int packet_errors_per0[num_snr]; unsigned int packet_errors_per2[num_snr]; // // set up parameters // float SNRdB_step = (SNRdB_max - SNRdB_min) / (num_snr-1); // // start trials // printf(" %8s %8s [%6s] %8s %8s %8s %8s\n", "SNR [dB]", "Eb/N0", "trials", "per", "(PER)", "reg", "(PER)"); unsigned int s; for (s=0; s 0.0f ? 0x80 : 0x00; msg_cor[i] |= crealf(sym_rec[8*i+1]) > 0.0f ? 0x40 : 0x00; msg_cor[i] |= crealf(sym_rec[8*i+2]) > 0.0f ? 0x20 : 0x00; msg_cor[i] |= crealf(sym_rec[8*i+3]) > 0.0f ? 0x10 : 0x00; msg_cor[i] |= crealf(sym_rec[8*i+4]) > 0.0f ? 0x08 : 0x00; msg_cor[i] |= crealf(sym_rec[8*i+5]) > 0.0f ? 0x04 : 0x00; msg_cor[i] |= crealf(sym_rec[8*i+6]) > 0.0f ? 0x02 : 0x00; msg_cor[i] |= crealf(sym_rec[8*i+7]) > 0.0f ? 0x01 : 0x00; } // decode packetizer_decode( q, msg_cor, msg_dec_per0); packetizer_decode_persistent2(q, msg_cor, msg_dec_per2); // tabulate results packet_errors_per0[s] += count_bit_errors_array(msg_org, msg_dec_per0, n) ? 1 : 0; packet_errors_per2[s] += count_bit_errors_array(msg_org, msg_dec_per2, n) ? 1 : 0; } // print results for this SNR step printf(" %8.3f %8.3f [%6u] %8u %8.2f %8u %8.2f\n", SNRdB, SNRdB - 10*log10f(rate), num_trials, packet_errors_per2[s], 100.0f * (float)(packet_errors_per2[s]) / (float)(num_trials), packet_errors_per0[s], 100.0f * (float)(packet_errors_per0[s]) / (float)(num_trials) ); } // clean up objects packetizer_destroy(q); // // export output file // FILE * fid = fopen(OUTPUT_FILENAME, "w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"\n\n"); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); fprintf(fid,"n = %u; %% frame size [bytes]\n", n); fprintf(fid,"k = %u; %% encoded frame size [bytes]\n", k); fprintf(fid,"r = n / k; %% true rate\n"); fprintf(fid,"num_snr = %u;\n", num_snr); fprintf(fid,"num_trials = %u;\n", num_trials); for (i=0; ibuffer_0; flip bits to try to get // CRC to pass for (i=0; i<_p->msg_len + _p->crc_length; i++) { unsigned int j; for (j=0; j<8; j++) { // flip bit unsigned char mask = 1 << (8-j-1); _p->buffer_0[i] ^= mask; // strip crc, validate message key = 0; unsigned int k; for (k=0; k<_p->crc_length; k++) { key <<= 8; key |= _p->buffer_0[_p->msg_len+k]; } // compute crc validity crc_pass = crc_validate_message(_p->check, _p->buffer_0, _p->msg_len, key); // check validity if (crc_pass) { // copy result to output and return memmove(_msg, _p->buffer_0, _p->msg_len); //printf("persistent decoding worked!\n"); return crc_pass; } else { // flip bit back _p->buffer_0[i] ^= mask; } } } // copy result to output and return memmove(_msg, _p->buffer_0, _p->msg_len); return crc_pass; } // double bit errors in a single byte // nchoosek(8,2) = 28 unsigned char packetizer_persistent_mask2[28] = { 0x03, // 00000011 0x06, // 00000110 0x0C, // 00001100 0x18, // 00011000 0x30, // 00110000 0x60, // 01100000 0xC0, // 11000000 0x05, // 00000101 0x0A, // 00001010 0x14, // 00010100 0x28, // 00101000 0x50, // 01010000 0xA0, // 10100000 0x09, // 00001001 0x12, // 00010010 0x24, // 00100100 0x48, // 01001000 0x90, // 10010000 0x11, // 00010001 0x22, // 00100010 0x44, // 01000100 0x88, // 10001000 0x21, // 00100001 0x42, // 01000010 0x84, // 10000100 0x41, // 01000001 0x82, // 10000010 0x81, // 10000001 }; // Execute the packetizer to decode an input message, return validity // check of resulting data; persistent attempts to find error(s) // // _p : packetizer object // _pkt : input message (coded bytes) // _msg : decoded output message int packetizer_decode_persistent2(packetizer _p, unsigned char * _pkt, unsigned char * _msg) { // try first-order persistent decoding int crc_pass = packetizer_decode_persistent(_p, _pkt, _msg); // return if decoding was successful if (crc_pass) return crc_pass; unsigned int i; unsigned int key=0; // result is stored in _p->buffer_0; flip bits to try to get // CRC to pass for (i=0; i<_p->msg_len + _p->crc_length; i++) { unsigned int j; for (j=0; j<28; j++) { // apply mask _p->buffer_0[i] ^= packetizer_persistent_mask2[j]; // strip crc, validate message key = 0; unsigned int k; for (k=0; k<_p->crc_length; k++) { key <<= 8; key |= _p->buffer_0[_p->msg_len+k]; } // compute crc validity crc_pass = crc_validate_message(_p->check, _p->buffer_0, _p->msg_len, key); // check validity if (crc_pass) { // copy result to output and return memmove(_msg, _p->buffer_0, _p->msg_len); //printf("persistent decoding worked! (2)\n"); return crc_pass; } else { // flip bit back _p->buffer_0[i] ^= packetizer_persistent_mask2[j]; } } } // copy result to output and return memmove(_msg, _p->buffer_0, _p->msg_len); return crc_pass; } liquid-dsp-1.3.1/sandbox/pll_design_test.c000066400000000000000000000057461317124540100205620ustar00rootroot00000000000000// // pll_design_test.c // // Demonstrates a basic phase-locked loop to track the phase of a // complex sinusoid. // #include #include #include #include #include #include "liquid.h" // output to octave-friendly format #define OUTPUT_FILENAME "pll_design_test.m" int main() { // parameters float phase_offset = 0.8f; float frequency_offset = 0.01f; float pll_bandwidth = 0.05f; float pll_damping_factor = 0.707f; unsigned int n=256; // number of iterations unsigned int d=n/32; // print every "d" lines // float theta[n]; // input phase float complex x[n]; // input sinusoid float phi[n]; // output phase float complex y[n]; // output sinusoid // generate iir loop filter(s) float a[3]; float b[3]; float wn = pll_bandwidth; float zeta = pll_damping_factor; float K = 10; // loop gain #if 0 // loop filter (active lag) float t1 = K/(wn*wn); float t2 = 2*zeta/wn - 1/K; b[0] = 2*K*(1.+t2/2.0f); b[1] = 2*K*2.; b[2] = 2*K*(1.-t2/2.0f); a[0] = 1 + t1/2.0f; a[1] = -t1; a[2] = -1 + t1/2.0f; #else // loop filter (active PI) float t1 = K/(wn*wn); float t2 = 2*zeta/wn; b[0] = 2*K*(1.+t2/2.0f); b[1] = 2*K*2.; b[2] = 2*K*(1.-t2/2.0f); a[0] = t1/2.0f; a[1] = -t1; a[2] = t1/2.0f; #endif iirfilt_rrrf H = iirfilt_rrrf_create(b,3,a,3); iirfilt_rrrf_print(H); unsigned int i; // generate input float t=phase_offset; float dt = frequency_offset; for (i=0; i #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "predemod_sync_test.m" // print usage/help message void usage() { printf("predemod_sync_test -- test pre-demodulation synchronization\n"); printf("options:\n"); printf(" h : print usage/help\n"); printf(" k : samples/symbol, default: 2\n"); printf(" m : filter delay [symbols], default: 4\n"); printf(" n : number of data symbols, default: 64\n"); printf(" b : bandwidth-time product, (0,1), default: 0.3\n"); printf(" t : fractional sample offset, (-0.5,0.5), default: 0\n"); printf(" F : frequency offset, default: 0\n"); printf(" P : phase offset, default: 0\n"); printf(" s : SNR [dB], default: 30\n"); } int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int k=2; // filter samples/symbol unsigned int m=4; // filter delay (symbols) float beta=0.3f; // bandwidth-time product float dt = 0.0f; // fractional sample timing offset unsigned int num_sync_symbols = 64; // number of data symbols float SNRdB = 30.0f; // signal-to-noise ratio [dB] float dphi = 0.0f; // carrier frequency offset float phi = 0.0f; // carrier phase offset unsigned int num_delay_symbols = 12; unsigned int num_dphi_hat = 21; // number of frequency offset estimates float dphi_hat_step = 0.01f; // frequency offset step size int dopt; while ((dopt = getopt(argc,argv,"uhk:m:n:b:t:F:P:s:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'n': num_sync_symbols = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 't': dt = atof(optarg); break; case 'F': dphi = atof(optarg); break; case 'P': phi = atof(optarg); break; case 's': SNRdB = atof(optarg); break; default: exit(1); } } unsigned int i; // validate input if (beta <= 0.0f || beta >= 1.0f) { fprintf(stderr,"error: %s, bandwidth-time product must be in (0,1)\n", argv[0]); exit(1); } else if (dt < -0.5 || dt > 0.5) { fprintf(stderr,"error: %s, fractional sample offset must be in (0,1)\n", argv[0]); exit(1); } // derived values unsigned int num_symbols = num_delay_symbols + num_sync_symbols + 2*m; unsigned int num_samples = k*num_symbols; unsigned int num_sync_samples = k*num_sync_symbols; float nstd = powf(10.0f, -SNRdB/20.0f); // arrays float complex seq[num_sync_symbols]; // data sequence (symbols) float complex s0[num_sync_samples]; // data sequence (interpolated samples) float complex x[num_samples]; // transmitted signal float complex y[num_samples]; // received signal float rxy[num_dphi_hat][num_samples]; // pre-demod output matrix // generate sequence for (i=0; i #include #include #include #include "liquid.h" #define DEBUG_BFGS 0 // utility function pointer typedef float (*utility)(float * _x, unsigned int _n); // utility function float myutility(float * _x, unsigned int _n); // useful function to print vector to screen void print_vector(const char * _str, float * _v, unsigned int _n); // estimate gradient at point _x // _x : input point, [size: _n x 1] // _n : dimension // _u : utility function pointer // _gradient : resulting gradient (normalized?) void estimate_gradient(float * _x, unsigned int _n, utility _u, float * _gradient); // update BFGS estimate of Hessian matrix inverse // _n : dimension // _dx : step size (previous), [size: _n x 1] // _y : gradient difference // _H0 : Hessian matrix inverse estimate (previous), [size: _n x _n] // _H1 : Hessian matrix inverse estimate [size: _n x _n] void bfgs_update(unsigned int _n, float * _dx, float * _y, float * _H0, float * _H1); // check the strong Wolfe conditions (c1=0.0001, c2=0.9) // _alpha : step length // _u0 : f(x) // _u1 : f(x + alpha*p) // _gamma0 : p'*grad(x) (NOTE: should be less than zero) // _gamma1 : p'*grad(x + alpha*p) int check_wolfe_conditions(float _alpha, float _u0, float _u1, float _gamma0, float _gamma1); // check Wolfe conditions // _x : input vector [size: _n x 1] // _p : step direction vector [size: _n x 1] // _n : dimension // _alpha : test step length // _u : utility function pointer int check_wolfe_conditions2(float * _x, float * _p, unsigned int _n, float _alpha, utility _u); int main() { // options unsigned int n = 4; // search dimension unsigned int num_iterations = 10; // number of steps // allocate memory for arrays float x[n]; // search vector float p[n]; // direction float dx[n]; // search vector step float gradient0[n]; float gradient1[n]; float y[n]; float H0[n*n]; float H1[n*n]; float alpha = 0.2f; unsigned int i; for (i=0; i 0 // _gamma < 0 // float c1 = 1e-4f; float c2 = 0.9f; // check first condition int cond1 = (_u1 <= _u0 + c1*_alpha*_gamma0) ? 1 : 0; // check second condition int cond2 = ( fabsf(_gamma1) <= c2*fabsf(_gamma0) ) ? 1 : 0; #if 0 printf("(g0: %12.8f g1: %12.8f) [%c %c]", _gamma0, _gamma1, cond1 ? '1' : '0', cond2 ? '1' : '0'); #endif // return cond1 && cond2; } // check Wolfe conditions // _x : input vector [size: _n x 1] // _p : step direction vector [size: _n x 1] // _n : dimension // _alpha : test step length // _u : utility function pointer int check_wolfe_conditions2(float * _x, float * _p, unsigned int _n, float _alpha, utility _u) { // allocate temporary arrays float grad0[_n]; float grad1[_n]; float x_prime[_n]; // compute f(x) float u0 = _u(_x,_n); // compute gradient(f(x)) estimate_gradient(_x,_n,_u,grad0); // compute f(x + alpha*p) unsigned int i; for (i=0; i<_n; i++) x_prime[i] = _x[i] + _alpha*_p[i]; float u1 = _u(x_prime, _n); // compute gradient(f(x + alpha*p)) estimate_gradient(x_prime, _n, _u, grad1); // compute p'*grad0 float gamma0 = 0.0f; for (i=0; i<_n; i++) gamma0 += _p[i] * grad0[i]; // compute p'*grad1 float gamma1 = 0.0f; for (i=0; i<_n; i++) gamma1 += _p[i] * grad1[i]; // test Wolfe conditions return check_wolfe_conditions(_alpha, u0, u1, gamma0, gamma1); } liquid-dsp-1.3.1/sandbox/recursive_qpsk_test.c000066400000000000000000000110411317124540100214700ustar00rootroot00000000000000// // recursive_qpsk_test.c // // Run recursive QPSK modulation/demodulation test. // #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "recursive_qpsk_test.m" // print usage/help message void usage() { printf("%s [options]\n", __FILE__); printf(" -h : print usage\n"); printf(" -b : beta value for constellation, beta in (0,1)\n"); } int main(int argc, char*argv[]) { // create mod/demod objects float beta = 0.25f; float SNRdB_min = 0.0f; float SNRdB_max = 30.0f; unsigned int num_snr = 31; unsigned int num_trials = 1e6; int dopt; while ((dopt = getopt(argc,argv,"hb:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'b': beta = atof(optarg); break; default: exit(1); } } unsigned int i; float complex map_qpsk[4] = { M_SQRT1_2 + _Complex_I*M_SQRT1_2, // 00 -M_SQRT1_2 + _Complex_I*M_SQRT1_2, // 01 M_SQRT1_2 - _Complex_I*M_SQRT1_2, // 10 -M_SQRT1_2 - _Complex_I*M_SQRT1_2, // 11 }; // generate composite constellation float complex map[16]; for (i=0; i<4; i++) { map[4*i+0] = map_qpsk[i] + beta*map_qpsk[0]; map[4*i+1] = map_qpsk[i] + beta*map_qpsk[1]; map[4*i+2] = map_qpsk[i] + beta*map_qpsk[2]; map[4*i+3] = map_qpsk[i] + beta*map_qpsk[3]; } // create arbitrary modem modem mod = modem_create_arbitrary(map, 16); // open file for writing FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); unsigned int sym_tx_0; unsigned int sym_tx_1; unsigned int sym_tx; float complex s; unsigned int sym_rx; unsigned int sym_rx_0; unsigned int sym_rx_1; unsigned int num_bit_errors_0 = 0; unsigned int num_bit_errors_1 = 0; // print constellation fprintf(fid,"map = zeros(1,16);\n"); for (i=0; i<16; i++) { modem_modulate(mod, i, &s); fprintf(fid,"map(%2u) = %12.4e + %12.4ei;\n", i+1, crealf(s), cimagf(s)); } unsigned int n; float complex SNRdB_step = (SNRdB_max - SNRdB_min) / (num_snr - 1); for (n=0; n> 2) & 0x3; sym_rx_1 = (sym_rx ) & 0x3; // accumulate errors num_bit_errors_0 += count_bit_errors(sym_tx_0, sym_rx_0); num_bit_errors_1 += count_bit_errors(sym_tx_1, sym_rx_1); } float BER_QPSK = 0.5f*erfcf(powf(10.0f,SNRdB/20.0f)*M_SQRT1_2); float BER_0 = num_bit_errors_0 / (float)(2*num_trials); float BER_1 = num_bit_errors_1 / (float)(2*num_trials); // print results to screen printf("%3u : SNR = %6.3f dB, {%8u %8u} / %8u, QPSK: %12.4e, BER : {%12.4e %12.4e}\n", n, SNRdB, num_bit_errors_0, num_bit_errors_1, 2*num_trials, BER_QPSK, BER_0, BER_1); // print results to file fprintf(fid,"SNRdB(%3u)=%6.3f; BER_QPSK(%3u)=%12.4e; BER_0(%3u)=%12.4e; BER_1(%3u)=%12.4e;\n", n+1, SNRdB, n+1, BER_QPSK, n+1, BER_0, n+1, BER_1); } fprintf(fid,"figure;\n"); fprintf(fid,"semilogy(SNRdB,BER_QPSK+1e-12,SNRdB,BER_0+1e-12,SNRdB,BER_1+1e-12);\n"); fprintf(fid,"axis([%.3f %.3f 1e-5 1]);\n", SNRdB_min, SNRdB_max); fprintf(fid,"grid on;\n"); fprintf(fid,"xlabel('SNR [dB]');\n"); fprintf(fid,"ylabel('BER');\n"); fprintf(fid,"legend('qpsk ', 'stream 0 ', 'stream 1 ', 'location', 'northeast');\n"); fclose(fid); printf("results written to '%s'\n", OUTPUT_FILENAME); // destroy modem object modem_destroy(mod); printf("done.\n"); return 0; } liquid-dsp-1.3.1/sandbox/resamp2_crcf_filterbank_test.c000066400000000000000000000117301317124540100231770ustar00rootroot00000000000000// // resamp2_crcf_filterbank_test.c // // Halfband (two-channel) filterbank example. This example demonstrates // the analyzer/synthesizer execute() methods for the resamp2_xxxt // family of objects. // // NOTE: The filterbank is not a perfect reconstruction filter; a // significant amount of distortion occurs in the transition band // of the half-band filters. // // SEE ALSO: resamp2_crcf_decim_example.c // resamp2_crcf_interp_example.c // #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "resamp2_crcf_filterbank_example.m" int main() { unsigned int m=9; // filter semi-length unsigned int num_samples=128; // number of input samples float As=60.0f; // stop-band attenuation [dB] // derived values unsigned int h_len = 4*m+1; // half-band filter length unsigned int N = num_samples + h_len; // ensure N is even N += (N%2); unsigned int n = N/2; // arrays float complex x[N]; // input time series float complex y[n][2]; // output time series (channelized) float complex z[N]; // output time series // generate input sequence unsigned int i; for (i=0; i #include #include #include "liquid.h" #define OUTPUT_FILENAME "resamp2_crcf_interp_recreate_test.m" int main() { unsigned int m0=5; unsigned int m1=4; unsigned int h0_len = 4*m0+1; // initial filter length unsigned int h1_len = 4*m1+1; // filter length (after recreate) float fc=0.10f; unsigned int N=32; float As=60.0f; resamp2_cccf f = resamp2_cccf_create(h0_len,0.0f,As); resamp2_cccf_print(f); FILE*fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s: auto-generated file\n",OUTPUT_FILENAME); fprintf(fid,"clear all;\nclose all;\n\n"); fprintf(fid,"h0_len = %u;\n", h0_len); fprintf(fid,"h1_len = %u;\n", h1_len); fprintf(fid,"N = %u;\n", N); unsigned int i; float theta=0.0f, dtheta=2*M_PI*fc; unsigned int ix=0, iy=0; float complex x, y[2]; for (i=0; i #include // slow implementation of byte reversal unsigned char reverse_byte(unsigned char _x) { unsigned char y = 0x00; unsigned int i; for (i=0; i<8; i++) { y <<= 1; y |= _x & 1; _x >>= 1; } return y; } int main() { printf("// auto-generated file (do not edit)\n"); printf("\n"); printf("// reverse byte table\n"); printf("unsigned const char liquid_reverse_byte[256] = {\n "); unsigned int i; for (i=0; i<256; i++) { // reverse byte unsigned char byte_rev = reverse_byte((unsigned char)i); // print results printf("0x%.2x", byte_rev); if ( i != 255 ) { printf(","); if ( ((i+1)%8)==0 ) printf("\n "); else printf(" "); } } printf("};\n\n"); return 0; } liquid-dsp-1.3.1/sandbox/rkaiser2_test.c000066400000000000000000000176531317124540100201640ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Design root-Nyquist Kaiser filter // // References // [Vaidyanathan:1993] Vaidyanathan, P. P., "Multirate Systems and // Filter Banks," 1993, Prentice Hall, Section 3.2.1 // #include #include #include #include "liquid.internal.h" #define DEBUG 0 #define OUTPUT_FILENAME "rkaiser2_test.m" struct gsuserdata_s { unsigned int k; // samples/symbol unsigned int m; // filter delay (symbols) float beta; // excess bandwidth factor float dt; // fractional delay float w0; // weighting for ISI float w1; // weighting for stop-band attenuation }; // Design frequency-shifted root-Nyquist filter based on // the Kaiser-windowed sinc. // // _k : filter over-sampling rate (samples/symbol) // _m : filter delay (symbols) // _beta : filter excess bandwidth factor (0,1) // _dt : filter fractional sample delay // _h : resulting filter [size: 2*_k*_m+1] void liquid_firdes_rkaiser_filter2(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h); // gradient search utility float gs_utility(void * _userdata, float * _h, unsigned int _n); int main() { // options unsigned int k=2; unsigned int m=5; float beta = 0.3; float dt = 0.0; // derived values unsigned int h_len = 2*k*m+1; float h1[h_len]; float h2[h_len]; liquid_firdes_rkaiser(k,m,beta,dt,h1); liquid_firdes_rkaiser_filter2(k,m,beta,dt,h2); // print filters // export results FILE * fid = fopen(OUTPUT_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); fprintf(fid,"\n"); fprintf(fid,"k = %u;\n", k); fprintf(fid,"m = %u;\n", m); fprintf(fid,"beta = %12.8f;\n", beta); fprintf(fid,"n = 2*k*m+1;\n"); fprintf(fid,"h1 = zeros(1,n);\n"); fprintf(fid,"h2 = zeros(1,n);\n"); unsigned int i; for (i=0; i= 1.0f) { fprintf(stderr,"error: liquid_firdes_rkaiser(), beta must be in (0,1)\n"); exit(1); } else if (_dt < -1.0f || _dt > 1.0f) { fprintf(stderr,"error: liquid_firdes_rkaiser(), dt must be in [-1,1]\n"); exit(1); } unsigned int h_len = 2*_k*_m + 1; // #if 0 float fc = 0.5*(1.0 + _beta)/(float)(_k); float As = 40.0f; #else float rho_hat = rkaiser_approximate_rho(_m,_beta); float fc = 0.5f*(1 + _beta*(1.0f-rho_hat))/(float)_k; // filter cutoff float del = _beta*rho_hat / (float)_k; // transition bandwidth float As = estimate_req_filter_As(del, h_len); // stop-band suppression // reduce slightly to help ensure solution isn't stuck // (not really necessary) fc *= 0.995f; As -= 1.0f; #endif float v[2] = {fc, As/1000}; struct gsuserdata_s q = { .k = _k, .m = _m, .beta = _beta, .dt = _dt, .w0 = 0.5f, .w1 = 0.5f}; // create gradsearch object gradsearch gs = gradsearch_create((void*)&q, v, 2, // vector optimizer gs_utility, LIQUID_OPTIM_MINIMIZE); // run search unsigned int i; unsigned int num_iterations = 100; for (i=0; iw0; float w1 = q->w1; unsigned int k = q->k; unsigned int m = q->m; float beta = q->beta; float dt = q->dt; unsigned int nfft=512; // parameters float fc = _v[0]; float As = _v[1]*1000; // derived values unsigned int h_len = 2*k*m+1; // utilities float u0 = 0.0; float u1 = 0.0; // compute filter float h[h_len]; liquid_firdes_kaiser(h_len,fc,As,dt,h); // normalize coefficients float e2 = 0.0f; unsigned int i; for (i=0; i #include #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "shadowing_test.m" int main(int argc, char*argv[]) { srand(time(NULL)); // properties unsigned int num_samples = 80e3; float sigma = 1.0f; float fd = 0.02f; unsigned int nfft = 2400; // spectral periodogram FFT size // generate Doppler filter #if 1 float alpha = fd; float a[2] = {1.0f, alpha-1.0f}; float b[2] = {alpha, 0}; iirfilt_rrrf filter = iirfilt_rrrf_create(b,2,a,2); #else iirfilt_rrrf filter = iirfilt_rrrf_create_lowpass(11,fd); #endif unsigned int i; // output channel gain float G[num_samples]; // generate samples for (i=0; i #include #include "liquid.h" void matrixf_pivot2(float * _x, unsigned int _m, unsigned int _n, unsigned int _i, unsigned int _j) { float v = 1.0f / matrix_access(_x,_m,_n,_i,_j); float g; // multiplier unsigned int r,c; for (r=0; r<_m; r++) { // skip over pivot row if (r == _i) continue; // compute multiplier g = matrix_access(_x,_m,_n,r,_j) * v; // back-substitution for (c=0; c<_n; c++) { matrix_access(_x,_m,_n,r,c) -= matrix_access(_x,_m,_n,_i,c)*g; } } // normalize row by multiplier for (c=0; c<_n; c++) matrix_access(_x,_m,_n,_i,c) *= v; } int main() { // problem definition float x[18] = { 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, 1.0f, 1.0f, 0.0f, 4.0f, 0.0f, 1.0f, 2.0f, 0.0f, 1.0f, 3.0f }; unsigned int r = 3; unsigned int c = 6; matrixf_print(x,r,c); // pivot around x(1,1) = 2 matrixf_pivot2(x,r,c, 1,1); matrixf_print(x,r,c); // pivot around x(2,2) = 1.5 matrixf_pivot2(x,r,c, 2,2); matrixf_print(x,r,c); // print solution printf("solution:\n"); printf("z : %12.8f\n", matrixf_access(x,r,c,0,c-1)); unsigned int i; for (i=1; i #include #include #include //#include #include "liquid.h" #define DEBUG 1 int main() { // problem definition // sig1 = sqrt(1248) // sig2 = 20 // sig3 = sqrt(384) // sig4 = 0 // sig5 = 0 float a[40] = { 22, 10, 2, 3, 7, 14, 7, 10, 0, 8, -1, 13, -1, -11, 3, -3, -2, 13, -2, 4, 9, 8, 1, -2, 4, 9, 1, -7, 5, -1, 2, -6, 6, 5, 1, 4, 5, 0, -2, 2}; // NOTE: m >= n unsigned int m = 8; unsigned int n = 5; #if 0 // initialize as random matrix unsigned int ii; for (ii=0; ii x) x = y; } // accumulation of right-hand transformations for (i=n-1; i>=0; i--) { //if (g != 0) { if ( fabs(g) > 1e-3 ) { h = matrix_access(u,m,n,i,i+1)*g; for (j=l; j=0; i--) { l = i+1; g = q[i]; for (j=l; j 1e-3 ) { h = matrix_access(u,m,n,i,i) * g; for (j=l; j=0; k--) { if (k==(n-2)) { printf("...\n"); break; } test_f_splitting: printf("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n"); printf("test f splitting\n"); printf(" k = %u\n", k); t--; if (t==0) { fprintf(stderr,"***********************************************\n"); fprintf(stderr," bailing\n"); fprintf(stderr,"***********************************************\n"); t=10; continue; } for (l=k; l>0; l--) { printf(" e[%3u] = %12.4e, q[%3u] = %12.4e (eps: %12.4e)\n", l, e[l], l-1, q[l-1], eps); if ( fabs(e[l]) <= eps ) goto test_f_convergence; if ( fabs(q[l-1]) <= eps ) goto cancellation; } // for l // FIXME: figure out logic here (need to set l > 0) l = 1; // cancellation of e[l] if l>0 cancellation: printf("cancellation\n"); c = 0; s = 1; l1 = l-1; for (i=l; i %f, f -> %f\n", g, f); // next QR transformation c = 1; s = 1; for (i=l+1; i #include #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "symsync_crcf_test.m" // print usage/help message void usage() { printf("symsync_crcf_test [options]\n"); printf(" u/h : print usage\n"); printf(" T : filter type: rrcos, rkaiser, [arkaiser], hM3, gmsk\n"); printf(" m : filter delay (symbols), default: 3\n"); printf(" b : filter excess bandwidth, default: 0.5\n"); printf(" B : filter polyphase banks, default: 32\n"); printf(" s : signal-to-noise ratio, default: 30dB\n"); printf(" w : timing pll bandwidth, default: 0.02\n"); printf(" n : number of symbols, default: 200\n"); printf(" t : timing phase offset [%% symbol], t in [-0.5,0.5], default: -0.2\n"); } // filter coefficients // alpha zeta settling time (symbols) // 0.90 1.5 70 // 0.92 1.4 100 // 0.94 1.2 110 // 0.96 0.5 140 // 0.98 0.2 210 // 0.985 0.08 410 // 0.990 0.05 500 // 0.995 0.01 1100 // 0.998 0.002 2500 // // Let bandwidth = 1/settling time, int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int k=2; // samples/symbol (input) unsigned int m=3; // filter delay (symbols) float beta=0.5f; // filter excess bandwidth factor unsigned int npfb=32; // number of filters in the bank unsigned int num_symbols=512; // number of data symbols float SNRdB = 30.0f; // signal-to-noise ratio liquid_firfilt_type ftype_tx = LIQUID_FIRFILT_ARKAISER; liquid_firfilt_type ftype_rx = LIQUID_FIRFILT_ARKAISER; float bt=0.02f; // loop filter bandwidth float tau=-0.2f; // fractional symbol offset int dopt; while ((dopt = getopt(argc,argv,"uhT:m:b:B:s:w:n:t:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'T': if (strcmp(optarg,"gmsk")==0) { ftype_tx = LIQUID_FIRFILT_GMSKTX; ftype_rx = LIQUID_FIRFILT_GMSKRX; } else { ftype_tx = liquid_getopt_str2firfilt(optarg); ftype_rx = liquid_getopt_str2firfilt(optarg); } if (ftype_tx == LIQUID_FIRFILT_UNKNOWN) { fprintf(stderr,"error: %s, unknown filter type '%s'\n", argv[0], optarg); exit(1); } break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'B': npfb = atoi(optarg); break; case 's': SNRdB = atof(optarg); break; case 'w': bt = atof(optarg); break; case 'n': num_symbols = atoi(optarg); break; case 't': tau = atof(optarg); break; default: exit(1); } } // validate input if (m < 1) { fprintf(stderr,"error: m (filter delay) must be greater than 0\n"); exit(1); } else if (beta <= 0.0f || beta > 1.0f) { fprintf(stderr,"error: beta (excess bandwidth factor) must be in (0,1]\n"); exit(1); } else if (npfb == 0) { fprintf(stderr,"error: number of polyphase filters must be greater than 0\n"); exit(1); } else if (bt <= 0.0f) { fprintf(stderr,"error: timing PLL bandwidth must be greater than 0\n"); exit(1); } else if (num_symbols == 0) { fprintf(stderr,"error: number of symbols must be greater than 0\n"); exit(1); } else if (tau < -1.0f || tau > 1.0f) { fprintf(stderr,"error: timing phase offset must be in [-1,1]\n"); exit(1); } unsigned int i; unsigned int num_samples = k*num_symbols; float complex sym_in[num_symbols]; // data symbols float complex x[num_samples]; // interpolated samples float complex y[num_samples]; // noisy samples float complex sym_out[num_symbols + 64]; // synchronized symbols // generate random QPSK symbols for (i=0; i npfb-1) { pfb_index -= npfb; pfb_soft -= npfb; pfb_timer++; } // save debugging outputs debug_pfb_error[n] = pfb_error; debug_pfb_q[n] = pfb_q; debug_pfb_soft[n] = pfb_soft; // increment output counter n++; } // decrement timer pfb_timer--; } // destroy filterbanks firpfb_crcf_destroy(mf); firpfb_crcf_destroy(dmf); // print last several symbols to screen printf("output symbols:\n"); for (i=n-10; i #include #include #include #include #include #include "liquid.h" #define OUTPUT_FILENAME "symsync_eqlms_test.m" // print usage/help message void usage() { printf("symsync_eqlms_test [options]\n"); printf(" u/h : print usage\n"); // transmit filter properties printf(" k : filter samples/symbol, default: 2\n"); printf(" m : filter delay (symbols), default: 3\n"); printf(" b : filter excess bandwidth, default: 0.5\n"); printf(" n : number of symbols, default: 400\n"); // symsync properties printf(" B : filter polyphase banks, default: 32\n"); printf(" w : timing pll bandwidth, default: 0.02\n"); // equalizer properties printf(" p : equalizer order [symbols], default: 3\n"); printf(" W : equalizer bandwidth, default: 0.05\n"); // channel printf(" s : signal-to-noise ratio, default: 30dB\n"); printf(" c : channel impulse response length, default: 5\n"); printf(" t : timing phase offset [%% symbol], -0.5 < t <= 0.5, default: 0\n"); } int main(int argc, char*argv[]) { srand(time(NULL)); // options unsigned int k=2; // samples/symbol (input) unsigned int m=3; // filter delay (symbols) float beta=0.5f; // filter excess bandwidth factor unsigned int npfb=32; // number of filters in the bank unsigned int p=3; // equalizer length (symbols, hp_len = 2*k*p+1) float mu = 0.05f; // equalizer learning rate unsigned int num_symbols=500; // number of data symbols unsigned int hc_len=5; // channel filter length float SNRdB = 30.0f; // signal-to-noise ratio liquid_firfilt_type ftype = LIQUID_FIRFILT_ARKAISER; float bt=0.05f; // symbol synchronizer loop filter bandwidth float tau=-0.1f; // fractional symbol offset int dopt; while ((dopt = getopt(argc,argv,"uhk:m:b:n:B:w:p:W:s:c:t:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; // transmit filter properties case 'k': k = atoi(optarg); break; case 'm': m = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'n': num_symbols = atoi(optarg); break; // symsync properties case 'B': npfb = atoi(optarg); break; case 'w': bt = atof(optarg); break; // equalizer properties case 'p': p = atoi(optarg); break; case 'W': mu = atof(optarg); break; // equalizer properties case 's': SNRdB = atof(optarg); break; case 'c': hc_len = atoi(optarg); break; case 't': tau = atof(optarg); break; default: exit(1); } } // validate input if (k < 2) { fprintf(stderr,"error: %s,k (samples/symbol) must be at least 2\n", argv[0]); exit(1); } else if (m < 1) { fprintf(stderr,"error: %s,m (filter delay) must be greater than 0\n", argv[0]); exit(1); } else if (beta <= 0.0f || beta > 1.0f) { fprintf(stderr,"error: %s,beta (excess bandwidth factor) must be in (0,1]\n", argv[0]); exit(1); } else if (num_symbols == 0) { fprintf(stderr,"error: %s,number of symbols must be greater than 0\n", argv[0]); exit(1); } else if (npfb == 0) { fprintf(stderr,"error: %s,number of polyphase filters must be greater than 0\n", argv[0]); exit(1); } else if (bt < 0.0f) { fprintf(stderr,"error: %s,timing PLL bandwidth cannot be negative\n", argv[0]); exit(1); } else if (p == 0) { fprintf(stderr,"error: %s, equalizer order must be at least 1\n", argv[0]); exit(1); } else if (mu < 0.0f || mu > 1.0f) { fprintf(stderr,"error: %s, equalizer learning rate must be in [0,1]\n", argv[0]); exit(1); } else if (hc_len < 1) { fprintf(stderr,"error: %s, channel response must have at least 1 tap\n", argv[0]); exit(1); } else if (tau < -1.0f || tau > 1.0f) { fprintf(stderr,"error: %s,timing phase offset must be in [-1,1]\n", argv[0]); exit(1); } // derived values unsigned int ht_len = 2*k*m+1; // transmit filter order unsigned int hp_len = 2*k*p+1; // equalizer order float nstd = powf(10.0f, -SNRdB/20.0f); float dt = tau; // fractional sample offset unsigned int ds = 0; // full sample delay unsigned int i; unsigned int num_samples = k*num_symbols; float complex s[num_symbols]; // data symbols float complex x[num_samples]; // interpolated samples float complex y[num_samples]; // channel output float complex z[k*num_symbols + 64]; // synchronized samples float complex sym_out[num_symbols + 64]; // synchronized symbols for (i=0; i 0.0f ? M_SQRT1_2 : -M_SQRT1_2) + (cimagf(d_hat) > 0.0f ? M_SQRT1_2 : -M_SQRT1_2) * _Complex_I; // update equalizer eqlms_cccf_step(eq, d_prime, d_hat); } // get equalizer weights eqlms_cccf_get_weights(eq, hp); // destroy equalizer object eqlms_cccf_destroy(eq); // print last several symbols to screen printf("output symbols:\n"); for (i=num_symbols_sync-10; i #include #include #include #include "liquid.internal.h" void compute_thiran_allpass(unsigned int _n, float _mu, float * _b, float * _a); int main() { unsigned int n = 4; float mu = 0.1f; float b[n+1]; float a[n+1]; // compute filter coefficients compute_thiran_allpass(n,mu,b,a); // print coefficients to screen unsigned int i; for (i=0; i<=n; i++) printf("a(%3u) = %12.8f; b(%3u) = %12.8f;\n", i+1, a[i], i+1, b[i]); // compute group delay float g = iir_group_delay(b,n+1,a,n+1,0.0f); printf(" g = %f\n", g); printf("done.\n"); return 0; } void compute_thiran_allpass(unsigned int _n, float _mu, float * _b, float * _a) { float nf = (float)_n; unsigned int k; for (k=0; k<=_n; k++) { _a[k] = ((k%2)==0 ? 1.0f : -1.0f) * liquid_nchoosek(_n, k); // check condition when mu is very small (eliminate divide-by-zero) if ( fabsf(_mu) < 1e-6f ) { _a[k] = _a[k]*_a[k]; continue; } // TODO : expand as sum of logarithms unsigned int n; for (n=0; n<=_n; n++) { _a[k] *= (_mu - nf + (float)n) / (_mu - nf + (float)(n+k)); } } for (k=0; k<=_n; k++) _b[k] = _a[_n-k]; } liquid-dsp-1.3.1/sandbox/vectorcf_test.c000066400000000000000000000012461317124540100202440ustar00rootroot00000000000000// // vectorcf_test.c : test complex floating-point vector operations // #include #include #include #include //#include #include "liquid.h" int main() { // options unsigned int n = 64; // unsigned int i; float complex v[n]; for (i=0; i #include #include #include "autoscript.h" #define NAME_LEN (256) #define AUTOSCRIPT_VERSION "0.3.1" #define DEBUG_AUTOSCRIPT 0 struct script_s { char name[NAME_LEN]; struct package_s * package; }; struct package_s { char name[NAME_LEN]; char filename[NAME_LEN]; struct script_s * scripts; unsigned int num_scripts; }; struct autoscript_s { char type[NAME_LEN]; char delim; unsigned int num_packages; struct package_s * packages; }; // create autoscript generator object autoscript autoscript_create(char * _type, char _delim) { autoscript q = (autoscript) malloc(sizeof(struct autoscript_s)); // copy type and delimiter (path separator) strncpy(q->type, _type, NAME_LEN); q->delim = _delim; q->num_packages = 0; q->packages = NULL; return q; } void autoscript_destroy(autoscript _q) { // free all internal scripts unsigned int i; for (i=0; i<_q->num_packages; i++) { if (_q->packages[i].scripts != NULL) free(_q->packages[i].scripts); } // free all internal packages if (_q->packages != NULL) free(_q->packages); // free main object memory free(_q); } // parse filename and file void autoscript_parse(autoscript _q, char * _filename) { #if DEBUG_AUTOSCRIPT fprintf(stderr,"autoscript_parse('%s')...\n", _filename); #endif char package_name[NAME_LEN]; // parse filename... autoscript_parsefilename(_q, _filename, package_name); // parse actual file... autoscript_parsefile(_q, _filename, package_name); } void autoscript_print(autoscript _q) { unsigned int i; unsigned int j; unsigned int n; // count total number of scripts unsigned int num_scripts = 0; for (i=0; i<_q->num_packages; i++) num_scripts += _q->packages[i].num_scripts; // print header printf("// auto-generated file, do not edit\n"); printf("// invoked with script type '%s' and delimiter '%c'\n", _q->type, _q->delim); printf("// the following types need to be defined externally:\n"); printf("// typedef ...(%s_function_t)(...);\n", _q->type); printf("// typedef struct {\n"); printf("// unsigned int id; // script identification number\n"); printf("// %s_function_t * api; // pointer to function API\n", _q->type); printf("// const char * name; // script name\n"); printf("// ...\n"); printf("// } %s_t;\n", _q->type); printf("// typedef struct {\n"); printf("// unsigned int id; // package identification number\n"); printf("// unsigned int index; // index of first script\n"); printf("// unsigned int n; // number of scripts in package\n"); printf("// const char * name; // name of package\n"); printf("// } package_t;\n"); printf("\n"); printf("#ifndef __LIQUID_AUTOSCRIPT_INCLUDE_H__\n"); printf("#define __LIQUID_AUTOSCRIPT_INCLUDE_H__\n\n"); printf("#define AUTOSCRIPT_VERSION \"%s\"\n\n", AUTOSCRIPT_VERSION); printf("// number of packages\n"); printf("#define NUM_PACKAGES (%u)\n\n", _q->num_packages); printf("// number of scripts\n"); printf("#define NUM_AUTOSCRIPTS (%u)\n\n", num_scripts); printf("// function declarations\n"); for (i=0; i<_q->num_packages; i++) { struct package_s * p = &_q->packages[i]; printf("// %s\n", p->filename); #if 0 for (j=0; jnum_scripts; j++) printf("void benchmark_%s(AUTOSCRIPT_ARGS);\n", p->scripts[j].name); #else for (j=0; jnum_scripts; j++) printf("%s_function_t %s_%s;\n", _q->type, _q->type, p->scripts[j].name); #endif } printf("\n"); // find longest name unsigned int max_len = 0; for (i=0; i<_q->num_packages; i++) { //struct package_s * p = &_q->packages[i]; for (j=0; j<_q->packages[i].num_scripts; j++) { unsigned int str_len = strlen(_q->packages[i].scripts[j].name); max_len = str_len > max_len ? str_len : max_len; } } char space[max_len+1]; memset(space, ' ', max_len); space[max_len] = '\0'; printf("// array of scripts\n"); printf("%s_t scripts[NUM_AUTOSCRIPTS] = {\n", _q->type); n=0; for (i=0; i<_q->num_packages; i++) { struct package_s * p = &_q->packages[i]; for (j=0; jnum_scripts; j++) { // print formatting line, adding appropriate space to align columns printf(" {.id = %4u, .api = &%s_%s,%s .name = \"%s\"}", n, _q->type, p->scripts[j].name, &space[strlen(p->scripts[j].name)], p->scripts[j].name); if ( n < num_scripts-1 ) printf(","); printf("\n"); n++; } } printf("};\n\n"); n=0; printf("// array of packages\n"); printf("package_t packages[NUM_PACKAGES] = {\n"); for (i=0; i<_q->num_packages; i++) { printf(" {.id = %4u, .index = %4u, .num_scripts = %4u, .name = \"%s\"}", i, n, _q->packages[i].num_scripts, _q->packages[i].name); if (i<_q->num_packages-1) printf(","); printf("\n"); n += _q->packages[i].num_scripts; } printf("};\n\n"); printf("#endif // __LIQUID_AUTOSCRIPT_INCLUDE_H__\n\n"); } // // internal methods // // parse filename // _q : generator object // _filename : name of file // _package_name : output package name (stripped filename) void autoscript_parsefilename(autoscript _q, char * _filename, char * _package_name) { #if DEBUG_AUTOSCRIPT fprintf(stderr,"autoscript_parsefilename('%s')...\n", _filename); #endif char * sptr; // pointer to base name char * tptr; // pointer to terminating tag char pathsep = _q->delim; // path separator character // generate tag (e.g. "_benchmark") unsigned int tag_len = strlen(_q->type) + 2; char tag[tag_len]; tag[0] = '_'; strcpy(tag+1, _q->type); tag[tag_len-1] = '\0'; //printf("// tag : '%s'\n", tag); // try to strip out path: find rightmost occurrence of pathsep //printf("%s\n", _filename); sptr = strrchr(_filename, pathsep); // obtain index of last pathsep if (sptr == NULL) { // path delimiter not found sptr = _filename; } else { sptr++; // increment to remove path separator character } // try to strip out tag tptr = strstr( sptr, tag ); if (tptr == NULL) { // TODO : handle this case differently otherwise fprintf(stderr,"error: autoscript_parsefilename('%s'), tag '%s' not found\n", _filename, tag); exit(1); } // copy base name to output int n = tptr - sptr; strncpy(_package_name, sptr, n); _package_name[n] = '\0'; //printf("// package name : '%s'\n", _package_name); } // parse file // _q : generator object // _filename : name of file // _package_name : input package name (stripped filename) void autoscript_parsefile(autoscript _q, char * _filename, char * _package_name) { // flag indicating if package has been added or not int package_added = 0; #if DEBUG_AUTOSCRIPT fprintf(stderr,"autoscript_parsefile('%s')...\n", _filename); #endif // try to open file... FILE * fid = fopen(_filename,"r"); if (!fid) { fprintf(stderr,"error: autoscript_parsefile('%s'), could not open file for reading\n", _filename); exit(1); } // generate tag (e.g. "void benchmark_"); unsigned int tag_len = 5 + strlen(_q->type) + 2; char tag[tag_len]; strcpy(tag, "void "); strcpy(tag+5, _q->type); tag[tag_len-2] = '_'; tag[tag_len-1] = '\0'; //printf("// tag : '%s'\n", tag); // parse file, looking for key char buffer[1024]; // line buffer char basename[1024]; // base script name char * cptr = NULL; // readline return value char * sptr = NULL; // tag string pointer int cterm; // terminating character unsigned int n=0; // line number do { // increment line number n++; // read line cptr = fgets(buffer, 1024, fid); if (cptr != NULL) { // search for key sptr = strstr(cptr, tag); if (sptr == NULL) { // no value found continue; } // key found: find terminating character and strip out base name sptr += strlen(tag); // increment string by tag length cterm = strcspn( sptr, " (\t\n\r" ); if (cterm == strlen(sptr)) { // no terminating character found continue; } // copy base name strncpy( basename, sptr, cterm ); basename[cterm] = '\0'; //printf("// line %3u : '%s'\n", n, basename); // key found: add package if not already done if (!package_added) { // TODO : add base name autoscript_addpackage(_q, _package_name, _filename); package_added = 1; } autoscript_addscript(_q, _package_name, basename); } } while (!feof(fid)); // close file fclose(fid); } void autoscript_addpackage(autoscript _q, char * _package_name, char * _filename) { // increase package size _q->num_packages++; // re-allocate memory for packages _q->packages = (struct package_s *) realloc(_q->packages, _q->num_packages*sizeof(struct package_s)); // initialize new package strncpy(_q->packages[_q->num_packages-1].name, _package_name, NAME_LEN); // initialize new package strncpy(_q->packages[_q->num_packages-1].filename, _filename, NAME_LEN); // initialize number of scripts _q->packages[_q->num_packages-1].num_scripts = 0; // set scripts pointer to NULL _q->packages[_q->num_packages-1].scripts = NULL; } void autoscript_addscript(autoscript _q, char * _package_name, char * _script_name) { // first validate that package exists unsigned int i; int package_found = 0; for (i=0; i<_q->num_packages; i++) { if ( strcmp(_q->packages[i].name, _package_name)==0 ) { package_found = 1; break; } } if (!package_found) { fprintf(stderr,"error: autoscript_addscript(), unknown package '%s'\n", _package_name); exit(1); } struct package_s * p = &_q->packages[i]; // increase script size p->num_scripts++; // re-allocate memory for scripts p->scripts = (struct script_s *) realloc(p->scripts, p->num_scripts*sizeof(struct script_s)); // initialize new script strncpy(p->scripts[p->num_scripts-1].name, _script_name, NAME_LEN); // associate script with package //_q->scripts[_q->num_scripts-1].package = &_q->packages[i]; } liquid-dsp-1.3.1/scripts/autoscript.h000066400000000000000000000046461317124540100176340ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef __LIQUID_AUTOSCRIPT_H__ #define __LIQUID_AUTOSCRIPT_H__ typedef struct autoscript_s * autoscript; // create autoscript generator object autoscript autoscript_create(char * _type, char _delim); // parse file void autoscript_parse(autoscript _q, char * _filename); void autoscript_print(autoscript _q); void autoscript_destroy(autoscript _q); // // internal methods // // parse filename // _q : generator object // _filename : name of file // _package_name : output package name (stripped filename) void autoscript_parsefilename(autoscript _q, char * _filename, char * _package_name); // parse file // _q : generator object // _filename : name of file // _package_name : input package name (stripped filename) void autoscript_parsefile(autoscript _q, char * _filename, char * _package_name); void autoscript_addpackage(autoscript _q, char * _package_name, char * _filename); void autoscript_addscript(autoscript _q, char * _package_name, char * _script_name); #endif // __LIQUID_AUTOSCRIPT_H__ liquid-dsp-1.3.1/scripts/ax_check_compile_flag.m4000066400000000000000000000062511317124540100217700ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) # # DESCRIPTION # # Check whether the given FLAG works with the current language's compiler # or gives an error. (Warnings, however, are ignored) # # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on # success/failure. # # If EXTRA-FLAGS is defined, it is added to the current language's default # flags (e.g. CFLAGS) when the check is done. The check is thus made with # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to # force the compiler to issue an error when a bad flag is given. # # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. # # LICENSE # # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 2 AC_DEFUN([AX_CHECK_COMPILE_FLAG], [AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl ])dnl AX_CHECK_COMPILE_FLAGS liquid-dsp-1.3.1/scripts/ax_ext.m4000066400000000000000000000124211317124540100170060ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_ext.html # =========================================================================== # # SYNOPSIS # # AX_EXT # # DESCRIPTION # # Find supported SIMD extensions by requesting cpuid. When an SIMD # extension is found, the -m"simdextensionname" is added to SIMD_FLAGS # (only if compilator support it) (ie : if "sse2" is available "-msse2" is # added to SIMD_FLAGS) # # This macro calls: # # AC_SUBST(SIMD_FLAGS) # # And defines: # # HAVE_MMX / HAVE_SSE / HAVE_SSE2 / HAVE_SSE3 / HAVE_SSSE3 / # HAVE_SSE41 / HAVE_SSE42 / HAVE_AVX # # LICENSE # # Copyright (c) 2008 Christophe Tournayre # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. # # MODIFIED # * March 23, 2012 Joseph D. Gaeddert # Including tests for proper intrinsics header files in addition to cpu # capabilities. # MMX : mmintrin.h # SSE : xmmintrin.h # SSE2 : emmintrin.h # SSE3 : pmmintrin.h # SSSE3 : tmmintrin.h # SSE4.1/4.2 : smmintrin.h # AVX : immintrin.h #serial 9 AC_DEFUN([AX_EXT], [ AC_REQUIRE([AX_GCC_X86_CPUID]) AX_GCC_X86_CPUID(0x00000001) ecx=0 edx=0 if test "$ax_cv_gcc_x86_cpuid_0x00000001" != "unknown"; then ecx=`echo $ax_cv_gcc_x86_cpuid_0x00000001 | cut -d ":" -f 3` edx=`echo $ax_cv_gcc_x86_cpuid_0x00000001 | cut -d ":" -f 4` fi AC_CHECK_HEADERS(mmintrin.h xmmintrin.h emmintrin.h pmmintrin.h tmmintrin.h smmintrin.h immintrin.h) AC_CACHE_CHECK([whether mmx is supported], [ax_cv_have_mmx_ext], [ ax_cv_have_mmx_ext=no if test "$((0x$edx>>23&0x01))" = 1; then ax_cv_have_mmx_ext=yes fi ]) AC_CACHE_CHECK([whether sse is supported], [ax_cv_have_sse_ext], [ ax_cv_have_sse_ext=no if test "$((0x$edx>>25&0x01))" = 1; then ax_cv_have_sse_ext=yes fi ]) AC_CACHE_CHECK([whether sse2 is supported], [ax_cv_have_sse2_ext], [ ax_cv_have_sse2_ext=no if test "$((0x$edx>>26&0x01))" = 1; then ax_cv_have_sse2_ext=yes fi ]) AC_CACHE_CHECK([whether sse3 is supported], [ax_cv_have_sse3_ext], [ ax_cv_have_sse3_ext=no if test "$((0x$ecx&0x01))" = 1; then ax_cv_have_sse3_ext=yes fi ]) AC_CACHE_CHECK([whether ssse3 is supported], [ax_cv_have_ssse3_ext], [ ax_cv_have_ssse3_ext=no if test "$((0x$ecx>>9&0x01))" = 1; then ax_cv_have_ssse3_ext=yes fi ]) AC_CACHE_CHECK([whether sse4.1 is supported], [ax_cv_have_sse41_ext], [ ax_cv_have_sse41_ext=no if test "$((0x$ecx>>19&0x01))" = 1; then ax_cv_have_sse41_ext=yes fi ]) AC_CACHE_CHECK([whether sse4.2 is supported], [ax_cv_have_sse42_ext], [ ax_cv_have_sse42_ext=no if test "$((0x$ecx>>20&0x01))" = 1; then ax_cv_have_sse42_ext=yes fi ]) AC_CACHE_CHECK([whether avx is supported], [ax_cv_have_avx_ext], [ ax_cv_have_avx_ext=no if test "$((0x$ecx>>28&0x01))" = 1; then ax_cv_have_avx_ext=yes fi ]) if [ test "$ax_cv_have_mmx_ext" = yes && test "$ac_cv_header_mmintrin_h" = yes ]; then AC_DEFINE(HAVE_MMX,, [Support MMX instructions]) AX_CHECK_COMPILE_FLAG(-mmmx, SIMD_FLAGS="$SIMD_FLAGS -mmmx", []) fi if [ test "$ax_cv_have_sse_ext" = yes && test "$ac_cv_header_xmmintrin_h" = yes ]; then AC_DEFINE(HAVE_SSE,, [Support SSE (Streaming SIMD Extensions) instructions]) AX_CHECK_COMPILE_FLAG(-msse, SIMD_FLAGS="$SIMD_FLAGS -msse", []) fi if [ test "$ax_cv_have_sse2_ext" = yes && test "$ac_cv_header_emmintrin_h" = yes ]; then AC_DEFINE(HAVE_SSE2,, [Support SSE2 (Streaming SIMD Extensions 2) instructions]) AX_CHECK_COMPILE_FLAG(-msse2, SIMD_FLAGS="$SIMD_FLAGS -msse2", []) fi if [ test "$ax_cv_have_sse3_ext" = yes && test "$ac_cv_header_pmmintrin_h" = yes ]; then AC_DEFINE(HAVE_SSE3,, [Support SSE3 (Streaming SIMD Extensions 3) instructions]) AX_CHECK_COMPILE_FLAG(-msse3, SIMD_FLAGS="$SIMD_FLAGS -msse3", []) fi if [ test "$ax_cv_have_ssse3_ext" = yes && test "$ac_cv_header_tmmintrin_h" = yes ]; then AC_DEFINE(HAVE_SSSE3,, [Support SSSE3 (Supplemental Streaming SIMD Extensions 3) instructions]) AX_CHECK_COMPILE_FLAG(-mssse3, SIMD_FLAGS="$SIMD_FLAGS -mssse3", []) fi if [ test "$ax_cv_have_sse41_ext" = yes && test "$ac_cv_header_smmintrin_h" = yes ]; then AC_DEFINE(HAVE_SSE41,, [Support SSE4.1 (Streaming SIMD Extensions 4.1) instructions]) AX_CHECK_COMPILE_FLAG(-msse4.1, SIMD_FLAGS="$SIMD_FLAGS -msse4.1", []) fi if [ test "$ax_cv_have_sse42_ext" = yes && test "$ac_cv_header_smmintrin_h" = yes ]; then AC_DEFINE(HAVE_SSE42, 1,[Support SSE4.2 (Streaming SIMD Extensions 4.2) instructions]) AX_CHECK_COMPILE_FLAG(-msse4.2, SIMD_FLAGS="$SIMD_FLAGS -msse4.2", []) fi if [ test "$ax_cv_have_avx_ext" = yes && test "$ac_cv_header_immintrin_h" = yes ]; then AC_DEFINE(HAVE_AVX,,[Support AVX (Advanced Vector Extensions) instructions]) AX_CHECK_COMPILE_FLAG(-mavx, SIMD_FLAGS="$SIMD_FLAGS -mavx", []) fi AC_SUBST(SIMD_FLAGS) ]) liquid-dsp-1.3.1/scripts/ax_gcc_archflag.m4000066400000000000000000000226511317124540100205770ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_gcc_archflag.html # =========================================================================== # # SYNOPSIS # # AX_GCC_ARCHFLAG([PORTABLE?], [ACTION-SUCCESS], [ACTION-FAILURE]) # # DESCRIPTION # # This macro tries to guess the "native" arch corresponding to the target # architecture for use with gcc's -march=arch or -mtune=arch flags. If # found, the cache variable $ax_cv_gcc_archflag is set to this flag and # ACTION-SUCCESS is executed; otherwise $ax_cv_gcc_archflag is set to # "unknown" and ACTION-FAILURE is executed. The default ACTION-SUCCESS is # to add $ax_cv_gcc_archflag to the end of $CFLAGS. # # PORTABLE? should be either [yes] (default) or [no]. In the former case, # the flag is set to -mtune (or equivalent) so that the architecture is # only used for tuning, but the instruction set used is still portable. In # the latter case, the flag is set to -march (or equivalent) so that # architecture-specific instructions are enabled. # # The user can specify --with-gcc-arch= in order to override the # macro's choice of architecture, or --without-gcc-arch to disable this. # # When cross-compiling, or if $CC is not gcc, then ACTION-FAILURE is # called unless the user specified --with-gcc-arch manually. # # Requires macros: AX_CHECK_COMPILE_FLAG, AX_GCC_X86_CPUID # # (The main emphasis here is on recent CPUs, on the principle that doing # high-performance computing on old hardware is uncommon.) # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2008 Matteo Frigo # Copyright (c) 2012 Tsukasa Oi # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 13 AC_DEFUN([AX_GCC_ARCHFLAG], [AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_CANONICAL_HOST]) AC_ARG_WITH(gcc-arch, [AS_HELP_STRING([--with-gcc-arch=], [use architecture for gcc -march/-mtune, instead of guessing])], ax_gcc_arch=$withval, ax_gcc_arch=yes) AC_MSG_CHECKING([for gcc architecture flag]) AC_MSG_RESULT([]) AC_CACHE_VAL(ax_cv_gcc_archflag, [ ax_cv_gcc_archflag="unknown" if test "$GCC" = yes; then if test "x$ax_gcc_arch" = xyes; then ax_gcc_arch="" if test "$cross_compiling" = no; then case $host_cpu in i[[3456]]86*|x86_64*|amd64*) # use cpuid codes AX_GCC_X86_CPUID(0) AX_GCC_X86_CPUID(1) case $ax_cv_gcc_x86_cpuid_0 in *:756e6547:*:*) # Intel case $ax_cv_gcc_x86_cpuid_1 in *5[[48]]?:*:*:*) ax_gcc_arch="pentium-mmx pentium" ;; *5??:*:*:*) ax_gcc_arch=pentium ;; *1?6[[7d]]?:*:*:*) ax_gcc_arch="penryn core2 pentium-m pentium3 pentiumpro" ;; *1?6[[aef]]?:*:*:*|*2?6[[5cef]]?:*:*:*) ax_gcc_arch="corei7 core2 pentium-m pentium3 pentiumpro" ;; *1?6c?:*:*:*|*[[23]]?66?:*:*:*) ax_gcc_arch="atom core2 pentium-m pentium3 pentiumpro" ;; *2?6[[ad]]?:*:*:*) ax_gcc_arch="corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; *[[1-9a-f]]?6??:*:*:*) ax_gcc_arch="core2 pentiumpro" ;; *6[[3456]]?:*:*:*) ax_gcc_arch="pentium2 pentiumpro" ;; *6a?:*[[01]]:*:*) ax_gcc_arch="pentium2 pentiumpro" ;; *6a?:*[[234]]:*:*) ax_gcc_arch="pentium3 pentiumpro" ;; *6[[9de]]?:*:*:*) ax_gcc_arch="pentium-m pentium3 pentiumpro" ;; *6[[78b]]?:*:*:*) ax_gcc_arch="pentium3 pentiumpro" ;; *6f?:*:*:*) ax_gcc_arch="core2 pentium-m pentium3 pentiumpro" ;; *6??:*:*:*) ax_gcc_arch=pentiumpro ;; *f3[[347]]:*:*:*|*f4[1347]:*:*:*|*f6?:*:*:*) case $host_cpu in x86_64*) ax_gcc_arch="nocona pentium4 pentiumpro" ;; *) ax_gcc_arch="prescott pentium4 pentiumpro" ;; esac ;; *f??:*:*:*) ax_gcc_arch="pentium4 pentiumpro";; esac ;; *:68747541:*:*) # AMD case $ax_cv_gcc_x86_cpuid_1 in *5[[67]]?:*:*:*) ax_gcc_arch=k6 ;; *5[[8d]]?:*:*:*) ax_gcc_arch="k6-2 k6" ;; *5[[9]]?:*:*:*) ax_gcc_arch="k6-3 k6" ;; *60?:*:*:*) ax_gcc_arch=k7 ;; *6[[12]]?:*:*:*) ax_gcc_arch="athlon k7" ;; *6[[34]]?:*:*:*) ax_gcc_arch="athlon-tbird k7" ;; *67?:*:*:*) ax_gcc_arch="athlon-4 athlon k7" ;; *6[[68a]]?:*:*:*) AX_GCC_X86_CPUID(0x80000006) # L2 cache size case $ax_cv_gcc_x86_cpuid_0x80000006 in *:*:*[[1-9a-f]]??????:*) # (L2 = ecx >> 16) >= 256 ax_gcc_arch="athlon-xp athlon-4 athlon k7" ;; *) ax_gcc_arch="athlon-4 athlon k7" ;; esac ;; *5??f??:*:*:*) ax_gcc_arch="btver1 amdfam10 k8" ;; *6??f??:*:*:*) ax_gcc_arch="bdver1 amdfam10 k8" ;; *[[1-9a-f]]??f??:*:*:*) ax_gcc_arch="amdfam10 k8" ;; *f[[4cef8b]]?:*:*:*) ax_gcc_arch="athlon64 k8" ;; *f5?:*:*:*) ax_gcc_arch="opteron k8" ;; *f7?:*:*:*) ax_gcc_arch="athlon-fx opteron k8" ;; *f??:*:*:*) ax_gcc_arch="k8" ;; esac ;; *:746e6543:*:*) # IDT case $ax_cv_gcc_x86_cpuid_1 in *54?:*:*:*) ax_gcc_arch=winchip-c6 ;; *58?:*:*:*) ax_gcc_arch=winchip2 ;; *6[[78]]?:*:*:*) ax_gcc_arch=c3 ;; *69?:*:*:*) ax_gcc_arch="c3-2 c3" ;; esac ;; esac if test x"$ax_gcc_arch" = x; then # fallback case $host_cpu in i586*) ax_gcc_arch=pentium ;; i686*) ax_gcc_arch=pentiumpro ;; esac fi ;; sparc*) AC_PATH_PROG([PRTDIAG], [prtdiag], [prtdiag], [$PATH:/usr/platform/`uname -i`/sbin/:/usr/platform/`uname -m`/sbin/]) cputype=`(((grep cpu /proc/cpuinfo | cut -d: -f2) ; ($PRTDIAG -v |grep -i sparc) ; grep -i cpu /var/run/dmesg.boot ) | head -n 1) 2> /dev/null` cputype=`echo "$cputype" | tr -d ' -' |tr $as_cr_LETTERS $as_cr_letters` case $cputype in *ultrasparciv*) ax_gcc_arch="ultrasparc4 ultrasparc3 ultrasparc v9" ;; *ultrasparciii*) ax_gcc_arch="ultrasparc3 ultrasparc v9" ;; *ultrasparc*) ax_gcc_arch="ultrasparc v9" ;; *supersparc*|*tms390z5[[05]]*) ax_gcc_arch="supersparc v8" ;; *hypersparc*|*rt62[[056]]*) ax_gcc_arch="hypersparc v8" ;; *cypress*) ax_gcc_arch=cypress ;; esac ;; alphaev5) ax_gcc_arch=ev5 ;; alphaev56) ax_gcc_arch=ev56 ;; alphapca56) ax_gcc_arch="pca56 ev56" ;; alphapca57) ax_gcc_arch="pca57 pca56 ev56" ;; alphaev6) ax_gcc_arch=ev6 ;; alphaev67) ax_gcc_arch=ev67 ;; alphaev68) ax_gcc_arch="ev68 ev67" ;; alphaev69) ax_gcc_arch="ev69 ev68 ev67" ;; alphaev7) ax_gcc_arch="ev7 ev69 ev68 ev67" ;; alphaev79) ax_gcc_arch="ev79 ev7 ev69 ev68 ev67" ;; powerpc*) cputype=`((grep cpu /proc/cpuinfo | head -n 1 | cut -d: -f2 | cut -d, -f1 | sed 's/ //g') ; /usr/bin/machine ; /bin/machine; grep CPU /var/run/dmesg.boot | head -n 1 | cut -d" " -f2) 2> /dev/null` cputype=`echo $cputype | sed -e 's/ppc//g;s/ *//g'` case $cputype in *750*) ax_gcc_arch="750 G3" ;; *740[[0-9]]*) ax_gcc_arch="$cputype 7400 G4" ;; *74[[4-5]][[0-9]]*) ax_gcc_arch="$cputype 7450 G4" ;; *74[[0-9]][[0-9]]*) ax_gcc_arch="$cputype G4" ;; *970*) ax_gcc_arch="970 G5 power4";; *POWER4*|*power4*|*gq*) ax_gcc_arch="power4 970";; *POWER5*|*power5*|*gr*|*gs*) ax_gcc_arch="power5 power4 970";; 603ev|8240) ax_gcc_arch="$cputype 603e 603";; *) ax_gcc_arch=$cputype ;; esac ax_gcc_arch="$ax_gcc_arch powerpc" ;; esac fi # not cross-compiling fi # guess arch if test "x$ax_gcc_arch" != x -a "x$ax_gcc_arch" != xno; then for arch in $ax_gcc_arch; do if test "x[]m4_default([$1],yes)" = xyes; then # if we require portable code flags="-mtune=$arch" # -mcpu=$arch and m$arch generate nonportable code on every arch except # x86. And some other arches (e.g. Alpha) don't accept -mtune. Grrr. case $host_cpu in i*86|x86_64*) flags="$flags -mcpu=$arch -m$arch";; esac else flags="-march=$arch -mcpu=$arch -m$arch" fi for flag in $flags; do AX_CHECK_COMPILE_FLAG($flag, [ax_cv_gcc_archflag=$flag; break]) done test "x$ax_cv_gcc_archflag" = xunknown || break done fi fi # $GCC=yes ]) AC_MSG_CHECKING([for gcc architecture flag]) AC_MSG_RESULT($ax_cv_gcc_archflag) if test "x$ax_cv_gcc_archflag" = xunknown; then m4_default([$3],:) else m4_default([$2], [CFLAGS="$CFLAGS $ax_cv_gcc_archflag"]) fi ]) liquid-dsp-1.3.1/scripts/ax_gcc_x86_cpuid.m4000066400000000000000000000063611317124540100206410ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_gcc_x86_cpuid.html # =========================================================================== # # SYNOPSIS # # AX_GCC_X86_CPUID(OP) # # DESCRIPTION # # On Pentium and later x86 processors, with gcc or a compiler that has a # compatible syntax for inline assembly instructions, run a small program # that executes the cpuid instruction with input OP. This can be used to # detect the CPU type. # # On output, the values of the eax, ebx, ecx, and edx registers are stored # as hexadecimal strings as "eax:ebx:ecx:edx" in the cache variable # ax_cv_gcc_x86_cpuid_OP. # # If the cpuid instruction fails (because you are running a # cross-compiler, or because you are not using gcc, or because you are on # a processor that doesn't have this instruction), ax_cv_gcc_x86_cpuid_OP # is set to the string "unknown". # # This macro mainly exists to be used in AX_GCC_ARCHFLAG. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2008 Matteo Frigo # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 7 AC_DEFUN([AX_GCC_X86_CPUID], [AC_REQUIRE([AC_PROG_CC]) AC_LANG_PUSH([C]) AC_CACHE_CHECK(for x86 cpuid $1 output, ax_cv_gcc_x86_cpuid_$1, [AC_RUN_IFELSE([AC_LANG_PROGRAM([#include ], [ int op = $1, eax, ebx, ecx, edx; FILE *f; __asm__("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (op)); f = fopen("conftest_cpuid", "w"); if (!f) return 1; fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx); fclose(f); return 0; ])], [ax_cv_gcc_x86_cpuid_$1=`cat conftest_cpuid`; rm -f conftest_cpuid], [ax_cv_gcc_x86_cpuid_$1=unknown; rm -f conftest_cpuid], [ax_cv_gcc_x86_cpuid_$1=unknown])]) AC_LANG_POP([C]) ]) liquid-dsp-1.3.1/scripts/benchmark_compare.c000066400000000000000000000220011317124540100210530ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // benchmark_compare.c // // compare benchmark runs // #include #include #include #include // print usage/help message void usage() { printf("benchmark_compare [old_benchmark] [new_benchmark]\n"); } // define benchmark_t struct benchmark_t { //unsigned int id; char name[64]; //unsigned int name_len; //unsigned int num_trials; //float extime; //float rate; float cycles_per_trial; // link to other benchmark struct benchmark_t * link; }; struct benchlist_s { struct benchmark_t * benchmarks; unsigned int num_benchmarks; }; typedef struct benchlist_s * benchlist; // benchlist benchlist_create(); void benchlist_destroy(benchlist _q); void benchlist_print(benchlist _q); void benchlist_append(benchlist _q, char * _name, float _cycles_per_trial); void benchlist_link(benchlist _q0, benchlist _q1); // is line a comment? int parse_file(const char * _filename, benchlist _benchmarks); // read line from file // _fid : input file // _buffer : output buffer // _n : buffer length void readline(FILE * _fid, char * _buffer, unsigned int _n); // is line a comment? int line_is_comment(char * _buffer); int main(int argc, char*argv[]) { if (argc != 3) { usage(); exit(1); } // parse old benchmarks benchlist benchmarks_old = benchlist_create(); parse_file(argv[1], benchmarks_old); //benchlist_print(benchmarks_old); // parse new benchmarks benchlist benchmarks_new = benchlist_create(); parse_file(argv[2], benchmarks_new); //benchlist_print(benchmarks_new); // link benchmarks and print results benchlist_link(benchmarks_old, benchmarks_new); benchlist_print(benchmarks_old); // destroy benchmark lists benchlist_destroy(benchmarks_old); benchlist_destroy(benchmarks_new); printf("done.\n"); return 0; } // benchlist benchlist_create() { benchlist q = (benchlist) malloc(sizeof(struct benchlist_s)); // initialize internals q->benchmarks = NULL; q->num_benchmarks = 0; // return main object return q; } void benchlist_destroy(benchlist _q) { // free internals if (_q->benchmarks != NULL) free(_q->benchmarks); // free main object memory free(_q); } #if 0 void benchlist_print(benchlist _q) { unsigned int i; printf("benchlist [%u]:\n", _q->num_benchmarks); for (i=0; i<_q->num_benchmarks; i++) { printf(" - %-32s : %14.2f", _q->benchmarks[i].name, _q->benchmarks[i].cycles_per_trial); if (_q->benchmarks[i].link == NULL) { printf("\n"); } else { // print delta float cycles_old = _q->benchmarks[i].cycles_per_trial; float cycles_new = _q->benchmarks[i].link->cycles_per_trial; float delta = (cycles_new - cycles_old)/cycles_old; // print static value printf(" : %12.3f %8.2f %%\n", cycles_new, 100*delta); } } } #else void benchlist_print(benchlist _q) { unsigned int i; printf("benchlist [%u]:\n", _q->num_benchmarks); for (i=0; i<_q->num_benchmarks; i++) { if (_q->benchmarks[i].link == NULL) continue; printf(" - %-28s ", _q->benchmarks[i].name); // print delta float cycles_old = _q->benchmarks[i].cycles_per_trial; float cycles_new = _q->benchmarks[i].link->cycles_per_trial; float speedup = (cycles_old + 1e-6f) / (cycles_new + 1e-6f); // print bar graph style response unsigned int num_spaces = 20; unsigned int num_hashes = (unsigned int) (0.4*fabsf(log2f(speedup)) * num_spaces); if (num_hashes > num_spaces) num_hashes = num_spaces; unsigned int j; if (speedup > 1.0) { // newer is better for (j=0; jnum_benchmarks; i++) { if ( strncmp(_q->benchmarks[i].name, _name, 64) == 0) { fprintf(stderr,"warning: cannot append benchmark '%s'; benchmark already exists\n", _name); return; } } // re-allocate memory array _q->num_benchmarks++; _q->benchmarks = (struct benchmark_t*)realloc(_q->benchmarks, (_q->num_benchmarks)*sizeof(struct benchmark_t)); //printf("appending '%s' (%f)\n", _name, _cycles_per_trial); // // append new element // // copy name strncpy(_q->benchmarks[_q->num_benchmarks-1].name, _name, 64); // copy properties _q->benchmarks[_q->num_benchmarks-1].cycles_per_trial = _cycles_per_trial; // set link to NULL _q->benchmarks[_q->num_benchmarks-1].link = NULL; } void benchlist_link(benchlist _q0, benchlist _q1) { // link nodes unsigned int i; unsigned int j; for (i=0; i<_q0->num_benchmarks; i++) { for (j=0; j<_q1->num_benchmarks; j++) { if ( strncmp(_q0->benchmarks[i].name, _q1->benchmarks[j].name, 64)==0 ) { // match found; link nodes _q0->benchmarks[i].link = &_q1->benchmarks[j]; _q1->benchmarks[j].link = &_q0->benchmarks[i]; } } } } // is line a comment? int parse_file(const char * _filename, benchlist _benchmarks) { // FILE * fid = fopen(_filename,"r"); if (!fid) { fprintf(stderr,"error: parse_file(), could not open '%s' for reading\n", _filename); exit(1); } printf("parsing '%s'...\n", _filename); char buffer[256]; // line buffer int id; char name[64]; unsigned long int num_trials; float execution_time; float rate; float cycles_per_trial; do { // read line into buffer readline(fid, buffer, 256); // skip comment lines if (line_is_comment(buffer)) continue; // scan line for results int results = sscanf(buffer,"%d %s %lu %f %f %f\n", &id, name, &num_trials, &execution_time, &rate, &cycles_per_trial); if (results < 6) { //fprintf(stderr,"warning: skipping line '%s'\n", buffer); continue; } // append... benchlist_append(_benchmarks, name, cycles_per_trial); } while (!feof(fid)); // close the file fclose(fid); // return return 0; } // read line from file // _fid : input file // _buffer : output buffer // _n : buffer length void readline(FILE * _fid, char * _buffer, unsigned int _n) { unsigned int i=0; char c; while ( (c = fgetc(_fid)) != EOF && c != '\n' && i < _n-1) { _buffer[i] = c; i++; } _buffer[i] = '\0'; } // is line a comment? int line_is_comment(char * _buffer) { // read first non-whitespace character unsigned int i=0; char c; do { c = _buffer[i]; i++; } while (c == ' ' || c == '\t'); if (c == '#' || c == '\0') return 1; return 0; } liquid-dsp-1.3.1/scripts/config.guess000077500000000000000000001236721317124540100176070ustar00rootroot00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2014 Free Software Foundation, Inc. timestamp='2014-11-04' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD # # Please send patches to . me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/lslpp ] ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="gnulibc1" ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-${LIBC} exit ;; or32:Linux:*:* | or1k*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub # that puts up a graphical alert prompting to install # developer tools. Any system running Mac OS X 10.7 or # later (Darwin 11 and later) is required to have a 64-bit # processor. This is not true of the ARM version of Darwin # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: liquid-dsp-1.3.1/scripts/config.sub000077500000000000000000001062231317124540100172430ustar00rootroot00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2014 Free Software Foundation, Inc. timestamp='2014-12-03' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; leon|leon[3-9]) basic_machine=sparc-$basic_machine ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; leon-*|leon[3-9]-*) basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; moxiebox) basic_machine=moxie-unknown os=-moxiebox ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: liquid-dsp-1.3.1/scripts/example_autotest.h000066400000000000000000000023731317124540100210150ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Example of a benchmark header // #include #include void autotest_mytest() { printf("this is my test\n"); } liquid-dsp-1.3.1/scripts/example_benchmark.h000066400000000000000000000035251317124540100210770ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Example of a benchmark header // #include #include // strings parsed by benchmarkgen.py const char * mybench_opts[3] = { "opt1a opt1b", "opt2a opt2b opt2c", "opt3a opt3b opt3c" }; void benchmark_mybench( struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) // unsigned int argc, // char *argv[]) { // DSP initiazation goes here unsigned int i; float x, y, theta; getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { // DSP execution goes here x = cosf(M_PI/2.0f); y = sinf(M_PI/2.0f); theta = atan2(y,x); } getrusage(RUSAGE_SELF, _finish); // DSP cleanup goes here } liquid-dsp-1.3.1/scripts/install-sh000077500000000000000000000316001317124540100172600ustar00rootroot00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2006-10-14.15 # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" posix_glob= posix_mkdir= # Desired mode of installed file. mode=0755 chmodcmd=$chmodprog chowncmd= chgrpcmd= stripcmd= rmcmd="$rmprog -f" mvcmd="$mvprog" src= dst= dir_arg= dstarg= no_target_directory= usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: -c (ignored) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. --help display this help and exit. --version display version info and exit. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) shift continue;; -d) dir_arg=true shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; --help) echo "$usage"; exit $?;; -m) mode=$2 shift shift case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -s) stripcmd=$stripprog shift continue;; -t) dstarg=$2 shift shift continue;; -T) no_target_directory=true shift continue;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac done if test $# -ne 0 && test -z "$dir_arg$dstarg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dstarg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dstarg" shift # fnord fi shift # arg dstarg=$arg done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call `install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then trap '(exit $?); exit' 1 2 13 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names starting with `-'. case $src in -*) src=./$src ;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dstarg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dstarg # Protect names starting with `-'. case $dst in -*) dst=./$dst ;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dstarg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writeable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix=/ ;; -*) prefix=./ ;; *) prefix= ;; esac case $posix_glob in '') if (set -f) 2>/dev/null; then posix_glob=true else posix_glob=false fi ;; esac oIFS=$IFS IFS=/ $posix_glob && set -f set fnord $dstdir shift $posix_glob && set +f IFS=$oIFS prefixes= for d do test -z "$d" && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # Now rename the file to the real destination. { $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \ || { # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { if test -f "$dst"; then $doit $rmcmd -f "$dst" 2>/dev/null \ || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \ && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\ || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } else : fi } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } } || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: liquid-dsp-1.3.1/scripts/main.c000066400000000000000000000045731317124540100163550ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // scripts/main.c // // Auto-script generator test program #include #include #include #include "autoscript.h" void usage() { printf("Usage: autoscript_test DELIM TYPE [LIST OF FILES]\n"); printf(" DELIM : path separation delimiter (e.g. '/')\n"); printf(" TYPE : base type for parsing (e.g. \"benchmark\")\n"); printf(" [LIST] : list of auto-script files, named MYPACKAGE_TYPE.h\n"); printf(" with internal scripts \"void TYPE_MYSCRIPT(...)\"\n"); } int main(int argc, char*argv[]) { // if (argc < 3) { // print help fprintf(stderr,"error: %s, too few arguments\n", argv[0]); usage(); exit(1); } else { //printf("// delim : '%c'\n", argv[1][0]); //printf("// type : \"%s\"\n", argv[2]); } // create autoscript object // first argument : type string (e.g. "benchmark") // second argument : delimiter character (file system) autoscript q = autoscript_create(argv[2], argv[1][0]); // parse files int i; for (i=3; i ''' import os import sys import re def usage(): print __doc__ if len(sys.argv) != 2: sys.stderr.write("error: please provide an input directory\n") usage() sys.exit(-1) elif sys.argv[1] in ('-h','--help'): usage() sys.exit(0) # new copyright newcopy = '''\ Copyright (c) 2007 - 2015 Joseph Gaeddert Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.'''.splitlines() # add new line character to end of each line for i in xrange(len(newcopy)): newcopy[i] += '\n' rootdir = sys.argv[1] # specific files to ignore ignore_files = ['update_copyright.py',] # directories to ignore ignore_directories = ['.git',] # only look at these extensions include_extensions = ['.h', '.c', '.md', '.tex', '.ac', '.in', '.m',] # print alignment for status align = 56 # def update_copyright(filename=""): """ Update copyright on file. """ # try to open file contents = [] with open( filename, 'r' ) as f: # read lines from file (removing newline character at end) for line in f: #contents.append(line.strip('\n\r')) contents.append(line) # parse contents index_start = -1 index_stop = -1 # search for copyright; starts at top of file for i in range(min(10, len(contents))): if re.search(r'Copyright .* Joseph Gaeddert',contents[i]): index_start = i break if index_start == -1: print " " + filename + ":" + " "*(align-len(filename)) + "no copyright found" return # look for end of copyright #for i in range(index_start+15,index_start+15+min(10, len(contents))): i = index_start + 15 if re.search(r'along with liquid. If not, see',contents[i]): index_stop = i elif re.search(r'AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM',contents[i]): print " " + filename + ":" + " "*(align-len(filename)) + "copyright already updated" return else: print " " + filename + ":" + " "*(align-len(filename)) + "could not find end of copyright" return # check comment type m = re.search(r'^( \*|#+) +Copyright',contents[index_start]) if m: comment = m.group(1) else: raise Exception('unexpected error') # delete items in list contents.__delslice__(index_start, index_stop+1) # insert new copyright for i in range(len(newcopy)): # only add space after comment characters if string is not empty # (e.g. print ' *' instead of ' * ') space = ' ' if len(newcopy[i].strip()) > 0 else '' # insert new comment contents.insert(index_start+i, comment + space + newcopy[i]) # open original file for writing with open( filename, 'w' ) as f: for line in contents: f.write(line) print " " + filename + ":" + " "*(align-len(filename)) + "updated" # for root, subFolders, files in os.walk(rootdir): # strip off leading './' if it exists if root.startswith('./'): root = root[2:] # print root directory print root # ignore certain directories if root in ignore_directories: print "(skipping directory)" continue # print subfolders #for folder in subFolders: # print "%s has subdirectory %s" % (root, folder) # parse each filename in directory for filename in files: filePath = os.path.join(root, filename) # check filename if filePath in ignore_files: print " " + filePath + ":" + " "*(align-len(filePath)) + "ignoring this specific file" continue; # check filename extension baseName, extension = os.path.splitext(filename) if extension not in include_extensions: print " " + filePath + ":" + " "*(align-len(filePath)) + "improper extension; ignoring file" continue; # continue on with this file update_copyright(filePath) liquid-dsp-1.3.1/src/000077500000000000000000000000001317124540100143545ustar00rootroot00000000000000liquid-dsp-1.3.1/src/agc/000077500000000000000000000000001317124540100151065ustar00rootroot00000000000000liquid-dsp-1.3.1/src/agc/bench/000077500000000000000000000000001317124540100161655ustar00rootroot00000000000000liquid-dsp-1.3.1/src/agc/bench/agc_crcf_benchmark.c000066400000000000000000000040621317124540100220740ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // helper function to keep code base small void benchmark_agc_crcf(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations) { unsigned int i; // initialize AGC object agc_crcf q = agc_crcf_create(); agc_crcf_set_bandwidth(q,0.05f); float complex x = 1e-6f; // input sample float complex y; // output sample getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { agc_crcf_execute(q, x, &y); agc_crcf_execute(q, x, &y); agc_crcf_execute(q, x, &y); agc_crcf_execute(q, x, &y); agc_crcf_execute(q, x, &y); agc_crcf_execute(q, x, &y); agc_crcf_execute(q, x, &y); agc_crcf_execute(q, x, &y); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 8; // destroy object agc_crcf_destroy(q); } liquid-dsp-1.3.1/src/agc/src/000077500000000000000000000000001317124540100156755ustar00rootroot00000000000000liquid-dsp-1.3.1/src/agc/src/agc.c000066400000000000000000000241721317124540100166010ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2017 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Automatic gain control // #include #include #include #include "liquid.internal.h" // default AGC loop bandwidth #define AGC_DEFAULT_BW (1e-2f) // internal method definition void AGC(_squelch_update_mode)(AGC() _q); // agc structure object struct AGC(_s) { // gain variables T g; // current gain value // gain control loop filter parameters float bandwidth;// bandwidth-time constant T alpha; // feed-back gain // signal level estimate T y2_prime; // filtered output signal energy estimate // AGC locked flag int is_locked; // squelch mode agc_squelch_mode squelch_mode; // squelch threshold T squelch_threshold; // squelch timeout unsigned int squelch_timeout; unsigned int squelch_timer; }; // create agc object AGC() AGC(_create)(void) { // create object and initialize to default parameters AGC() _q = (AGC()) malloc(sizeof(struct AGC(_s))); // initialize bandwidth AGC(_set_bandwidth)(_q, AGC_DEFAULT_BW); // reset object AGC(_reset)(_q); // squelch AGC(_squelch_disable)(_q); AGC(_squelch_set_threshold)(_q, 0.0f); AGC(_squelch_set_timeout )(_q, 100); // return object return _q; } // destroy agc object, freeing all internally-allocated memory void AGC(_destroy)(AGC() _q) { // free main object memory free(_q); } // print agc object internals void AGC(_print)(AGC() _q) { printf("agc [rssi: %12.4f dB]:\n", AGC(_get_rssi)(_q)); } // reset agc object's internal state void AGC(_reset)(AGC() _q) { // reset gain estimate _q->g = 1.0f; // reset signal level estimate _q->y2_prime = 1.0f; // unlock gain control AGC(_unlock)(_q); // reset squelch state _q->squelch_mode = (_q->squelch_mode == LIQUID_AGC_SQUELCH_DISABLED) ? LIQUID_AGC_SQUELCH_DISABLED : LIQUID_AGC_SQUELCH_ENABLED; } // execute automatic gain control loop // _q : agc object // _x : input sample // _y : output sample void AGC(_execute)(AGC() _q, TC _x, TC * _y) { // apply gain to input sample *_y = _x * _q->g; // compute output signal energy T y2 = crealf( (*_y)*conjf(*_y) ); // smooth energy estimate using single-pole low-pass filter _q->y2_prime = (1.0-_q->alpha)*_q->y2_prime + _q->alpha*y2; // return if locked if (_q->is_locked) return; // update gain according to output energy if (_q->y2_prime > 1e-6f) _q->g *= expf( -0.5f*_q->alpha*logf(_q->y2_prime) ); // clamp to 120 dB gain if (_q->g > 1e6f) _q->g = 1e6f; // udpate squelch mode appropriately AGC(_squelch_update_mode)(_q); } // execute automatic gain control on block of samples // _q : automatic gain control object // _x : input data array, [size: _n x 1] // _n : number of input, output samples // _y : output data array, [size: _n x 1] void AGC(_execute_block)(AGC() _q, TC * _x, unsigned int _n, TC * _y) { unsigned int i; for (i=0; i<_n; i++) AGC(_execute)(_q, _x[i], &_y[i]); } // lock agc void AGC(_lock)(AGC() _q) { _q->is_locked = 1; } // unlock agc void AGC(_unlock)(AGC() _q) { _q->is_locked = 0; } // get agc loop bandwidth float AGC(_get_bandwidth)(AGC() _q) { return _q->bandwidth; } // set agc loop bandwidth // _q : agc object // _BT : bandwidth void AGC(_set_bandwidth)(AGC() _q, float _bt) { // check to ensure bandwidth is reasonable if ( _bt < 0 ) { fprintf(stderr,"error: agc_%s_set_bandwidth(), bandwidth must be positive\n", EXTENSION_FULL); exit(-1); } else if ( _bt > 1.0f ) { fprintf(stderr,"error: agc_%s_set_bandwidth(), bandwidth must less than 1.0\n", EXTENSION_FULL); exit(-1); } // set internal bandwidth _q->bandwidth = _bt; // compute filter coefficient based on bandwidth _q->alpha = _q->bandwidth; } // get estimated signal level (linear) float AGC(_get_signal_level)(AGC() _q) { return 1.0f / _q->g; } // set estimated signal level (linear) void AGC(_set_signal_level)(AGC() _q, float _signal_level) { // check to ensure signal level is reasonable if ( _signal_level <= 0 ) { fprintf(stderr,"error: agc_%s_set_signal_level(), bandwidth must be greater than zero\n", EXTENSION_FULL); exit(-1); } // set internal gain appropriately _q->g = 1.0f / _signal_level; // reset internal output signal level _q->y2_prime = 1.0f; } // get estimated signal level (dB) float AGC(_get_rssi)(AGC() _q) { return -20*log10(_q->g); } // set estimated signal level (dB) void AGC(_set_rssi)(AGC() _q, float _rssi) { // set internal gain appropriately _q->g = powf(10.0f, -_rssi/20.0f); // ensure resulting gain is not arbitrarily low if (_q->g < 1e-16f) _q->g = 1e-16f; // reset internal output signal level _q->y2_prime = 1.0f; } // get internal gain float AGC(_get_gain)(AGC() _q) { return _q->g; } // set internal gain void AGC(_set_gain)(AGC() _q, float _gain) { // check to ensure gain is reasonable if ( _gain <= 0 ) { fprintf(stderr,"error: agc_%s_set_gain(), gain must be greater than zero\n", EXTENSION_FULL); exit(-1); } // set internal gain appropriately _q->g = _gain; } // initialize internal gain on input array // _q : automatic gain control object // _x : input data array, [size: _n x 1] // _n : number of input, output samples void AGC(_init)(AGC() _q, TC * _x, unsigned int _n) { // ensure number of samples is greater than zero if ( _n == 0 ) { fprintf(stderr,"error: agc_%s_init(), number of samples must be greater than zero\n", EXTENSION_FULL); exit(-1); } // compute sum squares on input // TODO: use vector methods for this unsigned int i; T x2 = 0; for (i=0; i<_n; i++) x2 += crealf( _x[i]*conjf(_x[i]) ); // compute RMS level and ensure result is positive x2 = sqrtf( x2 / (float) _n ) + 1e-16f; // set internal gain based on estimated signal level AGC(_set_signal_level)(_q, x2); } // enable squelch mode void AGC(_squelch_enable)(AGC() _q) { _q->squelch_mode = LIQUID_AGC_SQUELCH_ENABLED; } // disable squelch mode void AGC(_squelch_disable)(AGC() _q) { _q->squelch_mode = LIQUID_AGC_SQUELCH_DISABLED; } // is squelch enabled? int AGC(_squelch_is_enabled)(AGC() _q) { return _q->squelch_mode == LIQUID_AGC_SQUELCH_DISABLED ? 0 : 1; } // set squelch threshold // _q : automatic gain control object // _thresh_dB : threshold for enabling squelch [dB] void AGC(_squelch_set_threshold)(AGC() _q, T _threshold) { _q->squelch_threshold = _threshold; } // get squelch threshold [dB] T AGC(_squelch_get_threshold)(AGC() _q) { return _q->squelch_threshold; } // set squelch timeout // _q : automatic gain control object // _timeout : timeout before enabling squelch [samples] void AGC(_squelch_set_timeout)(AGC() _q, unsigned int _timeout) { _q->squelch_timeout = _timeout; } // get squelch timeout [samples] unsigned int AGC(_squelch_get_timeout)(AGC() _q) { return _q->squelch_timeout; } // get squelch mode int AGC(_squelch_get_status)(AGC() _q) { return _q->squelch_mode; } // // internal methods // // update squelch mode appropriately void AGC(_squelch_update_mode)(AGC() _q) { // int threshold_exceeded = (AGC(_get_rssi)(_q) > _q->squelch_threshold); // update state switch (_q->squelch_mode) { case LIQUID_AGC_SQUELCH_ENABLED: _q->squelch_mode = threshold_exceeded ? LIQUID_AGC_SQUELCH_RISE : LIQUID_AGC_SQUELCH_ENABLED; break; case LIQUID_AGC_SQUELCH_RISE: _q->squelch_mode = threshold_exceeded ? LIQUID_AGC_SQUELCH_SIGNALHI : LIQUID_AGC_SQUELCH_FALL; break; case LIQUID_AGC_SQUELCH_SIGNALHI: _q->squelch_mode = threshold_exceeded ? LIQUID_AGC_SQUELCH_SIGNALHI : LIQUID_AGC_SQUELCH_FALL; break; case LIQUID_AGC_SQUELCH_FALL: _q->squelch_mode = threshold_exceeded ? LIQUID_AGC_SQUELCH_SIGNALHI : LIQUID_AGC_SQUELCH_SIGNALLO; _q->squelch_timer = _q->squelch_timeout; break; case LIQUID_AGC_SQUELCH_SIGNALLO: _q->squelch_timer--; if (_q->squelch_timer == 0) _q->squelch_mode = LIQUID_AGC_SQUELCH_TIMEOUT; else if (threshold_exceeded) _q->squelch_mode = LIQUID_AGC_SQUELCH_SIGNALHI; break; case LIQUID_AGC_SQUELCH_TIMEOUT: _q->squelch_mode = LIQUID_AGC_SQUELCH_ENABLED; break; case LIQUID_AGC_SQUELCH_DISABLED: break; case LIQUID_AGC_SQUELCH_UNKNOWN: default: fprintf(stderr,"warning: agc_%s_execute(), invalid squelch mode: %d\n", EXTENSION_FULL, _q->squelch_mode); } } liquid-dsp-1.3.1/src/agc/src/agc_crcf.c000066400000000000000000000030411317124540100175660ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // AGC API: floating-point [complex] // #include "liquid.internal.h" // naming extensions (useful for print statements) #define EXTENSION_SHORT "f" #define EXTENSION_FULL "crcf" // macros #define AGC(name) LIQUID_CONCAT(agc_crcf,name) #define T float // general #define TC float complex // input/output #define TC_COMPLEX 1 // source files #include "agc.c" liquid-dsp-1.3.1/src/agc/src/agc_rrrf.c000066400000000000000000000030361317124540100176300ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // AGC API: floating-point [real] // #include "liquid.internal.h" // naming extensions (useful for print statements) #define EXTENSION_SHORT "f" #define EXTENSION_FULL "rrrf" // macros #define AGC(name) LIQUID_CONCAT(agc_rrrf,name) #define T float // general #define TC float // input/output #define TC_COMPLEX 0 // source files #include "agc.c" liquid-dsp-1.3.1/src/agc/tests/000077500000000000000000000000001317124540100162505ustar00rootroot00000000000000liquid-dsp-1.3.1/src/agc/tests/agc_crcf_autotest.c000066400000000000000000000155521317124540100221030ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.h" // // Test DC gain control // void autotest_agc_crcf_dc_gain_control() { // set paramaters float gamma = 0.1f; // nominal signal level float bt = 0.1f; // bandwidth-time product float tol = 0.001f; // error tolerance // create AGC object and initialize agc_crcf q = agc_crcf_create(); agc_crcf_set_bandwidth(q, bt); unsigned int i; float complex x = gamma; // input sample float complex y; // output sample for (i=0; i<256; i++) agc_crcf_execute(q, x, &y); // Check results CONTEND_DELTA( crealf(y), 1.0f, tol ); CONTEND_DELTA( cimagf(y), 0.0f, tol ); CONTEND_DELTA( agc_crcf_get_gain(q), 1.0f/gamma, tol ); // destroy AGC object agc_crcf_destroy(q); } // // Test AC gain control // void autotest_agc_crcf_ac_gain_control() { // set paramaters float gamma = 0.1f; // nominal signal level float bt = 0.1f; // bandwidth-time product float tol = 0.001f; // error tolerance float dphi = 0.1f; // NCO frequency // create AGC object and initialize agc_crcf q = agc_crcf_create(); agc_crcf_set_bandwidth(q, bt); unsigned int i; float complex x; float complex y; for (i=0; i<256; i++) { x = gamma * cexpf(_Complex_I*i*dphi); agc_crcf_execute(q, x, &y); } if (liquid_autotest_verbose) printf("gamma : %12.8f, rssi : %12.8f\n", gamma, agc_crcf_get_signal_level(q)); // Check results CONTEND_DELTA( agc_crcf_get_gain(q), 1.0f/gamma, tol); // destroy AGC object agc_crcf_destroy(q); } // // Test RSSI on sinusoidal input // void autotest_agc_crcf_rssi_sinusoid() { // set paramaters float gamma = 0.3f; // nominal signal level float bt = 0.05f; // agc bandwidth float tol = 0.001f; // error tolerance // signal properties float dphi = 0.1f; // signal frequency // create AGC object and initialize agc_crcf q = agc_crcf_create(); agc_crcf_set_bandwidth(q, bt); unsigned int i; float complex x, y; for (i=0; i<512; i++) { // generate sample (complex sinusoid) x = gamma * cexpf(_Complex_I*dphi*i); // execute agc agc_crcf_execute(q, x, &y); } // get received signal strength indication float rssi = agc_crcf_get_signal_level(q); if (liquid_autotest_verbose) printf("gamma : %12.8f, rssi : %12.8f\n", gamma, rssi); // Check results CONTEND_DELTA( rssi, gamma, tol ); // destroy agc object agc_crcf_destroy(q); } // // Test RSSI on noise input // void autotest_agc_crcf_rssi_noise() { // set paramaters float gamma = -30.0f; // nominal signal level [dB] float bt = 0.01f; // agc bandwidth float tol = 0.2f; // error tolerance [dB] // signal properties float nstd = powf(10.0f, gamma/20); // create AGC object and initialize agc_crcf q = agc_crcf_create(); agc_crcf_set_bandwidth(q, bt); unsigned int i; float complex x, y; for (i=0; i<3000; i++) { // generate sample (circular complex noise) x = nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2; // execute agc agc_crcf_execute(q, x, &y); } // get received signal strength indication float rssi = agc_crcf_get_rssi(q); if (liquid_autotest_verbose) printf("gamma : %12.8f, rssi : %12.8f\n", gamma, rssi); // Check results CONTEND_DELTA( rssi, gamma, tol ); // destroy agc object agc_crcf_destroy(q); } // // Test squelch functionality // void autotest_agc_crcf_squelch() { // create agc object, set loop bandwidth, and initialize parameters agc_crcf q = agc_crcf_create(); agc_crcf_set_bandwidth(q, 0.25); agc_crcf_set_signal_level(q,1e-3f); // initial guess at starting signal level // initialize squelch functionality agc_crcf_squelch_enable(q); // enable squelch agc_crcf_squelch_set_threshold(q, -50); // threshold for detection [dB] agc_crcf_squelch_set_timeout (q, 100); // timeout for hysteresis // run agc unsigned int num_samples = 2000; // total number of samples to run unsigned int i; for (i=0; i #include "liquid.h" // benchmark CVSD encoder void benchmark_cvsd_encode(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { unsigned long int i; // options unsigned int nbits=4; // number of adjacent bits to observe float zeta=1.5f; // slope adjustment multiplier float alpha = 0.95; // pre-/post-filter coefficient char bit = 0; // output bit // create cvsd encoder cvsd encoder = cvsd_create(nbits, zeta, alpha); // input time series (random) float x[8] = { 1.19403f, -0.76765f, -1.08415f, 0.65095f, 0.11647f, -0.80130f, -0.87540f, -0.14888f}; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { bit ^= cvsd_encode(encoder, x[0]); bit ^= cvsd_encode(encoder, x[2]); bit ^= cvsd_encode(encoder, x[3]); bit ^= cvsd_encode(encoder, x[3]); bit ^= cvsd_encode(encoder, x[4]); bit ^= cvsd_encode(encoder, x[5]); bit ^= cvsd_encode(encoder, x[6]); bit ^= cvsd_encode(encoder, x[7]); // randomize input x[i%8] += bit ? 0.1f : -0.1f; } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 8; // destroy cvsd encoder cvsd_destroy(encoder); } // benchmark CVSD decoder void benchmark_cvsd_decode(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { unsigned long int i; // options unsigned int nbits=4; // number of adjacent bits to observe float zeta=1.5f; // slope adjustment multiplier float alpha = 0.95; // pre-/post-filter coefficient float x = 0.0f; // create cvsd decoder cvsd decoder = cvsd_create(nbits, zeta, alpha); // input bit sequence (random) unsigned char b[8] = {1, 1, 1, 0, 1, 0, 0, 0}; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { x += cvsd_decode(decoder, b[0]); x += cvsd_decode(decoder, b[2]); x += cvsd_decode(decoder, b[3]); x += cvsd_decode(decoder, b[3]); x += cvsd_decode(decoder, b[4]); x += cvsd_decode(decoder, b[5]); x += cvsd_decode(decoder, b[6]); x += cvsd_decode(decoder, b[7]); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 8; // destroy cvsd decoder cvsd_destroy(decoder); } liquid-dsp-1.3.1/src/audio/src/000077500000000000000000000000001317124540100162445ustar00rootroot00000000000000liquid-dsp-1.3.1/src/audio/src/cvsd.c000066400000000000000000000150411317124540100173500ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // CVSD: continuously variable slope delta // #include #include #include "liquid.internal.h" // enable use of the pre-emphasis and post-emphasis filters #define CVSD_ENABLE_SIGNAL_CONDITIONING (1) struct cvsd_s { unsigned int num_bits; unsigned char bitref; // historical bit reference unsigned char bitmask; // historical bit reference mask float ref; // internal reference float zeta; // delta step factor float delta; // current step size float delta_min; // minimum delta float delta_max; // maximum delta #if CVSD_ENABLE_SIGNAL_CONDITIONING float alpha; // pre-/de-emphasis filter coefficient float beta; // DC-blocking coefficient (decoder) iirfilt_rrrf prefilt; // pre-emphasis filter (encoder) iirfilt_rrrf postfilt; // e-emphasis filter (decoder) #endif }; // create cvsd object // _num_bits : number of adjacent bits to observe // _zeta : slope adjustment multiplier // _alpha : pre-/post-emphasis filter coefficient (0.9 recommended) // NOTE: _alpha must be in [0,1] cvsd cvsd_create(unsigned int _num_bits, float _zeta, float _alpha) { if (_num_bits == 0) { fprintf(stderr, "error: cvsd_create(), _num_bits must be positive\n"); exit(1); } else if (_zeta <= 1.0f) { fprintf(stderr, "error: cvsd_create(), zeta must be greater than 1\n"); exit(1); } else if (_alpha < 0.0f || _alpha > 1.0f) { fprintf(stderr, "error: cvsd_create(), alpha must be in [0,1]\n"); exit(1); } cvsd q = (cvsd) malloc(sizeof(struct cvsd_s)); q->num_bits = _num_bits; q->bitref = 0; q->bitmask = (1<<(q->num_bits)) - 1; q->ref = 0.0f; q->zeta = _zeta; q->delta = 0.01f; q->delta_min = 0.01f; q->delta_max = 1.0f; #if CVSD_ENABLE_SIGNAL_CONDITIONING // design pre-emphasis filter q->alpha = _alpha; float b_pre[2] = {1.0f, -q->alpha}; float a_pre[2] = {1.0f, 0.0f}; q->prefilt = iirfilt_rrrf_create(b_pre,2,a_pre,2); // design post-emphasis filter q->beta = 0.99f; // DC-blocking parameter float b_post[3] = {1.0f, -1.0f, 0.0f}; float a_post[3] = {1.0f, -(q->alpha + q->beta), q->alpha*q->beta}; q->postfilt = iirfilt_rrrf_create(b_post,3,a_post,3); #endif return q; } // destroy cvsd object void cvsd_destroy(cvsd _q) { #if CVSD_ENABLE_SIGNAL_CONDITIONING // destroy filters iirfilt_rrrf_destroy(_q->prefilt); iirfilt_rrrf_destroy(_q->postfilt); #endif // free main object memory free(_q); } // print cvsd object parameters void cvsd_print(cvsd _q) { printf("cvsd codec:\n"); printf(" num bits: %u\n", _q->num_bits); printf(" zeta : %8.4f\n", _q->zeta); #if CVSD_ENABLE_SIGNAL_CONDITIONING printf(" alpha : %8.4f\n", _q->alpha); #endif } // encode single sample unsigned char cvsd_encode(cvsd _q, float _audio_sample) { // push audio sample through pre-filter float y; #if CVSD_ENABLE_SIGNAL_CONDITIONING iirfilt_rrrf_execute(_q->prefilt, _audio_sample, &y); #else y = _audio_sample; #endif // determine output value unsigned char bit = (_q->ref > y) ? 0 : 1; // shift last value into buffer _q->bitref <<= 1; _q->bitref |= bit; _q->bitref &= _q->bitmask; // update delta if (_q->bitref == 0 || _q->bitref == _q->bitmask) _q->delta *= _q->zeta; // increase delta else _q->delta /= _q->zeta; // decrease delta // limit delta _q->delta = (_q->delta > _q->delta_max) ? _q->delta_max : _q->delta; _q->delta = (_q->delta < _q->delta_min) ? _q->delta_min : _q->delta; // update reference _q->ref += (bit) ? _q->delta : -_q->delta; // limit reference _q->ref = (_q->ref > 1.0f) ? 1.0f : _q->ref; _q->ref = (_q->ref < -1.0f) ? -1.0f : _q->ref; return bit; } // decode single sample float cvsd_decode(cvsd _q, unsigned char _bit) { // append bit into register _q->bitref <<= 1; _q->bitref |= (_bit & 0x01); _q->bitref &= _q->bitmask; // update delta if (_q->bitref == 0 || _q->bitref == _q->bitmask) _q->delta *= _q->zeta; // increase delta else _q->delta /= _q->zeta; // decrease delta // limit delta _q->delta = (_q->delta > _q->delta_max) ? _q->delta_max : _q->delta; _q->delta = (_q->delta < _q->delta_min) ? _q->delta_min : _q->delta; // update reference _q->ref += (_bit&0x01) ? _q->delta : -_q->delta; // limit reference _q->ref = (_q->ref > 1.0f) ? 1.0f : _q->ref; _q->ref = (_q->ref < -1.0f) ? -1.0f : _q->ref; // push reference value through post-filter float y; #if CVSD_ENABLE_SIGNAL_CONDITIONING iirfilt_rrrf_execute(_q->postfilt, _q->ref, &y); #else y = _q->ref; #endif return y; } // encode 8 samples void cvsd_encode8(cvsd _q, float * _audio, unsigned char * _data) { unsigned char data=0x00; unsigned int i; for (i=0; i<8; i++) { data <<= 1; data |= cvsd_encode(_q, _audio[i]); } // set return value *_data = data; } // decode 8 samples void cvsd_decode8(cvsd _q, unsigned char _data, float * _audio) { unsigned char bit; unsigned int i; for (i=0; i<8; i++) { bit = (_data >> (8-i-1)) & 0x01; _audio[i] = cvsd_decode(_q, bit); } } liquid-dsp-1.3.1/src/audio/tests/000077500000000000000000000000001317124540100166175ustar00rootroot00000000000000liquid-dsp-1.3.1/src/audio/tests/cvsd_autotest.c000066400000000000000000000040071317124540100216530ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.internal.h" // // AUTOTEST: check RMSE for CVSD // void autotest_cvsd_rmse_sine() { unsigned int n=256; unsigned int nbits=3; float zeta=1.5f; float alpha=0.90f; // create cvsd codecs cvsd cvsd_encoder = cvsd_create(nbits,zeta,alpha); cvsd cvsd_decoder = cvsd_create(nbits,zeta,alpha); float phi=0.0f; float dphi=0.1f; unsigned int i; unsigned char b; float x,y; float rmse=0.0f; for (i=0; i #include #include #include "liquid.h" #define CBUFFERCF_BENCH_API(N, W, R) \ ( struct rusage * _start, \ struct rusage * _finish, \ unsigned long int * _num_iterations) \ { cbuffercf_bench(_start, _finish, _num_iterations, N, W, R); } // Helper function to keep code base small void cbuffercf_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _n, unsigned int _write_size, unsigned int _read_size) { // validate input if (_n < 2) { fprintf(stderr,"error: cbuffercf_bench(), number of elements must be at least 2\n"); exit(1); } else if (_write_size > _n-1) { fprintf(stderr,"error: cbuffercf_bench(), write size must be in (0,n)\n"); exit(1); } else if (_read_size > _n-1) { fprintf(stderr,"error: cbuffercf_bench(), read size must be in (0,n)\n"); exit(1); } // normalize number of iterations *_num_iterations *= _n; // create object cbuffercf q = cbuffercf_create(_n); // float complex v[_write_size]; // array for writing float complex * r; // read pointer unsigned int num_requested; // number of elements requested unsigned int num_read; // number of elements read // initialize array for writing unsigned int i; for (i=0; i<_write_size; i++) v[i] = 0.0f; // accumulate total number of elements unsigned long int num_total_elements = 0; // start trials getrusage(RUSAGE_SELF, _start); while (num_total_elements < *_num_iterations) { // write elements to buffer if space is available if (_n - cbuffercf_size(q) > _write_size) cbuffercf_write(q, v, _write_size); // read up to '_read_size' elements num_requested = _read_size; cbuffercf_read(q, num_requested, &r, &num_read); // release elements that were read cbuffercf_release(q, num_read); // increment counter by number of elements passing through num_total_elements += num_read; } getrusage(RUSAGE_SELF, _finish); // total number of iterations equal to to total number of elements // that have passed through the buffer *_num_iterations = num_total_elements; // clean up allocated memory cbuffercf_destroy(q); } // void benchmark_cbuffercf_n16 CBUFFERCF_BENCH_API( 16, 12, 11); void benchmark_cbuffercf_n32 CBUFFERCF_BENCH_API( 32, 24, 23); void benchmark_cbuffercf_n64 CBUFFERCF_BENCH_API( 64, 48, 47); void benchmark_cbuffercf_n128 CBUFFERCF_BENCH_API( 128, 96, 95); void benchmark_cbuffercf_n256 CBUFFERCF_BENCH_API( 256, 192, 191); void benchmark_cbuffercf_n512 CBUFFERCF_BENCH_API( 512, 384, 383); void benchmark_cbuffercf_n1024 CBUFFERCF_BENCH_API(1024, 768, 767); liquid-dsp-1.3.1/src/buffer/bench/window_push_benchmark.c000066400000000000000000000047471317124540100234440ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" #define WINDOW_PUSH_BENCH_API(N) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { window_push_bench(_start, _finish, _num_iterations, N); } // Helper function to keep code base small void window_push_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _n) { // normalize number of iterations *_num_iterations *= 8; if (*_num_iterations < 1) *_num_iterations = 1; // initialize port windowcf w = windowcf_create(_n); unsigned long int i; // start trials: // write to port, read from port getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { windowcf_push(w, 1.0f); windowcf_push(w, 1.0f); windowcf_push(w, 1.0f); windowcf_push(w, 1.0f); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; windowcf_destroy(w); } // void benchmark_windowcf_push_n16 WINDOW_PUSH_BENCH_API(16) void benchmark_windowcf_push_n32 WINDOW_PUSH_BENCH_API(32) void benchmark_windowcf_push_n64 WINDOW_PUSH_BENCH_API(64) void benchmark_windowcf_push_n128 WINDOW_PUSH_BENCH_API(128) void benchmark_windowcf_push_n256 WINDOW_PUSH_BENCH_API(256) liquid-dsp-1.3.1/src/buffer/bench/window_read_benchmark.c000066400000000000000000000050731317124540100233710ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" #define WINDOW_READ_BENCH_API(N) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { window_read_bench(_start, _finish, _num_iterations, N); } // Helper function to keep code base small void window_read_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _n) { // normalize number of iterations if (*_num_iterations < 1) *_num_iterations = 1; // initialize port windowcf w = windowcf_create(_n); unsigned long int i; float complex * r; // start trials: // write to buffer, read from buffer getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { windowcf_push(w,1.0f); windowcf_read(w, &r); windowcf_push(w,1.0f); windowcf_read(w, &r); windowcf_push(w,1.0f); windowcf_read(w, &r); windowcf_push(w,1.0f); windowcf_read(w, &r); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; windowcf_destroy(w); } // void benchmark_windowcf_read_n16 WINDOW_READ_BENCH_API(16) void benchmark_windowcf_read_n32 WINDOW_READ_BENCH_API(32) void benchmark_windowcf_read_n64 WINDOW_READ_BENCH_API(64) void benchmark_windowcf_read_n128 WINDOW_READ_BENCH_API(128) void benchmark_windowcf_read_n256 WINDOW_READ_BENCH_API(256) liquid-dsp-1.3.1/src/buffer/src/000077500000000000000000000000001317124540100164145ustar00rootroot00000000000000liquid-dsp-1.3.1/src/buffer/src/buffer.c000066400000000000000000000155411317124540100200370ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Buffers, defined by macro // #include #include #include #include "liquid.internal.h" struct BUFFER(_s) { T * v; unsigned int len; // length of buffer unsigned int N; // number of elements allocated // in memory unsigned int num_elements; // number of elements currently // in the buffer unsigned int read_index; unsigned int write_index; buffer_type type; // mutex/semaphore }; BUFFER() BUFFER(_create)(buffer_type _type, unsigned int _n) { BUFFER() b = (BUFFER()) malloc(sizeof(struct BUFFER(_s))); b->type = _type; b->len = _n; if (b->type == CIRCULAR) b->N = 2*(b->len) - 1; else b->N = b->len; b->v = (T*) malloc((b->N)*sizeof(T)); b->num_elements = 0; b->read_index = 0; b->write_index = 0; return b; } void BUFFER(_destroy)(BUFFER() _b) { free(_b->v); free(_b); } void BUFFER(_print)(BUFFER() _b) { if (_b->type == CIRCULAR) printf("circular "); else printf("static "); printf("buffer [%u elements] :\n", _b->num_elements); unsigned int i; for (i=0; i<_b->num_elements; i++) { printf("%u", i); BUFFER_PRINT_LINE(_b,(_b->read_index+i)%(_b->len)) printf("\n"); } } void BUFFER(_debug_print)(BUFFER() _b) { if (_b->type == CIRCULAR) printf("circular "); else printf("static "); printf("buffer [%u elements] :\n", _b->num_elements); unsigned int i; for (i=0; i<_b->len; i++) { // print read index pointer if (i==_b->read_index) printf(""); // print write index pointer if (i==_b->write_index) printf(""); // print buffer value BUFFER_PRINT_LINE(_b,i) printf("\n"); } printf("----------------------------------\n"); // print excess buffer memory for (i=_b->len; i<_b->N; i++) { BUFFER_PRINT_LINE(_b,i) printf("\n"); } } void BUFFER(_clear)(BUFFER() _b) { _b->read_index = 0; _b->write_index = 0; _b->num_elements = 0; } void BUFFER(_zero)(BUFFER() _b) { _b->read_index = 0; _b->write_index = 0; _b->num_elements = _b->len; memset(_b->v, 0, (_b->num_elements)*sizeof(T)); } void BUFFER(_read)(BUFFER() _b, T ** _v, unsigned int *_n) { if (_b->type == CIRCULAR) BUFFER(_c_read)(_b, _v, _n); else BUFFER(_s_read)(_b, _v, _n); } void BUFFER(_c_read)(BUFFER() _b, T ** _v, unsigned int *_n) { //printf("buffer_read() trying to read %u elements (%u available)\n", *_n, _b->num_elements); #if 0 if (*_n > _b->num_elements) { printf("error: buffer_read(), cannot read more elements than are available\n"); *_v = NULL; *_n = 0; return; } else #endif if (*_n > (_b->len - _b->read_index)) { // BUFFER(_linearize)(_b); } *_v = _b->v + _b->read_index; *_n = _b->num_elements; } void BUFFER(_s_read)(BUFFER() _b, T ** _v, unsigned int *_n) { //printf("buffer_s_read() reading %u elements\n", _b->num_elements); *_v = _b->v; *_n = _b->num_elements; } void BUFFER(_release)(BUFFER() _b, unsigned int _n) { if (_b->type == CIRCULAR) BUFFER(_c_release)(_b, _n); else BUFFER(_s_release)(_b, _n); } void BUFFER(_c_release)(BUFFER() _b, unsigned int _n) { // advance read_index by _n making sure not to step on write_index if (_n > _b->num_elements) { printf("error: buffer_c_release(), cannot release more elements in buffer than exist\n"); return; } _b->read_index = (_b->read_index + _n) % _b->len; _b->num_elements -= _n; } void BUFFER(_s_release)(BUFFER() _b, unsigned int _n) { BUFFER(_clear)(_b); } void BUFFER(_write)(BUFFER() _b, T * _v, unsigned int _n) { if (_b->type == CIRCULAR) BUFFER(_c_write)(_b, _v, _n); else BUFFER(_s_write)(_b, _v, _n); } void BUFFER(_c_write)(BUFFER() _b, T * _v, unsigned int _n) { // if (_n > (_b->len - _b->num_elements)) { printf("error: buffer_write(), cannot write more elements than are available\n"); return; } _b->num_elements += _n; // space available at end of buffer unsigned int k = _b->len - _b->write_index; //printf("n : %u, k : %u\n", _n, k); // check for condition where we need to wrap around if (_n > k) { memcpy(_b->v + _b->write_index, _v, k*sizeof(T)); memcpy(_b->v, &_v[k], (_n-k)*sizeof(T)); _b->write_index = _n - k; } else { memcpy(_b->v + _b->write_index, _v, _n*sizeof(T)); _b->write_index += _n; } } void BUFFER(_s_write)(BUFFER() _b, T * _v, unsigned int _n) { if (_n > (_b->len - _b->num_elements)) { printf("error: buffer_s_write(), cannot write more elements than are available\n"); return; } memcpy(_b->v + _b->num_elements, _v, _n*sizeof(T)); _b->num_elements += _n; } //void BUFFER(_force_write)(BUFFER() _b, T * _v, unsigned int _n) void BUFFER(_push)(BUFFER() _b, T _v) { // push value (force write) if (_b->type == CIRCULAR) BUFFER(_c_push)(_b, _v); else BUFFER(_s_push)(_b, _v); } void BUFFER(_c_push)(BUFFER() _b, T _v) { _b->v[_b->write_index] = _v; if (_b->num_elements < _b->len) { _b->num_elements++; } else { _b->read_index = (_b->read_index+1) % _b->len; } _b->write_index = (_b->write_index+1) % _b->len; } void BUFFER(_s_push)(BUFFER() _b, T _v) { } void BUFFER(_linearize)(BUFFER() _b) { // check to see if anything needs to be done if ( (_b->len - _b->read_index) > _b->num_elements) return; // perform memory copy memcpy(_b->v + _b->len, _b->v, (_b->write_index)*sizeof(T)); } liquid-dsp-1.3.1/src/buffer/src/buffercf.c000066400000000000000000000034361317124540100203500ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Complex Float buffer // #include "liquid.internal.h" // naming extensions (useful for print statements) #define EXTENSION "cf" #define BUFFER_TYPE_CFLOAT #define CBUFFER(name) LIQUID_CONCAT(cbuffercf, name) //#define SBUFFER(name) LIQUID_CONCAT(sbuffercf, name) #define WDELAY(name) LIQUID_CONCAT(wdelaycf, name) #define WINDOW(name) LIQUID_CONCAT(windowcf, name) #define T float complex #define BUFFER_PRINT_LINE(B,I) \ printf(" : %12.8f + %12.8f", crealf(B->v[I]), cimagf(B->v[I])); #define BUFFER_PRINT_VALUE(V) \ printf(" : %12.4e + %12.4e", crealf(V), cimagf(V)); #include "cbuffer.c" //#include "sbuffer.c" #include "window.c" #include "wdelay.c" liquid-dsp-1.3.1/src/buffer/src/bufferf.c000066400000000000000000000033121317124540100201760ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Float buffer // #include "liquid.internal.h" // naming extensions (useful for print statements) #define EXTENSION "f" #define BUFFER_TYPE_FLOAT #define CBUFFER(name) LIQUID_CONCAT(cbufferf, name) //#define SBUFFER(name) LIQUID_CONCAT(sbufferf, name) #define WDELAY(name) LIQUID_CONCAT(wdelayf, name) #define WINDOW(name) LIQUID_CONCAT(windowf, name) #define T float #define BUFFER_PRINT_LINE(B,I) \ printf(" : %12.8f", B->v[I]); #define BUFFER_PRINT_VALUE(V) \ printf(" : %12.4e", V); #include "cbuffer.c" //#include "sbuffer.c" #include "wdelay.c" #include "window.c" liquid-dsp-1.3.1/src/buffer/src/cbuffer.c000066400000000000000000000221271317124540100202000ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // circular buffer // #include #include #include #include "liquid.internal.h" // linearize buffer (if necessary) void CBUFFER(_linearize)(CBUFFER() _q); // cbuffer object struct CBUFFER(_s) { // allocated memory array T * v; // length of buffer unsigned int max_size; // maximum number of elements that can be read at any given time unsigned int max_read; // number of elements allocated in memory unsigned int num_allocated; // number of elements currently in buffer unsigned int num_elements; // index to read unsigned int read_index; // index to write unsigned int write_index; }; // create circular buffer object of a particular size CBUFFER() CBUFFER(_create)(unsigned int _max_size) { // create main object CBUFFER() q = CBUFFER(_create_max)(_max_size, _max_size); // return main object return q; } // create circular buffer object of a particular size and // specify the maximum number of elements that can be read // at any given time. CBUFFER() CBUFFER(_create_max)(unsigned int _max_size, unsigned int _max_read) { // create main object CBUFFER() q = (CBUFFER()) malloc(sizeof(struct CBUFFER(_s))); // set internal properties q->max_size = _max_size; q->max_read = _max_read; // internal memory allocation q->num_allocated = q->max_size + q->max_read - 1; // allocate internal memory array q->v = (T*) malloc((q->num_allocated)*sizeof(T)); // reset object CBUFFER(_reset)(q); // return main object return q; } // destroy cbuffer object, freeing all internal memory void CBUFFER(_destroy)(CBUFFER() _q) { // free internal memory free(_q->v); // free main object free(_q); } // print cbuffer object properties void CBUFFER(_print)(CBUFFER() _q) { printf("cbuffer%s [max size: %u, max read: %u, elements: %u]\n", EXTENSION, _q->max_size, _q->max_read, _q->num_elements); unsigned int i; for (i=0; i<_q->num_elements; i++) { printf("%u", i); BUFFER_PRINT_LINE(_q,(_q->read_index+i)%(_q->max_size)) printf("\n"); } } // print cbuffer object properties and internal state void CBUFFER(_debug_print)(CBUFFER() _q) { printf("cbuffer%s [max size: %u, max read: %u, elements: %u]\n", EXTENSION, _q->max_size, _q->max_read, _q->num_elements); unsigned int i; for (i=0; i<_q->max_size; i++) { // print read index pointer if (i==_q->read_index) printf(""); else printf(" "); // print write index pointer if (i==_q->write_index) printf(""); else printf(" "); // print buffer value BUFFER_PRINT_LINE(_q,i) printf("\n"); } printf("----------------------------------\n"); // print excess buffer memory for (i=_q->max_size; i<_q->num_allocated; i++) { printf(" "); BUFFER_PRINT_LINE(_q,i) printf("\n"); } } // clear internal buffer void CBUFFER(_reset)(CBUFFER() _q) { _q->read_index = 0; _q->write_index = 0; _q->num_elements = 0; } // get the number of elements currently in the buffer unsigned int CBUFFER(_size)(CBUFFER() _q) { return _q->num_elements; } // get the maximum number of elements the buffer can hold unsigned int CBUFFER(_max_size)(CBUFFER() _q) { return _q->max_size; } // get the maximum number of elements that can be read from // the buffer at any given time. unsigned int CBUFFER(_max_read)(CBUFFER() _q) { return _q->max_read; } // return number of elements available for writing unsigned int CBUFFER(_space_available)(CBUFFER() _q) { return _q->max_size - _q->num_elements; } // is buffer full? int CBUFFER(_is_full)(CBUFFER() _q) { return (_q->num_elements == _q->max_size ? 1 : 0); } // write a single sample into the buffer // _q : circular buffer object // _v : input sample void CBUFFER(_push)(CBUFFER() _q, T _v) { // ensure buffer isn't already full if (_q->num_elements == _q->max_size) { fprintf(stderr,"warning: cbuffer%s_push(), no space available\n", EXTENSION); return; } // add sample at write index _q->v[_q->write_index] = _v; // update write index _q->write_index = (_q->write_index+1) % _q->max_size; // increment number of elements _q->num_elements++; } // write samples to the buffer // _q : circular buffer object // _v : output array // _n : number of samples to write void CBUFFER(_write)(CBUFFER() _q, T * _v, unsigned int _n) { // ensure number of samples to write doesn't exceed space available if (_n > (_q->max_size - _q->num_elements)) { printf("warning: cbuffer%s_write(), cannot write more elements than are available\n", EXTENSION); return; } _q->num_elements += _n; // space available at end of buffer unsigned int k = _q->max_size - _q->write_index; //printf("n : %u, k : %u\n", _n, k); // check for condition where we need to wrap around if (_n > k) { memmove(_q->v + _q->write_index, _v, k*sizeof(T)); memmove(_q->v, &_v[k], (_n-k)*sizeof(T)); _q->write_index = _n - k; } else { memmove(_q->v + _q->write_index, _v, _n*sizeof(T)); _q->write_index += _n; } } // remove and return a single element from the buffer // _q : circular buffer object // _v : pointer to sample output void CBUFFER(_pop)(CBUFFER() _q, T * _v) { // ensure there is at least one element if (_q->num_elements == 0) { fprintf(stderr,"warning: cbuffer%s_pop(), no elements available\n", EXTENSION); return; } // set return value if (_v != NULL) *_v = _q->v[ _q->read_index ]; // increment read index _q->read_index = (_q->read_index + 1) % _q->max_size; // decrement number of elements in the buffer _q->num_elements--; } // read buffer contents // _q : circular buffer object // _num_requested : number of elements requested // _v : output pointer // _nr : number of elements referenced by _v void CBUFFER(_read)(CBUFFER() _q, unsigned int _num_requested, T ** _v, unsigned int * _num_read) { // adjust number requested depending upon availability if (_num_requested > _q->num_elements) _num_requested = _q->num_elements; // restrict maximum number of elements to originally specified value if (_num_requested > _q->max_read) _num_requested = _q->max_read; // linearize tail end of buffer if necessary if (_num_requested > (_q->max_size - _q->read_index)) CBUFFER(_linearize)(_q); // set output pointer appropriately *_v = _q->v + _q->read_index; *_num_read = _num_requested; } // release _n samples in the buffer void CBUFFER(_release)(CBUFFER() _q, unsigned int _n) { // advance read_index by _n making sure not to step on write_index if (_n > _q->num_elements) { printf("error: cbuffer%s_release(), cannot release more elements in buffer than exist\n", EXTENSION); return; } _q->read_index = (_q->read_index + _n) % _q->max_size; _q->num_elements -= _n; } // // internal methods // // internal linearization void CBUFFER(_linearize)(CBUFFER() _q) { #if 0 // check to see if anything needs to be done if ( (_q->max_size - _q->read_index) > _q->num_elements) return; #endif //printf("cbuffer linearize: [%6u : %6u], num elements: %6u, read index: %6u, write index: %6u\n", // _q->max_size, _q->max_read-1, _q->num_elements, _q->read_index, _q->write_index); // move maximum amount memmove(_q->v + _q->max_size, _q->v, (_q->max_read-1)*sizeof(T)); } liquid-dsp-1.3.1/src/buffer/src/wdelay.c000066400000000000000000000074031317124540100200510ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // windowed delay, defined by macro // #include "liquid.internal.h" #include #include #include struct WDELAY(_s) { T * v; // allocated array pointer unsigned int delay; // length of window unsigned int read_index; }; // create delay buffer object with '_delay' samples WDELAY() WDELAY(_create)(unsigned int _delay) { // create main object WDELAY() q = (WDELAY()) malloc(sizeof(struct WDELAY(_s))); // set internal values q->delay = _delay; // allocte memory q->v = (T*) malloc((q->delay)*sizeof(T)); q->read_index = 0; // clear window WDELAY(_reset)(q); return q; } // re-create delay buffer object with '_delay' samples // _q : old delay buffer object // _delay : delay for new object WDELAY() WDELAY(_recreate)(WDELAY() _q, unsigned int _delay) { // copy internal buffer, re-aligned unsigned int ktmp = _q->delay; T * vtmp = (T*) malloc(_q->delay * sizeof(T)); unsigned int i; for (i=0; i<_q->delay; i++) vtmp[i] = _q->v[ (i + _q->read_index) % _q->delay ]; // destroy object and re-create it WDELAY(_destroy)(_q); _q = WDELAY(_create)(_delay); // push old values for (i=0; iv); // free main object memory free(_q); } // print delay buffer object's state to stdout void WDELAY(_print)(WDELAY() _q) { printf("wdelay [%u elements] :\n", _q->delay); unsigned int i, j; for (i=0; i<_q->delay; i++) { j = (i + _q->read_index) % _q->delay; printf("%4u", i); BUFFER_PRINT_VALUE(_q->v[j]); printf("\n"); } } // clear/reset state of object void WDELAY(_reset)(WDELAY() _q) { _q->read_index = 0; memset(_q->v, 0, (_q->delay)*sizeof(T)); } // read delayed sample from delay buffer object // _q : delay buffer object // _v : value of delayed element void WDELAY(_read)(WDELAY() _q, T * _v) { // return value at end of buffer *_v = _q->v[_q->read_index]; } // push new sample into delay buffer object // _q : delay buffer object // _v : new value to be added to buffer void WDELAY(_push)(WDELAY() _q, T _v) { // append value to end of buffer _q->v[_q->read_index] = _v; // increment index _q->read_index++; // wrap around pointer _q->read_index %= _q->delay; } liquid-dsp-1.3.1/src/buffer/src/window.c000066400000000000000000000142741317124540100200770ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2016 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Windows, defined by macro // #include "liquid.internal.h" #include #include #include struct WINDOW(_s) { T * v; // allocated array pointer unsigned int len; // length of window unsigned int m; // floor(log2(len)) + 1 unsigned int n; // 2^m unsigned int mask; // n-1 unsigned int num_allocated; // number of elements allocated // in memory unsigned int read_index; }; // create window buffer object of length _n WINDOW() WINDOW(_create)(unsigned int _n) { // validate input if (_n == 0) { fprintf(stderr,"error: window%s_create(), window size must be greater than zero\n", EXTENSION); exit(1); } // create initial object WINDOW() q = (WINDOW()) malloc(sizeof(struct WINDOW(_s))); // set internal parameters q->len = _n; // nominal window size q->m = liquid_msb_index(_n); // effectively floor(log2(len))+1 q->n = 1<<(q->m); // 2^m q->mask = q->n - 1; // bit mask // number of elements to allocate to memory q->num_allocated = q->n + q->len - 1; // allocte memory q->v = (T*) malloc((q->num_allocated)*sizeof(T)); q->read_index = 0; // reset window WINDOW(_reset)(q); // return object return q; } // recreate window buffer object with new length // _q : old window object // _n : new window length WINDOW() WINDOW(_recreate)(WINDOW() _q, unsigned int _n) { // TODO: only create new window if old is too small if (_n == _q->len) return _q; // create new window WINDOW() w = WINDOW(_create)(_n); // copy old values T* r; WINDOW(_read)(_q, &r); //memmove(q->v, ...); unsigned int i; if (_n > _q->len) { // new buffer is larger; push zeros, then old values for (i=0; i<(_n-_q->len); i++) WINDOW(_push)(w, 0); for (i=0; i<_q->len; i++) WINDOW(_push)(w, r[i]); } else { // new buffer is shorter; push latest old values for (i=(_q->len-_n); i<_q->len; i++) WINDOW(_push)(w, r[i]); } // destroy old window WINDOW(_destroy)(_q); return w; } // destroy window object, freeing all internally memory void WINDOW(_destroy)(WINDOW() _q) { // free internal memory array free(_q->v); // free main object memory free(_q); } // print window object to stdout void WINDOW(_print)(WINDOW() _q) { printf("window [%u elements] :\n", _q->len); unsigned int i; T * r; WINDOW(_read)(_q, &r); for (i=0; i<_q->len; i++) { printf("%4u", i); BUFFER_PRINT_VALUE(r[i]); printf("\n"); } } // print window object to stdout (with extra information) void WINDOW(_debug_print)(WINDOW() _q) { printf("window [%u elements] :\n", _q->len); unsigned int i; for (i=0; i<_q->len; i++) { // print read index pointer if (i==_q->read_index) printf(""); // print window value BUFFER_PRINT_LINE(_q,i) printf("\n"); } printf("----------------------------------\n"); // print excess window memory for (i=_q->len; i<_q->num_allocated; i++) { BUFFER_PRINT_LINE(_q,i) printf("\n"); } } // reset window object (initialize to zeros) void WINDOW(_reset)(WINDOW() _q) { // reset read index _q->read_index = 0; // clear all allocated memory memset(_q->v, 0, (_q->num_allocated)*sizeof(T)); } // read window buffer contents // _q : window object // _v : output pointer (set to internal array) void WINDOW(_read)(WINDOW() _q, T ** _v) { // return pointer to buffer *_v = _q->v + _q->read_index; } // index single element in buffer at a particular index // _q : window object // _i : index of element to read // _v : output value pointer void WINDOW(_index)(WINDOW() _q, unsigned int _i, T * _v) { // validate input if (_i >= _q->len) { fprintf(stderr,"error: window_index(), index value out of range\n"); exit(1); } // return value at index *_v = _q->v[_q->read_index + _i]; } // push single element onto window buffer // _q : window object // _v : single input element void WINDOW(_push)(WINDOW() _q, T _v) { // increment index _q->read_index++; // wrap around pointer _q->read_index &= _q->mask; // if pointer wraps around, copy excess memory if (_q->read_index == 0) memmove(_q->v, _q->v + _q->n, (_q->len-1)*sizeof(T)); // append value to end of buffer _q->v[_q->read_index + _q->len - 1] = _v; } // write array of elements onto window buffer // _q : window object // _v : input array of values to write // _n : number of input values to write void WINDOW(_write)(WINDOW() _q, T * _v, unsigned int _n) { // TODO make this more efficient unsigned int i; for (i=0; i<_n; i++) WINDOW(_push)(_q, _v[i]); } liquid-dsp-1.3.1/src/buffer/tests/000077500000000000000000000000001317124540100167675ustar00rootroot00000000000000liquid-dsp-1.3.1/src/buffer/tests/cbuffer_autotest.c000066400000000000000000000243531317124540100225060ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // circular buffer autotest // #include #include "autotest/autotest.h" #include "liquid.h" // floating point void autotest_cbufferf() { // input array of values float v[] = {1, 2, 3, 4, 5, 6, 7, 8}; // output test arrays float test1[] = {1, 2, 3, 4}; float test2[] = {3, 4, 1, 2, 3, 4, 5, 6, 7, 8}; float test3[] = {3, 4, 5, 6, 7, 8}; float test4[] = {3, 4, 5, 6, 7, 8, 1, 2, 3}; float *r; // output read pointer unsigned int num_requested; // number of samples requested unsigned int num_read; // number of samples read // create new circular buffer with 10 elements cbufferf q = cbufferf_create(10); // cbuffer: { } // part 1: write 4 elements to the buffer cbufferf_write(q, v, 4); // cbuffer: {1 2 3 4} // part 2: try to read 4 elements num_requested = 4; cbufferf_read(q, num_requested, &r, &num_read); CONTEND_EQUALITY(num_read,4); CONTEND_SAME_DATA(r,test1,4*sizeof(float)); // part 3: release two elements, write 8 more, read 10 cbufferf_release(q, 2); // cbuffer: {3 4} cbufferf_write(q, v, 8); // cbuffer: {3 4 1 2 3 4 5 6 7 8} num_requested = 10; cbufferf_read(q, num_requested, &r, &num_read); CONTEND_EQUALITY(num_read,10); CONTEND_SAME_DATA(r,test2,10*sizeof(float)); // part 4: pop single element from buffer CONTEND_EQUALITY( cbufferf_size(q), 10 ); cbufferf_pop(q, r); // cbuffer: {4 1 2 3 4 5 6 7 8} CONTEND_EQUALITY( cbufferf_size(q), 9 ); CONTEND_EQUALITY( *r, 3.0f ); // part 5: release three elements, and try reading 10 cbufferf_release(q, 3); // cbuffer: {3 4 5 6 7 8} num_requested = 10; cbufferf_read(q, num_requested, &r, &num_read); CONTEND_EQUALITY(num_read,6); CONTEND_SAME_DATA(r,test3,6*sizeof(float)); // part 6: test pushing multiple elements cbufferf_push(q, 1); cbufferf_push(q, 2); cbufferf_push(q, 3); // cbuffer: {3 4 5 6 7 8 1 2 3} num_requested = 10; cbufferf_read(q, num_requested, &r, &num_read); CONTEND_EQUALITY(num_read,9); CONTEND_SAME_DATA(r,test4,9*sizeof(float)); // part 7: add one more element; buffer should be full CONTEND_EXPRESSION( cbufferf_is_full(q)==0 ); cbufferf_push(q, 1); // cbuffer: {3 4 5 6 7 8 1 2 3 1} CONTEND_EXPRESSION( cbufferf_is_full(q)==1 ); // memory leaks are evil cbufferf_destroy(q); } // complex float complexing point void autotest_cbuffercf() { // input array of values float complex v[] = {1.0 - 1.0 * _Complex_I, 2.0 + 2.0 * _Complex_I, 3.0 - 3.0 * _Complex_I, 4.0 + 4.0 * _Complex_I, 5.0 - 5.0 * _Complex_I, 6.0 + 6.0 * _Complex_I, 7.0 - 7.0 * _Complex_I, 8.0 + 8.0 * _Complex_I}; // output test arrays float complex test1[] = {1.0 - 1.0 * _Complex_I, 2.0 + 2.0 * _Complex_I, 3.0 - 3.0 * _Complex_I, 4.0 + 4.0 * _Complex_I}; float complex test2[] = {3.0 - 3.0 * _Complex_I, 4.0 + 4.0 * _Complex_I, 1.0 - 1.0 * _Complex_I, 2.0 + 2.0 * _Complex_I, 3.0 - 3.0 * _Complex_I, 4.0 + 4.0 * _Complex_I, 5.0 - 5.0 * _Complex_I, 6.0 + 6.0 * _Complex_I, 7.0 - 7.0 * _Complex_I, 8.0 + 8.0 * _Complex_I}; float complex test3[] = {3.0 - 3.0 * _Complex_I, 4.0 + 4.0 * _Complex_I, 5.0 - 5.0 * _Complex_I, 6.0 + 6.0 * _Complex_I, 7.0 - 7.0 * _Complex_I, 8.0 + 8.0 * _Complex_I}; float complex test4[] = {3.0 - 3.0 * _Complex_I, 4.0 + 4.0 * _Complex_I, 5.0 - 5.0 * _Complex_I, 6.0 + 6.0 * _Complex_I, 7.0 - 7.0 * _Complex_I, 8.0 + 8.0 * _Complex_I, 1.0 - 1.0 * _Complex_I, 2.0 + 2.0 * _Complex_I, 3.0 - 3.0 * _Complex_I}; float complex *r; // output read pointer unsigned int num_requested; // number of samples requested unsigned int num_read; // number of samples read // create new circular buffer with 10 elements cbuffercf q = cbuffercf_create(10); // cbuffer: { } // part 1: write 4 elements to the buffer cbuffercf_write(q, v, 4); // cbuffer: {1 2 3 4} // part 2: try to read 4 elements num_requested = 4; cbuffercf_read(q, num_requested, &r, &num_read); CONTEND_EQUALITY(num_read,4); CONTEND_SAME_DATA(r,test1,4*sizeof(float complex)); // part 3: release two elements, write 8 more, read 10 cbuffercf_release(q, 2); // cbuffer: {3 4} cbuffercf_write(q, v, 8); // cbuffer: {3 4 1 2 3 4 5 6 7 8} num_requested = 10; cbuffercf_read(q, num_requested, &r, &num_read); CONTEND_EQUALITY(num_read,10); CONTEND_SAME_DATA(r,test2,10*sizeof(float complex)); // part 4: pop single element from buffer CONTEND_EQUALITY( cbuffercf_size(q), 10 ); cbuffercf_pop(q, r); // cbuffer: {4 1 2 3 4 5 6 7 8} CONTEND_EQUALITY( cbuffercf_size(q), 9 ); CONTEND_EQUALITY( crealf(*r), 3.0f ); CONTEND_EQUALITY( cimagf(*r), -3.0f ); // part 5: release three elements, and try reading 10 cbuffercf_release(q, 3); // cbuffer: {3 4 5 6 7 8} num_requested = 10; cbuffercf_read(q, num_requested, &r, &num_read); CONTEND_EQUALITY(num_read,6); CONTEND_SAME_DATA(r,test3,6*sizeof(float complex)); // part 6: test pushing multiple elements cbuffercf_push(q, 1.0 - 1.0 * _Complex_I); cbuffercf_push(q, 2.0 + 2.0 * _Complex_I); cbuffercf_push(q, 3.0 - 3.0 * _Complex_I); // cbuffer: {3 4 5 6 7 8 1 2 3} num_requested = 10; cbuffercf_read(q, num_requested, &r, &num_read); CONTEND_EQUALITY(num_read,9); CONTEND_SAME_DATA(r,test4,9*sizeof(float complex)); // part 7: add one more element; buffer should be full CONTEND_EXPRESSION( cbuffercf_is_full(q)==0 ); cbuffercf_push(q, 1.0 - 1.0 * _Complex_I); // cbuffer: {3 4 5 6 7 8 1 2 3 1} CONTEND_EXPRESSION( cbuffercf_is_full(q)==1 ); // memory leaks are evil cbuffercf_destroy(q); } // test general flow void autotest_cbufferf_flow() { // options unsigned int max_size = 48; // maximum number of elements in buffer unsigned int max_read = 17; // maximum number of elements to read unsigned int num_elements = 1200; // total number of elements for run // flag to indicate if test was successful int success = 1; // temporary buffer to write samples before sending to cbuffer float write_buffer[max_size]; // create new circular buffer cbufferf q = cbufferf_create_max(max_size, max_read); // unsigned i; unsigned write_id = 0; // running total number of values written unsigned read_id = 0; // running total number of values read // continue running until while (1) { // write some values unsigned int num_available_to_write = cbufferf_space_available(q); // write samples if space is available if (num_available_to_write > 0) { // number of elements to write unsigned int num_to_write = (rand() % num_available_to_write) + 1; // generate samples to write for (i=0; i 0) { // number of elements to read unsigned int num_to_read = rand() % num_available_to_read; // read samples float *r; // output read pointer unsigned int num_read; // number of samples read cbufferf_read(q, num_to_read, &r, &num_read); // compare results for (i=0; i= num_elements) break; } // ensure test was successful CONTEND_EXPRESSION(success == 1); // destroy object cbufferf_destroy(q); } liquid-dsp-1.3.1/src/buffer/tests/sbuffer_autotest.c000066400000000000000000000061671317124540100225310ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // buffer autotest (static) // #include "autotest/autotest.h" #include "liquid.h" #define SBUFFER_AUTOTEST_DEFINE_API(X,T) \ T v[] = {1, 2, 3, 4, 5, 6, 7, 8}; \ T test1[] = {1, 2, 3, 4}; \ T test2[] = {1, 2, 3, 4, 5, 6, 7, 8}; \ T test3[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; \ T *r; \ unsigned int n; \ \ X() cb = X(_create)(STATIC,10); \ \ X(_write)(cb, v, 4); \ n = 4; \ X(_read)(cb, &r, &n); \ \ CONTEND_EQUALITY(n,4); \ CONTEND_SAME_DATA(r,test1,4*sizeof(T)); \ \ X(_release)(cb, 0); \ X(_write)(cb, v, 8); \ n = 8; \ X(_read)(cb, &r, &n); \ CONTEND_EQUALITY(n,8); \ CONTEND_SAME_DATA(r,test2,8*sizeof(T)); \ \ X(_zero)(cb); \ n = 10; \ X(_read)(cb, &r, &n); \ CONTEND_EQUALITY(n,10); \ CONTEND_SAME_DATA(r,test3,10*sizeof(T)); \ \ X(_destroy)(cb); // // AUTOTEST: static float buffer // void autotest_fbuffer_static() { SBUFFER_AUTOTEST_DEFINE_API(BUFFER_MANGLE_FLOAT, float) } // // AUTOTEST: static complex float buffer // void autotest_cfbuffer_static() { SBUFFER_AUTOTEST_DEFINE_API(BUFFER_MANGLE_CFLOAT, float complex) } #if 0 // // AUTOTEST: static unsigned int buffer // void xautotest_uibuffer_static() { SBUFFER_AUTOTEST_DEFINE_API(BUFFER_MANGLE_UINT, unsigned int) } #endif liquid-dsp-1.3.1/src/buffer/tests/wdelay_autotest.c000066400000000000000000000053041317124540100223520ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.h" // // AUTOTEST: wdelayf // void autotest_wdelayf() { float v; // reader unsigned int i; // create wdelay // wdelay: 0 0 0 0 wdelayf w = wdelayf_create(4); wdelayf_read(w, &v); CONTEND_EQUALITY(v, 0); float x0[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; float y0_test[10] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6}; float y0[10]; for (i=0; i<10; i++) { wdelayf_read(w, &y0[i]); wdelayf_push(w, x0[i]); //printf("%3u : %6.2f (%6.2f)\n", i, y0[i], y0_test[i]); } // 7 8 9 10 CONTEND_SAME_DATA(y0, y0_test, 10*sizeof(float)); // re-create wdelay object // wdelay: 0 0 7 8 9 10 w = wdelayf_recreate(w,6); float x1[10] = {3, 4, 5, 6, 7, 8, 9, 2, 2, 2}; float y1_test[10]= {0, 0, 7, 8, 9, 10,3, 4, 5, 6}; float y1[10]; for (i=0; i<10; i++) { wdelayf_read(w, &y1[i]); wdelayf_push(w, x1[i]); //printf("%3u : %6.2f (%6.2f)\n", i, y1[i], y1_test[i]); } // wdelay: 7 8 9 2 2 2 CONTEND_SAME_DATA(y1, y1_test, 10*sizeof(float)); // re-create wdelay object // wdelay: 8 9 2 2 2 w = wdelayf_recreate(w,5); float x2[10] = {1, 1, 1, 1, 1, 1, 1, 2, 3, 4}; float y2_test[10]= {8, 9, 2, 2, 2, 1, 1, 1, 1, 1}; float y2[10]; for (i=0; i<10; i++) { wdelayf_read(w, &y2[i]); wdelayf_push(w, x2[i]); //printf("%3u : %6.2f (%6.2f)\n", i, y1[i], y1_test[i]); } // wdelay: 1 1 2 3 4 CONTEND_SAME_DATA(y2, y2_test, 10*sizeof(float)); // destroy object wdelayf_destroy(w); } liquid-dsp-1.3.1/src/buffer/tests/window_autotest.c000066400000000000000000000103661317124540100224000ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.h" // // AUTOTEST: windowf // void autotest_windowf() { float v[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; float *r; // reader pointer float x; // temporary value holder unsigned int i; float test0[10] = {0,0,0,0,0,0,0,0,0,0}; float test1[10] = {0,0,0,0,0,0,1,1,1,1}; float test2[10] = {0,0,1,1,1,1,9,8,7,6}; float test3[10] = {1,1,9,8,7,6,3,3,3,3}; float test4[10] = {7,6,3,3,3,3,5,5,5,5}; float test5[6] = {3,3,5,5,5,5}; float test6[6] = {5,5,5,5,6,7}; float test7[10] = {0,0,0,0,5,5,5,5,6,7}; float test8[10] = {0,0,0,0,0,0,0,0,0,0}; // create window // 0 0 0 0 0 0 0 0 0 0 windowf w = windowf_create(10); windowf_read(w, &r); CONTEND_SAME_DATA(r,test0,10*sizeof(float)); // push 4 elements // 0 0 0 0 0 0 1 1 1 1 windowf_push(w, 1); windowf_push(w, 1); windowf_push(w, 1); windowf_push(w, 1); windowf_read(w, &r); CONTEND_SAME_DATA(r,test1,10*sizeof(float)); // push 4 more elements // 0 0 1 1 1 1 9 8 7 6 windowf_write(w, v, 4); windowf_read(w, &r); CONTEND_SAME_DATA(r,test2,10*sizeof(float)); // push 4 more elements // 1 1 9 8 7 6 3 3 3 3 windowf_push(w, 3); windowf_push(w, 3); windowf_push(w, 3); windowf_push(w, 3); windowf_read(w, &r); CONTEND_SAME_DATA(r,test3,10*sizeof(float)); // test indexing operation windowf_index(w, 0, &x); CONTEND_EQUALITY(x, 1); windowf_index(w, 1, &x); CONTEND_EQUALITY(x, 1); windowf_index(w, 2, &x); CONTEND_EQUALITY(x, 9); windowf_index(w, 3, &x); CONTEND_EQUALITY(x, 8); windowf_index(w, 4, &x); CONTEND_EQUALITY(x, 7); windowf_index(w, 5, &x); CONTEND_EQUALITY(x, 6); windowf_index(w, 6, &x); CONTEND_EQUALITY(x, 3); windowf_index(w, 7, &x); CONTEND_EQUALITY(x, 3); windowf_index(w, 8, &x); CONTEND_EQUALITY(x, 3); windowf_index(w, 9, &x); CONTEND_EQUALITY(x, 3); // push 4 more elements // 7 6 3 3 3 3 5 5 5 5 windowf_push(w, 5); windowf_push(w, 5); windowf_push(w, 5); windowf_push(w, 5); windowf_read(w, &r); CONTEND_SAME_DATA(r,test4,10*sizeof(float)); if (liquid_autotest_verbose) windowf_debug_print(w); // recreate window (truncate to last 6 elements) // 3 3 5 5 5 5 w = windowf_recreate(w,6); windowf_read(w, &r); CONTEND_SAME_DATA(r,test5,6*sizeof(float)); // push 2 more elements // 5 5 5 5 6 7 windowf_push(w, 6); windowf_push(w, 7); windowf_read(w, &r); CONTEND_SAME_DATA(r,test6,6*sizeof(float)); // recreate window (extend to 10 elements) // 0 0 0 0 5 5 5 5 6 7 w = windowf_recreate(w,10); windowf_read(w,&r); CONTEND_SAME_DATA(r,test7,10*sizeof(float)); // reset // 0 0 0 0 0 0 0 0 0 0 windowf_reset(w); windowf_read(w, &r); CONTEND_SAME_DATA(r,test8,10*sizeof(float)); if (liquid_autotest_verbose) { // manual print printf("manual output:\n"); for (i=0; i<10; i++) printf("%6u : %f\n", i, r[i]); windowf_debug_print(w); } windowf_destroy(w); printf("done.\n"); } liquid-dsp-1.3.1/src/buffer/window.readme.txt000066400000000000000000000033221317124540100211310ustar00rootroot00000000000000## ## Window methods ## window window_create(unsigned int _n) Creates a window (circular/ring buffer) with _n accessable elements. By default the window is filled with zeros. window window_recreate(window _w, unsigned int _n) Re-creates a window from a previously instantiated one with a new length _n. If the length of the window increases, the old values are preserved and zeros are pushed into the beginning (oldest). If the length of the window decreases, the oldest values are truncated. Similar to the standard C realloc() function. void window_destroy(window _w) Destroys a window object (de-allocates memory). void window_print(window _w) Prints elements in a window object to the file stdout in a well-formatted manner. void window_debug_print(window _w) Prints all internal elements in a window object to the file stdout in a well-formatted manner. void window_clear(window _w) Clears all elements in a window object by setting them to zero. void window_read(window _w, T ** _v) Returns a pointer to the beginning of the buffer. NOTE: the intention is to read values from the window buffer and not to change them. The result of changing values in the returned array pointer _v is undefined due to the internal mechanism the window methods use for efficient bookkeeping. void window_push(window _w, T _v) Push a single value to the end of the window. Oldest value is removed from the buffer and all values are logically shifted left by one index. void window_write(window _w, T * _v, unsigned int _n) Writes _n elements in the array _v to the window object. This is equivalent to iterating window_push() _n times over the array. liquid-dsp-1.3.1/src/channel/000077500000000000000000000000001317124540100157645ustar00rootroot00000000000000liquid-dsp-1.3.1/src/channel/src/000077500000000000000000000000001317124540100165535ustar00rootroot00000000000000liquid-dsp-1.3.1/src/channel/src/channel.c000066400000000000000000000232511317124540100203320ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2016 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Generic channel // #include #include #include #include // portable structured channel object struct CHANNEL(_s) { // additive white Gauss noise int enabled_awgn; // AWGN enabled? T gamma; // channel gain T nstd; // noise standard deviation float noise_floor_dB; // noise floor float SNRdB; // signal-to-noise ratio [dB] // carrier offset int enabled_carrier; // carrier offset enabled? float dphi; // channel gain float phi; // noise standard deviation NCO() nco; // oscillator // multi-path channel int enabled_multipath; // enable multi-path channel filter? FIRFILT() channel_filter; // multi-path channel filter object TC * h; // multi-path channel filter coefficients unsigned int h_len; // multi-path channel filter length // shadowing channel int enabled_shadowing; // enable shadowing? IIRFILT() shadowing_filter; // shadowing filter object float shadowing_std; // shadowing standard deviation float shadowing_fd; // shadowing Doppler frequency }; // create structured channel object with default parameters CHANNEL() CHANNEL(_create)(void) { CHANNEL() q = (CHANNEL()) malloc(sizeof(struct CHANNEL(_s))); // initialize all options as off q->enabled_awgn = 0; q->enabled_carrier = 0; q->enabled_multipath = 0; q->enabled_shadowing = 0; // create internal objects q->nco = NCO(_create)(LIQUID_VCO); q->h_len = 1; q->h = (TC*) malloc(q->h_len*sizeof(TC)); q->h[0] = 1.0f; q->channel_filter = FIRFILT(_create)(q->h, q->h_len); q->shadowing_filter = NULL; // return object return q; } // destroy channel object void CHANNEL(_destroy)(CHANNEL() _q) { // destroy internal objects NCO(_destroy)(_q->nco); FIRFILT(_destroy)(_q->channel_filter); if (_q->shadowing_filter != NULL) IIRFILT(_destroy)(_q->shadowing_filter); free(_q->h); // free main object memory free(_q); } // print channel object void CHANNEL(_print)(CHANNEL() _q) { printf("channel\n"); if (_q->enabled_awgn) printf(" AWGN: SNR=%.3f dB, gamma=%.3f, std=%.6f\n", _q->SNRdB, _q->gamma, _q->nstd); if (_q->enabled_carrier) printf(" carrier: dphi=%.3f, phi=%.3f\n", _q->dphi, _q->phi); if (_q->enabled_multipath) printf(" multipath: h_len=%u\n", _q->h_len); if (_q->enabled_shadowing) printf(" shadowing: std=%.3fdB, fd=%.3f\n", _q->shadowing_std, _q->shadowing_fd); } // apply additive white Gausss noise impairment // _q : channel object // _noise_floor_dB : noise floor power spectral density // _SNR_dB : signal-to-noise ratio [dB] void CHANNEL(_add_awgn)(CHANNEL() _q, float _noise_floor_dB, float _SNRdB) { // enable module _q->enabled_awgn = 1; // _q->noise_floor_dB = _noise_floor_dB; _q->SNRdB = _SNRdB; // set values appropriately _q->nstd = powf(10.0f, _noise_floor_dB/20.0f); _q->gamma = powf(10.0f, (_q->SNRdB+_q->noise_floor_dB)/20.0f); } // apply carrier offset impairment // _q : channel object // _frequency : carrier frequency offse [radians/sample // _phase : carrier phase offset [radians] void CHANNEL(_add_carrier_offset)(CHANNEL() _q, float _frequency, float _phase) { // enable module _q->enabled_carrier = 1; // carrier frequency/phase offsets _q->dphi = _frequency; _q->phi = _phase; // set values appropriately NCO(_set_frequency)(_q->nco, _q->dphi); NCO(_set_phase) (_q->nco, _q->phi); } // apply multi-path channel impairment // _q : channel object // _h : channel coefficients (NULL for random) // _h_len : number of channel coefficients void CHANNEL(_add_multipath)(CHANNEL() _q, TC * _h, unsigned int _h_len) { if (_h_len == 0) { fprintf(stderr,"warning: channel_%s_add_multipath(), filter length is zero (ignoring)\n", EXTENSION_FULL); return; } else if (_h_len > 1000) { fprintf(stderr,"warning: channel_%s_add_multipath(), filter length exceeds maximum\n", EXTENSION_FULL); exit(1); } // enable module _q->enabled_multipath = 1; // set values appropriately // TODO: test for types other than float complex if (_q->h_len != _h_len) _q->h = (TC*) realloc(_q->h, _h_len*sizeof(TC)); // update length _q->h_len = _h_len; // copy coefficients internally if (_h == NULL) { // generate random coefficients using m-sequence generator // TODO: support types other than float _q->h[0] = 1.0f; unsigned int i; msequence ms = msequence_create_default(14); for (i=1; i<_q->h_len; i++) { float vi = msequence_generate_symbol(ms, 8) / 256.0f - 0.5f; float vq = msequence_generate_symbol(ms, 8) / 256.0f - 0.5f; _q->h[i] = (vi + _Complex_I*vq) * 0.5f; } msequence_destroy(ms); } else { // copy coefficients internally memmove(_q->h, _h, _q->h_len*sizeof(TC)); } // re-create channel filter _q->channel_filter = FIRFILT(_recreate)(_q->channel_filter, _q->h, _q->h_len); } // apply slowly-varying shadowing impairment // _q : channel object // _sigma : std. deviation for log-normal shadowing // _fd : Doppler frequency, _fd in (0,0.5) void CHANNEL(_add_shadowing)(CHANNEL() _q, float _sigma, float _fd) { if (_q->enabled_shadowing) { fprintf(stderr,"warning: channel_%s_add_shadowing(), shadowing already enabled\n", EXTENSION_FULL); return; } else if (_sigma <= 0) { fprintf(stderr,"warning: channel_%s_add_shadowing(), standard deviation less than or equal to zero\n", EXTENSION_FULL); exit(1); } else if (_fd <= 0 || _fd >= 0.5) { fprintf(stderr,"warning: channel_%s_add_shadowing(), Doppler frequency must be in (0,0.5)\n", EXTENSION_FULL); exit(1); } // enable module _q->enabled_shadowing = 1; // TODO: set values appropriately _q->shadowing_std = _sigma; _q->shadowing_fd = _fd; // re-create channel filter // TODO: adjust gain //_q->shadowing_filter = IIRFILT(_create_lowpass)(11, _q->shadowing_fd); float alpha = _q->shadowing_fd; float a[2] = {1.0f, alpha-1.0f}; float b[2] = {alpha, 0}; _q->shadowing_filter = IIRFILT(_create)(b,2,a,2); } // apply channel impairments on single input sample // _q : channel object // _x : input sample // _y : output sample pointer void CHANNEL(_execute)(CHANNEL() _q, TI _x, TO * _y) { float complex r; // apply filter if (_q->enabled_multipath) { FIRFILT(_push)( _q->channel_filter, _x); FIRFILT(_execute)(_q->channel_filter, &r); } else { r = _x; } // apply shadowing if enabled if (_q->enabled_shadowing) { // TODO: use type-specific value other than float float g = 0; IIRFILT(_execute)(_q->shadowing_filter, randnf()*_q->shadowing_std, &g); g /= _q->shadowing_fd * 6.9f; g = powf(10.0f, g/20.0f); r *= g; } // apply carrier if enabled if (_q->enabled_carrier) { NCO(_mix_up)(_q->nco, r, &r); NCO(_step) (_q->nco); } // apply AWGN if enabled if (_q->enabled_awgn) { r *= _q->gamma; r += _q->nstd * ( randnf() + _Complex_I*randnf() ) * M_SQRT1_2; } // set output value *_y = r; } // apply channel impairments on single input sample // _q : channel object // _x : input array [size: _n x 1] // _n : input array length // _y : output array [size: _n x 1] void CHANNEL(_execute_block)(CHANNEL() _q, TI * _x, unsigned int _n, TO * _y) { // apply channel effects on each input sample // TODO: apply in blocks unsigned int i; for (i=0; i<_n; i++) CHANNEL(_execute)(_q, _x[i], &_y[i]); } liquid-dsp-1.3.1/src/channel/src/channel_cccf.c000066400000000000000000000040611317124540100213060ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Complex floating-point channel // #include #include "liquid.internal.h" // naming extensions (useful for print statements) #define EXTENSION_SHORT "f" #define EXTENSION_FULL "cccf" #define CHANNEL(name) LIQUID_CONCAT(channel_cccf,name) #define DOTPROD(name) LIQUID_CONCAT(dotprod_cccf,name) #define FIRFILT(name) LIQUID_CONCAT(firfilt_cccf,name) #define IIRFILT(name) LIQUID_CONCAT(iirfilt_rrrf,name) #define NCO(name) LIQUID_CONCAT(nco_crcf,name) #define RESAMP(name) LIQUID_CONCAT(resamp_crcf,name) #define TVMPCH(name) LIQUID_CONCAT(tvmpch_cccf,name) #define WINDOW(name) LIQUID_CONCAT(windowcf,name) #define TO float complex // output type #define TC float complex // coefficients type #define TI float complex // input type #define T float // primitive type #define PRINTVAL_TC(X,F) PRINTVAL_CFLOAT(X,F) #include "channel.c" #include "tvmpch.c" liquid-dsp-1.3.1/src/channel/src/tvmpch.c000066400000000000000000000136721317124540100202310ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // tvmpch : finite impulse response (FIR) filter // #include #include #include // tvmpch object structure struct TVMPCH(_s) { TC * h; // filter coefficients array [size; h_len x 1] unsigned int h_len; // filter length // use window object for internal buffer WINDOW() w; // float std; float alpha; float beta; }; // create time-varying multi-path channel emulator object // _n : number of coefficients, _n > 0 // _std : standard deviation // _tau : coherence time TVMPCH() TVMPCH(_create)(unsigned int _n, float _std, float _tau) { // validate input if (_n < 1) { fprintf(stderr,"error: tvmpch_%s_create(), filter length must be greater than one\n", EXTENSION_FULL); exit(1); } else if (_std < 0.0f) { fprintf(stderr,"error: tvmpch_%s_create(), standard deviation must be positive\n", EXTENSION_FULL); exit(1); } else if (_tau < 0.0f || _tau > 1.0f) { fprintf(stderr,"error: tvmpch_%s_create(), coherence time must be in [0,1]\n", EXTENSION_FULL); exit(1); } // create filter object and initialize TVMPCH() q = (TVMPCH()) malloc(sizeof(struct TVMPCH(_s))); q->h_len = _n; q->h = (TC *) malloc((q->h_len)*sizeof(TC)); q->beta = _tau; q->std = 2.0f * _std / sqrtf(q->beta); q->alpha = 1.0f - q->beta; // time-reverse coefficients unsigned int i; q->h[q->h_len-1] = 1.0f; for (i=0; ih_len-1; i++) q->h[i] = 0.0f; // create window (internal buffer) q->w = WINDOW(_create)(q->h_len); // reset filter state (clear buffer) TVMPCH(_reset)(q); // return q; } // destroy tvmpch object void TVMPCH(_destroy)(TVMPCH() _q) { WINDOW(_destroy)(_q->w); free(_q->h); free(_q); } // reset internal state of filter object void TVMPCH(_reset)(TVMPCH() _q) { WINDOW(_reset)(_q->w); } // print filter object internals (taps, buffer) void TVMPCH(_print)(TVMPCH() _q) { printf("tvmpch_%s:\n", EXTENSION_FULL); unsigned int i; unsigned int n = _q->h_len; for (i=0; iw); } // push sample into filter object's internal buffer // _q : filter object // _x : input sample void TVMPCH(_push)(TVMPCH() _q, TI _x) { // update coefficients unsigned int i; for (i=0; i<_q->h_len-1; i++) _q->h[i] = _q->alpha*_q->h[i] + _q->beta*(randnf() + _Complex_I*randnf()) * _q->std * M_SQRT1_2; // push sample into window buffer WINDOW(_push)(_q->w, _x); } // compute output sample (dot product between internal // filter coefficients and internal buffer) // _q : filter object // _y : output sample pointer void TVMPCH(_execute)(TVMPCH() _q, TO * _y) { // read buffer (retrieve pointer to aligned memory array) TI *r; WINDOW(_read)(_q->w, &r); // execute dot product DOTPROD(_run4)(r, _q->h, _q->h_len, _y); } // execute the filter on a block of input samples; the // input and output buffers may be the same // _q : filter object // _x : pointer to input array [size: _n x 1] // _n : number of input, output samples // _y : pointer to output array [size: _n x 1] void TVMPCH(_execute_block)(TVMPCH() _q, TI * _x, unsigned int _n, TO * _y) { unsigned int i; for (i=0; i<_n; i++) { // push sample into filter TVMPCH(_push)(_q, _x[i]); // compute output sample TVMPCH(_execute)(_q, &_y[i]); } } #if 0 // get filter length unsigned int TVMPCH(_get_length)(TVMPCH() _q) { return _q->h_len; } // compute complex frequency response // _q : filter object // _fc : frequency // _H : output frequency response void TVMPCH(_freqresponse)(TVMPCH() _q, float _fc, float complex * _H) { unsigned int i; float complex H = 0.0f; // compute dot product between coefficients and exp{ 2 pi fc {0..n-1} } for (i=0; i<_q->h_len; i++) H += _q->h[i] * cexpf(_Complex_I*2*M_PI*_fc*i); // apply scaling H *= _q->scale; // set return value *_H = H; } // compute group delay in samples // _q : filter object // _fc : frequency float TVMPCH(_groupdelay)(TVMPCH() _q, float _fc) { // copy coefficients to be in correct order float h[_q->h_len]; unsigned int i; unsigned int n = _q->h_len; for (i=0; ih[n-i-1]); return fir_group_delay(h, n, _fc); } #endif liquid-dsp-1.3.1/src/dotprod/000077500000000000000000000000001317124540100160275ustar00rootroot00000000000000liquid-dsp-1.3.1/src/dotprod/bench/000077500000000000000000000000001317124540100171065ustar00rootroot00000000000000liquid-dsp-1.3.1/src/dotprod/bench/dotprod_cccf_benchmark.c000066400000000000000000000055771317124540100237330ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // Helper function to keep code base small void dotprod_cccf_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _n) { // normalize number of iterations *_num_iterations *= 100; *_num_iterations /= _n; if (*_num_iterations < 1) *_num_iterations = 1; float complex x[_n]; float complex h[_n]; float complex y[8]; unsigned int i; for (i=0; i<_n; i++) { x[i] = randnf() + _Complex_I*randnf(); h[i] = randnf() + _Complex_I*randnf(); } // create dotprod structure; dotprod_cccf dp = dotprod_cccf_create(h,_n); // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { dotprod_cccf_execute(dp, x, &y[0]); dotprod_cccf_execute(dp, x, &y[1]); dotprod_cccf_execute(dp, x, &y[2]); dotprod_cccf_execute(dp, x, &y[3]); dotprod_cccf_execute(dp, x, &y[4]); dotprod_cccf_execute(dp, x, &y[5]); dotprod_cccf_execute(dp, x, &y[6]); dotprod_cccf_execute(dp, x, &y[7]); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 8; // clean up objects dotprod_cccf_destroy(dp); } #define DOTPROD_CCCF_BENCHMARK_API(N) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { dotprod_cccf_bench(_start, _finish, _num_iterations, N); } void benchmark_dotprod_cccf_4 DOTPROD_CCCF_BENCHMARK_API(4) void benchmark_dotprod_cccf_16 DOTPROD_CCCF_BENCHMARK_API(16) void benchmark_dotprod_cccf_64 DOTPROD_CCCF_BENCHMARK_API(64) void benchmark_dotprod_cccf_256 DOTPROD_CCCF_BENCHMARK_API(256) liquid-dsp-1.3.1/src/dotprod/bench/dotprod_crcf_benchmark.c000066400000000000000000000055411317124540100237410ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // Helper function to keep code base small void dotprod_crcf_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _n) { // normalize number of iterations *_num_iterations *= 100; *_num_iterations /= _n; if (*_num_iterations < 1) *_num_iterations = 1; float complex x[_n]; float h[_n]; float complex y[8]; unsigned int i; for (i=0; i<_n; i++) { x[i] = randnf() + _Complex_I*randnf(); h[i] = randnf(); } // create dotprod structure; dotprod_crcf dp = dotprod_crcf_create(h,_n); // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { dotprod_crcf_execute(dp, x, &y[0]); dotprod_crcf_execute(dp, x, &y[1]); dotprod_crcf_execute(dp, x, &y[2]); dotprod_crcf_execute(dp, x, &y[3]); dotprod_crcf_execute(dp, x, &y[4]); dotprod_crcf_execute(dp, x, &y[5]); dotprod_crcf_execute(dp, x, &y[6]); dotprod_crcf_execute(dp, x, &y[7]); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 8; // clean up objects dotprod_crcf_destroy(dp); } #define DOTPROD_CRCF_BENCHMARK_API(N) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { dotprod_crcf_bench(_start, _finish, _num_iterations, N); } void benchmark_dotprod_crcf_4 DOTPROD_CRCF_BENCHMARK_API(4) void benchmark_dotprod_crcf_16 DOTPROD_CRCF_BENCHMARK_API(16) void benchmark_dotprod_crcf_64 DOTPROD_CRCF_BENCHMARK_API(64) void benchmark_dotprod_crcf_256 DOTPROD_CRCF_BENCHMARK_API(256) liquid-dsp-1.3.1/src/dotprod/bench/dotprod_rrrf_benchmark.c000066400000000000000000000051341317124540100237750ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // Helper function to keep code base small void dotprod_rrrf_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _n) { // normalize number of iterations *_num_iterations *= 128; *_num_iterations /= _n; if (*_num_iterations < 1) *_num_iterations = 1; float x[_n], h[_n], y; unsigned int i; for (i=0; i<_n; i++) { x[i] = 1.0f; h[i] = 1.0f; } // create dotprod structure; dotprod_rrrf dp = dotprod_rrrf_create(h,_n); // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { dotprod_rrrf_execute(dp,x,&y); dotprod_rrrf_execute(dp,x,&y); dotprod_rrrf_execute(dp,x,&y); dotprod_rrrf_execute(dp,x,&y); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; // clean up objects dotprod_rrrf_destroy(dp); } #define DOTPROD_RRRF_BENCHMARK_API(N) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { dotprod_rrrf_bench(_start, _finish, _num_iterations, N); } void benchmark_dotprod_rrrf_4 DOTPROD_RRRF_BENCHMARK_API(4) void benchmark_dotprod_rrrf_16 DOTPROD_RRRF_BENCHMARK_API(16) void benchmark_dotprod_rrrf_64 DOTPROD_RRRF_BENCHMARK_API(64) void benchmark_dotprod_rrrf_256 DOTPROD_RRRF_BENCHMARK_API(256) liquid-dsp-1.3.1/src/dotprod/bench/sumsqcf_benchmark.c000066400000000000000000000047351317124540100227560ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // Helper function to keep code base small void sumsqcf_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _n) { // normalize number of iterations *_num_iterations *= 128; *_num_iterations /= _n; if (*_num_iterations < 1) *_num_iterations = 1; float complex x[_n]; float complex y = 0.0f; unsigned int long i; for (i=0; i<_n; i++) x[i] = 0.2f + 0.2f*_Complex_I; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { y += liquid_sumsqcf(x, _n); y -= liquid_sumsqcf(x, _n); y += liquid_sumsqcf(x, _n); y -= liquid_sumsqcf(x, _n); // change input x[i%_n] = y; } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; } #define SUMSQCF_BENCHMARK_API(N) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { sumsqcf_bench(_start, _finish, _num_iterations, N); } void benchmark_sumsqcf_4 SUMSQCF_BENCHMARK_API(4) void benchmark_sumsqcf_16 SUMSQCF_BENCHMARK_API(16) void benchmark_sumsqcf_64 SUMSQCF_BENCHMARK_API(64) void benchmark_sumsqcf_256 SUMSQCF_BENCHMARK_API(256) liquid-dsp-1.3.1/src/dotprod/bench/sumsqf_benchmark.c000066400000000000000000000046661317124540100226160ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // Helper function to keep code base small void sumsqf_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _n) { // normalize number of iterations *_num_iterations *= 128; *_num_iterations /= _n; if (*_num_iterations < 1) *_num_iterations = 1; float x[_n]; float y = 0.0f; unsigned int long i; for (i=0; i<_n; i++) x[i] = 1.0f; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { y += liquid_sumsqf(x, _n); y -= liquid_sumsqf(x, _n); y += liquid_sumsqf(x, _n); y -= liquid_sumsqf(x, _n); // change input x[i%_n] = y; } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; } #define SUMSQF_BENCHMARK_API(N) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { sumsqf_bench(_start, _finish, _num_iterations, N); } void benchmark_sumsqf_4 SUMSQF_BENCHMARK_API(4) void benchmark_sumsqf_16 SUMSQF_BENCHMARK_API(16) void benchmark_sumsqf_64 SUMSQF_BENCHMARK_API(64) void benchmark_sumsqf_256 SUMSQF_BENCHMARK_API(256) liquid-dsp-1.3.1/src/dotprod/src/000077500000000000000000000000001317124540100166165ustar00rootroot00000000000000liquid-dsp-1.3.1/src/dotprod/src/dotprod.c000066400000000000000000000110641317124540100204370ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Generic dot product // #include #include #include // portable structured dot product object struct DOTPROD(_s) { TC * h; // coefficients array unsigned int n; // length }; // basic dot product // _h : coefficients array [size: 1 x _n] // _x : input array [size: 1 x _n] // _n : input lengths // _y : output dot product void DOTPROD(_run)(TC * _h, TI * _x, unsigned int _n, TO * _y) { // initialize accumulator TO r=0; unsigned int i; for (i=0; i<_n; i++) r += _h[i] * _x[i]; // return result *_y = r; } // basic dotproduct, unrolling loop // _h : coefficients array [size: 1 x _n] // _x : input array [size: 1 x _n] // _n : input lengths // _y : output dot product void DOTPROD(_run4)(TC * _h, TI * _x, unsigned int _n, TO * _y) { // initialize accumulator TO r=0; // t = 4*(floor(_n/4)) unsigned int t=(_n>>2)<<2; // compute dotprod in groups of 4 unsigned int i; for (i=0; in = _n; // allocate memory for coefficients q->h = (TC*) malloc((q->n)*sizeof(TC)); // move coefficients memmove(q->h, _h, (q->n)*sizeof(TC)); // return object return q; } // re-create dot product object // _q : old dot dot product object // _h : new coefficients [size: 1 x _n] // _n : new dot product size DOTPROD() DOTPROD(_recreate)(DOTPROD() _q, TC * _h, unsigned int _n) { // check to see if length has changed if (_q->n != _n) { // set new length _q->n = _n; // re-allocate memory _q->h = (TC*) realloc(_q->h, (_q->n)*sizeof(TC)); } // move new coefficients memmove(_q->h, _h, (_q->n)*sizeof(TC)); // return re-structured object return _q; } // destroy dot product object void DOTPROD(_destroy)(DOTPROD() _q) { free(_q->h); // free coefficients memory free(_q); // free main object memory } // print dot product object void DOTPROD(_print)(DOTPROD() _q) { printf("dotprod [portable, %u coefficients]:\n", _q->n); unsigned int i; for (i=0; i<_q->n; i++) { printf(" %4u: %12.8f + j*%12.8f\n", i, crealf(_q->h[i]), cimagf(_q->h[i])); } } // execute structured dot product // _q : dot product object // _x : input array [size: 1 x _n] // _y : output dot product void DOTPROD(_execute)(DOTPROD() _q, TI * _x, TO * _y) { // run basic dot product with unrolled loops DOTPROD(_run4)(_q->h, _x, _q->n, _y); } liquid-dsp-1.3.1/src/dotprod/src/dotprod_cccf.c000066400000000000000000000026121317124540100214140ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Complex floating-point dot product // #include #include "liquid.internal.h" #define DOTPROD(name) LIQUID_CONCAT(dotprod_cccf,name) #define TO float complex #define TC float complex #define TI float complex #include "dotprod.c" liquid-dsp-1.3.1/src/dotprod/src/dotprod_cccf.mmx.c000066400000000000000000000253011317124540100222140ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Floating-point dot product (MMX) // #include #include #include #include "liquid.internal.h" // include proper SIMD extensions for x86 platforms // NOTE: these pre-processor macros are defined in config.h #if HAVE_MMINTRIN_H #include // MMX #endif #if HAVE_XMMINTRIN_H #include // SSE #endif #if HAVE_EMMINTRIN_H #include // SSE2 #endif #if HAVE_PMMINTRIN_H #include // SSE3 #endif #define DEBUG_DOTPROD_CCCF_MMX 0 // forward declaration of internal methods void dotprod_cccf_execute_mmx(dotprod_cccf _q, float complex * _x, float complex * _y); void dotprod_cccf_execute_mmx4(dotprod_cccf _q, float complex * _x, float complex * _y); // basic dot product (ordinal calculation) void dotprod_cccf_run(float complex * _h, float complex * _x, unsigned int _n, float complex * _y) { float complex r = 0; unsigned int i; for (i=0; i<_n; i++) r += _h[i] * _x[i]; *_y = r; } // basic dot product (ordinal calculation) with loop unrolled void dotprod_cccf_run4(float complex * _h, float complex * _x, unsigned int _n, float complex * _y) { float complex r = 0; // t = 4*(floor(_n/4)) unsigned int t=(_n>>2)<<2; // compute dotprod in groups of 4 unsigned int i; for (i=0; in = _n; // allocate memory for coefficients, 16-byte aligned q->hi = (float*) _mm_malloc( 2*q->n*sizeof(float), 16 ); q->hq = (float*) _mm_malloc( 2*q->n*sizeof(float), 16 ); // set coefficients, repeated // hi = { crealf(_h[0]), crealf(_h[0]), ... crealf(_h[n-1]), crealf(_h[n-1])} // hq = { cimagf(_h[0]), cimagf(_h[0]), ... cimagf(_h[n-1]), cimagf(_h[n-1])} unsigned int i; for (i=0; in; i++) { q->hi[2*i+0] = crealf(_h[i]); q->hi[2*i+1] = crealf(_h[i]); q->hq[2*i+0] = cimagf(_h[i]); q->hq[2*i+1] = cimagf(_h[i]); } // return object return q; } // re-create the structured dotprod object dotprod_cccf dotprod_cccf_recreate(dotprod_cccf _q, float complex * _h, unsigned int _n) { // completely destroy and re-create dotprod object dotprod_cccf_destroy(_q); return dotprod_cccf_create(_h,_n); } void dotprod_cccf_destroy(dotprod_cccf _q) { _mm_free(_q->hi); _mm_free(_q->hq); free(_q); } void dotprod_cccf_print(dotprod_cccf _q) { printf("dotprod_cccf [mmx, %u coefficients]\n", _q->n); unsigned int i; for (i=0; i<_q->n; i++) printf(" %3u : %12.9f +j%12.9f\n", i, _q->hi[i], _q->hq[i]); } // execute structured dot product // _q : dotprod object // _x : input array // _y : output sample void dotprod_cccf_execute(dotprod_cccf _q, float complex * _x, float complex * _y) { // switch based on size if (_q->n < 32) { dotprod_cccf_execute_mmx(_q, _x, _y); } else { dotprod_cccf_execute_mmx4(_q, _x, _y); } } // use MMX/SSE extensions // // (a + jb)(c + jd) = (ac - bd) + j(ad + bc) // // mm_x = { x[0].real, x[0].imag, x[1].real, x[1].imag } // mm_hi = { h[0].real, h[0].real, h[1].real, h[1].real } // mm_hq = { h[0].imag, h[0].imag, h[1].imag, h[1].imag } // // mm_y0 = mm_x * mm_hi // = { x[0].real * h[0].real, // x[0].imag * h[0].real, // x[1].real * h[1].real, // x[1].imag * h[1].real }; // // mm_y1 = mm_x * mm_hq // = { x[0].real * h[0].imag, // x[0].imag * h[0].imag, // x[1].real * h[1].imag, // x[1].imag * h[1].imag }; // void dotprod_cccf_execute_mmx(dotprod_cccf _q, float complex * _x, float complex * _y) { // type cast input as floating point array float * x = (float*) _x; // double effective length unsigned int n = 2*_q->n; // temporary buffers __m128 v; // input vector __m128 hi; // coefficients vector (real) __m128 hq; // coefficients vector (imag) __m128 ci; // output multiplication (v * hi) __m128 cq; // output multiplication (v * hq) // aligned output array float w[4] __attribute__((aligned(16))) = {0,0,0,0}; #if HAVE_PMMINTRIN_H // SSE3 __m128 s; // dot product __m128 sum = _mm_setzero_ps(); // load zeros into sum register #else // no SSE3 float wi[4] __attribute__((aligned(16))); float wq[4] __attribute__((aligned(16))); #endif // t = 4*(floor(_n/4)) unsigned int t = (n >> 2) << 2; // unsigned int i; for (i=0; ihi[i]); hq = _mm_load_ps(&_q->hq[i]); // compute parallel multiplications ci = _mm_mul_ps(v, hi); cq = _mm_mul_ps(v, hq); // shuffle values cq = _mm_shuffle_ps( cq, cq, _MM_SHUFFLE(2,3,0,1) ); #if HAVE_PMMINTRIN_H // SSE3: combine using addsub_ps() s = _mm_addsub_ps( ci, cq ); // accumulate sum = _mm_add_ps(sum, s); #else // no SSE3: combine using slow method // FIXME: implement slow method // unload values _mm_store_ps(wi, ci); _mm_store_ps(wq, cq); // accumulate w[0] += wi[0] - wq[0]; w[1] += wi[1] + wq[1]; w[2] += wi[2] - wq[2]; w[3] += wi[3] + wq[3]; #endif } #if HAVE_PMMINTRIN_H // unload packed array _mm_store_ps(w, sum); #endif // add in-phase and quadrature components w[0] += w[2]; // I w[1] += w[3]; // Q //float complex total = *((float complex*)w); float complex total = w[0] + w[1] * _Complex_I; // cleanup for (i=t/2; i<_q->n; i++) total += _x[i] * ( _q->hi[2*i] + _q->hq[2*i]*_Complex_I ); // set return value *_y = total; } // use MMX/SSE extensions void dotprod_cccf_execute_mmx4(dotprod_cccf _q, float complex * _x, float complex * _y) { // type cast input as floating point array float * x = (float*) _x; // double effective length unsigned int n = 2*_q->n; // first cut: ... __m128 v0, v1, v2, v3; // input vectors __m128 hi0, hi1, hi2, hi3; // coefficients vectors (real) __m128 hq0, hq1, hq2, hq3; // coefficients vectors (imag) __m128 ci0, ci1, ci2, ci3; // output multiplications (v * hi) __m128 cq0, cq1, cq2, cq3; // output multiplications (v * hq) // load zeros into sum registers __m128 sumi = _mm_setzero_ps(); __m128 sumq = _mm_setzero_ps(); // r = 4*floor(n/16) unsigned int r = (n >> 4) << 2; // unsigned int i; for (i=0; ihi[4*i+0]); hi1 = _mm_load_ps(&_q->hi[4*i+4]); hi2 = _mm_load_ps(&_q->hi[4*i+8]); hi3 = _mm_load_ps(&_q->hi[4*i+12]); // load real coefficients into registers (aligned) hq0 = _mm_load_ps(&_q->hq[4*i+0]); hq1 = _mm_load_ps(&_q->hq[4*i+4]); hq2 = _mm_load_ps(&_q->hq[4*i+8]); hq3 = _mm_load_ps(&_q->hq[4*i+12]); // compute parallel multiplications (real) ci0 = _mm_mul_ps(v0, hi0); ci1 = _mm_mul_ps(v1, hi1); ci2 = _mm_mul_ps(v2, hi2); ci3 = _mm_mul_ps(v3, hi3); // compute parallel multiplications (imag) cq0 = _mm_mul_ps(v0, hq0); cq1 = _mm_mul_ps(v1, hq1); cq2 = _mm_mul_ps(v2, hq2); cq3 = _mm_mul_ps(v3, hq3); // accumulate sumi = _mm_add_ps(sumi, ci0); sumq = _mm_add_ps(sumq, cq0); sumi = _mm_add_ps(sumi, ci1); sumq = _mm_add_ps(sumq, cq1); sumi = _mm_add_ps(sumi, ci2); sumq = _mm_add_ps(sumq, cq2); sumi = _mm_add_ps(sumi, ci3); sumq = _mm_add_ps(sumq, cq3); } // shuffle values sumq = _mm_shuffle_ps( sumq, sumq, _MM_SHUFFLE(2,3,0,1) ); // unload float wi[4] __attribute__((aligned(16))); float wq[4] __attribute__((aligned(16))); _mm_store_ps(wi, sumi); _mm_store_ps(wq, sumq); // fold down (add/sub) float complex total = ((wi[0] - wq[0]) + (wi[2] - wq[2])) + ((wi[1] + wq[1]) + (wi[3] + wq[3])) * _Complex_I; // cleanup (note: n _must_ be even) // TODO : clean this method up for (i=2*r; i<_q->n; i++) { total += _x[i] * ( _q->hi[2*i] + _q->hq[2*i]*_Complex_I ); } // set return value *_y = total; } liquid-dsp-1.3.1/src/dotprod/src/dotprod_cccf.neon.c000066400000000000000000000236051317124540100223570ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Floating-point dot product (ARM Neon) // #include #include #include #include "liquid.internal.h" // include proper SIMD extensions for ARM Neon #include #define DEBUG_DOTPROD_CCCF_NEON 0 // forward declaration of internal methods void dotprod_cccf_execute_neon(dotprod_cccf _q, float complex * _x, float complex * _y); void dotprod_cccf_execute_neon4(dotprod_cccf _q, float complex * _x, float complex * _y); // basic dot product (ordinal calculation) void dotprod_cccf_run(float complex * _h, float complex * _x, unsigned int _n, float complex * _y) { float complex r = 0; unsigned int i; for (i=0; i<_n; i++) r += _h[i] * _x[i]; *_y = r; } // basic dot product (ordinal calculation) with loop unrolled void dotprod_cccf_run4(float complex * _h, float complex * _x, unsigned int _n, float complex * _y) { float complex r = 0; // t = 4*(floor(_n/4)) unsigned int t=(_n>>2)<<2; // compute dotprod in groups of 4 unsigned int i; for (i=0; in = _n; // allocate memory for coefficients q->hi = (float*) malloc( 2*q->n*sizeof(float) ); q->hq = (float*) malloc( 2*q->n*sizeof(float) ); // set coefficients, repeated // hi = { crealf(_h[0]), crealf(_h[0]), ... crealf(_h[n-1]), crealf(_h[n-1])} // hq = { cimagf(_h[0]), cimagf(_h[0]), ... cimagf(_h[n-1]), cimagf(_h[n-1])} unsigned int i; for (i=0; in; i++) { q->hi[2*i+0] = crealf(_h[i]); q->hi[2*i+1] = crealf(_h[i]); q->hq[2*i+0] = cimagf(_h[i]); q->hq[2*i+1] = cimagf(_h[i]); } // return object return q; } // re-create the structured dotprod object dotprod_cccf dotprod_cccf_recreate(dotprod_cccf _q, float complex * _h, unsigned int _n) { // completely destroy and re-create dotprod object dotprod_cccf_destroy(_q); return dotprod_cccf_create(_h,_n); } void dotprod_cccf_destroy(dotprod_cccf _q) { // free coefficients arrays free(_q->hi); free(_q->hq); // free main memory free(_q); } void dotprod_cccf_print(dotprod_cccf _q) { printf("dotprod_cccf [arm-neon, %u coefficients]\n", _q->n); unsigned int i; for (i=0; i<_q->n; i++) printf(" %3u : %12.9f +j%12.9f\n", i, _q->hi[i], _q->hq[i]); } // execute structured dot product // _q : dotprod object // _x : input array // _y : output sample void dotprod_cccf_execute(dotprod_cccf _q, float complex * _x, float complex * _y) { // switch based on size if (_q->n < 32) { dotprod_cccf_execute_neon(_q, _x, _y); } else { dotprod_cccf_execute_neon4(_q, _x, _y); } } // use ARM Neon extensions // // (a + jb)(c + jd) = (ac - bd) + j(ad + bc) // // mm_x = { x[0].real, x[0].imag, x[1].real, x[1].imag } // mm_hi = { h[0].real, h[0].real, h[1].real, h[1].real } // mm_hq = { h[0].imag, h[0].imag, h[1].imag, h[1].imag } // // mm_y0 = mm_x * mm_hi // = { x[0].real * h[0].real, // x[0].imag * h[0].real, // x[1].real * h[1].real, // x[1].imag * h[1].real }; // // mm_y1 = mm_x * mm_hq // = { x[0].real * h[0].imag, // x[0].imag * h[0].imag, // x[1].real * h[1].imag, // x[1].imag * h[1].imag }; // void dotprod_cccf_execute_neon(dotprod_cccf _q, float complex * _x, float complex * _y) { // type cast input as floating point array float * x = (float*) _x; // double effective length unsigned int n = 2*_q->n; // temporary buffers float32x4_t v; // input vector float32x4_t hi; // coefficients vector (real) float32x4_t hq; // coefficients vector (imag) float32x4_t ci; // output multiplication (v * hi) float32x4_t cq; // output multiplication (v * hq) // output accumulators float zeros[4] = {0,0,0,0}; float32x4_t sumi = vld1q_f32(zeros); float32x4_t sumq = vld1q_f32(zeros); // t = 4*(floor(_n/4)) unsigned int t = (n >> 2) << 2; // unsigned int i; for (i=0; ihi[i]); hq = vld1q_f32(&_q->hq[i]); // compute parallel multiplications ci = vmulq_f32(v, hi); cq = vmulq_f32(v, hq); // parallel addition sumi = vaddq_f32(sumi, ci); sumq = vaddq_f32(sumq, cq); } // unload and combine float wi[4]; float wq[4]; vst1q_f32(wi, sumi); vst1q_f32(wq, sumq); // fold down (add/sub) float complex total = ((wi[0] - wq[1]) + (wi[2] - wq[3])) + ((wi[1] + wq[0]) + (wi[3] + wq[2])) * _Complex_I; // cleanup for (i=t/2; i<_q->n; i++) total += _x[i] * ( _q->hi[2*i] + _q->hq[2*i]*_Complex_I ); // set return value *_y = total; } // use ARM Neon extensions (unrolled loop) // NOTE: unrolling doesn't show any appreciable performance difference void dotprod_cccf_execute_neon4(dotprod_cccf _q, float complex * _x, float complex * _y) { // type cast input as floating point array float * x = (float*) _x; // double effective length unsigned int n = 2*_q->n; // first cut: ... float32x4_t v0, v1, v2, v3; // input vectors float32x4_t hi0, hi1, hi2, hi3; // coefficients vectors (real) float32x4_t hq0, hq1, hq2, hq3; // coefficients vectors (imag) float32x4_t ci0, ci1, ci2, ci3; // output multiplications (v * hi) float32x4_t cq0, cq1, cq2, cq3; // output multiplications (v * hq) // load zeros into sum registers float zeros[4] = {0,0,0,0}; float32x4_t sumi = vld1q_f32(zeros); float32x4_t sumq = vld1q_f32(zeros); // r = 4*floor(n/16) unsigned int r = (n >> 4) << 2; // unsigned int i; for (i=0; ihi[4*i+0]); hi1 = vld1q_f32(&_q->hi[4*i+4]); hi2 = vld1q_f32(&_q->hi[4*i+8]); hi3 = vld1q_f32(&_q->hi[4*i+12]); // load real coefficients into registers (aligned) hq0 = vld1q_f32(&_q->hq[4*i+0]); hq1 = vld1q_f32(&_q->hq[4*i+4]); hq2 = vld1q_f32(&_q->hq[4*i+8]); hq3 = vld1q_f32(&_q->hq[4*i+12]); // compute parallel multiplications (real) ci0 = vmulq_f32(v0, hi0); ci1 = vmulq_f32(v1, hi1); ci2 = vmulq_f32(v2, hi2); ci3 = vmulq_f32(v3, hi3); // compute parallel multiplications (imag) cq0 = vmulq_f32(v0, hq0); cq1 = vmulq_f32(v1, hq1); cq2 = vmulq_f32(v2, hq2); cq3 = vmulq_f32(v3, hq3); // accumulate sumi = vaddq_f32(sumi, ci0); sumq = vaddq_f32(sumq, cq0); sumi = vaddq_f32(sumi, ci1); sumq = vaddq_f32(sumq, cq1); sumi = vaddq_f32(sumi, ci2); sumq = vaddq_f32(sumq, cq2); sumi = vaddq_f32(sumi, ci3); sumq = vaddq_f32(sumq, cq3); } // unload float wi[4]; float wq[4]; vst1q_f32(wi, sumi); vst1q_f32(wq, sumq); // fold down (add/sub) float complex total = ((wi[0] - wq[1]) + (wi[2] - wq[3])) + ((wi[1] + wq[0]) + (wi[3] + wq[2])) * _Complex_I; // cleanup (note: n _must_ be even) // TODO : clean this method up for (i=2*r; i<_q->n; i++) { total += _x[i] * ( _q->hi[2*i] + _q->hq[2*i]*_Complex_I ); } // set return value *_y = total; } liquid-dsp-1.3.1/src/dotprod/src/dotprod_crcf.av.c000066400000000000000000000143551317124540100220470ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Complex floating-point dot product (altivec velocity engine) // #include #include #include "liquid.internal.h" #define DEBUG_DOTPROD_CRCF_AV 0 // basic dot product // basic dot product // _h : coefficients array [size: 1 x _n] // _x : input array [size: 1 x _n] // _n : input lengths // _y : output dot product void dotprod_crcf_run(float * _h, float complex * _x, unsigned int _n, float complex * _y) { float complex r=0; unsigned int i; for (i=0; i<_n; i++) r += _h[i] * _x[i]; *_y = r; } // basic dot product, unrolling loop // _h : coefficients array [size: 1 x _n] // _x : input array [size: 1 x _n] // _n : input lengths // _y : output dot product void dotprod_crcf_run4(float * _h, float complex * _x, unsigned int _n, float complex * _y) { float complex r=0; // t = 4*(floor(_n/4)) unsigned int t=(_n>>2)<<2; // compute dotprod in groups of 4 unsigned int i; for (i=0; in = _n; // create 4 copies of the input coefficients (one for each // data alignment). For example: _h[4] = {1,2,3,4,5,6} // dp->h[0] = {1,1,2,2,3,3,4,4,5,5,6,6} // dp->h[1] = {. 1,1,2,2,3,3,4,4,5,5,6,6} // dp->h[2] = {. . 1,1,2,2,3,3,4,4,5,5,6,6} // dp->h[3] = {. . . 1,1,2,2,3,3,4,4,5,5,6,6} // NOTE: double allocation size; coefficients are real, but // need to be multiplied by real and complex components // of input. unsigned int i,j; for (i=0; i<4; i++) { dp->h[i] = calloc(1+(2*dp->n+i-1)/4,2*sizeof(vector float)); for (j=0; jn; j++) { dp->h[i][2*j+0+i] = _h[j]; dp->h[i][2*j+1+i] = _h[j]; } } return dp; } // re-create the structured dotprod object dotprod_crcf dotprod_crcf_recreate(dotprod_crcf _q, float * _h, unsigned int _n) { // completely destroy and re-create dotprod object dotprod_crcf_destroy(_q); return dotprod_crcf_create(_h,_n); } // destroy the structured dotprod object void dotprod_crcf_destroy(dotprod_crcf _q) { // clean up coefficients arrays unsigned int i; for (i=0; i<4; i++) free(_q->h[i]); // free allocated object memory free(_q); } // print the dotprod object void dotprod_crcf_print(dotprod_crcf _q) { printf("dotprod_crcf [altivec, %u coefficients]:\n", _q->n); unsigned int i; for (i=0; i<_q->n; i++) printf(" %3u : %12.9f\n", i, _q->h[0][2*i]); } // exectue vectorized structured inner dot product void dotprod_crcf_execute(dotprod_crcf _q, float complex * _x, float complex * _r) { int al; // input data alignment vector float *ar,*d; vector float s0,s1,s2,s3; union { vector float v; float w[4];} s; unsigned int nblocks; ar = (vector float*)( (int)_x & ~15); al = ((int)_x & 15)/sizeof(float); d = (vector float*)_q->h[al]; // number of blocks doubles because of complex type nblocks = (2*_q->n + al - 1)/4 + 1; // split into four vectors each with four 32-bit // partial sums. Effectively each loop iteration // operates on 16 input samples at a time. s0 = s1 = s2 = s3 = (vector float)(0); while (nblocks >= 4) { s0 = vec_madd(ar[nblocks-1],d[nblocks-1],s0); s1 = vec_madd(ar[nblocks-2],d[nblocks-2],s1); s2 = vec_madd(ar[nblocks-3],d[nblocks-3],s2); s3 = vec_madd(ar[nblocks-4],d[nblocks-4],s3); nblocks -= 4; } // fold the resulting partial sums into vector s0 s0 = vec_add(s0,s1); // s0 = s0+s1 s2 = vec_add(s2,s3); // s2 = s2+s3 s0 = vec_add(s0,s2); // s0 = s0+s2 // finish partial summing operations while (nblocks-- > 0) s0 = vec_madd(ar[nblocks],d[nblocks],s0); // move the result into the union s (effetively, // this loads the four 32-bit values in s0 into // the array w). s.v = vec_add(s0,(vector float)(0)); // sum the resulting array //*_r = s.w[0] + s.w[1] + s.w[2] + s.w[3]; *_r = (s.w[0] + s.w[2]) + (s.w[1] + s.w[3]) * _Complex_I; } liquid-dsp-1.3.1/src/dotprod/src/dotprod_crcf.c000066400000000000000000000026021317124540100214320ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Complex floating-point dot product // #include #include "liquid.internal.h" #define DOTPROD(name) LIQUID_CONCAT(dotprod_crcf,name) #define TO float complex #define TC float #define TI float complex #include "dotprod.c" liquid-dsp-1.3.1/src/dotprod/src/dotprod_crcf.mmx.c000066400000000000000000000172411317124540100222370ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Floating-point dot product (MMX) // #include #include #include #include #include #include "liquid.internal.h" #define DEBUG_DOTPROD_CRCF_MMX 0 // forward declaration of internal methods void dotprod_crcf_execute_mmx(dotprod_crcf _q, float complex * _x, float complex * _y); void dotprod_crcf_execute_mmx4(dotprod_crcf _q, float complex * _x, float complex * _y); // basic dot product (ordinal calculation) void dotprod_crcf_run(float * _h, float complex * _x, unsigned int _n, float complex * _y) { float complex r = 0; unsigned int i; for (i=0; i<_n; i++) r += _h[i] * _x[i]; *_y = r; } // basic dot product (ordinal calculation) with loop unrolled void dotprod_crcf_run4(float * _h, float complex * _x, unsigned int _n, float complex * _y) { float complex r = 0; // t = 4*(floor(_n/4)) unsigned int t=(_n>>2)<<2; // compute dotprod in groups of 4 unsigned int i; for (i=0; in = _n; // allocate memory for coefficients, 16-byte aligned q->h = (float*) _mm_malloc( 2*q->n*sizeof(float), 16 ); // set coefficients, repeated // h = { _h[0], _h[0], _h[1], _h[1], ... _h[n-1], _h[n-1]} unsigned int i; for (i=0; in; i++) { q->h[2*i+0] = _h[i]; q->h[2*i+1] = _h[i]; } // return object return q; } // re-create the structured dotprod object dotprod_crcf dotprod_crcf_recreate(dotprod_crcf _q, float * _h, unsigned int _n) { // completely destroy and re-create dotprod object dotprod_crcf_destroy(_q); return dotprod_crcf_create(_h,_n); } void dotprod_crcf_destroy(dotprod_crcf _q) { _mm_free(_q->h); free(_q); } void dotprod_crcf_print(dotprod_crcf _q) { // print coefficients to screen, skipping odd entries (due // to repeated coefficients) printf("dotprod_crcf [mmx, %u coefficients]\n", _q->n); unsigned int i; for (i=0; i<_q->n; i++) printf(" %3u : %12.9f\n", i, _q->h[2*i]); } // void dotprod_crcf_execute(dotprod_crcf _q, float complex * _x, float complex * _y) { // switch based on size if (_q->n < 32) { dotprod_crcf_execute_mmx(_q, _x, _y); } else { dotprod_crcf_execute_mmx4(_q, _x, _y); } } // use MMX/SSE extensions void dotprod_crcf_execute_mmx(dotprod_crcf _q, float complex * _x, float complex * _y) { // type cast input as floating point array float * x = (float*) _x; // double effective length unsigned int n = 2*_q->n; // first cut: ... __m128 v; // input vector __m128 h; // coefficients vector __m128 s; // dot product __m128 sum = _mm_setzero_ps(); // load zeros into sum register // t = 4*(floor(_n/4)) unsigned int t = (n >> 2) << 2; // unsigned int i; for (i=0; ih[i]); // compute multiplication s = _mm_mul_ps(v, h); // accumulate sum = _mm_add_ps(sum, s); } // aligned output array float w[4] __attribute__((aligned(16))); // unload packed array _mm_store_ps(w, sum); // add in-phase and quadrature components w[0] += w[2]; w[1] += w[3]; // cleanup (note: n _must_ be even) for (; ih[i ]; w[1] += x[i+1] * _q->h[i+1]; } // set return value *_y = w[0] + _Complex_I*w[1]; } // use MMX/SSE extensions void dotprod_crcf_execute_mmx4(dotprod_crcf _q, float complex * _x, float complex * _y) { // type cast input as floating point array float * x = (float*) _x; // double effective length unsigned int n = 2*_q->n; // first cut: ... __m128 v0, v1, v2, v3; // input vectors __m128 h0, h1, h2, h3; // coefficients vectors __m128 s0, s1, s2, s3; // dot products [re, im, re, im] // load zeros into sum registers __m128 sum0 = _mm_setzero_ps(); __m128 sum1 = _mm_setzero_ps(); __m128 sum2 = _mm_setzero_ps(); __m128 sum3 = _mm_setzero_ps(); // r = 4*floor(n/16) unsigned int r = (n >> 4) << 2; // unsigned int i; for (i=0; ih[4*i+0]); h1 = _mm_load_ps(&_q->h[4*i+4]); h2 = _mm_load_ps(&_q->h[4*i+8]); h3 = _mm_load_ps(&_q->h[4*i+12]); // compute multiplication s0 = _mm_mul_ps(v0, h0); s1 = _mm_mul_ps(v1, h1); s2 = _mm_mul_ps(v2, h2); s3 = _mm_mul_ps(v3, h3); // parallel addition sum0 = _mm_add_ps( sum0, s0 ); sum1 = _mm_add_ps( sum1, s1 ); sum2 = _mm_add_ps( sum2, s2 ); sum3 = _mm_add_ps( sum3, s3 ); } // fold down sum0 = _mm_add_ps( sum0, sum1 ); sum2 = _mm_add_ps( sum2, sum3 ); sum0 = _mm_add_ps( sum0, sum2 ); // aligned output array float w[4] __attribute__((aligned(16))); // unload packed array and perform manual sum _mm_store_ps(w, sum0); w[0] += w[2]; w[1] += w[3]; // cleanup (note: n _must_ be even) for (i=4*r; ih[i ]; w[1] += x[i+1] * _q->h[i+1]; } // set return value *_y = w[0] + w[1]*_Complex_I; } liquid-dsp-1.3.1/src/dotprod/src/dotprod_crcf.neon.c000066400000000000000000000176411317124540100224010ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Floating-point dot product (ARM Neon) // #include #include #include #include #include "liquid.internal.h" // include proper SIMD extensions for ARM Neon #include #define DEBUG_DOTPROD_CRCF_NEON 0 // forward declaration of internal methods void dotprod_crcf_execute_neon(dotprod_crcf _q, float complex * _x, float complex * _y); void dotprod_crcf_execute_neon4(dotprod_crcf _q, float complex * _x, float complex * _y); // basic dot product (ordinal calculation) using neon extensions void dotprod_crcf_run(float * _h, float complex * _x, unsigned int _n, float complex * _y) { // initialize accumulator float complex r=0; unsigned int i; for (i=0; i<_n; i++) r += _h[i] * _x[i]; // return result *_y = r; } // basic dot product (ordinal calculation) with loop unrolled void dotprod_crcf_run4(float * _h, float complex * _x, unsigned int _n, float complex * _y) { float complex r = 0; // t = 4*(floor(_n/4)) unsigned int t=(_n>>2)<<2; // compute dotprod in groups of 4 unsigned int i; for (i=0; in = _n; // allocate memory for coefficients (double size) q->h = (float*) malloc( 2*q->n*sizeof(float) ); // set coefficients, repeated // h = { _h[0], _h[0], _h[1], _h[1], ... _h[n-1], _h[n-1]} unsigned int i; for (i=0; in; i++) { q->h[2*i+0] = _h[i]; q->h[2*i+1] = _h[i]; } // return object return q; } // re-create the structured dotprod object dotprod_crcf dotprod_crcf_recreate(dotprod_crcf _q, float * _h, unsigned int _n) { // completely destroy and re-create dotprod object dotprod_crcf_destroy(_q); return dotprod_crcf_create(_h,_n); } void dotprod_crcf_destroy(dotprod_crcf _q) { // free coefficients array free(_q->h); // free main memory free(_q); } void dotprod_crcf_print(dotprod_crcf _q) { // print coefficients to screen, skipping odd entries (due // to repeated coefficients) printf("dotprod_crcf [arm-neon, %u coefficients]\n", _q->n); unsigned int i; for (i=0; i<_q->n; i++) printf(" %3u : %12.9f\n", i, _q->h[2*i]); } // void dotprod_crcf_execute(dotprod_crcf _q, float complex * _x, float complex * _y) { // switch based on size if (_q->n < 32) { dotprod_crcf_execute_neon(_q, _x, _y); } else { dotprod_crcf_execute_neon4(_q, _x, _y); } } // use ARM Neon extensions void dotprod_crcf_execute_neon(dotprod_crcf _q, float complex * _x, float complex * _y) { // type cast input as floating point array float * x = (float*) _x; // double effective length unsigned int n = 2*_q->n; // first cut: ... float32x4_t v; // input vector float32x4_t h; // coefficients vector float32x4_t s; // dot product // load zeros into sum register float zeros[4] = {0,0,0,0}; float32x4_t sum = vld1q_f32(zeros); // t = 4*(floor(_n/4)) unsigned int t = (n >> 2) << 2; // unsigned int i; for (i=0; ih[i]); // compute multiplication s = vmulq_f32(h,v); // accumulate sum = vaddq_f32(sum, s); } // unload packed array float w[4]; vst1q_f32(w, sum); // add in-phase and quadrature components w[0] += w[2]; w[1] += w[3]; // cleanup (note: n _must_ be even) for (; ih[i ]; w[1] += x[i+1] * _q->h[i+1]; } // set return value *_y = w[0] + _Complex_I*w[1]; } // use ARM Neon extensions void dotprod_crcf_execute_neon4(dotprod_crcf _q, float complex * _x, float complex * _y) { #if 1 // type cast input as floating point array float * x = (float*) _x; // double effective length unsigned int n = 2*_q->n; // first cut: ... float32x4_t v0, v1, v2, v3; // input vectors float32x4_t h0, h1, h2, h3; // coefficients vectors float32x4_t s0, s1, s2, s3; // dot products [re, im, re, im] // load zeros into sum registers float zeros[4] = {0,0,0,0}; float32x4_t sum0 = vld1q_f32(zeros); float32x4_t sum1 = vld1q_f32(zeros); float32x4_t sum2 = vld1q_f32(zeros); float32x4_t sum3 = vld1q_f32(zeros); // r = 4*floor(n/16) unsigned int r = (n >> 4) << 2; // unsigned int i; for (i=0; ih[4*i+0]); h1 = vld1q_f32(&_q->h[4*i+4]); h2 = vld1q_f32(&_q->h[4*i+8]); h3 = vld1q_f32(&_q->h[4*i+12]); // compute multiplication s0 = vmulq_f32(v0, h0); s1 = vmulq_f32(v1, h1); s2 = vmulq_f32(v2, h2); s3 = vmulq_f32(v3, h3); // parallel addition sum0 = vaddq_f32( sum0, s0 ); sum1 = vaddq_f32( sum1, s1 ); sum2 = vaddq_f32( sum2, s2 ); sum3 = vaddq_f32( sum3, s3 ); } // fold down into sum0 sum0 = vaddq_f32( sum0, sum1 ); sum2 = vaddq_f32( sum2, sum3 ); sum0 = vaddq_f32( sum0, sum2 ); // unload packed array float w[4]; vst1q_f32(w, sum0); // add in-phase and quadrature components w[0] += w[2]; w[1] += w[3]; // cleanup (note: n _must_ be even) for (i=4*r; ih[i ]; w[1] += x[i+1] * _q->h[i+1]; } // set return value *_y = w[0] + w[1]*_Complex_I; #else dotprod_crcf_execute_neon(_q, _x, _y); #endif } liquid-dsp-1.3.1/src/dotprod/src/dotprod_rrrf.av.c000066400000000000000000000134641317124540100221050ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Floating-point dot product (altivec velocity engine) // #include #include #include "liquid.internal.h" #define DEBUG_DOTPROD_RRRF_AV 0 // basic dot product // basic dot product // _h : coefficients array [size: 1 x _n] // _x : input array [size: 1 x _n] // _n : input lengths // _y : output dot product void dotprod_rrrf_run(float * _h, float * _x, unsigned int _n, float * _y) { float r=0; unsigned int i; for (i=0; i<_n; i++) r += _h[i] * _x[i]; *_y = r; } // basic dot product, unrolling loop // _h : coefficients array [size: 1 x _n] // _x : input array [size: 1 x _n] // _n : input lengths // _y : output dot product void dotprod_rrrf_run4(float * _h, float * _x, unsigned int _n, float * _y) { float r=0; // t = 4*(floor(_n/4)) unsigned int t=(_n>>2)<<2; // compute dotprod in groups of 4 unsigned int i; for (i=0; in = _n; // create 4 copies of the input coefficients (one for each // data alignment). For example: _h[4] = {1,2,3,4,5,6} // dp->h[0] = {1,2,3,4,5,6} // dp->h[1] = {. 1,2,3,4,5,6} // dp->h[2] = {. . 1,2,3,4,5,6} // dp->h[3] = {. . . 1,2,3,4,5,6} unsigned int i,j; for (i=0; i<4; i++) { dp->h[i] = calloc(1+(dp->n+i-1)/4,sizeof(vector float)); for (j=0; jn; j++) dp->h[i][j+i] = _h[j]; } return dp; } // re-create the structured dotprod object dotprod_rrrf dotprod_rrrf_recreate(dotprod_rrrf _q, float * _h, unsigned int _n) { // completely destroy and re-create dotprod object dotprod_rrrf_destroy(_q); return dotprod_rrrf_create(_h,_n); } // destroy the structured dotprod object void dotprod_rrrf_destroy(dotprod_rrrf _q) { // clean up coefficients arrays unsigned int i; for (i=0; i<4; i++) free(_q->h[i]); // free allocated object memory free(_q); } // print the dotprod object void dotprod_rrrf_print(dotprod_rrrf _q) { printf("dotprod_rrrf [altivec, %u coefficients]:\n", _q->n); unsigned int i; for (i=0; i<_q->n; i++) printf(" %3u : %12.9f\n", i, _q->h[0][i]); } // exectue vectorized structured inner dot product void dotprod_rrrf_execute(dotprod_rrrf _q, float * _x, float * _r) { int al; // input data alignment vector float *ar,*d; vector float s0,s1,s2,s3; union { vector float v; float w[4];} s; unsigned int nblocks; ar = (vector float*)( (int)_x & ~15); al = ((int)_x & 15)/sizeof(float); d = (vector float*)_q->h[al]; nblocks = (_q->n + al - 1)/4 + 1; // split into four vectors each with four 32-bit // partial sums. Effectively each loop iteration // operates on 16 input samples at a time. s0 = s1 = s2 = s3 = (vector float)(0); while (nblocks >= 4) { s0 = vec_madd(ar[nblocks-1],d[nblocks-1],s0); s1 = vec_madd(ar[nblocks-2],d[nblocks-2],s1); s2 = vec_madd(ar[nblocks-3],d[nblocks-3],s2); s3 = vec_madd(ar[nblocks-4],d[nblocks-4],s3); nblocks -= 4; } // fold the resulting partial sums into vector s0 s0 = vec_add(s0,s1); // s0 = s0+s1 s2 = vec_add(s2,s3); // s2 = s2+s3 s0 = vec_add(s0,s2); // s0 = s0+s2 // finish partial summing operations while (nblocks-- > 0) s0 = vec_madd(ar[nblocks],d[nblocks],s0); // move the result into the union s (effetively, // this loads the four 32-bit values in s0 into // the array w). s.v = vec_add(s0,(vector float)(0)); // sum the resulting array *_r = s.w[0] + s.w[1] + s.w[2] + s.w[3]; } liquid-dsp-1.3.1/src/dotprod/src/dotprod_rrrf.c000066400000000000000000000025251317124540100214740ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Floating-point dot product // #include "liquid.internal.h" #define DOTPROD(name) LIQUID_CONCAT(dotprod_rrrf,name) #define TO float #define TC float #define TI float #include "dotprod.c" liquid-dsp-1.3.1/src/dotprod/src/dotprod_rrrf.mmx.c000066400000000000000000000173541317124540100223020ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Floating-point dot product (MMX) // #include #include #include #include #include "liquid.internal.h" // include proper SIMD extensions for x86 platforms // NOTE: these pre-processor macros are defined in config.h #if HAVE_MMINTRIN_H #include // MMX #endif #if HAVE_XMMINTRIN_H #include // SSE #endif #if HAVE_EMMINTRIN_H #include // SSE2 #endif #if HAVE_PMMINTRIN_H #include // SSE3 #endif #define DEBUG_DOTPROD_RRRF_MMX 0 // internal methods void dotprod_rrrf_execute_mmx(dotprod_rrrf _q, float * _x, float * _y); void dotprod_rrrf_execute_mmx4(dotprod_rrrf _q, float * _x, float * _y); // basic dot product (ordinal calculation) void dotprod_rrrf_run(float * _h, float * _x, unsigned int _n, float * _y) { float r=0; unsigned int i; for (i=0; i<_n; i++) r += _h[i] * _x[i]; *_y = r; } // basic dot product (ordinal calculation) with loop unrolled void dotprod_rrrf_run4(float * _h, float * _x, unsigned int _n, float * _y) { float r=0; // t = 4*(floor(_n/4)) unsigned int t=(_n>>2)<<2; // compute dotprod in groups of 4 unsigned int i; for (i=0; in = _n; // allocate memory for coefficients, 16-byte aligned q->h = (float*) _mm_malloc( q->n*sizeof(float), 16); // set coefficients memmove(q->h, _h, _n*sizeof(float)); // return object return q; } // re-create the structured dotprod object dotprod_rrrf dotprod_rrrf_recreate(dotprod_rrrf _q, float * _h, unsigned int _n) { // completely destroy and re-create dotprod object dotprod_rrrf_destroy(_q); return dotprod_rrrf_create(_h,_n); } void dotprod_rrrf_destroy(dotprod_rrrf _q) { _mm_free(_q->h); free(_q); } void dotprod_rrrf_print(dotprod_rrrf _q) { printf("dotprod_rrrf [mmx, %u coefficients]\n", _q->n); unsigned int i; for (i=0; i<_q->n; i++) printf("%3u : %12.9f\n", i, _q->h[i]); } // void dotprod_rrrf_execute(dotprod_rrrf _q, float * _x, float * _y) { // switch based on size if (_q->n < 16) { dotprod_rrrf_execute_mmx(_q, _x, _y); } else { dotprod_rrrf_execute_mmx4(_q, _x, _y); } } // use MMX/SSE extensions void dotprod_rrrf_execute_mmx(dotprod_rrrf _q, float * _x, float * _y) { // first cut: ... __m128 v; // input vector __m128 h; // coefficients vector __m128 s; // dot product __m128 sum = _mm_setzero_ps(); // load zeros into sum register // t = 4*(floor(_n/4)) unsigned int t = (_q->n >> 2) << 2; // unsigned int i; for (i=0; ih[i]); // compute multiplication s = _mm_mul_ps(v, h); // parallel addition sum = _mm_add_ps( sum, s ); } // aligned output array float w[4] __attribute__((aligned(16))); #if HAVE_PMMINTRIN_H // fold down into single value __m128 z = _mm_setzero_ps(); sum = _mm_hadd_ps(sum, z); sum = _mm_hadd_ps(sum, z); // unload single (lower value) _mm_store_ss(w, sum); float total = w[0]; #else // unload packed array _mm_store_ps(w, sum); float total = w[0] + w[1] + w[2] + w[3]; #endif // cleanup for (; i<_q->n; i++) total += _x[i] * _q->h[i]; // set return value *_y = total; } // use MMX/SSE extensions, unrolled loop void dotprod_rrrf_execute_mmx4(dotprod_rrrf _q, float * _x, float * _y) { // first cut: ... __m128 v0, v1, v2, v3; __m128 h0, h1, h2, h3; __m128 s0, s1, s2, s3; // load zeros into sum registers __m128 sum0 = _mm_setzero_ps(); __m128 sum1 = _mm_setzero_ps(); __m128 sum2 = _mm_setzero_ps(); __m128 sum3 = _mm_setzero_ps(); // r = 4*floor(n/16) unsigned int r = (_q->n >> 4) << 2; // unsigned int i; for (i=0; ih[4*i+0]); h1 = _mm_load_ps(&_q->h[4*i+4]); h2 = _mm_load_ps(&_q->h[4*i+8]); h3 = _mm_load_ps(&_q->h[4*i+12]); // compute multiplication s0 = _mm_mul_ps(v0, h0); s1 = _mm_mul_ps(v1, h1); s2 = _mm_mul_ps(v2, h2); s3 = _mm_mul_ps(v3, h3); // parallel addition sum0 = _mm_add_ps( sum0, s0 ); sum1 = _mm_add_ps( sum1, s1 ); sum2 = _mm_add_ps( sum2, s2 ); sum3 = _mm_add_ps( sum3, s3 ); } // fold down into single 4-element register sum0 = _mm_add_ps( sum0, sum1 ); sum2 = _mm_add_ps( sum2, sum3 ); sum0 = _mm_add_ps( sum0, sum2); // aligned output array float w[4] __attribute__((aligned(16))); #if HAVE_PMMINTRIN_H // SSE3: fold down to single value using _mm_hadd_ps() __m128 z = _mm_setzero_ps(); sum0 = _mm_hadd_ps(sum0, z); sum0 = _mm_hadd_ps(sum0, z); // unload single (lower value) _mm_store_ss(w, sum0); float total = w[0]; #else // SSE2 and below: unload packed array and perform manual sum _mm_store_ps(w, sum0); float total = w[0] + w[1] + w[2] + w[3]; #endif // cleanup // TODO : use intrinsics here as well for (i=4*r; i<_q->n; i++) total += _x[i] * _q->h[i]; // set return value *_y = total; } liquid-dsp-1.3.1/src/dotprod/src/dotprod_rrrf.neon.c000066400000000000000000000137061317124540100224350ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Floating-point dot product (ARM Neon) // #include #include #include #include #include "liquid.internal.h" // include proper SIMD extensions for ARM Neon #include #define DEBUG_DOTPROD_RRRF_NEON 0 // basic dot product (ordinal calculation) using neon extensions void dotprod_rrrf_run(float * _h, float * _x, unsigned int _n, float * _y) { float32x4_t v; // input vector float32x4_t h; // coefficients vector float32x4_t s; // dot product // load zeros into sum register float zeros[4] = {0,0,0,0}; float32x4_t sum = vld1q_f32(zeros); // t = 4*(floor(_n/4)) unsigned int t = (_n >> 2) << 2; // unsigned int i; for (i=0; i> 4) << 2; // unsigned int i; for (i=0; in = _n; // allocate memory for coefficients q->h = (float*) malloc( q->n*sizeof(float) ); // set coefficients memmove(q->h, _h, _n*sizeof(float)); // return object return q; } // re-create the structured dotprod object dotprod_rrrf dotprod_rrrf_recreate(dotprod_rrrf _q, float * _h, unsigned int _n) { // completely destroy and re-create dotprod object dotprod_rrrf_destroy(_q); return dotprod_rrrf_create(_h,_n); } // destroy dotprod object, freeing internal memory void dotprod_rrrf_destroy(dotprod_rrrf _q) { // free coefficients free(_q->h); // free main object free(_q); } // print dotprod internal state void dotprod_rrrf_print(dotprod_rrrf _q) { printf("dotprod_rrrf [arm-neon, %u coefficients]\n", _q->n); unsigned int i; for (i=0; i<_q->n; i++) printf("%3u : %12.9f\n", i, _q->h[i]); } // execute dot product on input vector void dotprod_rrrf_execute(dotprod_rrrf _q, float * _x, float * _y) { // switch based on size if (_q->n < 16) { dotprod_rrrf_run(_q->h, _x, _q->n, _y); } else { dotprod_rrrf_run4(_q->h, _x, _q->n, _y); } } liquid-dsp-1.3.1/src/dotprod/src/dotprod_rrrf.sse4.c000066400000000000000000000155551317124540100223600ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Floating-point dot product (SSE4.1/2) // #include #include #include #include #include "liquid.internal.h" // include proper SIMD extensions for x86 platforms // NOTE: these pre-processor macros are defined in config.h #if 0 #include // MMX #include // SSE #include // SSE2 #include // SSE3 #endif #include // SSE4.1/2 #define DEBUG_DOTPROD_RRRF_SSE4 0 // internal methods void dotprod_rrrf_execute_sse4(dotprod_rrrf _q, float * _x, float * _y); void dotprod_rrrf_execute_sse4u(dotprod_rrrf _q, float * _x, float * _y); // basic dot product (ordinal calculation) void dotprod_rrrf_run(float * _h, float * _x, unsigned int _n, float * _y) { float r=0; unsigned int i; for (i=0; i<_n; i++) r += _h[i] * _x[i]; *_y = r; } // basic dot product (ordinal calculation) with loop unrolled void dotprod_rrrf_run4(float * _h, float * _x, unsigned int _n, float * _y) { float r=0; // t = 4*(floor(_n/4)) unsigned int t=(_n>>2)<<2; // compute dotprod in groups of 4 unsigned int i; for (i=0; in = _n; // allocate memory for coefficients, 16-byte aligned q->h = (float*) _mm_malloc( q->n*sizeof(float), 16); // set coefficients memmove(q->h, _h, _n*sizeof(float)); // return object return q; } // re-create the structured dotprod object dotprod_rrrf dotprod_rrrf_recreate(dotprod_rrrf _q, float * _h, unsigned int _n) { // completely destroy and re-create dotprod object dotprod_rrrf_destroy(_q); return dotprod_rrrf_create(_h,_n); } void dotprod_rrrf_destroy(dotprod_rrrf _q) { _mm_free(_q->h); free(_q); } void dotprod_rrrf_print(dotprod_rrrf _q) { printf("dotprod_rrrf [sse4.1/4.2, %u coefficients]\n", _q->n); unsigned int i; for (i=0; i<_q->n; i++) printf("%3u : %12.9f\n", i, _q->h[i]); } // void dotprod_rrrf_execute(dotprod_rrrf _q, float * _x, float * _y) { // switch based on size if (_q->n < 16) { dotprod_rrrf_execute_sse4(_q, _x, _y); } else { dotprod_rrrf_execute_sse4u(_q, _x, _y); } } // use MMX/SSE extensions void dotprod_rrrf_execute_sse4(dotprod_rrrf _q, float * _x, float * _y) { __m128 v; // input vector __m128 h; // coefficients vector __m128 s; // dot product __m128 sum = _mm_setzero_ps(); // load zeros into sum register // t = 4*(floor(_n/4)) unsigned int t = (_q->n >> 2) << 2; // unsigned int i; for (i=0; ih[i]); // compute dot product s = _mm_dp_ps(v, h, 0xffffffff); // parallel addition sum = _mm_add_ps( sum, s ); } // aligned output array float w[4] __attribute__((aligned(16))); // unload packed array _mm_store_ps(w, sum); float total = w[0]; // cleanup for (; i<_q->n; i++) total += _x[i] * _q->h[i]; // set return value *_y = total; } // use MMX/SSE extensions (unrolled) void dotprod_rrrf_execute_sse4u(dotprod_rrrf _q, float * _x, float * _y) { __m128 v0, v1, v2, v3; __m128 h0, h1, h2, h3; __m128 s0, s1, s2, s3; __m128 sum = _mm_setzero_ps(); // load zeros into sum register // t = 4*(floor(_n/16)) unsigned int r = (_q->n >> 4) << 2; // unsigned int i; for (i=0; ih[4*i+ 0]); h1 = _mm_load_ps(&_q->h[4*i+ 4]); h2 = _mm_load_ps(&_q->h[4*i+ 8]); h3 = _mm_load_ps(&_q->h[4*i+12]); // compute dot products s0 = _mm_dp_ps(v0, h0, 0xffffffff); s1 = _mm_dp_ps(v1, h1, 0xffffffff); s2 = _mm_dp_ps(v2, h2, 0xffffffff); s3 = _mm_dp_ps(v3, h3, 0xffffffff); // parallel addition // FIXME: these additions are by far the limiting factor sum = _mm_add_ps( sum, s0 ); sum = _mm_add_ps( sum, s1 ); sum = _mm_add_ps( sum, s2 ); sum = _mm_add_ps( sum, s3 ); } // aligned output array float w[4] __attribute__((aligned(16))); // unload packed array _mm_store_ps(w, sum); float total = w[0]; // cleanup for (i=4*r; i<_q->n; i++) total += _x[i] * _q->h[i]; // set return value *_y = total; } liquid-dsp-1.3.1/src/dotprod/src/sumsq.c000066400000000000000000000042461317124540100201400ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // sumsq.c : sum of squares // #include #include #include #include "liquid.internal.h" // sum squares, basic loop // _v : input array [size: 1 x _n] // _n : input length float liquid_sumsqf(float * _v, unsigned int _n) { // initialize accumulator float r=0; // t = 4*(floor(_n/4)) unsigned int t=(_n>>2)<<2; // run computation in groups of 4 unsigned int i; for (i=0; i #include #include #include "liquid.internal.h" // include proper SIMD extensions for x86 platforms // NOTE: these pre-processor macros are defined in config.h #if HAVE_MMINTRIN_H #include // MMX #endif #if HAVE_XMMINTRIN_H #include // SSE #endif #if HAVE_EMMINTRIN_H #include // SSE2 #endif #if HAVE_PMMINTRIN_H #include // SSE3 #endif // sum squares, basic loop // _v : input array [size: 1 x _n] // _n : input length float liquid_sumsqf(float * _v, unsigned int _n) { // first cut: ... __m128 v; // input vector __m128 s; // dot product __m128 sum = _mm_setzero_ps(); // load zeros into sum register // t = 4*(floor(_n/4)) unsigned int t = (_n >> 2) << 2; // unsigned int i; for (i=0; i #include "autotest/autotest.h" #include "liquid.internal.h" // // AUTOTEST: basic dot product // void autotest_dotprod_rrrf_basic() { float tol = 1e-6; // error tolerance float y; // return value float h[16] = { 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1}; float x0[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; float test0 = 0; dotprod_rrrf_run(h,x0,16,&y); CONTEND_DELTA(y, test0, tol); dotprod_rrrf_run4(h,x0,16,&y); CONTEND_DELTA(y, test0, tol); float x1[16] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; float test1 = 0; dotprod_rrrf_run(h,x1,16,&y); CONTEND_DELTA(y, test1, tol); dotprod_rrrf_run4(h,x1,16,&y); CONTEND_DELTA(y, test1, tol); float x2[16] = {0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1}; float test2 = -8; dotprod_rrrf_run(h,x2,16,&y); CONTEND_DELTA(y, test2, tol); dotprod_rrrf_run4(h,x2,16,&y); CONTEND_DELTA(y, test2, tol); float x3[16] = {1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0}; float test3 = 8; dotprod_rrrf_run(h,x3,16,&y); CONTEND_DELTA(y, test3, tol); dotprod_rrrf_run4(h,x3,16,&y); CONTEND_DELTA(y, test3, tol); float test4 = 16; dotprod_rrrf_run(h,h,16,&y); CONTEND_DELTA(y, test4, tol); dotprod_rrrf_run4(h,h,16,&y); CONTEND_DELTA(y, test4, tol); } // // AUTOTEST: uneven dot product // void autotest_dotprod_rrrf_uneven() { float tol = 1e-6; float y; float h[16] = { 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1}; float x[16] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; float test1 = 1; dotprod_rrrf_run(h,x,1,&y); CONTEND_DELTA(y, test1, tol); float test2 = 0; dotprod_rrrf_run(h,x,2,&y); CONTEND_DELTA(y, test2, tol); float test3 = 1; dotprod_rrrf_run(h,x,3,&y); CONTEND_DELTA(y, test3, tol); float test11 = 1; dotprod_rrrf_run(h,x,11,&y); CONTEND_DELTA(y, test11, tol); float test13 = 1; dotprod_rrrf_run(h,x,13,&y); CONTEND_DELTA(y, test13, tol); float test15 = 1; dotprod_rrrf_run(h,x,15,&y); CONTEND_DELTA(y, test15, tol); } // // AUTOTEST: structured dot product // void autotest_dotprod_rrrf_struct() { float tol = 1e-6; float y; float h[16] = { 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1}; // create object dotprod_rrrf dp = dotprod_rrrf_create(h,16); float x0[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; float test0 = 0; dotprod_rrrf_execute(dp,x0,&y); CONTEND_DELTA(y, test0, tol); float x1[16] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; float test1 = 0; dotprod_rrrf_execute(dp,x1,&y); CONTEND_DELTA(y, test1, tol); float x2[16] = {0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1}; float test2 = -8; dotprod_rrrf_execute(dp,x2,&y); CONTEND_DELTA(y, test2, tol); float *x3 = h; float test3 = 16; dotprod_rrrf_execute(dp,x3,&y); CONTEND_DELTA(y, test3, tol); // clean-up dotprod_rrrf_destroy(dp); } // // AUTOTEST: structured dot product with floating-point data // void autotest_dotprod_rrrf_struct_align() { float h[16] = { -0.050565, -0.952580, 0.274320, 1.232400, 1.268200, 0.565770, 0.800830, 0.923970, 0.517060, -0.530340, -0.378550, -1.127100, 1.123100, -1.006000, -1.483800, -0.062007 }; float x[16] = { -0.384280, -0.812030, 0.156930, 1.919500, 0.564580, -0.123610, -0.138640, 0.004984, -1.100200, -0.497620, 0.089977, -1.745500, 0.463640, 0.592100, 1.150000, -1.225400 }; float test = 3.66411513609863; float tol = 1e-3f; float y; // create dotprod object dotprod_rrrf dp = dotprod_rrrf_create(h,16); // test data mis-alignment conditions float x_buffer[20]; float * x_hat; unsigned int i; for (i=0; i<4; i++) { // set pointer to array aligned with counter x_hat = &x_buffer[i]; // copy input data to buffer memmove(x_hat, x, 16*sizeof(float)); // execute dotprod dotprod_rrrf_execute(dp,x_hat,&y); CONTEND_DELTA(y,test,tol); } // destroy dotprod object dotprod_rrrf_destroy(dp); } // // AUTOTEST: dot product with floating-point data // void autotest_dotprod_rrrf_rand01() { float h[16] = { -0.050565, -0.952580, 0.274320, 1.232400, 1.268200, 0.565770, 0.800830, 0.923970, 0.517060, -0.530340, -0.378550, -1.127100, 1.123100, -1.006000, -1.483800, -0.062007 }; float x[16] = { -0.384280, -0.812030, 0.156930, 1.919500, 0.564580, -0.123610, -0.138640, 0.004984, -1.100200, -0.497620, 0.089977, -1.745500, 0.463640, 0.592100, 1.150000, -1.225400 }; float test = 3.66411513609863; float tol = 1e-3f; float y; dotprod_rrrf_run(h,x,16,&y); CONTEND_DELTA(y,test,tol); } // // AUTOTEST: dot product with floating-point data // void autotest_dotprod_rrrf_rand02() { float h[16] = { 2.595300, 1.243600, -0.818550, -1.439800, 0.055795, -1.476000, 0.445900, 0.325460, -3.451200, 0.058528, -0.246990, 0.476290, -0.598780, -0.885250, 0.464660, -0.610140 }; float x[16] = { -0.917010, -1.278200, -0.533190, 2.309200, 0.592980, 0.964820, 0.183220, -0.082864, 0.057171, -1.186500, -0.738260, 0.356960, -0.144000, -1.435200, -0.893420, 1.657800 }; float test = -8.17832326680587; float tol = 1e-3f; float y; dotprod_rrrf_run(h,x,16,&y); CONTEND_DELTA(y,test,tol); } // // AUTOTEST: structured dot product, odd lengths // void autotest_dotprod_rrrf_struct_lengths() { float tol = 2e-6; float y; float x[35] = { 0.03117498, -1.54311769, -0.58759073, -0.73882202, 0.86592259, -0.26669417, -0.70153724, -1.24555787, -1.09272288, -1.41984975, -1.40299260, 0.95861481, -0.67361246, 2.05305710, 1.26576873, -0.77474848, -0.93143252, -1.05724660, 0.21455006, 1.07554168, -0.46703810, 0.68878404, -1.11900266, -0.52016966, 0.61400744, -0.46506142, -0.16801031, 0.48237303, 0.51286055, -0.57239385, -0.64462740, -0.75596668, 1.95612355, -0.47917908, 0.52384983, }; float h[35] = { -0.12380948, 0.88417134, 2.27373797, -2.61506417, 0.35022002, 0.07481393, 0.52984228, -0.65542307, -2.14893606, 0.62466395, 0.07330391, -1.28014856, 0.16347776, 0.21238151, 0.05462232, -0.60290942, -1.27658956, 3.05114996, 1.34789601, -1.22098592, 1.70899633, -0.41002037, 3.08009931, -1.39895771, -0.50875066, 0.25817865, 1.08668549, 0.05494174, -1.05337166, 1.26772604, 1.00369204, -0.55129338, 1.01828299, 0.76014664, -0.15605569, }; float v32 = -7.99577847f; float v33 = -6.00389114f; float v34 = -6.36813751f; float v35 = -6.44988725f; // dotprod_rrrf dp; // n = 32 dp = dotprod_rrrf_create(h,32); dotprod_rrrf_execute(dp, x, &y); CONTEND_DELTA(y, v32, tol); dotprod_rrrf_destroy(dp); if (liquid_autotest_verbose) printf(" dotprod-rrrf-32 : %12.8f (expected %12.8f)\n", y, v32); // n = 33 dp = dotprod_rrrf_create(h,33); dotprod_rrrf_execute(dp, x, &y); CONTEND_DELTA(y, v33, tol); dotprod_rrrf_destroy(dp); if (liquid_autotest_verbose) printf(" dotprod-rrrf-33 : %12.8f (expected %12.8f)\n", y, v33); // n = 34 dp = dotprod_rrrf_create(h,34); dotprod_rrrf_execute(dp, x, &y); CONTEND_DELTA(y, v34, tol); dotprod_rrrf_destroy(dp); if (liquid_autotest_verbose) printf(" dotprod-rrrf-34 : %12.8f (expected %12.8f)\n", y, v34); // n = 35 dp = dotprod_rrrf_create(h,35); dotprod_rrrf_execute(dp, x, &y); CONTEND_DELTA(y, v35, tol); dotprod_rrrf_destroy(dp); if (liquid_autotest_verbose) printf(" dotprod-rrrf-35 : %12.8f (expected %12.8f)\n", y, v35); } // // AUTOTEST: compare structured result to oridinal computation // // helper function (compare structured object to ordinal computation) void runtest_dotprod_rrrf(unsigned int _n) { float tol = 1e-4; float h[_n]; float x[_n]; // generate random coefficients unsigned int i; for (i=0; i<_n; i++) { h[i] = randnf(); x[i] = randnf(); } // compute expected value (ordinal computation) float y_test=0; for (i=0; i<_n; i++) y_test += h[i] * x[i]; // create and run dot product object float y; dotprod_rrrf dp; dp = dotprod_rrrf_create(h,_n); dotprod_rrrf_execute(dp, x, &y); dotprod_rrrf_destroy(dp); // print results if (liquid_autotest_verbose) printf(" dotprod-rrrf-%-4u : %12.8f (expected %12.8f)\n", _n, y, y_test); // validate result CONTEND_DELTA(y, y_test, tol); } // compare structured object to ordinal computation void autotest_dotprod_rrrf_struct_vs_ordinal() { // run many, many tests unsigned int i; for (i=1; i<=512; i++) runtest_dotprod_rrrf(i); } liquid-dsp-1.3.1/src/dotprod/tests/sumsqcf_autotest.c000066400000000000000000000126641317124540100227570ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.internal.h" // test data float complex sumsqcf_test_x3[3]; float sumsqcf_test_y3; float complex sumsqcf_test_x4[4]; float sumsqcf_test_y4; float complex sumsqcf_test_x7[7]; float sumsqcf_test_y7; float complex sumsqcf_test_x8[8]; float sumsqcf_test_y8; float complex sumsqcf_test_x15[15]; float sumsqcf_test_y15; float complex sumsqcf_test_x16[16]; float sumsqcf_test_y16; // helper function void sumsqcf_runtest(float complex * _x, unsigned int _n, float _y) { float tol = 1e-6; // error tolerance // run test float y = liquid_sumsqcf(_x, _n); CONTEND_DELTA( y, _y, tol ); } // // AUTOTESTS : run test with pre-determined data sets // void autotest_sumsqcf_3() { sumsqcf_runtest( sumsqcf_test_x3, 3, sumsqcf_test_y3 ); } void autotest_sumsqcf_4() { sumsqcf_runtest( sumsqcf_test_x4, 4, sumsqcf_test_y4 ); } void autotest_sumsqcf_7() { sumsqcf_runtest( sumsqcf_test_x7, 7, sumsqcf_test_y7 ); } void autotest_sumsqcf_8() { sumsqcf_runtest( sumsqcf_test_x8, 8, sumsqcf_test_y8 ); } void autotest_sumsqcf_15() { sumsqcf_runtest( sumsqcf_test_x15, 15, sumsqcf_test_y15 ); } void autotest_sumsqcf_16() { sumsqcf_runtest( sumsqcf_test_x16, 16, sumsqcf_test_y16 ); } float complex sumsqcf_test_x3[3] = { -0.143606511525 + -0.137405158308*_Complex_I, -0.155077565599 + -0.128712786230*_Complex_I, 0.259257309730 + -0.354313982924*_Complex_I}; float sumsqcf_test_y3 = 0.272871791516851; float complex sumsqcf_test_x4[4] = { -0.027688113439 + 0.014257850202*_Complex_I, 0.135913101830 + -0.193497844930*_Complex_I, -0.184688262513 + -0.018367564232*_Complex_I, 0.033677897260 + -0.365996497668*_Complex_I}; float sumsqcf_test_y4 = 0.226418463954813; float complex sumsqcf_test_x7[7] = { -0.052790293375 + 0.173778162166*_Complex_I, 0.026113336498 + -0.228399854303*_Complex_I, 0.060259677552 + -0.064704230326*_Complex_I, -0.085637350173 + -0.140391580928*_Complex_I, 0.137662823620 + -0.049602389650*_Complex_I, 0.081078554377 + 0.103320097893*_Complex_I, -0.140068020211 + -0.028552894932*_Complex_I}; float sumsqcf_test_y7 = 0.179790025178960; float complex sumsqcf_test_x8[8] = { -0.114842287937 + -0.044108491804*_Complex_I, -0.027032488500 + -0.098073597323*_Complex_I, -0.248865158871 + -0.058431293594*_Complex_I, 0.152349654138 + 0.011146740847*_Complex_I, 0.100890388238 + 0.037191727983*_Complex_I, -0.173317554621 + -0.287191794305*_Complex_I, 0.159045702603 + -0.097006888823*_Complex_I, -0.048463564653 + -0.123659611524*_Complex_I}; float sumsqcf_test_y8 = 0.290592731534459; float complex sumsqcf_test_x15[15] = { -0.233166865552 + -0.325575589001*_Complex_I, -0.062157314569 + -0.052675113778*_Complex_I, -0.184924733094 + -0.037448582846*_Complex_I, -0.019336799407 + -0.146627815330*_Complex_I, 0.014671587594 + -0.040490423681*_Complex_I, -0.070920638099 + 0.353056761369*_Complex_I, 0.342121380549 + 0.016365636789*_Complex_I, 0.407809024847 + -0.067677610212*_Complex_I, 0.166345037028 + -0.070618449000*_Complex_I, -0.151572833379 + -0.241061531174*_Complex_I, -0.295395183108 + 0.107933512849*_Complex_I, 0.214887288420 + 0.158211288996*_Complex_I, 0.089528110626 + 0.534731503540*_Complex_I, -0.387245894254 + 0.127860010582*_Complex_I, -0.123711595377 + 0.212526707755*_Complex_I}; float sumsqcf_test_y15 = 1.44880523546855; float complex sumsqcf_test_x16[16] = { -0.065168142317 + 0.069453199546*_Complex_I, 0.175268433034 + -0.227486860237*_Complex_I, -0.190532229460 + 0.079975095234*_Complex_I, 0.119309235855 + -0.238114343006*_Complex_I, 0.125737810036 + 0.045214179459*_Complex_I, -0.197170380197 + -0.159688600627*_Complex_I, 0.075166226059 + 0.148949236785*_Complex_I, -0.290229918639 + 0.019293769432*_Complex_I, -0.145299853755 + -0.083512058709*_Complex_I, -0.256618190275 + -0.450932031739*_Complex_I, -0.169487127499 + 0.187004249967*_Complex_I, 0.203885942759 + 0.121347578873*_Complex_I, -0.176280563451 + -0.304717971490*_Complex_I, 0.240587060249 + -0.055540407201*_Complex_I, 0.022889112723 + 0.027170265053*_Complex_I, 0.265769617236 + -0.023686695049*_Complex_I}; float sumsqcf_test_y16 = 1.07446555417927; liquid-dsp-1.3.1/src/dotprod/tests/sumsqf_autotest.c000066400000000000000000000077531317124540100226170ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.internal.h" // test data float sumsqf_test_x3[3]; float sumsqf_test_y3; float sumsqf_test_x4[4]; float sumsqf_test_y4; float sumsqf_test_x7[7]; float sumsqf_test_y7; float sumsqf_test_x8[8]; float sumsqf_test_y8; float sumsqf_test_x15[15]; float sumsqf_test_y15; float sumsqf_test_x16[16]; float sumsqf_test_y16; // helper function void sumsqf_runtest(float * _x, unsigned int _n, float _y) { float tol = 1e-6; // error tolerance // run test float y = liquid_sumsqf(_x, _n); CONTEND_DELTA( y, _y, tol ); } // // AUTOTESTS : run test with pre-determined data sets // void autotest_sumsqf_3() { sumsqf_runtest( sumsqf_test_x3, 3, sumsqf_test_y3 ); } void autotest_sumsqf_4() { sumsqf_runtest( sumsqf_test_x4, 4, sumsqf_test_y4 ); } void autotest_sumsqf_7() { sumsqf_runtest( sumsqf_test_x7, 7, sumsqf_test_y7 ); } void autotest_sumsqf_8() { sumsqf_runtest( sumsqf_test_x8, 8, sumsqf_test_y8 ); } void autotest_sumsqf_15() { sumsqf_runtest( sumsqf_test_x15, 15, sumsqf_test_y15 ); } void autotest_sumsqf_16() { sumsqf_runtest( sumsqf_test_x16, 16, sumsqf_test_y16 ); } float sumsqf_test_x3[3] = { -0.4546496371984978f, 0.4451201395218938f, 0.0138788690209525f}; float sumsqf_test_y3 = 0.405030854218017; float sumsqf_test_x4[4] = { 0.1322698385026883f, -0.0569081631536912f, -0.3244384492417431f, -0.2872733941910143f}; float sumsqf_test_y4 = 0.208520159567467; float sumsqf_test_x7[7] = { -0.221079351597278f, -0.227902662215897f, 0.382941891419158f, 0.246800053933030f, -0.190152017725480f, 0.395758452636014f, 0.211220685416265f}; float sumsqf_test_y7 = 0.545767182598435; float sumsqf_test_x8[8] = { -0.3405090291337944f, 0.5568858414046379f, -0.0870643704340343f, 0.1724369367547939f, -0.7379946538182081f, -0.3514326419380984f, 0.2782541955998314f, 0.4354875172406391f}; float sumsqf_test_y8 = 1.39859872696022; float sumsqf_test_x15[15] = { -0.4630291295549499f, -0.2776019612369674f, -0.4933486186123937f, -0.0850997992116534f, 0.0117036410972943f, 0.0215560948199280f, 0.1203298759952301f, 0.5866344749815807f, 0.3791165816771581f, -0.4070288299889871f, -0.4971431800502791f, -0.2142770391709351f, 0.3330589842198580f, -0.0150675851612766f, -0.3947266044391958f}; float sumsqf_test_y15 = 1.77074683901981f; float sumsqf_test_x16[16] = { -0.2975264216819841f, 0.5642827287388987f, -0.7956166087428503f, -0.1931368701566655f, -0.0287212417958668f, 0.3697266870899014f, 0.0791822603183984f, 0.1668276194302965f, 0.2048176237333448f, -0.0617609549162579f, 0.5317006403634014f, -0.3964290790294236f, 0.5404940967800361f, 0.1755457122664283f, 0.1585602895144933f, 0.0791731424937176f}; float sumsqf_test_y16 = 2.08885480396333f; liquid-dsp-1.3.1/src/equalization/000077500000000000000000000000001317124540100170615ustar00rootroot00000000000000liquid-dsp-1.3.1/src/equalization/bench/000077500000000000000000000000001317124540100201405ustar00rootroot00000000000000liquid-dsp-1.3.1/src/equalization/bench/eqlms_cccf_benchmark.c000066400000000000000000000061331317124540100244200ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "liquid.h" #define EQLMS_CCCF_TRAIN_BENCH_API(N) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { eqlms_cccf_train_bench(_start, _finish, _num_iterations, N); } // Helper function to keep code base small void eqlms_cccf_train_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _h_len) { // scale number of iterations appropriately // log(cycles/trial) ~ 5.63 + 0.767*log(_h_len) *_num_iterations *= 3200; *_num_iterations /= (unsigned int) expf(5.63f + 0.767f*logf(_h_len)); *_num_iterations = (*_num_iterations < 4) ? 4 : *_num_iterations; eqlms_cccf eq = eqlms_cccf_create(NULL,_h_len); unsigned long int i; // set up initial arrays to 'randomize' inputs/outputs float complex y[11]; for (i=0; i<11; i++) y[i] = randnf() + _Complex_I*randnf(); float complex d[13]; for (i=0; i<13; i++) d[i] = randnf() + _Complex_I*randnf(); unsigned int iy=0; unsigned int id=0; float complex z; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { eqlms_cccf_push(eq, y[iy]); // push input into equalizer eqlms_cccf_execute(eq, &z); // compute equalizer output eqlms_cccf_step(eq, d[id], z); // step equalizer internals // update counters iy = (iy+1)%11; id = (id+1)%13; } getrusage(RUSAGE_SELF, _finish); eqlms_cccf_destroy(eq); } // void benchmark_eqlms_cccf_n4 EQLMS_CCCF_TRAIN_BENCH_API(4) void benchmark_eqlms_cccf_n8 EQLMS_CCCF_TRAIN_BENCH_API(8) void benchmark_eqlms_cccf_n16 EQLMS_CCCF_TRAIN_BENCH_API(16) void benchmark_eqlms_cccf_n32 EQLMS_CCCF_TRAIN_BENCH_API(32) void benchmark_eqlms_cccf_n64 EQLMS_CCCF_TRAIN_BENCH_API(64) liquid-dsp-1.3.1/src/equalization/bench/eqrls_cccf_benchmark.c000066400000000000000000000061311317124540100244230ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "liquid.h" #define EQRLS_CCCF_TRAIN_BENCH_API(N) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { eqrls_cccf_train_bench(_start, _finish, _num_iterations, N); } // Helper function to keep code base small void eqrls_cccf_train_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _h_len) { // scale number of iterations appropriately // log(cycles/trial) ~ 5.57 + 2.74*log(_h_len) *_num_iterations *= 2400; *_num_iterations /= (unsigned int) expf(5.57f + 2.64f*logf(_h_len)); *_num_iterations = (*_num_iterations < 4) ? 4 : *_num_iterations; eqrls_cccf eq = eqrls_cccf_create(NULL,_h_len); unsigned long int i; // set up initial arrays to 'randomize' inputs/outputs float complex y[11]; for (i=0; i<11; i++) y[i] = randnf() + _Complex_I*randnf(); float complex d[13]; for (i=0; i<13; i++) d[i] = randnf() + _Complex_I*randnf(); unsigned int iy=0; unsigned int id=0; float complex z; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { eqrls_cccf_push(eq, y[iy]); // push input into equalizer eqrls_cccf_execute(eq, &z); // compute equalizer output eqrls_cccf_step(eq, d[id], z); // step equalizer internals // update counters iy = (iy+1)%11; id = (id+1)%13; } getrusage(RUSAGE_SELF, _finish); eqrls_cccf_destroy(eq); } // void benchmark_eqrls_cccf_n4 EQRLS_CCCF_TRAIN_BENCH_API(4) void benchmark_eqrls_cccf_n8 EQRLS_CCCF_TRAIN_BENCH_API(8) void benchmark_eqrls_cccf_n16 EQRLS_CCCF_TRAIN_BENCH_API(16) void benchmark_eqrls_cccf_n32 EQRLS_CCCF_TRAIN_BENCH_API(32) void benchmark_eqrls_cccf_n64 EQRLS_CCCF_TRAIN_BENCH_API(64) liquid-dsp-1.3.1/src/equalization/src/000077500000000000000000000000001317124540100176505ustar00rootroot00000000000000liquid-dsp-1.3.1/src/equalization/src/eqlms.c000066400000000000000000000320021317124540100211320ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Least mean-squares (LMS) equalizer // #include #include #include #include //#define DEBUG struct EQLMS(_s) { unsigned int h_len; // filter length float mu; // LMS step size // internal matrices T * h0; // initial coefficients T * w0; // weights [px1] T * w1; // weights [px1] unsigned int count; // input sample count int buf_full; // input buffer full flag WINDOW() buffer; // input buffer wdelayf x2; // buffer of |x|^2 values float x2_sum; // sum{ |x|^2 } }; // update sum{|x|^2} void EQLMS(_update_sumsq)(EQLMS() _q, T _x); // create least mean-squares (LMS) equalizer object // _h : initial coefficients [size: _h_len x 1], default if NULL // _p : equalizer length (number of taps) EQLMS() EQLMS(_create)(T * _h, unsigned int _h_len) { EQLMS() q = (EQLMS()) malloc(sizeof(struct EQLMS(_s))); // set filter order, other params q->h_len = _h_len; q->mu = 0.5f; q->h0 = (T*) malloc((q->h_len)*sizeof(T)); q->w0 = (T*) malloc((q->h_len)*sizeof(T)); q->w1 = (T*) malloc((q->h_len)*sizeof(T)); q->buffer = WINDOW(_create)(q->h_len); q->x2 = wdelayf_create(q->h_len); // copy coefficients (if not NULL) if (_h == NULL) { // initial coefficients with delta at first index unsigned int i; for (i=0; ih_len; i++) q->h0[i] = (i==0) ? 1.0 : 0.0; } else { // copy user-defined initial coefficients memmove(q->h0, _h, (q->h_len)*sizeof(T)); } // reset equalizer object EQLMS(_reset)(q); // return main object return q; } // create square-root Nyquist interpolator // _type : filter type (e.g. LIQUID_RNYQUIST_RRC) // _k : samples/symbol _k > 1 // _m : filter delay (symbols), _m > 0 // _beta : excess bandwidth factor, 0 < _beta < 1 // _dt : fractional sample delay, 0 <= _dt < 1 EQLMS() EQLMS(_create_rnyquist)(int _type, unsigned int _k, unsigned int _m, float _beta, float _dt) { // validate input if (_k < 2) { fprintf(stderr,"error: eqlms_%s_create_rnyquist(), samples/symbol must be greater than 1\n", EXTENSION_FULL); exit(1); } else if (_m == 0) { fprintf(stderr,"error: eqlms_%s_create_rnyquist(), filter delay must be greater than 0\n", EXTENSION_FULL); exit(1); } else if (_beta < 0.0f || _beta > 1.0f) { fprintf(stderr,"error: eqlms_%s_create_rnyquist(), filter excess bandwidth factor must be in [0,1]\n", EXTENSION_FULL); exit(1); } else if (_dt < -1.0f || _dt > 1.0f) { fprintf(stderr,"error: eqlms_%s_create_rnyquist(), filter fractional sample delay must be in [-1,1]\n", EXTENSION_FULL); exit(1); } // generate square-root Nyquist filter unsigned int h_len = 2*_k*_m + 1; float h[h_len]; liquid_firdes_prototype(_type,_k,_m,_beta,_dt,h); // copy coefficients to type-specific array (e.g. float complex) // and scale by samples/symbol unsigned int i; T hc[h_len]; for (i=0; i 0.5f) { fprintf(stderr,"error: eqlms_%s_create_rnyquist(), filter cutoff must be in (0,0.5]\n", EXTENSION_FULL); exit(1); } // generate low-pass filter prototype float h[_h_len]; liquid_firdes_kaiser(_h_len, _fc, 40.0f, 0.0f, h); // copy coefficients to type-specific array (e.g. float complex) unsigned int i; T hc[_h_len]; for (i=0; i<_h_len; i++) hc[i] = h[i]; // return equalizer object return EQLMS(_create)(hc, _h_len); } // re-create least mean-squares (LMS) equalizer object // _q : old equalizer object // _h : initial coefficients [size: _p x 1], default if NULL // _p : equalizer length (number of taps) EQLMS() EQLMS(_recreate)(EQLMS() _q, T * _h, unsigned int _p) { if (_q->h_len == _p) { // length hasn't changed; copy default coefficients // and return object unsigned int i; for (i=0; i<_q->h_len; i++) _q->h0[i] = _h[i]; return _q; } // completely destroy old equalizer object EQLMS(_destroy)(_q); // create new one and return return EQLMS(_create)(_h,_p); } // destroy eqlms object void EQLMS(_destroy)(EQLMS() _q) { free(_q->h0); free(_q->w0); free(_q->w1); WINDOW(_destroy)(_q->buffer); wdelayf_destroy(_q->x2); free(_q); } // reset equalizer void EQLMS(_reset)(EQLMS() _q) { // copy default coefficients memmove(_q->w0, _q->h0, (_q->h_len)*sizeof(T)); WINDOW(_reset)(_q->buffer); wdelayf_reset(_q->x2); // reset input count _q->count = 0; _q->buf_full = 0; // reset squared magnitude sum _q->x2_sum = 0; } // print eqlms object internals void EQLMS(_print)(EQLMS() _q) { printf("equalizer (LMS):\n"); printf(" order: %u\n", _q->h_len); unsigned int i; for (i=0; i<_q->h_len; i++) printf(" h(%3u) = %12.4e + j*%12.4e;\n", i+1, creal(_q->w0[i]), cimag(_q->w0[i])); } // get learning rate of equalizer float EQLMS(_get_bw)(EQLMS() _q) { return _q->mu; } // set learning rate of equalizer // _q : equalizer object // _mu : LMS learning rate (should be near 0), 0 < _mu < 1 void EQLMS(_set_bw)(EQLMS() _q, float _mu) { if (_mu < 0.0f) { fprintf(stderr,"error: eqlms_%s_set_bw(), learning rate cannot be less than zero\n", EXTENSION_FULL); exit(1); } _q->mu = _mu; } // push sample into equalizer internal buffer // _q : equalizer object // _x : received sample void EQLMS(_push)(EQLMS() _q, T _x) { // push value into buffer WINDOW(_push)(_q->buffer, _x); // update sum{|x|^2} EQLMS(_update_sumsq)(_q, _x); // increment count _q->count++; } // push sample into equalizer internal buffer as block // _q : equalizer object // _x : input sample array // _n : input sample array length void EQLMS(_push_block)(EQLMS() _q, T * _x, unsigned int _n) { unsigned int i; for (i=0; i<_n; i++) EQLMS(_push)(_q, _x[i]); } // execute internal dot product // _q : equalizer object // _y : output sample void EQLMS(_execute)(EQLMS() _q, T * _y) { T y = 0; // temporary accumulator T * r; // read buffer WINDOW(_read)(_q->buffer, &r); // compute conjugate vector dot product //DOTPROD(_run)(_q->w0, r, _q->h_len, &y); unsigned int i; for (i=0; i<_q->h_len; i++) { T sum = conj(_q->w0[i])*r[i]; y += sum; } // set output *_y = y; } // execute equalizer with block of samples using constant // modulus algorithm, operating on a decimation rate of _k // samples. // _q : equalizer object // _k : down-sampling rate // _x : input sample array [size: _n x 1] // _n : input sample array length // _y : output sample array [size: _n x 1] void EQLMS(_execute_block)(EQLMS() _q, unsigned int _k, T * _x, unsigned int _n, T * _y) { if (_k == 0) { fprintf(stderr,"error: eqlms_%s_execute_block(), down-sampling rate 'k' must be greater than 0\n", EXTENSION_FULL); exit(-1); } unsigned int i; T d_hat; for (i=0; i<_n; i++) { // push input sample EQLMS(_push)(_q, _x[i]); // compute output sample EQLMS(_execute)(_q, &d_hat); // store result in output _y[i] = d_hat; // decimate by _k if ( ((_q->count+_k-1) % _k) == 0 ) { // update equalizer independent of the signal: estimate error // assuming constant modulus signal EQLMS(_step_blind)(_q, d_hat); } } } // step through one cycle of equalizer training // _q : equalizer object // _d : desired output // _d_hat : filtered output void EQLMS(_step)(EQLMS() _q, T _d, T _d_hat) { // check count; only run step when buffer is full if (!_q->buf_full) { if (_q->count < _q->h_len) return; else _q->buf_full = 1; } unsigned int i; // compute error (a priori) T alpha = _d - _d_hat; // read buffer T * r; // read buffer WINDOW(_read)(_q->buffer, &r); // update weighting vector // w[n+1] = w[n] + mu*conj(d-d_hat)*x[n]/(x[n]' * conj(x[n])) for (i=0; i<_q->h_len; i++) _q->w1[i] = _q->w0[i] + (_q->mu)*conj(alpha)*r[i]/_q->x2_sum; #ifdef DEBUG printf("w0: \n"); for (i=0; i<_q->h_len; i++) { PRINTVAL(_q->w0[i]); printf("\n"); } printf("w1: \n"); for (i=0; i<_q->h_len; i++) { PRINTVAL(_q->w1[i]); printf("\n"); } #endif // copy old values memmove(_q->w0, _q->w1, _q->h_len*sizeof(T)); } // step through one cycle of equalizer training // _q : equalizer object // _d_hat : filtered output void EQLMS(_step_blind)(EQLMS() _q, T _d_hat) { // update equalizer using constant modulus method #if T_COMPLEX T d = _d_hat / cabsf(_d_hat); #else T d = _d_hat > 0 ? 1 : -1; #endif EQLMS(_step)(_q, d, _d_hat); } // retrieve internal filter coefficients void EQLMS(_get_weights)(EQLMS() _q, T * _w) { // copy output weight vector unsigned int i; for (i=0; i<_q->h_len; i++) _w[i] = conj(_q->w0[_q->h_len-i-1]); } // train equalizer object // _q : equalizer object // _w : initial weights / output weights // _x : received sample vector // _d : desired output vector // _n : vector length void EQLMS(_train)(EQLMS() _q, T * _w, T * _x, T * _d, unsigned int _n) { unsigned int p=_q->h_len; if (_n < _q->h_len) { fprintf(stderr,"warning: eqlms_%s_train(), traning sequence less than filter order\n", EXTENSION_FULL); } unsigned int i; // reset equalizer state EQLMS(_reset)(_q); // copy initial weights into buffer for (i=0; iw0[i] = _w[p - i - 1]; T d_hat; for (i=0; i<_n; i++) { // push sample into internal buffer EQLMS(_push)(_q, _x[i]); // execute vector dot product EQLMS(_execute)(_q, &d_hat); // step through training cycle EQLMS(_step)(_q, _d[i], d_hat); } // copy output weight vector EQLMS(_get_weights)(_q, _w); } // // internal methods // // update sum{|x|^2} void EQLMS(_update_sumsq)(EQLMS() _q, T _x) { // update estimate of signal magnitude squared // |x[n-1]|^2 (input sample) float x2_n = crealf(_x * conjf(_x)); // |x[0] |^2 (oldest sample) float x2_0; // read oldest sample wdelayf_read(_q->x2, &x2_0); // push newest sample wdelayf_push(_q->x2, x2_n); // update sum( |x|^2 ) of last 'n' input samples _q->x2_sum = _q->x2_sum + x2_n - x2_0; } liquid-dsp-1.3.1/src/equalization/src/eqrls.c000066400000000000000000000245451317124540100211540ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Recursive least-squares (RLS) equalizer // #include #include #include //#define DEBUG struct EQRLS(_s) { unsigned int p; // filter order float lambda; // RLS forgetting factor float delta; // RLS initialization factor // internal matrices T * h0; // initial coefficients T * w0, * w1; // weights [px1] T * P0, * P1; // recursion matrix [pxp] T * g; // gain vector [px1] // temporary matrices T * xP0; // [1xp] T zeta; // constant T * gxl; // [pxp] T * gxlP0; // [pxp] unsigned int n; // input counter WINDOW() buffer; // input buffer }; // create recursive least-squares (RLS) equalizer object // _h : initial coefficients [size: _p x 1], default if NULL // _p : equalizer length (number of taps) EQRLS() EQRLS(_create)(T * _h, unsigned int _p) { EQRLS() q = (EQRLS()) malloc(sizeof(struct EQRLS(_s))); // set filter order, other parameters q->p = _p; // filter order q->lambda = 0.99f; // learning rate q->delta = 0.1f; // initialization factor // allocate memory for matrices q->h0 = (T*) malloc((q->p)*sizeof(T)); q->w0 = (T*) malloc((q->p)*sizeof(T)); q->w1 = (T*) malloc((q->p)*sizeof(T)); q->P0 = (T*) malloc((q->p)*(q->p)*sizeof(T)); q->P1 = (T*) malloc((q->p)*(q->p)*sizeof(T)); q->g = (T*) malloc((q->p)*sizeof(T)); q->xP0 = (T*) malloc((q->p)*sizeof(T)); q->gxl = (T*) malloc((q->p)*(q->p)*sizeof(T)); q->gxlP0 = (T*) malloc((q->p)*(q->p)*sizeof(T)); q->buffer = WINDOW(_create)(q->p); // copy coefficients (if not NULL) if (_h == NULL) { // initial coefficients with delta at first index unsigned int i; for (i=0; ip; i++) q->h0[i] = (i==0) ? 1.0 : 0.0; } else { // copy user-defined initial coefficients memmove(q->h0, _h, (q->p)*sizeof(T)); } // reset equalizer EQRLS(_reset)(q); // return object return q; } // re-create recursive least-squares (RLS) equalizer object // _q : old equalizer object // _h : filter coefficients (NULL for {1,0,0...}) // _p : equalizer length (number of taps) EQRLS() EQRLS(_recreate)(EQRLS() _q, T * _h, unsigned int _p) { if (_q->p == _p) { // length hasn't changed; copy default coefficients // and return object unsigned int i; for (i=0; i<_q->p; i++) _q->h0[i] = _h[i]; return _q; } // completely destroy old equalizer object EQRLS(_destroy)(_q); // create new one and return return EQRLS(_create)(_h,_p); } // destroy eqrls object void EQRLS(_destroy)(EQRLS() _q) { // free vectors and matrices free(_q->h0); free(_q->w0); free(_q->w1); free(_q->P0); free(_q->P1); free(_q->g); free(_q->xP0); free(_q->gxl); free(_q->gxlP0); // destroy window buffer WINDOW(_destroy)(_q->buffer); // free main object memory free(_q); } // print eqrls object internals void EQRLS(_print)(EQRLS() _q) { printf("equalizer (RLS):\n"); printf(" order: %u\n", _q->p); #ifdef DEBUG unsigned int r,c,p=_q->p; printf("P0:\n"); for (r=0; rP0,p,p,r,c)); } printf("\n"); } printf("P1:\n"); for (r=0; rP1,p,p,r,c)); } printf("\n"); } printf("gxl:\n"); for (r=0; rgxl,p,p,r,c)); } printf("\n"); } #endif } // reset equalizer void EQRLS(_reset)(EQRLS() _q) { // reset input counter _q->n = 0; unsigned int i, j; // initialize... for (i=0; i<_q->p; i++) { for (j=0; j<_q->p; j++) { if (i==j) _q->P0[(_q->p)*i + j] = 1 / (_q->delta); else _q->P0[(_q->p)*i + j] = 0; } } // copy default coefficients memmove(_q->w0, _q->h0, (_q->p)*sizeof(T)); // clear window object WINDOW(_reset)(_q->buffer); } // get learning rate of equalizer float EQRLS(_get_bw)(EQRLS() _q) { return _q->lambda; } // set learning rate of equalizer // _q : equalizer object // _lambda : RLS learning rate (should be close to 1.0), 0 < _lambda < 1 void EQRLS(_set_bw)(EQRLS() _q, float _lambda) { if (_lambda < 0.0f || _lambda > 1.0f) { printf("error: eqrls_%s_set_bw(), learning rate must be in (0,1)\n", EXTENSION_FULL); exit(1); } // set internal value _q->lambda = _lambda; } // push sample into equalizer internal buffer // _q : equalizer object // _x : received sample void EQRLS(_push)(EQRLS() _q, T _x) { // push value into buffer WINDOW(_push)(_q->buffer, _x); } // execute internal dot product // _q : equalizer object // _y : output sample void EQRLS(_execute)(EQRLS() _q, T * _y) { // compute vector dot product T * r; // read buffer WINDOW(_read)(_q->buffer, &r); DOTPROD(_run)(_q->w0, r, _q->p, _y); } // execute cycle of equalizer, filtering output // _q : equalizer object // _x : received sample // _d : desired output // _d_hat : filtered output void EQRLS(_step)(EQRLS() _q, T _d, T _d_hat) { unsigned int i,r,c; unsigned int p=_q->p; // compute error (a priori) T alpha = _d - _d_hat; // read buffer T * x; WINDOW(_read)(_q->buffer, &x); // compute gain vector for (c=0; cxP0[c] = 0; for (r=0; rxP0[c] += x[r] * matrix_access(_q->P0,p,p,r,c); } } #ifdef DEBUG printf("x: "); for (i=0; ixP0[c]); printf("\n"); #endif // zeta = lambda + [x.']*[P0]*[conj(x)] _q->zeta = 0; for (c=0; cxP0[c] * conj(x[c]); _q->zeta += sum; } _q->zeta += _q->lambda; #ifdef DEBUG printf("zeta : "); PRINTVAL(_q->zeta); printf("\n"); #endif for (r=0; rg[r] = 0; for (c=0; cP0,p,p,r,c) * conj(x[c]); _q->g[r] += sum; } _q->g[r] /= _q->zeta; } #ifdef DEBUG printf("g: "); for (i=0; ig[i]); //printf("%6.3f ", _q->g[i]); printf("\n"); #endif // update recursion matrix for (r=0; rgxl,p,p,r,c) = _q->g[r] * x[c] / _q->lambda; } } // multiply two [pxp] matrices: gxlP0 = gxl * P0 MATRIX(_mul)(_q->gxl, p,p, _q->P0, p,p, _q->gxlP0,p,p); for (i=0; iP1[i] = _q->P0[i] / _q->lambda - _q->gxlP0[i]; // update weighting vector for (i=0; iw1[i] = _q->w0[i] + alpha*(_q->g[i]); #ifdef DEBUG printf("w0: \n"); for (i=0; iw0[i]); printf("\n"); } printf("w1: \n"); for (i=0; iw1[i]); printf("\n"); EQRLS(_print)(_q); } //if (_q->n == 7) // exit(0); #endif // copy old values memmove(_q->w0, _q->w1, p*sizeof(T)); memmove(_q->P0, _q->P1, p*p*sizeof(T)); } // retrieve internal filter coefficients // _q : equalizer object // _w : weights [size: _p x 1] void EQRLS(_get_weights)(EQRLS() _q, T * _w) { // copy output weight vector, reversing order unsigned int i; for (i=0; i<_q->p; i++) _w[i] = _q->w1[_q->p-i-1]; } // train equalizer object // _q : equalizer object // _w : initial weights / output weights // _x : received sample vector // _d : desired output vector // _n : vector length void EQRLS(_train)(EQRLS() _q, T * _w, T * _x, T * _d, unsigned int _n) { unsigned int i; if (_n < _q->p) { printf("warning: eqrls_%s_train(), traning sequence less than filter order\n", EXTENSION_FULL); return; } // reset equalizer state EQRLS(_reset)(_q); // copy initial weights into buffer for (i=0; i<_q->p; i++) _q->w0[i] = _w[_q->p - i - 1]; T d_hat; for (i=0; i<_n; i++) { // push sample into internal buffer EQRLS(_push)(_q, _x[i]); // execute vector dot product EQRLS(_execute)(_q, &d_hat); // step through training cycle EQRLS(_step)(_q, _d[i], d_hat); } // copy output weight vector EQRLS(_get_weights)(_q, _w); } liquid-dsp-1.3.1/src/equalization/src/equalizer_cccf.c000066400000000000000000000033341317124540100227760ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Floating-point equalizers // #include "liquid.internal.h" // naming extensions (useful for print statements) #define EXTENSION_SHORT "f" #define EXTENSION_FULL "cccf" #define EQLMS(name) LIQUID_CONCAT(eqlms_cccf,name) #define EQRLS(name) LIQUID_CONCAT(eqrls_cccf,name) #define DOTPROD(name) LIQUID_CONCAT(dotprod_cccf,name) #define WINDOW(name) LIQUID_CONCAT(windowcf,name) #define MATRIX(name) LIQUID_CONCAT(matrixcf,name) #define T_COMPLEX 1 #define T float complex #define PRINTVAL(V) printf("%5.2f+j%5.2f ", crealf(V), cimagf(V)); #include "eqlms.c" #include "eqrls.c" liquid-dsp-1.3.1/src/equalization/src/equalizer_rrrf.c000066400000000000000000000032701317124540100230520ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Floating-point equalizers // #include "liquid.internal.h" // naming extensions (useful for print statements) #define EXTENSION_SHORT "f" #define EXTENSION_FULL "rrrf" #define EQLMS(name) LIQUID_CONCAT(eqlms_rrrf,name) #define EQRLS(name) LIQUID_CONCAT(eqrls_rrrf,name) #define DOTPROD(name) LIQUID_CONCAT(dotprod_rrrf,name) #define WINDOW(name) LIQUID_CONCAT(windowf,name) #define MATRIX(name) LIQUID_CONCAT(matrixf,name) #define T_COMPLEX 0 #define T float #define PRINTVAL(V) printf("%5.2f ", V); #include "eqlms.c" #include "eqrls.c" liquid-dsp-1.3.1/src/equalization/tests/000077500000000000000000000000001317124540100202235ustar00rootroot00000000000000liquid-dsp-1.3.1/src/equalization/tests/eqlms_cccf_autotest.c000066400000000000000000000163651317124540100244310ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.h" // // AUTOTEST: static channel filter, blind equalization on QPSK symbols // void autotest_eqlms_cccf_blind() { // parameters float tol = 2e-2f; // error tolerance unsigned int k = 2; // samples/symbol unsigned int m = 7; // filter delay float beta = 0.3f; // excess bandwidth factor unsigned int p = 7; // equalizer order float mu = 0.7f; // equalizer bandwidth unsigned int num_symbols = 400; // number of symbols to observe // create sequence generator for repeatability msequence ms = msequence_create_default(12); // create interpolating filter firinterp_crcf interp = firinterp_crcf_create_prototype(LIQUID_FIRFILT_ARKAISER,k,m,beta,0); // create equalizer eqlms_cccf eq = eqlms_cccf_create_rnyquist(LIQUID_FIRFILT_ARKAISER,k,p,beta,0); eqlms_cccf_set_bw(eq, mu); // create channel filter float complex h[5] = { { 1.00f, 0.00f}, { 0.00f, -0.01f}, {-0.11f, 0.02f}, { 0.02f, 0.01f}, {-0.09f, -0.04f} }; firfilt_cccf fchannel = firfilt_cccf_create(h,5); // arrays float complex buf[k]; // filter buffer float complex sym_in [num_symbols]; // input symbols float complex sym_out[num_symbols]; // equalized symbols // run equalization unsigned int i; unsigned int j; for (i=0; i m + p) eqlms_cccf_step(eq, sym_out[i]/cabsf(sym_out[i]), sym_out[i]); } } // compare input, output unsigned int settling_delay = 285; for (i=m+p; i tol ? "*" : ""); if (i == settling_delay + m + p) printf("--- start of test ---\n"); } // check error if (i > settling_delay + m + p) CONTEND_DELTA(error, 0.0f, tol); } // clean up objects firfilt_cccf_destroy(fchannel); eqlms_cccf_destroy(eq); msequence_destroy(ms); } // // AUTOTEST: static channel filter, decision-directed on QPSK symbols // void autotest_eqlms_cccf_decisiondirected() { // parameters float tol = 1e-2f; // error tolerance unsigned int k = 2; // samples/symbol unsigned int m = 7; // filter delay float beta = 0.3f; // excess bandwidth factor unsigned int p = 7; // equalizer order unsigned int num_symbols = 400; // number of symbols to observe // create sequence generator for repeatability msequence ms = msequence_create_default(12); // create interpolating filter firinterp_crcf interp = firinterp_crcf_create_prototype(LIQUID_FIRFILT_ARKAISER,k,m,beta,0); // create equalizer eqlms_cccf eq = eqlms_cccf_create_rnyquist(LIQUID_FIRFILT_ARKAISER,k,p,beta,0); eqlms_cccf_set_bw(eq, 0.5f); // create channel filter unsigned int h_len = 5; // channel filter length float complex h[5] = {1.0f, 0.0f, -0.1f, 0.02f, -0.1f}; firfilt_cccf fchannel = firfilt_cccf_create(h,h_len); // arrays float complex buf[k]; // filter buffer float complex sym_in [num_symbols]; // input symbols float complex sym_out[num_symbols]; // equalized symbols // run equalization unsigned int i; unsigned int j; for (i=0; i m + p) eqlms_cccf_step(eq, sym_out[i]/cabsf(sym_out[i]), sym_out[i]); } } // compare input, output unsigned int settling_delay = 250; for (i=m+p; i tol ? "*" : ""); if (i == settling_delay + m + p) printf("--- start of test ---\n"); } // check error if (i > settling_delay + m + p) CONTEND_DELTA(error, 0.0f, tol); } // clean up objects firfilt_cccf_destroy(fchannel); eqlms_cccf_destroy(eq); msequence_destroy(ms); } liquid-dsp-1.3.1/src/equalization/tests/eqrls_rrrf_autotest.c000066400000000000000000000060271317124540100245050ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.h" // constant data sequence const float eqrls_rrrf_autotest_data_sequence[64] = { -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0 }; // // AUTOTEST: channel filter: delta with zero delay // void autotest_eqrls_rrrf_01() { float tol=1e-2f; // error tolerance // fixed parameters (do not change) unsigned int h_len=4; // channel filter length unsigned int p=6; // equalizer order unsigned int n=64; // number of symbols to observe // bookkeeping variables float y[n]; // received data sequence (filtered by channel) //float d_hat[n]; // recovered data sequence float h[h_len]; // channel filter coefficients float w[p]; // equalizer filter coefficients unsigned int i; // create equalizer eqrls_rrrf eq = eqrls_rrrf_create(NULL, p); // create channel filter h[0] = 1.0f; for (i=1; i #include #include #include #include "liquid.internal.h" #define CRC_BENCH_API(CRC,N) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { crc_bench(_start, _finish, _num_iterations, CRC, N); } // Helper function to keep code base small void crc_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, crc_scheme _crc, unsigned int _n) { // normalize number of iterations if (_crc != LIQUID_CRC_CHECKSUM) *_num_iterations /= 8; unsigned long int i; // create arrays unsigned char msg[_n]; unsigned int key = 0; // initialze message for (i=0; i<_n; i++) msg[i] = rand() & 0xff; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { key ^= crc_generate_key(_crc, msg, _n); key ^= crc_generate_key(_crc, msg, _n); key ^= crc_generate_key(_crc, msg, _n); key ^= crc_generate_key(_crc, msg, _n); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; } // // BENCHMARKS // void benchmark_crc_checksum_n256 CRC_BENCH_API(LIQUID_CRC_CHECKSUM, 256) void benchmark_crc_crc8_n256 CRC_BENCH_API(LIQUID_CRC_8, 256) void benchmark_crc_crc16_n256 CRC_BENCH_API(LIQUID_CRC_16, 256) void benchmark_crc_crc24_n256 CRC_BENCH_API(LIQUID_CRC_24, 256) void benchmark_crc_crc32_n256 CRC_BENCH_API(LIQUID_CRC_32, 256) liquid-dsp-1.3.1/src/fec/bench/fec_decode_benchmark.c000066400000000000000000000172211317124540100224110ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "liquid.internal.h" #define FEC_DECODE_BENCH_API(FS,N, OPT) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { fec_decode_bench(_start, _finish, _num_iterations, FS, N, OPT); } // Helper function to keep code base small void fec_decode_bench( struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, fec_scheme _fs, unsigned int _n, void * _opts) { #if !LIBFEC_ENABLED if ( _fs == LIQUID_FEC_CONV_V27 || _fs == LIQUID_FEC_CONV_V29 || _fs == LIQUID_FEC_CONV_V39 || _fs == LIQUID_FEC_CONV_V615 || _fs == LIQUID_FEC_CONV_V27P23 || _fs == LIQUID_FEC_CONV_V27P34 || _fs == LIQUID_FEC_CONV_V27P45 || _fs == LIQUID_FEC_CONV_V27P56 || _fs == LIQUID_FEC_CONV_V27P67 || _fs == LIQUID_FEC_CONV_V27P78 || _fs == LIQUID_FEC_CONV_V29P23 || _fs == LIQUID_FEC_CONV_V29P34 || _fs == LIQUID_FEC_CONV_V29P45 || _fs == LIQUID_FEC_CONV_V29P56 || _fs == LIQUID_FEC_CONV_V29P67 || _fs == LIQUID_FEC_CONV_V29P78 || _fs == LIQUID_FEC_RS_M8) { fprintf(stderr,"warning: convolutional, Reed-Solomon codes unavailable (install libfec)\n"); getrusage(RUSAGE_SELF, _start); memmove((void*)_finish,(void*)_start,sizeof(struct rusage)); return; } #endif // normalize number of iterations *_num_iterations /= _n; switch (_fs) { case LIQUID_FEC_NONE: *_num_iterations *= 500; break; case LIQUID_FEC_REP3: *_num_iterations *= 200; break; case LIQUID_FEC_REP5: *_num_iterations *= 100; break; case LIQUID_FEC_HAMMING74: *_num_iterations *= 10; break; case LIQUID_FEC_HAMMING84: *_num_iterations *= 10; break; case LIQUID_FEC_HAMMING128: *_num_iterations *= 10; break; case LIQUID_FEC_SECDED2216: *_num_iterations *= 10; break; case LIQUID_FEC_SECDED3932: *_num_iterations *= 10; break; case LIQUID_FEC_SECDED7264: *_num_iterations *= 10; break; case LIQUID_FEC_GOLAY2412: *_num_iterations *= 2; break; case LIQUID_FEC_CONV_V27: *_num_iterations /= 5; break; case LIQUID_FEC_CONV_V29: *_num_iterations /= 10; break; case LIQUID_FEC_CONV_V39: *_num_iterations /= 100; break; case LIQUID_FEC_CONV_V615: *_num_iterations /= 200; break; case LIQUID_FEC_CONV_V27P23: case LIQUID_FEC_CONV_V27P34: case LIQUID_FEC_CONV_V27P45: case LIQUID_FEC_CONV_V27P56: case LIQUID_FEC_CONV_V27P67: case LIQUID_FEC_CONV_V27P78: *_num_iterations /= 20; break; case LIQUID_FEC_CONV_V29P23: case LIQUID_FEC_CONV_V29P34: case LIQUID_FEC_CONV_V29P45: case LIQUID_FEC_CONV_V29P56: case LIQUID_FEC_CONV_V29P67: case LIQUID_FEC_CONV_V29P78: *_num_iterations /= 50; break; case LIQUID_FEC_RS_M8: *_num_iterations *= 1; break; default:; } if (*_num_iterations < 1) *_num_iterations = 1; // generate fec object fec q = fec_create(_fs,_opts); // create arrays unsigned int n_enc = fec_get_enc_msg_length(_fs,_n); unsigned char msg[_n]; // original message unsigned char msg_enc[n_enc]; // decoded message unsigned char msg_dec[_n]; // decoded message // initialze message unsigned long int i; for (i=0; i<_n; i++) msg[i] = rand() & 0xff; // encode message fec_encode(q,_n,msg,msg_enc); // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { fec_decode(q,_n,msg_enc,msg_dec); fec_decode(q,_n,msg_enc,msg_dec); fec_decode(q,_n,msg_enc,msg_dec); fec_decode(q,_n,msg_enc,msg_dec); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; // clean up objects fec_destroy(q); } // // BENCHMARKS // void benchmark_fec_dec_none_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_NONE, 64, NULL) void benchmark_fec_dec_rep3_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_REP3, 64, NULL) void benchmark_fec_dec_rep5_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_REP5, 64, NULL) void benchmark_fec_dec_hamming74_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_HAMMING74, 64, NULL) void benchmark_fec_dec_hamming84_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_HAMMING84, 64, NULL) void benchmark_fec_dec_hamming128_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_HAMMING128,64, NULL) // SEC-DED block codes void benchmark_fec_dec_secded2216_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_SECDED2216,64, NULL) void benchmark_fec_dec_secded3932_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_SECDED3932,64, NULL) void benchmark_fec_dec_secded7264_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_SECDED7264,64, NULL) void benchmark_fec_dec_golay2412_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_GOLAY2412, 64, NULL) void benchmark_fec_dec_conv27_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_CONV_V27, 64, NULL) void benchmark_fec_dec_conv29_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_CONV_V29, 64, NULL) void benchmark_fec_dec_conv39_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_CONV_V39, 64, NULL) void benchmark_fec_dec_conv615_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_CONV_V615, 64, NULL) void benchmark_fec_dec_conv27p23_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_CONV_V27P23,64, NULL) void benchmark_fec_dec_conv27p34_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_CONV_V27P34,64, NULL) void benchmark_fec_dec_conv27p45_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_CONV_V27P45,64, NULL) void benchmark_fec_dec_conv27p56_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_CONV_V27P56,64, NULL) void benchmark_fec_dec_conv27p67_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_CONV_V27P67,64, NULL) void benchmark_fec_dec_conv27p78_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_CONV_V27P78,64, NULL) void benchmark_fec_dec_conv29p23_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_CONV_V29P23,64, NULL) void benchmark_fec_dec_conv29p34_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_CONV_V29P34,64, NULL) void benchmark_fec_dec_conv29p45_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_CONV_V29P45,64, NULL) void benchmark_fec_dec_conv29p56_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_CONV_V29P56,64, NULL) void benchmark_fec_dec_conv29p67_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_CONV_V29P67,64, NULL) void benchmark_fec_dec_conv29p78_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_CONV_V29P78,64, NULL) void benchmark_fec_dec_rs8_n64 FEC_DECODE_BENCH_API(LIQUID_FEC_RS_M8, 64, NULL) liquid-dsp-1.3.1/src/fec/bench/fec_encode_benchmark.c000066400000000000000000000147151317124540100224300ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "liquid.internal.h" #define FEC_ENCODE_BENCH_API(FS,N, OPT) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { fec_encode_bench(_start, _finish, _num_iterations, FS, N, OPT); } // Helper function to keep code base small void fec_encode_bench( struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, fec_scheme _fs, unsigned int _n, void * _opts) { #if !LIBFEC_ENABLED if ( _fs == LIQUID_FEC_CONV_V27 || _fs == LIQUID_FEC_CONV_V29 || _fs == LIQUID_FEC_CONV_V39 || _fs == LIQUID_FEC_CONV_V615 || _fs == LIQUID_FEC_CONV_V27P23 || _fs == LIQUID_FEC_CONV_V27P34 || _fs == LIQUID_FEC_CONV_V27P45 || _fs == LIQUID_FEC_CONV_V27P56 || _fs == LIQUID_FEC_CONV_V27P67 || _fs == LIQUID_FEC_CONV_V27P78 || _fs == LIQUID_FEC_CONV_V29P23 || _fs == LIQUID_FEC_CONV_V29P34 || _fs == LIQUID_FEC_CONV_V29P45 || _fs == LIQUID_FEC_CONV_V29P56 || _fs == LIQUID_FEC_CONV_V29P67 || _fs == LIQUID_FEC_CONV_V29P78 || _fs == LIQUID_FEC_RS_M8) { fprintf(stderr,"warning: convolutional, Reed-Solomon codes unavailable (install libfec)\n"); getrusage(RUSAGE_SELF, _start); memmove((void*)_finish,(void*)_start,sizeof(struct rusage)); return; } #endif // normalize number of iterations *_num_iterations /= _n; switch (_fs) { case LIQUID_FEC_NONE: *_num_iterations *= 500; break; case LIQUID_FEC_REP3: *_num_iterations *= 200; break; case LIQUID_FEC_REP5: *_num_iterations *= 100; break; case LIQUID_FEC_HAMMING74: *_num_iterations *= 30; break; case LIQUID_FEC_HAMMING84: *_num_iterations *= 100; break; case LIQUID_FEC_HAMMING128: *_num_iterations *= 100; break; case LIQUID_FEC_SECDED2216: *_num_iterations *= 10; break; case LIQUID_FEC_SECDED3932: *_num_iterations *= 10; break; case LIQUID_FEC_SECDED7264: *_num_iterations *= 10; break; case LIQUID_FEC_GOLAY2412: *_num_iterations *= 2; break; case LIQUID_FEC_CONV_V27: case LIQUID_FEC_CONV_V29: case LIQUID_FEC_CONV_V39: case LIQUID_FEC_CONV_V615: case LIQUID_FEC_CONV_V27P23: case LIQUID_FEC_CONV_V27P34: case LIQUID_FEC_CONV_V27P45: case LIQUID_FEC_CONV_V27P56: case LIQUID_FEC_CONV_V27P67: case LIQUID_FEC_CONV_V27P78: case LIQUID_FEC_CONV_V29P23: case LIQUID_FEC_CONV_V29P34: case LIQUID_FEC_CONV_V29P45: case LIQUID_FEC_CONV_V29P56: case LIQUID_FEC_CONV_V29P67: case LIQUID_FEC_CONV_V29P78: case LIQUID_FEC_RS_M8: *_num_iterations *= 1; break; default:; } if (*_num_iterations < 1) *_num_iterations = 1; // generate fec object fec q = fec_create(_fs,_opts); // create arrays unsigned int n_enc = fec_get_enc_msg_length(_fs,_n); unsigned char msg[_n]; // original message unsigned char msg_enc[n_enc]; // encoded message // initialze message unsigned long int i; for (i=0; i<_n; i++) { msg[i] = rand() & 0xff; } // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { fec_encode(q,_n,msg,msg_enc); fec_encode(q,_n,msg,msg_enc); fec_encode(q,_n,msg,msg_enc); fec_encode(q,_n,msg,msg_enc); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; // clean up objects fec_destroy(q); } // // BENCHMARKS // void benchmark_fec_enc_none_n64 FEC_ENCODE_BENCH_API(LIQUID_FEC_NONE, 64, NULL) void benchmark_fec_enc_rep3_n64 FEC_ENCODE_BENCH_API(LIQUID_FEC_REP3, 64, NULL) void benchmark_fec_enc_rep5_n64 FEC_ENCODE_BENCH_API(LIQUID_FEC_REP5, 64, NULL) void benchmark_fec_enc_hamming74_n64 FEC_ENCODE_BENCH_API(LIQUID_FEC_HAMMING74, 64, NULL) void benchmark_fec_enc_hamming84_n64 FEC_ENCODE_BENCH_API(LIQUID_FEC_HAMMING84, 64, NULL) void benchmark_fec_enc_hamming128_n64 FEC_ENCODE_BENCH_API(LIQUID_FEC_HAMMING128,64, NULL) // SEC-DED block codes void benchmark_fec_enc_secded2216_n64 FEC_ENCODE_BENCH_API(LIQUID_FEC_SECDED2216,64, NULL) void benchmark_fec_enc_secded3932_n64 FEC_ENCODE_BENCH_API(LIQUID_FEC_SECDED3932,64, NULL) void benchmark_fec_enc_secded7264_n64 FEC_ENCODE_BENCH_API(LIQUID_FEC_SECDED7264,64, NULL) void benchmark_fec_enc_golay2412_n64 FEC_ENCODE_BENCH_API(LIQUID_FEC_GOLAY2412, 64, NULL) void benchmark_fec_enc_conv27_n64 FEC_ENCODE_BENCH_API(LIQUID_FEC_CONV_V27, 64, NULL) void benchmark_fec_enc_conv29_n64 FEC_ENCODE_BENCH_API(LIQUID_FEC_CONV_V29, 64, NULL) void benchmark_fec_enc_conv39_n64 FEC_ENCODE_BENCH_API(LIQUID_FEC_CONV_V39, 64, NULL) void benchmark_fec_enc_conv615_n64 FEC_ENCODE_BENCH_API(LIQUID_FEC_CONV_V615, 64, NULL) void benchmark_fec_enc_conv27p23_n64 FEC_ENCODE_BENCH_API(LIQUID_FEC_CONV_V27P23,64, NULL) void benchmark_fec_enc_conv27p34_n64 FEC_ENCODE_BENCH_API(LIQUID_FEC_CONV_V27P34,64, NULL) void benchmark_fec_enc_conv27p45_n64 FEC_ENCODE_BENCH_API(LIQUID_FEC_CONV_V27P45,64, NULL) void benchmark_fec_enc_rs8_n64 FEC_ENCODE_BENCH_API(LIQUID_FEC_RS_M8, 64, NULL) liquid-dsp-1.3.1/src/fec/bench/fecsoft_decode_benchmark.c000066400000000000000000000174641317124540100233160ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fecsoft_decode_benchmark.h // // Test soft decoding speeds of certain FEC codecs // #include #include #include #include #include "liquid.internal.h" #define FECSOFT_DECODE_BENCH_API(FS,N, OPT) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { fecsoft_decode_bench(_start, _finish, _num_iterations, FS, N, OPT); } // Helper function to keep code base small void fecsoft_decode_bench( struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, fec_scheme _fs, unsigned int _n, void * _opts) { #if !LIBFEC_ENABLED if ( _fs == LIQUID_FEC_CONV_V27 || _fs == LIQUID_FEC_CONV_V29 || _fs == LIQUID_FEC_CONV_V39 || _fs == LIQUID_FEC_CONV_V615 || _fs == LIQUID_FEC_CONV_V27P23 || _fs == LIQUID_FEC_CONV_V27P34 || _fs == LIQUID_FEC_CONV_V27P45 || _fs == LIQUID_FEC_CONV_V27P56 || _fs == LIQUID_FEC_CONV_V27P67 || _fs == LIQUID_FEC_CONV_V27P78 || _fs == LIQUID_FEC_CONV_V29P23 || _fs == LIQUID_FEC_CONV_V29P34 || _fs == LIQUID_FEC_CONV_V29P45 || _fs == LIQUID_FEC_CONV_V29P56 || _fs == LIQUID_FEC_CONV_V29P67 || _fs == LIQUID_FEC_CONV_V29P78 || _fs == LIQUID_FEC_RS_M8) { fprintf(stderr,"warning: convolutional, Reed-Solomon codes unavailable (install libfec)\n"); getrusage(RUSAGE_SELF, _start); memmove((void*)_finish,(void*)_start,sizeof(struct rusage)); return; } #endif // normalize number of iterations *_num_iterations /= _n; switch (_fs) { case LIQUID_FEC_NONE: *_num_iterations *= 50; break; case LIQUID_FEC_REP3: *_num_iterations *= 20; break; case LIQUID_FEC_REP5: *_num_iterations *= 10; break; case LIQUID_FEC_HAMMING74: *_num_iterations *= 1; break; case LIQUID_FEC_HAMMING84: *_num_iterations *= 1; break; case LIQUID_FEC_HAMMING128: *_num_iterations *= 1; break; case LIQUID_FEC_CONV_V27: *_num_iterations /= 5; break; case LIQUID_FEC_CONV_V29: *_num_iterations /= 50; break; case LIQUID_FEC_CONV_V39: *_num_iterations /= 50; break; case LIQUID_FEC_CONV_V615: *_num_iterations /= 800; break; case LIQUID_FEC_CONV_V27P23: case LIQUID_FEC_CONV_V27P34: case LIQUID_FEC_CONV_V27P45: case LIQUID_FEC_CONV_V27P56: case LIQUID_FEC_CONV_V27P67: case LIQUID_FEC_CONV_V27P78: *_num_iterations /= 5; break; case LIQUID_FEC_CONV_V29P23: case LIQUID_FEC_CONV_V29P34: case LIQUID_FEC_CONV_V29P45: case LIQUID_FEC_CONV_V29P56: case LIQUID_FEC_CONV_V29P67: case LIQUID_FEC_CONV_V29P78: *_num_iterations /= 50; break; case LIQUID_FEC_RS_M8: *_num_iterations *= 1; break; default:; } if (*_num_iterations < 1) *_num_iterations = 1; // generate fec object fec q = fec_create(_fs,_opts); // create arrays unsigned int n_enc = fec_get_enc_msg_length(_fs,_n); unsigned char msg[_n]; // original message unsigned char msg_enc[n_enc]; // encoded message unsigned char msg_soft[8*n_enc];// encoded message (soft bits) unsigned char msg_dec[_n]; // decoded message // initialze message unsigned long int i; for (i=0; i<_n; i++) msg[i] = rand() & 0xff; // encode message fec_encode(q,_n,msg,msg_enc); // expand to soft bits for (i=0; i #include #include #include "liquid.h" #define INTERLEAVER_BENCH_API(N) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { interleaver_bench(_start, _finish, _num_iterations, N); } // Helper function to keep code base small void interleaver_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _n) { // scale number of iterations by block size // iterations = 4: cycles/trial ~ exp( -0.883 + 0.708*log(_n) ) *_num_iterations /= 0.7f*expf( -0.883 + 0.708*logf(_n) ); // initialize interleaver interleaver q = interleaver_create(_n); interleaver_set_depth(q, 4); unsigned char x[_n]; unsigned char y[_n]; unsigned long int i; for (i=0; i<_n; i++) x[i] = rand() & 0xff; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { interleaver_encode(q, x, y); interleaver_encode(q, x, y); interleaver_encode(q, x, y); interleaver_encode(q, x, y); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; // destroy interleaver object interleaver_destroy(q); } void benchmark_interleaver_8 INTERLEAVER_BENCH_API(8 ) void benchmark_interleaver_16 INTERLEAVER_BENCH_API(16 ) void benchmark_interleaver_32 INTERLEAVER_BENCH_API(32 ) void benchmark_interleaver_64 INTERLEAVER_BENCH_API(64 ) void benchmark_interleaver_128 INTERLEAVER_BENCH_API(128 ) void benchmark_interleaver_256 INTERLEAVER_BENCH_API(256 ) void benchmark_interleaver_512 INTERLEAVER_BENCH_API(512 ) void benchmark_interleaver_1024 INTERLEAVER_BENCH_API(1024 ) liquid-dsp-1.3.1/src/fec/bench/packetizer_decode_benchmark.c000066400000000000000000000077621317124540100240260ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include "liquid.internal.h" #define PACKETIZER_DECODE_BENCH_API(N, CRC, FEC0, FEC1) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { packetizer_decode_bench(_start, _finish, _num_iterations, N, CRC, FEC0, FEC1); } // Helper function to keep code base small void packetizer_decode_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _n, crc_scheme _crc, fec_scheme _fec0, fec_scheme _fec1) { // unsigned int msg_dec_len = _n; unsigned int msg_enc_len = packetizer_compute_enc_msg_len(_n,_crc,_fec0,_fec1); // adjust number of iterations // k-cycles/trial ~ 221 + 1.6125*msg_dec_len; // TODO: adjust iterations based on encoder types *_num_iterations *= 1000; *_num_iterations /= 221 + 1.6125*msg_dec_len; unsigned char msg_rec[msg_enc_len]; unsigned char msg_dec[msg_dec_len]; // initialize data unsigned long int i; for (i=0; i #include #include #include #include "liquid.internal.h" #define SUMPRODUCT_BENCH_API(M) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { sumproduct_bench(_start, _finish, _num_iterations, M); } // generate half-rate LDPC generator and parity-check matrices void sumproduct_generate(unsigned int _m, unsigned char * _G, unsigned char * _H); // Helper function to keep code base small void sumproduct_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _m) { // normalize number of iterations // M cycles/trial ~ 2^{ -11.5920 + 2.503*log2(_m) } *_num_iterations /= 4*_m*_m; if (*_num_iterations < 1) *_num_iterations = 1; unsigned long int i; // derived values unsigned int _n = 2*_m; // create arrays unsigned char Gs[_m*_n]; // generator matrix [m x n] unsigned char Hs[_m*_n]; // parity check matrix [m x n] sumproduct_generate(_m, Gs, Hs); // generate sparse binary matrices smatrixb G = smatrixb_create_array(Gs, _n, _m); smatrixb H = smatrixb_create_array(Hs, _m, _n); // print matrices //printf("G:\n"); smatrixb_print_expanded(G); //printf("H:\n"); smatrixb_print_expanded(H); unsigned char x[_m]; // original message signal unsigned char c[_n]; // transmitted codeword float LLR[_n]; // log-likelihood ratio unsigned char c_hat[_n]; // estimated codeword // initialize message array for (i=0; i<_m; i++) x[i] = rand() % 2; // compute encoded message smatrixb_vmul(G, x, c); // print status //printf("x = ["); for (i=0; i<_m; i++) printf("%2u", x[i]); printf(" ];\n"); //printf("c = ["); for (i=0; i<_n; i++) printf("%2u", c[i]); printf(" ];\n"); // compute log-likelihood ratio (LLR) for (i=0; i<_n; i++) LLR[i] = (c[i] == 0 ? 1.0f : -1.0f) + 0.5*randnf(); // start trials getrusage(RUSAGE_SELF, _start); int parity_pass; for (i=0; i<(*_num_iterations); i++) { parity_pass = fec_sumproduct(_m, _n, H, LLR, c_hat, 1); LLR[i%_m] += parity_pass ? 1 : -1; parity_pass = fec_sumproduct(_m, _n, H, LLR, c_hat, 1); LLR[i%_m] += parity_pass ? 1 : -1; parity_pass = fec_sumproduct(_m, _n, H, LLR, c_hat, 1); LLR[i%_m] += parity_pass ? 1 : -1; parity_pass = fec_sumproduct(_m, _n, H, LLR, c_hat, 1); LLR[i%_m] += parity_pass ? 1 : -1; } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; } // // BENCHMARKS // void benchmark_sumproduct_m16 SUMPRODUCT_BENCH_API(16) void benchmark_sumproduct_m32 SUMPRODUCT_BENCH_API(32) void benchmark_sumproduct_m64 SUMPRODUCT_BENCH_API(64) void benchmark_sumproduct_m128 SUMPRODUCT_BENCH_API(128) // generate half-rate LDPC generator and parity-check matrices void sumproduct_generate(unsigned int _m, unsigned char * _G, unsigned char * _H) { unsigned int i; unsigned int j; // derived values unsigned int _n = 2*_m; // initial generator polynomial [1 x m] unsigned char p[_m]; // initialize generator polynomial (systematic) for (i=0; i<_m; i++) p[i] = 0; unsigned int t = 0; unsigned int k = 2; for (i=0; i<_m; i++) { t++; if (t == k) { t = 0; k *= 2; p[i] = 1; } } // initialze matrices for (i=0; i<_m; i++) { for (j=0; j<_m; j++) { // G = [I(m) P]^T _G[j*_m + i] = (i==j) ? 1 : 0; _G[j*_m + i + _m*_m] = p[(i+j)%_m]; // H = [P^T I(m)] _H[i*_n + j + _m] = (i==j) ? 1 : 0; _H[i*_n + j] = p[(i+j)%_m]; } } } liquid-dsp-1.3.1/src/fec/readme.rs.txt000066400000000000000000000056561317124540100175460ustar00rootroot00000000000000=================================== Reed-Solomon codes =================================== This document gives several notes on the usage of Reed-Solomon (RS) codes in liquid. The fec object for RS codes allows for any length input sequence to be encoded. This is accomplished by splitting the uncoded input sequence into a discrete number of blocks of nearly equal length. Each block is then padded with zeros (internally) before the encoding process. For example, the 8-bit (255,223) code adds 32 parity symbols to an uncoded input message of length 223 symbols. To encode messages of lengths less than 223, the input is padded with zeros until its length is exactly 223. The 32 parity symbols are then computed and appended to the end. Internally, libfec does this efficiently and seamlessly. However, there is no simply way to encode messages of lengths larger than 223 (for this 8-bit example). Let us assume that we want to encode a message of 1024 8-bit symbols. Unfortuantely 223 does not evenly divide 1024, so we cannot simply break the original message into blocks that neatly fit our codec. As an alternative, we could split the message into four blocks of 223 and one block of 132, viz. 1024 = (4)*223 + 132 At first glance this is a tractable solution, however it has several inherent disadvantages: 1. libfec uses an internal object to handle padding for blocks less than 223, so if we want to take advantage of its efficient implementation we will need to either create two RS libfec objects (one for blocks of lenght 223 and one for blocks of length 132) or re-create the object every time. As an alternative we could just use one RS object which operates on blocks of length 223 and just manually pad the data for the block of length 132, however this can be cumbersome and inefficient. 2. Because the same number of parity symbols (in this case, 32) are applied to each block during the encoding process, blocks of shorter lengths will have more error-correction capabilities. In this case, the blocks of length 223 will have weaker error protection than those of length 132 and the resulting total error protection will be degraded. For these reasons, liquid splits the input message into (nearly) equally-sized blocks. For our example, we need a minimum of five blocks because ceil(1024 / 223) = ceil(4.5919) = 5 We would like to split the message into five blocks whose lenghts are of perfect equality, but unfortunately five does not evenly divide 1024. The closest we can get is four blocks of 205 and one block of 204, viz. 1024 = (4)*205 + 204 As a result, each block has (nearly) the same error protection, and just one RS libfec object can be used. It is important to remember that the last block needs to be padded by just one zero before encoding. References: [Karn:2002] Karn, P. "libfec," http://www.ka9q.net/code/fec/ liquid-dsp-1.3.1/src/fec/src/000077500000000000000000000000001317124540100157005ustar00rootroot00000000000000liquid-dsp-1.3.1/src/fec/src/c_ones_mod2.c000066400000000000000000000037251317124540100202420ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // // unsigned char c_ones_mod2[] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; liquid-dsp-1.3.1/src/fec/src/c_ones_mod2_gentab.c000066400000000000000000000036541317124540100215630ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // script to generate c_ones_mod2 table // #include // count the number of ones in a byte unsigned int count_ones(unsigned char); int main() { unsigned char c_ones_mod2[256]; unsigned int b; for (b=0; b<256; b++) c_ones_mod2[b] = count_ones((unsigned char)b) % 2; // print results printf("unsigned char c_ones_mod2[] = {\n "); for (b=0; b<256; b++) { printf("%1u", c_ones_mod2[b]); if (b==255) printf("\n"); else if (((b+1)%16)==0) printf(",\n "); else printf(", "); } printf("};\n"); return 0; } // count the number of ones in a byte unsigned int count_ones(unsigned char _b) { unsigned int i, n=0; for (i=0; i<8; i++) { n += _b & 0x01; _b >>= 1; } return n; } liquid-dsp-1.3.1/src/fec/src/crc.c000066400000000000000000000245031317124540100166170ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // cyclic redundancy check (and family) // #include #include #include #include "liquid.internal.h" // object-independent methods const char * crc_scheme_str[LIQUID_CRC_NUM_SCHEMES][2] = { // short name, long name {"unknown", "unknown"}, {"none", "none"}, {"checksum", "checksum (8-bit)"}, {"crc8", "CRC (8-bit)"}, {"crc16", "CRC (16-bit)"}, {"crc24", "CRC (24-bit)"}, {"crc32", "CRC (32-bit)"} }; // Print compact list of existing and available crc schemes void liquid_print_crc_schemes() { unsigned int i; unsigned int len = 10; // print all available MOD schemes printf(" "); for (i=0; i 48 && i != LIQUID_CRC_NUM_SCHEMES-1) { len = 10; printf("\n "); } } printf("\n"); } crc_scheme liquid_getopt_str2crc(const char * _str) { // compare each string to short name unsigned int i; for (i=0; i> (len - i - 1)*8) & 0xff; } // validate message using error-detection key // _scheme : error-detection scheme // _msg : input data message, [size: _n x 1] // _n : input data message size // _key : error-detection key int crc_validate_message(crc_scheme _scheme, unsigned char * _msg, unsigned int _n, unsigned int _key) { if (_scheme == LIQUID_CRC_UNKNOWN) { fprintf(stderr,"error: crc_validate_message(), cannot validate with CRC type \"UNKNOWN\"\n"); exit(-1); } else if (_scheme == LIQUID_CRC_NONE) { return 1; } return crc_generate_key(_scheme, _msg, _n) == _key; } // check message with key appended to end of array // _scheme : error-detection scheme (resulting in 'p' bytes) // _msg : input data message, [size: _n+p x 1] // _n : input data message size (excluding key at end) int crc_check_key(crc_scheme _scheme, unsigned char * _msg, unsigned int _n) { // get key size unsigned int len = crc_sizeof_key(_scheme); // extract key from end of message unsigned int key = 0; unsigned int i; for (i=0; i>1) ^ (poly & mask); } } return (~key8) & 0xff; } // // CRC-16 // // generate 16-bit cyclic redundancy check key. // // slow method, operates one bit at a time // algorithm from: http://www.hackersdelight.org/crc.pdf // // _msg : input data message [size: _n x 1] // _n : input data message size unsigned int crc16_generate_key(unsigned char *_msg, unsigned int _n) { unsigned int i, j, b, mask, key16=~0; unsigned int poly = liquid_reverse_uint16(CRC16_POLY); for (i=0; i<_n; i++) { b = _msg[i]; key16 ^= b; for (j=0; j<8; j++) { mask = -(key16 & 1); key16 = (key16>>1) ^ (poly & mask); } } return (~key16) & 0xffff; } // // CRC-24 // // generate 24-bit cyclic redundancy check key. // // slow method, operates one bit at a time // algorithm from: http://www.hackersdelight.org/crc.pdf // // _msg : input data message [size: _n x 1] // _n : input data message size unsigned int crc24_generate_key(unsigned char *_msg, unsigned int _n) { unsigned int i, j, b, mask, key24=~0; unsigned int poly = liquid_reverse_uint24(CRC24_POLY); for (i=0; i<_n; i++) { b = _msg[i]; key24 ^= b; for (j=0; j<8; j++) { mask = -(key24 & 1); key24 = (key24>>1) ^ (poly & mask); } } return (~key24) & 0xffffff; } // // CRC-32 // // generate 32-bit cyclic redundancy check key. // // slow method, operates one bit at a time // algorithm from: http://www.hackersdelight.org/crc.pdf // // _msg : input data message [size: _n x 1] // _n : input data message size unsigned int crc32_generate_key(unsigned char *_msg, unsigned int _n) { unsigned int i, j, b, mask, key32=~0; unsigned int poly = liquid_reverse_uint32(CRC32_POLY); for (i=0; i<_n; i++) { b = _msg[i]; key32 ^= b; for (j=0; j<8; j++) { mask = -(key32 & 1); key32 = (key32>>1) ^ (poly & mask); } } return (~key32) & 0xffffffff; } #if 0 void crc32_generate_key(unsigned char *_msg, unsigned int _n, unsigned char *_key) { unsigned int key32 = crc32_generate_key32(_msg,_n); _key[0] = (key32 & 0xFF000000) >> 24; _key[1] = (key32 & 0x00FF0000) >> 16; _key[2] = (key32 & 0x0000FF00) >> 8; _key[3] = (key32 & 0x000000FF); } #endif liquid-dsp-1.3.1/src/fec/src/fec.c000066400000000000000000000613731317124540100166130ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // FEC (generic functions) // #include #include #include #include "liquid.internal.h" // object-independent methods const char * fec_scheme_str[LIQUID_FEC_NUM_SCHEMES][2] = { // short name, long name {"unknown", "unknown"}, {"none", "none"}, {"rep3", "repeat(3)"}, {"rep5", "repeat(5)"}, {"h74", "Hamming(7,4)"}, {"h84", "Hamming(8,4)"}, {"h128", "Hamming(12,8)"}, {"g2412", "Golay(24,12)"}, {"secded2216", "SEC-DEC(22,16)"}, {"secded3932", "SEC-DEC(39,32)"}, {"secded7264", "SEC-DEC(72,64)"}, {"v27", "convolutional r1/2 K=7"}, {"v29", "convolutional r1/2 K=9"}, {"v39", "convolutional r1/3 K=9"}, {"v615", "convolutional r1/6 K=15"}, {"v27p23", "convolutional r2/3 K=7 (punctured)"}, {"v27p34", "convolutional r3/4 K=7 (punctured)"}, {"v27p45", "convolutional r4/5 K=7 (punctured)"}, {"v27p56", "convolutional r5/6 K=7 (punctured)"}, {"v27p67", "convolutional r6/7 K=7 (punctured)"}, {"v27p78", "convolutional r7/8 K=7 (punctured)"}, {"v29p23", "convolutional r2/3 K=9 (punctured)"}, {"v29p34", "convolutional r3/4 K=9 (punctured)"}, {"v29p45", "convolutional r4/5 K=9 (punctured)"}, {"v29p56", "convolutional r5/6 K=9 (punctured)"}, {"v29p67", "convolutional r6/7 K=9 (punctured)"}, {"v29p78", "convolutional r7/8 K=9 (punctured)"}, {"rs8", "Reed-Solomon, 223/255"} }; // Print compact list of existing and available fec schemes void liquid_print_fec_schemes() { unsigned int i; unsigned int len = 10; // print all available MOD schemes printf(" "); for (i=0; i 48 && i != LIQUID_FEC_NUM_SCHEMES-1) { len = 10; printf("\n "); } } printf("\n"); } fec_scheme liquid_getopt_str2fec(const char * _str) { // compare each string to short name unsigned int i; for (i=0; ischeme != _scheme) { // destroy old object and create new one fec_destroy(_q); _q = fec_create(_scheme,_opts); } // scheme hasn't changed; just return original object return _q; } // destroy fec object void fec_destroy(fec _q) { switch (_q->scheme) { case LIQUID_FEC_UNKNOWN: printf("error: fec_destroy(), cannot destroy fec object of type \"UNKNOWN\"\n"); exit(-1); case LIQUID_FEC_NONE: fec_pass_destroy(_q); return; case LIQUID_FEC_REP3: fec_rep3_destroy(_q); return; case LIQUID_FEC_REP5: fec_rep5_destroy(_q); return; case LIQUID_FEC_HAMMING74: fec_hamming74_destroy(_q); return; case LIQUID_FEC_HAMMING84: fec_hamming84_destroy(_q); return; case LIQUID_FEC_HAMMING128: fec_hamming128_destroy(_q); return; case LIQUID_FEC_GOLAY2412: fec_golay2412_destroy(_q); return; // SEC-DED codecs (single error correction, double error detection) case LIQUID_FEC_SECDED2216: fec_secded2216_destroy(_q); return; case LIQUID_FEC_SECDED3932: fec_secded3932_destroy(_q); return; case LIQUID_FEC_SECDED7264: fec_secded7264_destroy(_q); return; // convolutional codes #if LIBFEC_ENABLED case LIQUID_FEC_CONV_V27: case LIQUID_FEC_CONV_V29: case LIQUID_FEC_CONV_V39: case LIQUID_FEC_CONV_V615: fec_conv_destroy(_q); return; // punctured case LIQUID_FEC_CONV_V27P23: case LIQUID_FEC_CONV_V27P34: case LIQUID_FEC_CONV_V27P45: case LIQUID_FEC_CONV_V27P56: case LIQUID_FEC_CONV_V27P67: case LIQUID_FEC_CONV_V27P78: case LIQUID_FEC_CONV_V29P23: case LIQUID_FEC_CONV_V29P34: case LIQUID_FEC_CONV_V29P45: case LIQUID_FEC_CONV_V29P56: case LIQUID_FEC_CONV_V29P67: case LIQUID_FEC_CONV_V29P78: fec_conv_punctured_destroy(_q); return; // Reed-Solomon codes case LIQUID_FEC_RS_M8: fec_rs_destroy(_q); return; #else case LIQUID_FEC_CONV_V27: case LIQUID_FEC_CONV_V29: case LIQUID_FEC_CONV_V39: case LIQUID_FEC_CONV_V615: case LIQUID_FEC_CONV_V27P23: case LIQUID_FEC_CONV_V27P34: case LIQUID_FEC_CONV_V27P45: case LIQUID_FEC_CONV_V27P56: case LIQUID_FEC_CONV_V27P67: case LIQUID_FEC_CONV_V27P78: case LIQUID_FEC_CONV_V29P23: case LIQUID_FEC_CONV_V29P34: case LIQUID_FEC_CONV_V29P45: case LIQUID_FEC_CONV_V29P56: case LIQUID_FEC_CONV_V29P67: case LIQUID_FEC_CONV_V29P78: fprintf(stderr,"error: fec_destroy(), convolutional codes unavailable (install libfec)\n"); exit(-1); case LIQUID_FEC_RS_M8: fprintf(stderr,"error: fec_destroy(), Reed-Solomon codes unavailable (install libfec)\n"); exit(-1); #endif default: printf("error: fec_destroy(), unknown/unsupported scheme: %d\n", _q->scheme); exit(-1); } } // print basic fec object internals void fec_print(fec _q) { printf("fec: %s [rate: %4.3f]\n", fec_scheme_str[_q->scheme][1], _q->rate); } // encode a block of data using a fec scheme // _q : fec object // _dec_msg_len : decoded message length // _msg_dec : decoded message // _msg_enc : encoded message void fec_encode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_dec, unsigned char * _msg_enc) { // call internal encoding method _q->encode_func(_q, _dec_msg_len, _msg_dec, _msg_enc); } // decode a block of data using a fec scheme // _q : fec object // _dec_msg_len : decoded message length // _msg_enc : encoded message // _msg_dec : decoded message void fec_decode(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec) { // call internal decoding method _q->decode_func(_q, _dec_msg_len, _msg_enc, _msg_dec); } // decode a block of data using a fec scheme // _q : fec object // _dec_msg_len : decoded message length // _msg_enc : encoded message // _msg_dec : decoded message void fec_decode_soft(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec) { if (_q->decode_soft_func != NULL) { // call internal decoding method _q->decode_soft_func(_q, _dec_msg_len, _msg_enc, _msg_dec); } else { // pack bytes and use hard-decision decoding unsigned enc_msg_len = fec_get_enc_msg_length(_q->scheme, _dec_msg_len); unsigned char msg_enc_hard[enc_msg_len]; unsigned int i; for (i=0; i> 0) & 0x80; msg_enc_hard[i] |= (_msg_enc[8*i+1] >> 1) & 0x40; msg_enc_hard[i] |= (_msg_enc[8*i+2] >> 2) & 0x20; msg_enc_hard[i] |= (_msg_enc[8*i+3] >> 3) & 0x10; msg_enc_hard[i] |= (_msg_enc[8*i+4] >> 4) & 0x08; msg_enc_hard[i] |= (_msg_enc[8*i+5] >> 5) & 0x04; msg_enc_hard[i] |= (_msg_enc[8*i+6] >> 6) & 0x02; msg_enc_hard[i] |= (_msg_enc[8*i+7] >> 7) & 0x01; } // use hard-decoding method fec_decode(_q, _dec_msg_len, msg_enc_hard, _msg_dec); } } liquid-dsp-1.3.1/src/fec/src/fec_conv.c000066400000000000000000000201351317124540100176270ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // convolutional code (macros) // #include #include #include #include "liquid.internal.h" #define VERBOSE_FEC_CONV 0 #if LIBFEC_ENABLED #include "fec.h" fec fec_conv_create(fec_scheme _fs) { fec q = (fec) malloc(sizeof(struct fec_s)); q->scheme = _fs; q->rate = fec_get_rate(q->scheme); q->encode_func = &fec_conv_encode; q->decode_func = &fec_conv_decode_hard; // default to hard-decision decoding q->decode_soft_func = &fec_conv_decode_soft; switch (q->scheme) { case LIQUID_FEC_CONV_V27: fec_conv_init_v27(q); break; case LIQUID_FEC_CONV_V29: fec_conv_init_v29(q); break; case LIQUID_FEC_CONV_V39: fec_conv_init_v39(q); break; case LIQUID_FEC_CONV_V615: fec_conv_init_v615(q); break; default: fprintf(stderr,"error: fec_conv_create(), invalid type\n"); exit(1); } // convolutional-specific decoding q->num_dec_bytes = 0; q->enc_bits = NULL; q->vp = NULL; return q; } void fec_conv_destroy(fec _q) { // delete viterbi decoder if (_q->vp != NULL) _q->delete_viterbi(_q->vp); if (_q->enc_bits != NULL) free(_q->enc_bits); free(_q); } void fec_conv_encode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_dec, unsigned char *_msg_enc) { unsigned int i,j,r; // bookkeeping unsigned int sr=0; // convolutional shift register unsigned int n=0; // output bit counter unsigned char bit; unsigned char byte_in; unsigned char byte_out=0; for (i=0; i<_dec_msg_len; i++) { byte_in = _msg_dec[i]; // break byte into individual bits for (j=0; j<8; j++) { // shift bit starting with most significant bit = (byte_in >> (7-j)) & 0x01; sr = (sr << 1) | bit; // compute parity bits for each polynomial for (r=0; r<_q->R; r++) { byte_out = (byte_out<<1) | parity(sr & _q->poly[r]); _msg_enc[n/8] = byte_out; n++; } } } // tail bits for (i=0; i<(_q->K)-1; i++) { // shift register: push zeros sr = (sr << 1); // compute parity bits for each polynomial for (r=0; r<_q->R; r++) { byte_out = (byte_out<<1) | parity(sr & _q->poly[r]); _msg_enc[n/8] = byte_out; n++; } } // ensure even number of bytes while (n%8) { // shift zeros byte_out <<= 1; _msg_enc[n/8] = byte_out; n++; } assert(n == 8*fec_get_enc_msg_length(_q->scheme,_dec_msg_len)); } //unsigned int void fec_conv_decode_hard(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { // re-allocate resources if necessary fec_conv_setlength(_q, _dec_msg_len); // unpack bytes unsigned int num_written; liquid_unpack_bytes(_msg_enc, // encoded message (bytes) _q->num_enc_bytes, // encoded message length (#bytes) _q->enc_bits, // encoded messsage (bits) _q->num_enc_bytes*8, // encoded message length (#bits) &num_written); #if VERBOSE_FEC_CONV unsigned int i; printf("msg encoded (bits):\n"); for (i=0; i<8*_q->num_enc_bytes; i++) { printf("%1u", _q->enc_bits[i]); if (((i+1)%8)==0) printf(" "); } printf("\n"); #endif // invoke hard-decision scaling unsigned int k; for (k=0; k<8*_q->num_enc_bytes; k++) _q->enc_bits[k] = _q->enc_bits[k] ? LIQUID_SOFTBIT_1 : LIQUID_SOFTBIT_0; // run internal decoder fec_conv_decode(_q, _msg_dec); } //unsigned int void fec_conv_decode_soft(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { // re-allocate resources if necessary fec_conv_setlength(_q, _dec_msg_len); // copy soft input bits unsigned int k; for (k=0; k<8*_q->num_enc_bytes; k++) _q->enc_bits[k] = _msg_enc[k]; // run internal decoder fec_conv_decode(_q, _msg_dec); } //unsigned int void fec_conv_decode(fec _q, unsigned char *_msg_dec) { // run decoder _q->init_viterbi(_q->vp,0); _q->update_viterbi_blk(_q->vp, _q->enc_bits, 8*_q->num_dec_bytes+_q->K-1); _q->chainback_viterbi(_q->vp, _msg_dec, 8*_q->num_dec_bytes, 0); #if VERBOSE_FEC_CONV for (i=0; i<_dec_msg_len; i++) printf("%.2x ", _msg_dec[i]); printf("\n"); #endif } void fec_conv_setlength(fec _q, unsigned int _dec_msg_len) { // re-allocate resources as necessary unsigned int num_dec_bytes = _dec_msg_len; // return if length has not changed if (num_dec_bytes == _q->num_dec_bytes) return; #if VERBOSE_FEC_CONV printf("(re)creating viterbi decoder, %u frame bytes\n", num_dec_bytes); #endif // reset number of framebits _q->num_dec_bytes = num_dec_bytes; _q->num_enc_bytes = fec_get_enc_msg_length(_q->scheme, _dec_msg_len); // delete old decoder if necessary if (_q->vp != NULL) _q->delete_viterbi(_q->vp); // re-create / re-allocate memory buffers _q->vp = _q->create_viterbi(8*_q->num_dec_bytes); _q->enc_bits = (unsigned char*) realloc(_q->enc_bits, _q->num_enc_bytes*8*sizeof(unsigned char)); } // // internal // void fec_conv_init_v27(fec _q) { _q->R=2; _q->K=7; _q->poly = fec_conv27_poly; _q->create_viterbi = create_viterbi27; _q->init_viterbi = init_viterbi27; _q->update_viterbi_blk = update_viterbi27_blk; _q->chainback_viterbi = chainback_viterbi27; _q->delete_viterbi = delete_viterbi27; } void fec_conv_init_v29(fec _q) { _q->R=2; _q->K=9; _q->poly = fec_conv29_poly; _q->create_viterbi = create_viterbi29; _q->init_viterbi = init_viterbi29; _q->update_viterbi_blk = update_viterbi29_blk; _q->chainback_viterbi = chainback_viterbi29; _q->delete_viterbi = delete_viterbi29; } void fec_conv_init_v39(fec _q) { _q->R=3; _q->K=9; _q->poly = fec_conv39_poly; _q->create_viterbi = create_viterbi39; _q->init_viterbi = init_viterbi39; _q->update_viterbi_blk = update_viterbi39_blk; _q->chainback_viterbi = chainback_viterbi39; _q->delete_viterbi = delete_viterbi39; } void fec_conv_init_v615(fec _q) { _q->R=6; _q->K=15; _q->poly = fec_conv615_poly; _q->create_viterbi = create_viterbi615; _q->init_viterbi = init_viterbi615; _q->update_viterbi_blk = update_viterbi615_blk; _q->chainback_viterbi = chainback_viterbi615; _q->delete_viterbi = delete_viterbi615; } #else // LIBFEC_ENABLED fec fec_conv_create(fec_scheme _fs) { return NULL; } void fec_conv_destroy(fec _q) { } #endif // LIBFEC_ENABLED liquid-dsp-1.3.1/src/fec/src/fec_conv_pmatrix.c000066400000000000000000000047631317124540100214040ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "liquid.internal.h" // 2/3-rate K=7 punctured convolutional code int fec_conv27p23_matrix[4] = { 1, 1, 1, 0 }; // 3/4-rate K=7 punctured convolutional code int fec_conv27p34_matrix[6] = { 1, 1, 0, 1, 0, 1 }; // 4/5-rate K=7 punctured convolutional code int fec_conv27p45_matrix[8] = { 1, 1, 1, 1, 1, 0, 0, 0 }; // 5/6-rate K=7 punctured convolutional code int fec_conv27p56_matrix[10] = { 1, 1, 0, 1, 0, 1, 0, 1, 0, 1 }; // 6/7-rate K=7 punctured convolutional code int fec_conv27p67_matrix[12] = { 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1 }; // 7/8-rate K=7 punctured convolutional code int fec_conv27p78_matrix[14] = { 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1 }; // 2/3-rate K=9 punctured convolutional code int fec_conv29p23_matrix[4] = { 1, 1, 1, 0 }; // 3/4-rate K=9 punctured convolutional code int fec_conv29p34_matrix[6] = { 1, 1, 1, 1, 0, 0 }; // 4/5-rate K=9 punctured convolutional code int fec_conv29p45_matrix[8] = { 1, 1, 0, 1, 1, 0, 1, 0 }; // 5/6-rate K=9 punctured convolutional code int fec_conv29p56_matrix[10] = { 1, 0, 1, 1, 0, 1, 1, 0, 0, 1 }; // 6/7-rate K=9 punctured convolutional code int fec_conv29p67_matrix[12] = { 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1 }; // 7/8-rate K=9 punctured convolutional code int fec_conv29p78_matrix[14] = { 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0 }; liquid-dsp-1.3.1/src/fec/src/fec_conv_poly.c000066400000000000000000000035411317124540100206740ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // convolutional code polynomials // #include "liquid.internal.h" #if LIBFEC_ENABLED #include int fec_conv27_poly[2] = {V27POLYA, V27POLYB}; int fec_conv29_poly[2] = {V29POLYA, V29POLYB}; int fec_conv39_poly[3] = {V39POLYA, V39POLYB, V39POLYC}; int fec_conv615_poly[6] = {V615POLYA, V615POLYB, V615POLYC, V615POLYD, V615POLYE, V615POLYF}; #else int fec_conv27_poly[2] = {0,0}; int fec_conv29_poly[2] = {0,0}; int fec_conv39_poly[3] = {0,0,0}; int fec_conv615_poly[6] = {0,0,0,0,0,0}; #endif liquid-dsp-1.3.1/src/fec/src/fec_conv_punctured.c000066400000000000000000000320471317124540100217250ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // convolutional code (macros) // #include #include #include #include "liquid.internal.h" #define VERBOSE_FEC_CONV_PUNCTURED 0 #if LIBFEC_ENABLED #include "fec.h" fec fec_conv_punctured_create(fec_scheme _fs) { fec q = (fec) malloc(sizeof(struct fec_s)); q->scheme = _fs; q->rate = fec_get_rate(q->scheme); q->encode_func = &fec_conv_punctured_encode; q->decode_func = &fec_conv_punctured_decode_hard; q->decode_soft_func = &fec_conv_punctured_decode_soft; switch (q->scheme) { case LIQUID_FEC_CONV_V27P23: fec_conv_init_v27p23(q); break; case LIQUID_FEC_CONV_V27P34: fec_conv_init_v27p34(q); break; case LIQUID_FEC_CONV_V27P45: fec_conv_init_v27p45(q); break; case LIQUID_FEC_CONV_V27P56: fec_conv_init_v27p56(q); break; case LIQUID_FEC_CONV_V27P67: fec_conv_init_v27p67(q); break; case LIQUID_FEC_CONV_V27P78: fec_conv_init_v27p78(q); break; case LIQUID_FEC_CONV_V29P23: fec_conv_init_v29p23(q); break; case LIQUID_FEC_CONV_V29P34: fec_conv_init_v29p34(q); break; case LIQUID_FEC_CONV_V29P45: fec_conv_init_v29p45(q); break; case LIQUID_FEC_CONV_V29P56: fec_conv_init_v29p56(q); break; case LIQUID_FEC_CONV_V29P67: fec_conv_init_v29p67(q); break; case LIQUID_FEC_CONV_V29P78: fec_conv_init_v29p78(q); break; default: fprintf(stderr,"error: fec_conv_punctured_create(), invalid type\n"); exit(1); } // convolutional-specific decoding q->num_dec_bytes = 0; q->enc_bits = NULL; q->vp = NULL; return q; } void fec_conv_punctured_destroy(fec _q) { // delete viterbi decoder if (_q->vp != NULL) _q->delete_viterbi(_q->vp); if (_q->enc_bits != NULL) free(_q->enc_bits); free(_q); } void fec_conv_punctured_encode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_dec, unsigned char *_msg_enc) { unsigned int i,j,r; // bookkeeping unsigned int sr=0; // convolutional shift register unsigned int n=0; // output bit counter unsigned int p=0; // puncturing matrix column index unsigned char bit; unsigned char byte_in; unsigned char byte_out=0; for (i=0; i<_dec_msg_len; i++) { byte_in = _msg_dec[i]; // break byte into individual bits for (j=0; j<8; j++) { // shift bit starting with most significant bit = (byte_in >> (7-j)) & 0x01; sr = (sr << 1) | bit; // compute parity bits for each polynomial for (r=0; r<_q->R; r++) { // enable output determined by puncturing matrix if (_q->puncturing_matrix[r*(_q->P)+p]) { byte_out = (byte_out<<1) | parity(sr & _q->poly[r]); _msg_enc[n/8] = byte_out; n++; } else { } } // update puncturing matrix column index p = (p+1) % _q->P; } } //printf("\n"); //printf("*** n = %u\n", n); // tail bits for (i=0; i<_q->K-1; i++) { // shift register: push zeros sr = (sr << 1); // compute parity bits for each polynomial for (r=0; r<_q->R; r++) { if (_q->puncturing_matrix[r*(_q->P)+p]) { byte_out = (byte_out<<1) | parity(sr & _q->poly[r]); _msg_enc[n/8] = byte_out; n++; } } // update puncturing matrix column index p = (p+1) % _q->P; } //printf("+++ n = %u\n", n); // ensure even number of bytes while (n%8) { // shift zeros byte_out <<= 1; _msg_enc[n/8] = byte_out; n++; } //printf("n = %u (expected %u)\n", n, 8*fec_get_enc_msg_length(LIQUID_FEC_CONV(_mode),_dec_msg_len)); assert(n == 8*fec_get_enc_msg_length(_q->scheme,_dec_msg_len)); } //unsigned int void fec_conv_punctured_decode_hard(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { // re-allocate resources if necessary fec_conv_punctured_setlength(_q, _dec_msg_len); // unpack bytes, adding erasures at punctured indices unsigned int num_dec_bits = _q->num_dec_bytes * 8 + _q->K - 1; unsigned int num_enc_bits = num_dec_bits * _q->R; unsigned int i,r; unsigned int n=0; // input byte index unsigned int k=0; // intput bit index (0<=k<8) unsigned int p=0; // puncturing matrix column index unsigned char bit; unsigned char byte_in = _msg_enc[n]; for (i=0; iR) { // for (r=0; r<_q->R; r++) { if (_q->puncturing_matrix[r*(_q->P)+p]) { // push bit from input bit = (byte_in >> (7-k)) & 0x01; _q->enc_bits[i+r] = bit ? LIQUID_SOFTBIT_1 : LIQUID_SOFTBIT_0; k++; if (k==8) { k = 0; n++; byte_in = _msg_enc[n]; } } else { // push erasure _q->enc_bits[i+r] = LIQUID_SOFTBIT_ERASURE; } } p = (p+1) % _q->P; } #if VERBOSE_FEC_CONV_PUNCTURED unsigned int ii; printf("msg encoded (bits):\n"); for (ii=0; iienc_bits[ii]); if (((ii+1)%8)==0) printf("\n"); } printf("\n"); #endif // run decoder _q->init_viterbi(_q->vp,0); // TODO : check to see if this shouldn't be num_enc_bits (punctured) _q->update_viterbi_blk(_q->vp, _q->enc_bits, 8*_q->num_dec_bytes+_q->K-1); _q->chainback_viterbi(_q->vp, _msg_dec, 8*_q->num_dec_bytes, 0); #if VERBOSE_FEC_CONV_PUNCTURED for (ii=0; ii<_dec_msg_len; ii++) printf("%.2x ", _msg_dec[ii]); printf("\n"); #endif } //unsigned int void fec_conv_punctured_decode_soft(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { // re-allocate resources if necessary fec_conv_punctured_setlength(_q, _dec_msg_len); // unpack bytes, adding erasures at punctured indices unsigned int num_dec_bits = _q->num_dec_bytes * 8 + _q->K - 1; unsigned int num_enc_bits = num_dec_bits * _q->R; unsigned int i,r; unsigned int n=0; // input soft bit index unsigned int p=0; // puncturing matrix column index for (i=0; iR) { // for (r=0; r<_q->R; r++) { if (_q->puncturing_matrix[r*(_q->P)+p]) { // push bit from input _q->enc_bits[i+r] = _msg_enc[n++]; } else { // push erasure _q->enc_bits[i+r] = LIQUID_SOFTBIT_ERASURE; } } p = (p+1) % _q->P; } #if VERBOSE_FEC_CONV_PUNCTURED unsigned int ii; printf("msg encoded (bits):\n"); for (ii=0; iienc_bits[ii]); if (((ii+1)%8)==0) printf("\n"); } printf("\n"); #endif // run decoder _q->init_viterbi(_q->vp,0); // TODO : check to see if this shouldn't be num_enc_bits (punctured) _q->update_viterbi_blk(_q->vp, _q->enc_bits, 8*_q->num_dec_bytes+_q->K-1); _q->chainback_viterbi(_q->vp, _msg_dec, 8*_q->num_dec_bytes, 0); #if VERBOSE_FEC_CONV_PUNCTURED for (ii=0; ii<_dec_msg_len; ii++) printf("%.2x ", _msg_dec[ii]); printf("\n"); #endif } void fec_conv_punctured_setlength(fec _q, unsigned int _dec_msg_len) { // re-allocate resources as necessary unsigned int num_dec_bytes = _dec_msg_len; // return if length has not changed if (num_dec_bytes == _q->num_dec_bytes) return; // reset number of framebits _q->num_dec_bytes = num_dec_bytes; _q->num_enc_bytes = fec_get_enc_msg_length(_q->scheme, _dec_msg_len); // puncturing: need to expand to full length (decoder // injects erasures at punctured values) unsigned int num_dec_bits = 8*_q->num_dec_bytes; unsigned int n = num_dec_bits + _q->K - 1; unsigned int num_enc_bits = n*(_q->R); #if VERBOSE_FEC_CONV_PUNCTURED printf("(re)creating viterbi decoder, %u frame bytes\n", num_dec_bytes); printf(" num decoded bytes : %u\n", _q->num_dec_bytes); printf(" num encoded bytes : %u\n", _q->num_enc_bytes); printf(" num decoded bits : %u\n", num_dec_bits); printf(" num decoded bits (padded) : %u\n", n); printf(" num encoded bits (full) : %u\n", num_enc_bits); #endif // delete old decoder if necessary if (_q->vp != NULL) _q->delete_viterbi(_q->vp); // re-create / re-allocate memory buffers _q->vp = _q->create_viterbi(8*_q->num_dec_bytes); _q->enc_bits = (unsigned char*) realloc(_q->enc_bits, num_enc_bits*sizeof(unsigned char)); } // // internal // void fec_conv_init_v27p23(fec _q) { // initialize R, K, polynomial, and viterbi methods fec_conv_init_v27(_q); _q->P = 2; _q->puncturing_matrix = fec_conv27p23_matrix; } void fec_conv_init_v27p34(fec _q) { // initialize R, K, polynomial, and viterbi methods fec_conv_init_v27(_q); _q->P = 3; _q->puncturing_matrix = fec_conv27p34_matrix; } void fec_conv_init_v27p45(fec _q) { // initialize R, K, polynomial, and viterbi methods fec_conv_init_v27(_q); _q->P = 4; _q->puncturing_matrix = fec_conv27p45_matrix; } void fec_conv_init_v27p56(fec _q) { // initialize R, K, polynomial, and viterbi methods fec_conv_init_v27(_q); _q->P = 5; _q->puncturing_matrix = fec_conv27p56_matrix; } void fec_conv_init_v27p67(fec _q) { // initialize R, K, polynomial, and viterbi methods fec_conv_init_v27(_q); _q->P = 6; _q->puncturing_matrix = fec_conv27p67_matrix; } void fec_conv_init_v27p78(fec _q) { // initialize R, K, polynomial, and viterbi methods fec_conv_init_v27(_q); _q->P = 7; _q->puncturing_matrix = fec_conv27p78_matrix; } void fec_conv_init_v29p23(fec _q) { // initialize R, K, polynomial, and viterbi methods fec_conv_init_v29(_q); _q->P = 2; _q->puncturing_matrix = fec_conv29p23_matrix; } void fec_conv_init_v29p34(fec _q) { // initialize R, K, polynomial, and viterbi methods fec_conv_init_v29(_q); _q->P = 3; _q->puncturing_matrix = fec_conv29p34_matrix; } void fec_conv_init_v29p45(fec _q) { // initialize R, K, polynomial, and viterbi methods fec_conv_init_v29(_q); _q->P = 4; _q->puncturing_matrix = fec_conv29p45_matrix; } void fec_conv_init_v29p56(fec _q) { // initialize R, K, polynomial, and viterbi methods fec_conv_init_v29(_q); _q->P = 5; _q->puncturing_matrix = fec_conv29p56_matrix; } void fec_conv_init_v29p67(fec _q) { // initialize R, K, polynomial, and viterbi methods fec_conv_init_v29(_q); _q->P = 6; _q->puncturing_matrix = fec_conv29p67_matrix; } void fec_conv_init_v29p78(fec _q) { // initialize R, K, polynomial, and viterbi methods fec_conv_init_v29(_q); _q->P = 7; _q->puncturing_matrix = fec_conv29p78_matrix; } #else // LIBFEC_ENABLED fec fec_conv_punctured_create(fec_scheme _fs) { return NULL; } void fec_conv_punctured_destroy(fec _q) { } void fec_conv_punctured_encode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_dec, unsigned char *_msg_enc) { } //unsigned int void fec_conv_punctured_decode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { } #endif // LIBFEC_ENABLED liquid-dsp-1.3.1/src/fec/src/fec_golay2412.c000066400000000000000000000322331317124540100203100ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Golay(24,12) half-rate forward error-correction code // // References: // [Lin:2004] Lin, Shu and Costello, Daniel L. Jr., "Error Control // Coding," Prentice Hall, New Jersey, 2nd edition, 2004. // #include #include #include #include "liquid.internal.h" #define DEBUG_FEC_GOLAY2412 0 // P matrix [12 x 12] unsigned int golay2412_P[12] = { 0x08ed, 0x01db, 0x03b5, 0x0769, 0x0ed1, 0x0da3, 0x0b47, 0x068f, 0x0d1d, 0x0a3b, 0x0477, 0x0ffe}; #if 0 // generator matrix [12 x 24] unsigned int golay2412_G[12] = { 0x008ed800, 0x001db400, 0x003b5200, 0x00769100, 0x00ed1080, 0x00da3040, 0x00b47020, 0x0068f010, 0x00d1d008, 0x00a3b004, 0x00477002, 0x00ffe001}; #endif // generator matrix transposed [24 x 12] unsigned int golay2412_Gt[24] = { 0x08ed, 0x01db, 0x03b5, 0x0769, 0x0ed1, 0x0da3, 0x0b47, 0x068f, 0x0d1d, 0x0a3b, 0x0477, 0x0ffe, 0x0800, 0x0400, 0x0200, 0x0100, 0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001}; // parity check matrix [12 x 24] unsigned int golay2412_H[12] = { 0x008008ed, 0x004001db, 0x002003b5, 0x00100769, 0x00080ed1, 0x00040da3, 0x00020b47, 0x0001068f, 0x00008d1d, 0x00004a3b, 0x00002477, 0x00001ffe}; // multiply input vector with parity check matrix, H unsigned int golay2412_matrix_mul(unsigned int _v, unsigned int * _A, unsigned int _n) { unsigned int x = 0; unsigned int i; for (i=0; i<_n; i++) { x <<= 1; #if 0 // compute dot product mod 2 x |= liquid_count_ones_mod2( _A[i] & _v ); #else // same as above, but exploit the fact that vectors are at // most 24 bits long; liquid_count_ones_mod2() assumes full // 32- or 64-bit integer unsigned int c = 0; unsigned int p = _A[i] & _v; c += liquid_c_ones[ p & 0xff ]; p >>= 8; c += liquid_c_ones[ p & 0xff ]; p >>= 8; c += liquid_c_ones[ p & 0xff ]; x |= c & 0x0001; // mod 2 #endif } return x; } unsigned int fec_golay2412_encode_symbol(unsigned int _sym_dec) { // validate input if (_sym_dec >= (1<<12)) { fprintf(stderr,"error, fec_golay2412_encode_symbol(), input symbol too large\n"); exit(1); } // compute encoded/transmitted message: v = m*G return golay2412_matrix_mul(_sym_dec, golay2412_Gt, 24); } // search for p[i] such that w(v+p[i]) <= 2, return -1 on fail int golay2412_parity_search(unsigned int _v) { //assert( _v < (1<<12) ); unsigned int i; for (i=0; i<12; i++) { #if 0 unsigned int wj = liquid_count_ones(_v ^ golay2412_P[i]); #else // same as above but faster, exploiting fact that P has // only 12 bits of resolution unsigned int wj = 0; unsigned int p = _v ^ golay2412_P[i]; wj += liquid_c_ones[ (p ) & 0xff ]; wj += liquid_c_ones[ (p >> 8) & 0xff ]; #endif if (wj <= 2) return i; } // could not find p[i] to satisfy criteria return -1; } unsigned int fec_golay2412_decode_symbol(unsigned int _sym_enc) { // validate input if (_sym_enc >= (1<<24)) { fprintf(stderr,"error, fec_golay2412_decode_symbol(), input symbol too large\n"); exit(1); } // state variables unsigned int s=0; // syndrome vector unsigned int e_hat=0; // estimated error vector unsigned int v_hat=0; // estimated transmitted message unsigned int m_hat=0; // estimated original message // compute syndrome vector, s = r*H^T = ( H*r^T )^T s = golay2412_matrix_mul(_sym_enc, golay2412_H, 12); #if DEBUG_FEC_GOLAY2412 printf("s (syndrome vector): "); liquid_print_bitstring(s,12); printf("\n"); #endif // compute weight of s (12 bits) unsigned int ws = liquid_count_ones_uint16(s); #if DEBUG_FEC_GOLAY2412 printf("w(s) = %u\n", ws); #endif // step 2: e_hat = 0; if (ws <= 3) { #if DEBUG_FEC_GOLAY2412 printf(" w(s) <= 3: estimating error vector as [s, 0(12)]\n"); #endif // set e_hat = [s 0(12)] e_hat = (s << 12) & 0xfff000; } else { // step 3: search for p[i] s.t. w(s+p[i]) <= 2 #if DEBUG_FEC_GOLAY2412 printf(" searching for w(s + p_i) <= 2...\n"); #endif int s_index = golay2412_parity_search(s); if (s_index >= 0) { // vector found! #if DEBUG_FEC_GOLAY2412 printf(" w(s + p[%2u]) <= 2: estimating error vector as [s+p[%2u],u[%2u]]\n", s_index, s_index, s_index); #endif // NOTE : uj = 1 << (12-j-1) e_hat = ((s ^ golay2412_P[s_index]) << 12) | (1 << (11-s_index)); } else { // step 4: compute s*P unsigned int sP = golay2412_matrix_mul(s, golay2412_P, 12); #if DEBUG_FEC_GOLAY2412 printf("s*P: "); liquid_print_bitstring(sP,12); printf("\n"); #endif // compute weight of sP (12 bits) unsigned int wsP = liquid_count_ones_uint16(sP); #if DEBUG_FEC_GOLAY2412 printf("w(s*P) = %u\n", wsP); #endif if (wsP == 2 || wsP == 3) { // step 5: set e = [0, s*P] #if DEBUG_FEC_GOLAY2412 printf(" w(s*P) in [2,3]: estimating error vector as [0(12), s*P]\n"); #endif e_hat = sP; } else { // step 6: search for p[i] s.t. w(s*P + p[i]) == 2... #if DEBUG_FEC_GOLAY2412 printf(" searching for w(s*P + p_i) == 2...\n"); #endif int sP_index = golay2412_parity_search(sP); if (sP_index >= 0) { // vector found! #if DEBUG_FEC_GOLAY2412 printf(" w(s*P + p[%2u]) == 2: estimating error vector as [u[%2u],s*P+p[%2u]]\n", sP_index, sP_index, sP_index); #endif // NOTE : uj = 1 << (12-j-1) // [ uj << 1 2 ] [ sP + p[j] ] e_hat = (1 << (23-sP_index)) | (sP ^ golay2412_P[sP_index]); } else { // step 7: decoding error #if DEBUG_FEC_GOLAY2412 printf(" **** decoding error\n"); #endif } } } } // step 8: compute estimated transmitted message: v_hat = r + e_hat v_hat = _sym_enc ^ e_hat; #if DEBUG_FEC_GOLAY2412 printf("r (recevied vector): "); liquid_print_bitstring(_sym_enc,24); printf("\n"); printf("e-hat (estimated error vector): "); liquid_print_bitstring(e_hat,24); printf("\n"); printf("v-hat (estimated tx vector): "); liquid_print_bitstring(v_hat,24); printf("\n"); #endif // compute estimated original message: (last 12 bits of encoded message) m_hat = v_hat & 0x0fff; return m_hat; } // create Golay(24,12) codec object fec fec_golay2412_create(void * _opts) { fec q = (fec) malloc(sizeof(struct fec_s)); // set scheme q->scheme = LIQUID_FEC_GOLAY2412; q->rate = fec_get_rate(q->scheme); // set internal function pointers q->encode_func = &fec_golay2412_encode; q->decode_func = &fec_golay2412_decode; q->decode_soft_func = NULL; return q; } // destroy Golay(24,12) object void fec_golay2412_destroy(fec _q) { free(_q); } // encode block of data using Golay(24,12) encoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_dec : decoded message [size: 1 x _dec_msg_len] // _msg_enc : encoded message [size: 1 x 2*_dec_msg_len] void fec_golay2412_encode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_dec, unsigned char *_msg_enc) { unsigned int i=0; // decoded byte counter unsigned int j=0; // encoded byte counter unsigned int s0, s1, s2; // three 8-bit symbols unsigned int m0, m1; // two 12-bit symbols (uncoded) unsigned int v0, v1; // two 24-bit symbols (encoded) // determine remainder of input length / 3 unsigned int r = _dec_msg_len % 3; for (i=0; i<_dec_msg_len-r; i+=3) { // strip three input bytes (two uncoded symbols) s0 = _msg_dec[i+0]; s1 = _msg_dec[i+1]; s2 = _msg_dec[i+2]; // pack into two 12-bit symbols m0 = ((s0 << 4) & 0x0ff0) | ((s1 >> 4) & 0x000f); m1 = ((s1 << 8) & 0x0f00) | ((s2 ) & 0x00ff); // encode each 12-bit symbol into a 24-bit symbol v0 = fec_golay2412_encode_symbol(m0); v1 = fec_golay2412_encode_symbol(m1); // unpack two 24-bit symbols into six 8-bit bytes // retaining order of bits in output _msg_enc[j+0] = (v0 >> 16) & 0xff; _msg_enc[j+1] = (v0 >> 8) & 0xff; _msg_enc[j+2] = (v0 ) & 0xff; _msg_enc[j+3] = (v1 >> 16) & 0xff; _msg_enc[j+4] = (v1 >> 8) & 0xff; _msg_enc[j+5] = (v1 ) & 0xff; j += 6; } // if input length isn't divisible by 3, encode last 1 or two bytes for (i=_dec_msg_len-r; i<_dec_msg_len; i++) { // strip last input symbol s0 = _msg_dec[i]; // extend as 12-bit symbol m0 = s0; // encode into 24-bit symbol v0 = fec_golay2412_encode_symbol(m0); // unpack one 24-bit symbol into three 8-bit bytes, and // append to output array _msg_enc[j+0] = ( v0 >> 16 ) & 0xff; _msg_enc[j+1] = ( v0 >> 8 ) & 0xff; _msg_enc[j+2] = ( v0 ) & 0xff; j += 3; } assert( j == fec_get_enc_msg_length(LIQUID_FEC_GOLAY2412,_dec_msg_len) ); assert( i == _dec_msg_len); } // decode block of data using Golay(24,12) decoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_enc : encoded message [size: 1 x 2*_dec_msg_len] // _msg_dec : decoded message [size: 1 x _dec_msg_len] // //unsigned int void fec_golay2412_decode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { unsigned int i=0; // decoded byte counter unsigned int j=0; // encoded byte counter unsigned int r0, r1, r2, r3, r4, r5; // six 8-bit bytes unsigned int v0, v1; // two 24-bit encoded symbols unsigned int m0_hat, m1_hat; // two 12-bit decoded symbols // determine remainder of input length / 3 unsigned int r = _dec_msg_len % 3; for (i=0; i<_dec_msg_len-r; i+=3) { // strip six input bytes (two encoded symbols) r0 = _msg_enc[j+0]; r1 = _msg_enc[j+1]; r2 = _msg_enc[j+2]; r3 = _msg_enc[j+3]; r4 = _msg_enc[j+4]; r5 = _msg_enc[j+5]; // pack six 8-bit symbols into two 24-bit symbols v0 = ((r0 << 16) & 0xff0000) | ((r1 << 8) & 0x00ff00) | ((r2 ) & 0x0000ff); v1 = ((r3 << 16) & 0xff0000) | ((r4 << 8) & 0x00ff00) | ((r5 << 0) & 0x0000ff); // decode each symbol into a 12-bit symbol m0_hat = fec_golay2412_decode_symbol(v0); m1_hat = fec_golay2412_decode_symbol(v1); // unpack two 12-bit symbols into three 8-bit bytes _msg_dec[i+0] = ((m0_hat >> 4) & 0xff); _msg_dec[i+1] = ((m0_hat << 4) & 0xf0) | ((m1_hat >> 8) & 0x0f); _msg_dec[i+2] = ((m1_hat ) & 0xff); j += 6; } // if input length isn't divisible by 3, decode last 1 or two bytes for (i=_dec_msg_len-r; i<_dec_msg_len; i++) { // strip last input symbol (three bytes) r0 = _msg_enc[j+0]; r1 = _msg_enc[j+1]; r2 = _msg_enc[j+2]; // pack three 8-bit symbols into one 24-bit symbol v0 = ((r0 << 16) & 0xff0000) | ((r1 << 8) & 0x00ff00) | ((r2 ) & 0x0000ff); // decode into a 12-bit symbol m0_hat = fec_golay2412_decode_symbol(v0); // retain last 8 bits of 12-bit symbol _msg_dec[i] = m0_hat & 0xff; j += 3; } assert( j== fec_get_enc_msg_length(LIQUID_FEC_GOLAY2412,_dec_msg_len) ); assert( i == _dec_msg_len); //return num_errors; } liquid-dsp-1.3.1/src/fec/src/fec_hamming128.c000066400000000000000000000400441317124540100205360ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // 2/3-rate (12,8) Hamming code // // bit position 1 2 3 4 5 6 7 8 9 10 11 12 // encoded bits P1 P2 1 P4 2 3 4 P8 5 6 7 8 // // parity bit P1 x . x . x . x . x . x . // coveratge P2 . x x . . x x . . x x . // P4 . . . x x x x . . . . x // P8 . . . . . . . x x x x x #include #include #include #include "liquid.internal.h" #define DEBUG_FEC_HAMMING128 0 // debugging flag #define FEC_HAMMING128_ENC_GENTAB 1 // use look-up table for encoding? // parity bit coverage mask for encoder (collapsed version of figure // above, stripping out parity bits P1, P2, P4, P8 and only including // data bits 1:8) // // bit position 3 5 6 7 9 10 11 12 // // parity bit P1 x x . x x . x . = 1101 1010 // coverage P2 x . x x . x x . = 1011 0110 // P4 . x x x . . . x = 0111 0001 // P8 . . . . x x x x = 0000 1111 #define HAMMING128_M1 0xda // 1101 1010 #define HAMMING128_M2 0xb6 // 1011 0110 #define HAMMING128_M4 0x71 // 0111 0001 #define HAMMING128_M8 0x0f // 0000 1111 // parity bit coverage mask for decoder; used to compute syndromes // for decoding a received message (see first figure, above). #define HAMMING128_S1 0x0aaa // .... 1010 1010 1010 #define HAMMING128_S2 0x0666 // .... 0110 0110 0110 #define HAMMING128_S4 0x01e1 // .... 0001 1110 0001 #define HAMMING128_S8 0x001f // .... 0000 0001 1111 unsigned int fec_hamming128_encode_symbol(unsigned int _sym_dec) { // validate input if (_sym_dec >= (1<<8)) { fprintf(stderr,"error, fec_hamming128_encode(), input symbol too large\n"); exit(1); } // compute parity bits unsigned int p1 = liquid_bdotprod_uint16(_sym_dec, HAMMING128_M1); unsigned int p2 = liquid_bdotprod_uint16(_sym_dec, HAMMING128_M2); unsigned int p4 = liquid_bdotprod_uint16(_sym_dec, HAMMING128_M4); unsigned int p8 = liquid_bdotprod_uint16(_sym_dec, HAMMING128_M8); #if DEBUG_FEC_HAMMING128 printf("parity bits (p1,p2,p4,p8) : (%1u,%1u,%1u,%1u)\n", p1, p2, p4, p8); #endif // encode symbol by inserting parity bits with data bits to // make a 12-bit symbol unsigned int sym_enc = ((_sym_dec & 0x000f) << 0) | ((_sym_dec & 0x0070) << 1) | ((_sym_dec & 0x0080) << 2) | ( p1 << 11 ) | ( p2 << 10 ) | ( p4 << 8 ) | ( p8 << 4 ); return sym_enc; } unsigned int fec_hamming128_decode_symbol(unsigned int _sym_enc) { // validate input if (_sym_enc >= (1<<12)) { fprintf(stderr,"error, fec_hamming128_decode(), input symbol too large\n"); exit(1); } // compute syndrome bits unsigned int s1 = liquid_bdotprod_uint16(_sym_enc, HAMMING128_S1); unsigned int s2 = liquid_bdotprod_uint16(_sym_enc, HAMMING128_S2); unsigned int s4 = liquid_bdotprod_uint16(_sym_enc, HAMMING128_S4); unsigned int s8 = liquid_bdotprod_uint16(_sym_enc, HAMMING128_S8); // index unsigned int z = (s8<<3) | (s4<<2) | (s2<<1) | s1; #if DEBUG_FEC_HAMMING128 printf("syndrome bits (s1,s2,s4,s8) : (%1u,%1u,%1u,%1u)\n", s1, s2, s4, s8); printf("syndrome z : %u\n", z); #endif // flip bit at this position if (z) { if (z > 12) { // if this happens there are likely too many errors // to correct; just pass without trying to do anything //fprintf(stderr,"warning, fec_hamming128_decode_symbol(), syndrome index exceeds 12\n"); } else { //printf("error detected!\n"); _sym_enc ^= 1 << (12-z); } } // strip data bits (x) from encoded symbol with parity bits (.) // symbol: [..x. xxx. xxxx] // 0000 0000 1111 > 0x000f // 0000 1110 0000 > 0x00e0 // 0010 0000 0000 > 0x0200 unsigned int sym_dec = ((_sym_enc & 0x000f) ) | ((_sym_enc & 0x00e0) >> 1) | ((_sym_enc & 0x0200) >> 2); return sym_dec; } // create Hamming(12,8) codec object fec fec_hamming128_create(void * _opts) { fec q = (fec) malloc(sizeof(struct fec_s)); // set scheme q->scheme = LIQUID_FEC_HAMMING128; q->rate = fec_get_rate(q->scheme); // set internal function pointers q->encode_func = &fec_hamming128_encode; q->decode_func = &fec_hamming128_decode; q->decode_soft_func = &fec_hamming128_decode_soft; return q; } // destroy Hamming(12,8) object void fec_hamming128_destroy(fec _q) { free(_q); } // encode block of data using Hamming(12,8) encoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_dec : decoded message [size: 1 x _dec_msg_len] // _msg_enc : encoded message [size: 1 x 2*_dec_msg_len] void fec_hamming128_encode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_dec, unsigned char *_msg_enc) { unsigned int i, j=0; // input/output symbol counters unsigned char s0, s1; // input 8-bit symbols unsigned int m0, m1; // output 12-bit symbols // determine if input length is odd unsigned int r = _dec_msg_len % 2; for (i=0; i<_dec_msg_len-r; i+=2) { // strip two input bytes s0 = _msg_dec[i+0]; s1 = _msg_dec[i+1]; // encode each byte into 12-bit symbols #if FEC_HAMMING128_ENC_GENTAB m0 = hamming128_enc_gentab[s0]; m1 = hamming128_enc_gentab[s1]; #else m0 = fec_hamming128_encode_symbol(s0); m1 = fec_hamming128_encode_symbol(s1); #endif // append both 12-bit symbols to output (three 8-bit bytes), // retaining order of bits in output _msg_enc[j+0] = (m0 >> 4) & 0xff; _msg_enc[j+1] = ((m0 << 4) & 0xf0) | ((m1 >> 8) & 0x0f); _msg_enc[j+2] = (m1 ) & 0xff; j += 3; } // if input length is even, encode last symbol by itself if (r) { // strip last input symbol s0 = _msg_dec[_dec_msg_len-1]; // encode into 12-bit symbol #if FEC_HAMMING128_ENC_GENTAB m0 = hamming128_enc_gentab[s0]; #else m0 = fec_hamming128_encode_symbol(s0); #endif // append to output _msg_enc[j+0] = ( m0 & 0x0ff0 ) >> 4; _msg_enc[j+1] = ( m0 & 0x000f ) << 4; j += 2; } assert(j== fec_get_enc_msg_length(LIQUID_FEC_HAMMING128,_dec_msg_len)); } // decode block of data using Hamming(12,8) decoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_enc : encoded message [size: 1 x 2*_dec_msg_len] // _msg_dec : decoded message [size: 1 x _dec_msg_len] // //unsigned int void fec_hamming128_decode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { unsigned int i=0,j=0; unsigned int r = _dec_msg_len % 2; unsigned char r0, r1, r2; unsigned int m0, m1; for (i=0; i<_dec_msg_len-r; i+=2) { // strip three input symbols r0 = _msg_enc[j+0]; r1 = _msg_enc[j+1]; r2 = _msg_enc[j+2]; // combine three 8-bit symbols into two 12-bit symbols m0 = ((r0 << 4) & 0x0ff0) | ((r1 >> 4) & 0x000f); m1 = ((r1 << 8) & 0x0f00) | ((r2 ) & 0x00ff); // decode each symbol into an 8-bit byte _msg_dec[i+0] = fec_hamming128_decode_symbol(m0); _msg_dec[i+1] = fec_hamming128_decode_symbol(m1); j += 3; } // if input length is even, decode last symbol by itself if (r) { // strip last two input bytes (last byte should only contain // for bits) r0 = _msg_enc[j+0]; r1 = _msg_enc[j+1]; // pack into 12-bit symbol m0 = ((r0 << 4) & 0x0ff0) | ((r1 >> 4) & 0x000f); // decode symbol into an 8-bit byte _msg_dec[i++] = fec_hamming128_decode_symbol(m0); j += 2; } assert(j== fec_get_enc_msg_length(LIQUID_FEC_HAMMING128,_dec_msg_len)); //return num_errors; } // decode block of data using Hamming(12,8) soft decoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_enc : encoded message [size: 8*_enc_msg_len x 1] // _msg_dec : decoded message [size: _dec_msg_len x 1] // //unsigned int void fec_hamming128_decode_soft(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { unsigned int i; unsigned int k=0; // array bit index unsigned int r = _dec_msg_len % 2; // compute encoded message length unsigned int enc_msg_len = (3*_dec_msg_len)/2 + r; unsigned char s; // decoded 8-bit symbol //unsigned char num_errors=0; for (i=0; i<_dec_msg_len; i++) { #if 0 // use true ML soft decoding: about 1.45 dB improvement in Eb/N_0 for a BER of 10^-5 // with a decoding complexity of 1.43M cycles/trial (64-byte block) s = fecsoft_hamming128_decode(&_msg_enc[k]); #else // use n-3 nearest neighbors: about 0.54 dB improvement in Eb/N_0 for a BER of 10^-5 // with a decoding complexity of 124k cycles/trial (64-byte block) s = fecsoft_hamming128_decode_n3(&_msg_enc[k]); #endif k += 12; _msg_dec[i] = (unsigned char)(s & 0xff); //printf(" %3u : 0x%.2x > 0x%.2x, 0x%.2x > 0x%.2x (k=%u)\n", i, r0, s0, r1, s1, k); } k += r*4; // for assert method assert(k == 8*enc_msg_len); //return num_errors; } // // internal methods // // soft decoding of one symbol // NOTE : because this method compares the received symbol to every // possible (256) encoded symbols, it is painfully slow to // run. unsigned int fecsoft_hamming128_decode(unsigned char * _soft_bits) { // find symbol with minimum distance from all 2^8 possible unsigned int d; // distance metric unsigned int dmin = 0; // minimum distance unsigned int s_hat = 0; // estimated transmitted symbol unsigned int c; // encoded symbol unsigned int s; for (s=0; s<256; s++) { // encode symbol #if FEC_HAMMING128_ENC_GENTAB c = hamming128_enc_gentab[s]; #else c = fec_hamming128_encode_symbol(s); #endif // compute distance metric d = 0; d += (c & 0x0800) ? 255 - _soft_bits[ 0] : _soft_bits[ 0]; d += (c & 0x0400) ? 255 - _soft_bits[ 1] : _soft_bits[ 1]; d += (c & 0x0200) ? 255 - _soft_bits[ 2] : _soft_bits[ 2]; d += (c & 0x0100) ? 255 - _soft_bits[ 3] : _soft_bits[ 3]; d += (c & 0x0080) ? 255 - _soft_bits[ 4] : _soft_bits[ 4]; d += (c & 0x0040) ? 255 - _soft_bits[ 5] : _soft_bits[ 5]; d += (c & 0x0020) ? 255 - _soft_bits[ 6] : _soft_bits[ 6]; d += (c & 0x0010) ? 255 - _soft_bits[ 7] : _soft_bits[ 7]; d += (c & 0x0008) ? 255 - _soft_bits[ 8] : _soft_bits[ 8]; d += (c & 0x0004) ? 255 - _soft_bits[ 9] : _soft_bits[ 9]; d += (c & 0x0002) ? 255 - _soft_bits[10] : _soft_bits[10]; d += (c & 0x0001) ? 255 - _soft_bits[11] : _soft_bits[11]; if (d < dmin || s==0) { s_hat = s; dmin = d; } } return s_hat; } // soft decoding of one symbol using nearest neighbors unsigned int fecsoft_hamming128_decode_n3(unsigned char * _soft_bits) { // find symbol with minimum distance from 17 nearest neighbors unsigned int d; // distance metric unsigned int dmin = 0; // minimum distance unsigned int s_hat = 0; // estimated transmitted symbol unsigned int c; // encoded symbol // compute hard-decoded symbol c = 0x0000; c |= (_soft_bits[ 0] > 127) ? 0x0800 : 0; c |= (_soft_bits[ 1] > 127) ? 0x0400 : 0; c |= (_soft_bits[ 2] > 127) ? 0x0200 : 0; c |= (_soft_bits[ 3] > 127) ? 0x0100 : 0; c |= (_soft_bits[ 4] > 127) ? 0x0080 : 0; c |= (_soft_bits[ 5] > 127) ? 0x0040 : 0; c |= (_soft_bits[ 6] > 127) ? 0x0020 : 0; c |= (_soft_bits[ 7] > 127) ? 0x0010 : 0; c |= (_soft_bits[ 8] > 127) ? 0x0008 : 0; c |= (_soft_bits[ 9] > 127) ? 0x0004 : 0; c |= (_soft_bits[10] > 127) ? 0x0002 : 0; c |= (_soft_bits[11] > 127) ? 0x0001 : 0; // decode symbol s_hat = fec_hamming128_decode_symbol(c); // re-encode and compute distance #if FEC_HAMMING128_ENC_GENTAB c = hamming128_enc_gentab[s_hat]; #else c = fec_hamming128_encode_symbol(s_hat); #endif // compute distance metric d = 0; d += (c & 0x0800) ? 255 - _soft_bits[ 0] : _soft_bits[ 0]; d += (c & 0x0400) ? 255 - _soft_bits[ 1] : _soft_bits[ 1]; d += (c & 0x0200) ? 255 - _soft_bits[ 2] : _soft_bits[ 2]; d += (c & 0x0100) ? 255 - _soft_bits[ 3] : _soft_bits[ 3]; d += (c & 0x0080) ? 255 - _soft_bits[ 4] : _soft_bits[ 4]; d += (c & 0x0040) ? 255 - _soft_bits[ 5] : _soft_bits[ 5]; d += (c & 0x0020) ? 255 - _soft_bits[ 6] : _soft_bits[ 6]; d += (c & 0x0010) ? 255 - _soft_bits[ 7] : _soft_bits[ 7]; d += (c & 0x0008) ? 255 - _soft_bits[ 8] : _soft_bits[ 8]; d += (c & 0x0004) ? 255 - _soft_bits[ 9] : _soft_bits[ 9]; d += (c & 0x0002) ? 255 - _soft_bits[10] : _soft_bits[10]; d += (c & 0x0001) ? 255 - _soft_bits[11] : _soft_bits[11]; dmin = d; // search over 17 nearest neighbors unsigned int s; unsigned int i; for (i=0; i<17; i++) { // use look-up table for nearest neighbors s = fecsoft_hamming128_n3[s_hat][i]; // encode symbol #if FEC_HAMMING128_ENC_GENTAB c = hamming128_enc_gentab[s]; #else c = fec_hamming128_encode_symbol(s); #endif // compute distance metric d = 0; d += (c & 0x0800) ? 255 - _soft_bits[ 0] : _soft_bits[ 0]; d += (c & 0x0400) ? 255 - _soft_bits[ 1] : _soft_bits[ 1]; d += (c & 0x0200) ? 255 - _soft_bits[ 2] : _soft_bits[ 2]; d += (c & 0x0100) ? 255 - _soft_bits[ 3] : _soft_bits[ 3]; d += (c & 0x0080) ? 255 - _soft_bits[ 4] : _soft_bits[ 4]; d += (c & 0x0040) ? 255 - _soft_bits[ 5] : _soft_bits[ 5]; d += (c & 0x0020) ? 255 - _soft_bits[ 6] : _soft_bits[ 6]; d += (c & 0x0010) ? 255 - _soft_bits[ 7] : _soft_bits[ 7]; d += (c & 0x0008) ? 255 - _soft_bits[ 8] : _soft_bits[ 8]; d += (c & 0x0004) ? 255 - _soft_bits[ 9] : _soft_bits[ 9]; d += (c & 0x0002) ? 255 - _soft_bits[10] : _soft_bits[10]; d += (c & 0x0001) ? 255 - _soft_bits[11] : _soft_bits[11]; if (d < dmin) { s_hat = s; dmin = d; } } return s_hat; } liquid-dsp-1.3.1/src/fec/src/fec_hamming128_gentab.c000066400000000000000000000747711317124540100220740ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // 2/3-rate (12,8) Hamming code generated tables // // encoding table unsigned short int hamming128_enc_gentab[256] = { 0x0000, 0x0111, 0x0c12, 0x0d03, 0x0414, 0x0505, 0x0806, 0x0917, 0x0818, 0x0909, 0x040a, 0x051b, 0x0c0c, 0x0d1d, 0x001e, 0x010f, 0x0d20, 0x0c31, 0x0132, 0x0023, 0x0934, 0x0825, 0x0526, 0x0437, 0x0538, 0x0429, 0x092a, 0x083b, 0x012c, 0x003d, 0x0d3e, 0x0c2f, 0x0540, 0x0451, 0x0952, 0x0843, 0x0154, 0x0045, 0x0d46, 0x0c57, 0x0d58, 0x0c49, 0x014a, 0x005b, 0x094c, 0x085d, 0x055e, 0x044f, 0x0860, 0x0971, 0x0472, 0x0563, 0x0c74, 0x0d65, 0x0066, 0x0177, 0x0078, 0x0169, 0x0c6a, 0x0d7b, 0x046c, 0x057d, 0x087e, 0x096f, 0x0980, 0x0891, 0x0592, 0x0483, 0x0d94, 0x0c85, 0x0186, 0x0097, 0x0198, 0x0089, 0x0d8a, 0x0c9b, 0x058c, 0x049d, 0x099e, 0x088f, 0x04a0, 0x05b1, 0x08b2, 0x09a3, 0x00b4, 0x01a5, 0x0ca6, 0x0db7, 0x0cb8, 0x0da9, 0x00aa, 0x01bb, 0x08ac, 0x09bd, 0x04be, 0x05af, 0x0cc0, 0x0dd1, 0x00d2, 0x01c3, 0x08d4, 0x09c5, 0x04c6, 0x05d7, 0x04d8, 0x05c9, 0x08ca, 0x09db, 0x00cc, 0x01dd, 0x0cde, 0x0dcf, 0x01e0, 0x00f1, 0x0df2, 0x0ce3, 0x05f4, 0x04e5, 0x09e6, 0x08f7, 0x09f8, 0x08e9, 0x05ea, 0x04fb, 0x0dec, 0x0cfd, 0x01fe, 0x00ef, 0x0e00, 0x0f11, 0x0212, 0x0303, 0x0a14, 0x0b05, 0x0606, 0x0717, 0x0618, 0x0709, 0x0a0a, 0x0b1b, 0x020c, 0x031d, 0x0e1e, 0x0f0f, 0x0320, 0x0231, 0x0f32, 0x0e23, 0x0734, 0x0625, 0x0b26, 0x0a37, 0x0b38, 0x0a29, 0x072a, 0x063b, 0x0f2c, 0x0e3d, 0x033e, 0x022f, 0x0b40, 0x0a51, 0x0752, 0x0643, 0x0f54, 0x0e45, 0x0346, 0x0257, 0x0358, 0x0249, 0x0f4a, 0x0e5b, 0x074c, 0x065d, 0x0b5e, 0x0a4f, 0x0660, 0x0771, 0x0a72, 0x0b63, 0x0274, 0x0365, 0x0e66, 0x0f77, 0x0e78, 0x0f69, 0x026a, 0x037b, 0x0a6c, 0x0b7d, 0x067e, 0x076f, 0x0780, 0x0691, 0x0b92, 0x0a83, 0x0394, 0x0285, 0x0f86, 0x0e97, 0x0f98, 0x0e89, 0x038a, 0x029b, 0x0b8c, 0x0a9d, 0x079e, 0x068f, 0x0aa0, 0x0bb1, 0x06b2, 0x07a3, 0x0eb4, 0x0fa5, 0x02a6, 0x03b7, 0x02b8, 0x03a9, 0x0eaa, 0x0fbb, 0x06ac, 0x07bd, 0x0abe, 0x0baf, 0x02c0, 0x03d1, 0x0ed2, 0x0fc3, 0x06d4, 0x07c5, 0x0ac6, 0x0bd7, 0x0ad8, 0x0bc9, 0x06ca, 0x07db, 0x0ecc, 0x0fdd, 0x02de, 0x03cf, 0x0fe0, 0x0ef1, 0x03f2, 0x02e3, 0x0bf4, 0x0ae5, 0x07e6, 0x06f7, 0x07f8, 0x06e9, 0x0bea, 0x0afb, 0x03ec, 0x02fd, 0x0ffe, 0x0eef}; // nearest neighbors with Hamming distance 3 (for soft decoding) unsigned char fecsoft_hamming128_n3[256][17] = { {0x01, 0x04, 0x06, 0x08, 0x0a, 0x13, 0x20, 0x25, 0x30, 0x40, 0x49, 0x50, 0x80, 0x82, 0x8c, 0x90, 0xe0}, {0x00, 0x05, 0x07, 0x09, 0x0b, 0x12, 0x21, 0x24, 0x31, 0x41, 0x48, 0x51, 0x81, 0x83, 0x8d, 0x91, 0xe1}, {0x03, 0x04, 0x06, 0x08, 0x0a, 0x11, 0x22, 0x27, 0x32, 0x42, 0x4b, 0x52, 0x80, 0x82, 0x8e, 0x92, 0xe2}, {0x02, 0x05, 0x07, 0x09, 0x0b, 0x10, 0x23, 0x26, 0x33, 0x43, 0x4a, 0x53, 0x81, 0x83, 0x8f, 0x93, 0xe3}, {0x00, 0x02, 0x05, 0x0c, 0x0e, 0x17, 0x21, 0x24, 0x34, 0x44, 0x4d, 0x54, 0x84, 0x86, 0x88, 0x94, 0xe4}, {0x01, 0x03, 0x04, 0x0d, 0x0f, 0x16, 0x20, 0x25, 0x35, 0x45, 0x4c, 0x55, 0x85, 0x87, 0x89, 0x95, 0xe5}, {0x00, 0x02, 0x07, 0x0c, 0x0e, 0x15, 0x23, 0x26, 0x36, 0x46, 0x4f, 0x56, 0x84, 0x86, 0x8a, 0x96, 0xe6}, {0x01, 0x03, 0x06, 0x0d, 0x0f, 0x14, 0x22, 0x27, 0x37, 0x47, 0x4e, 0x57, 0x85, 0x87, 0x8b, 0x97, 0xe7}, {0x00, 0x02, 0x09, 0x0c, 0x0e, 0x1b, 0x28, 0x2d, 0x38, 0x41, 0x48, 0x58, 0x84, 0x88, 0x8a, 0x98, 0xe8}, {0x01, 0x03, 0x08, 0x0d, 0x0f, 0x1a, 0x29, 0x2c, 0x39, 0x40, 0x49, 0x59, 0x85, 0x89, 0x8b, 0x99, 0xe9}, {0x00, 0x02, 0x0b, 0x0c, 0x0e, 0x19, 0x2a, 0x2f, 0x3a, 0x43, 0x4a, 0x5a, 0x86, 0x88, 0x8a, 0x9a, 0xea}, {0x01, 0x03, 0x0a, 0x0d, 0x0f, 0x18, 0x2b, 0x2e, 0x3b, 0x42, 0x4b, 0x5b, 0x87, 0x89, 0x8b, 0x9b, 0xeb}, {0x04, 0x06, 0x08, 0x0a, 0x0d, 0x1f, 0x29, 0x2c, 0x3c, 0x45, 0x4c, 0x5c, 0x80, 0x8c, 0x8e, 0x9c, 0xec}, {0x05, 0x07, 0x09, 0x0b, 0x0c, 0x1e, 0x28, 0x2d, 0x3d, 0x44, 0x4d, 0x5d, 0x81, 0x8d, 0x8f, 0x9d, 0xed}, {0x04, 0x06, 0x08, 0x0a, 0x0f, 0x1d, 0x2b, 0x2e, 0x3e, 0x47, 0x4e, 0x5e, 0x82, 0x8c, 0x8e, 0x9e, 0xee}, {0x05, 0x07, 0x09, 0x0b, 0x0e, 0x1c, 0x2a, 0x2f, 0x3f, 0x46, 0x4f, 0x5f, 0x83, 0x8d, 0x8f, 0x9f, 0xef}, {0x03, 0x11, 0x14, 0x16, 0x18, 0x1a, 0x20, 0x30, 0x35, 0x40, 0x50, 0x59, 0x80, 0x90, 0x92, 0x9c, 0xf0}, {0x02, 0x10, 0x15, 0x17, 0x19, 0x1b, 0x21, 0x31, 0x34, 0x41, 0x51, 0x58, 0x81, 0x91, 0x93, 0x9d, 0xf1}, {0x01, 0x13, 0x14, 0x16, 0x18, 0x1a, 0x22, 0x32, 0x37, 0x42, 0x52, 0x5b, 0x82, 0x90, 0x92, 0x9e, 0xf2}, {0x00, 0x12, 0x15, 0x17, 0x19, 0x1b, 0x23, 0x33, 0x36, 0x43, 0x53, 0x5a, 0x83, 0x91, 0x93, 0x9f, 0xf3}, {0x07, 0x10, 0x12, 0x15, 0x1c, 0x1e, 0x24, 0x31, 0x34, 0x44, 0x54, 0x5d, 0x84, 0x94, 0x96, 0x98, 0xf4}, {0x06, 0x11, 0x13, 0x14, 0x1d, 0x1f, 0x25, 0x30, 0x35, 0x45, 0x55, 0x5c, 0x85, 0x95, 0x97, 0x99, 0xf5}, {0x05, 0x10, 0x12, 0x17, 0x1c, 0x1e, 0x26, 0x33, 0x36, 0x46, 0x56, 0x5f, 0x86, 0x94, 0x96, 0x9a, 0xf6}, {0x04, 0x11, 0x13, 0x16, 0x1d, 0x1f, 0x27, 0x32, 0x37, 0x47, 0x57, 0x5e, 0x87, 0x95, 0x97, 0x9b, 0xf7}, {0x0b, 0x10, 0x12, 0x19, 0x1c, 0x1e, 0x28, 0x38, 0x3d, 0x48, 0x51, 0x58, 0x88, 0x94, 0x98, 0x9a, 0xf8}, {0x0a, 0x11, 0x13, 0x18, 0x1d, 0x1f, 0x29, 0x39, 0x3c, 0x49, 0x50, 0x59, 0x89, 0x95, 0x99, 0x9b, 0xf9}, {0x09, 0x10, 0x12, 0x1b, 0x1c, 0x1e, 0x2a, 0x3a, 0x3f, 0x4a, 0x53, 0x5a, 0x8a, 0x96, 0x98, 0x9a, 0xfa}, {0x08, 0x11, 0x13, 0x1a, 0x1d, 0x1f, 0x2b, 0x3b, 0x3e, 0x4b, 0x52, 0x5b, 0x8b, 0x97, 0x99, 0x9b, 0xfb}, {0x0f, 0x14, 0x16, 0x18, 0x1a, 0x1d, 0x2c, 0x39, 0x3c, 0x4c, 0x55, 0x5c, 0x8c, 0x90, 0x9c, 0x9e, 0xfc}, {0x0e, 0x15, 0x17, 0x19, 0x1b, 0x1c, 0x2d, 0x38, 0x3d, 0x4d, 0x54, 0x5d, 0x8d, 0x91, 0x9d, 0x9f, 0xfd}, {0x0d, 0x14, 0x16, 0x18, 0x1a, 0x1f, 0x2e, 0x3b, 0x3e, 0x4e, 0x57, 0x5e, 0x8e, 0x92, 0x9c, 0x9e, 0xfe}, {0x0c, 0x15, 0x17, 0x19, 0x1b, 0x1e, 0x2f, 0x3a, 0x3f, 0x4f, 0x56, 0x5f, 0x8f, 0x93, 0x9d, 0x9f, 0xff}, {0x00, 0x05, 0x10, 0x21, 0x24, 0x26, 0x28, 0x2a, 0x33, 0x60, 0x69, 0x70, 0xa0, 0xa2, 0xac, 0xb0, 0xc0}, {0x01, 0x04, 0x11, 0x20, 0x25, 0x27, 0x29, 0x2b, 0x32, 0x61, 0x68, 0x71, 0xa1, 0xa3, 0xad, 0xb1, 0xc1}, {0x02, 0x07, 0x12, 0x23, 0x24, 0x26, 0x28, 0x2a, 0x31, 0x62, 0x6b, 0x72, 0xa0, 0xa2, 0xae, 0xb2, 0xc2}, {0x03, 0x06, 0x13, 0x22, 0x25, 0x27, 0x29, 0x2b, 0x30, 0x63, 0x6a, 0x73, 0xa1, 0xa3, 0xaf, 0xb3, 0xc3}, {0x01, 0x04, 0x14, 0x20, 0x22, 0x25, 0x2c, 0x2e, 0x37, 0x64, 0x6d, 0x74, 0xa4, 0xa6, 0xa8, 0xb4, 0xc4}, {0x00, 0x05, 0x15, 0x21, 0x23, 0x24, 0x2d, 0x2f, 0x36, 0x65, 0x6c, 0x75, 0xa5, 0xa7, 0xa9, 0xb5, 0xc5}, {0x03, 0x06, 0x16, 0x20, 0x22, 0x27, 0x2c, 0x2e, 0x35, 0x66, 0x6f, 0x76, 0xa4, 0xa6, 0xaa, 0xb6, 0xc6}, {0x02, 0x07, 0x17, 0x21, 0x23, 0x26, 0x2d, 0x2f, 0x34, 0x67, 0x6e, 0x77, 0xa5, 0xa7, 0xab, 0xb7, 0xc7}, {0x08, 0x0d, 0x18, 0x20, 0x22, 0x29, 0x2c, 0x2e, 0x3b, 0x61, 0x68, 0x78, 0xa4, 0xa8, 0xaa, 0xb8, 0xc8}, {0x09, 0x0c, 0x19, 0x21, 0x23, 0x28, 0x2d, 0x2f, 0x3a, 0x60, 0x69, 0x79, 0xa5, 0xa9, 0xab, 0xb9, 0xc9}, {0x0a, 0x0f, 0x1a, 0x20, 0x22, 0x2b, 0x2c, 0x2e, 0x39, 0x63, 0x6a, 0x7a, 0xa6, 0xa8, 0xaa, 0xba, 0xca}, {0x0b, 0x0e, 0x1b, 0x21, 0x23, 0x2a, 0x2d, 0x2f, 0x38, 0x62, 0x6b, 0x7b, 0xa7, 0xa9, 0xab, 0xbb, 0xcb}, {0x09, 0x0c, 0x1c, 0x24, 0x26, 0x28, 0x2a, 0x2d, 0x3f, 0x65, 0x6c, 0x7c, 0xa0, 0xac, 0xae, 0xbc, 0xcc}, {0x08, 0x0d, 0x1d, 0x25, 0x27, 0x29, 0x2b, 0x2c, 0x3e, 0x64, 0x6d, 0x7d, 0xa1, 0xad, 0xaf, 0xbd, 0xcd}, {0x0b, 0x0e, 0x1e, 0x24, 0x26, 0x28, 0x2a, 0x2f, 0x3d, 0x67, 0x6e, 0x7e, 0xa2, 0xac, 0xae, 0xbe, 0xce}, {0x0a, 0x0f, 0x1f, 0x25, 0x27, 0x29, 0x2b, 0x2e, 0x3c, 0x66, 0x6f, 0x7f, 0xa3, 0xad, 0xaf, 0xbf, 0xcf}, {0x00, 0x10, 0x15, 0x23, 0x31, 0x34, 0x36, 0x38, 0x3a, 0x60, 0x70, 0x79, 0xa0, 0xb0, 0xb2, 0xbc, 0xd0}, {0x01, 0x11, 0x14, 0x22, 0x30, 0x35, 0x37, 0x39, 0x3b, 0x61, 0x71, 0x78, 0xa1, 0xb1, 0xb3, 0xbd, 0xd1}, {0x02, 0x12, 0x17, 0x21, 0x33, 0x34, 0x36, 0x38, 0x3a, 0x62, 0x72, 0x7b, 0xa2, 0xb0, 0xb2, 0xbe, 0xd2}, {0x03, 0x13, 0x16, 0x20, 0x32, 0x35, 0x37, 0x39, 0x3b, 0x63, 0x73, 0x7a, 0xa3, 0xb1, 0xb3, 0xbf, 0xd3}, {0x04, 0x11, 0x14, 0x27, 0x30, 0x32, 0x35, 0x3c, 0x3e, 0x64, 0x74, 0x7d, 0xa4, 0xb4, 0xb6, 0xb8, 0xd4}, {0x05, 0x10, 0x15, 0x26, 0x31, 0x33, 0x34, 0x3d, 0x3f, 0x65, 0x75, 0x7c, 0xa5, 0xb5, 0xb7, 0xb9, 0xd5}, {0x06, 0x13, 0x16, 0x25, 0x30, 0x32, 0x37, 0x3c, 0x3e, 0x66, 0x76, 0x7f, 0xa6, 0xb4, 0xb6, 0xba, 0xd6}, {0x07, 0x12, 0x17, 0x24, 0x31, 0x33, 0x36, 0x3d, 0x3f, 0x67, 0x77, 0x7e, 0xa7, 0xb5, 0xb7, 0xbb, 0xd7}, {0x08, 0x18, 0x1d, 0x2b, 0x30, 0x32, 0x39, 0x3c, 0x3e, 0x68, 0x71, 0x78, 0xa8, 0xb4, 0xb8, 0xba, 0xd8}, {0x09, 0x19, 0x1c, 0x2a, 0x31, 0x33, 0x38, 0x3d, 0x3f, 0x69, 0x70, 0x79, 0xa9, 0xb5, 0xb9, 0xbb, 0xd9}, {0x0a, 0x1a, 0x1f, 0x29, 0x30, 0x32, 0x3b, 0x3c, 0x3e, 0x6a, 0x73, 0x7a, 0xaa, 0xb6, 0xb8, 0xba, 0xda}, {0x0b, 0x1b, 0x1e, 0x28, 0x31, 0x33, 0x3a, 0x3d, 0x3f, 0x6b, 0x72, 0x7b, 0xab, 0xb7, 0xb9, 0xbb, 0xdb}, {0x0c, 0x19, 0x1c, 0x2f, 0x34, 0x36, 0x38, 0x3a, 0x3d, 0x6c, 0x75, 0x7c, 0xac, 0xb0, 0xbc, 0xbe, 0xdc}, {0x0d, 0x18, 0x1d, 0x2e, 0x35, 0x37, 0x39, 0x3b, 0x3c, 0x6d, 0x74, 0x7d, 0xad, 0xb1, 0xbd, 0xbf, 0xdd}, {0x0e, 0x1b, 0x1e, 0x2d, 0x34, 0x36, 0x38, 0x3a, 0x3f, 0x6e, 0x77, 0x7e, 0xae, 0xb2, 0xbc, 0xbe, 0xde}, {0x0f, 0x1a, 0x1f, 0x2c, 0x35, 0x37, 0x39, 0x3b, 0x3e, 0x6f, 0x76, 0x7f, 0xaf, 0xb3, 0xbd, 0xbf, 0xdf}, {0x00, 0x09, 0x10, 0x41, 0x44, 0x46, 0x48, 0x4a, 0x53, 0x60, 0x65, 0x70, 0xa0, 0xc0, 0xc2, 0xcc, 0xd0}, {0x01, 0x08, 0x11, 0x40, 0x45, 0x47, 0x49, 0x4b, 0x52, 0x61, 0x64, 0x71, 0xa1, 0xc1, 0xc3, 0xcd, 0xd1}, {0x02, 0x0b, 0x12, 0x43, 0x44, 0x46, 0x48, 0x4a, 0x51, 0x62, 0x67, 0x72, 0xa2, 0xc0, 0xc2, 0xce, 0xd2}, {0x03, 0x0a, 0x13, 0x42, 0x45, 0x47, 0x49, 0x4b, 0x50, 0x63, 0x66, 0x73, 0xa3, 0xc1, 0xc3, 0xcf, 0xd3}, {0x04, 0x0d, 0x14, 0x40, 0x42, 0x45, 0x4c, 0x4e, 0x57, 0x61, 0x64, 0x74, 0xa4, 0xc4, 0xc6, 0xc8, 0xd4}, {0x05, 0x0c, 0x15, 0x41, 0x43, 0x44, 0x4d, 0x4f, 0x56, 0x60, 0x65, 0x75, 0xa5, 0xc5, 0xc7, 0xc9, 0xd5}, {0x06, 0x0f, 0x16, 0x40, 0x42, 0x47, 0x4c, 0x4e, 0x55, 0x63, 0x66, 0x76, 0xa6, 0xc4, 0xc6, 0xca, 0xd6}, {0x07, 0x0e, 0x17, 0x41, 0x43, 0x46, 0x4d, 0x4f, 0x54, 0x62, 0x67, 0x77, 0xa7, 0xc5, 0xc7, 0xcb, 0xd7}, {0x01, 0x08, 0x18, 0x40, 0x42, 0x49, 0x4c, 0x4e, 0x5b, 0x68, 0x6d, 0x78, 0xa8, 0xc4, 0xc8, 0xca, 0xd8}, {0x00, 0x09, 0x19, 0x41, 0x43, 0x48, 0x4d, 0x4f, 0x5a, 0x69, 0x6c, 0x79, 0xa9, 0xc5, 0xc9, 0xcb, 0xd9}, {0x03, 0x0a, 0x1a, 0x40, 0x42, 0x4b, 0x4c, 0x4e, 0x59, 0x6a, 0x6f, 0x7a, 0xaa, 0xc6, 0xc8, 0xca, 0xda}, {0x02, 0x0b, 0x1b, 0x41, 0x43, 0x4a, 0x4d, 0x4f, 0x58, 0x6b, 0x6e, 0x7b, 0xab, 0xc7, 0xc9, 0xcb, 0xdb}, {0x05, 0x0c, 0x1c, 0x44, 0x46, 0x48, 0x4a, 0x4d, 0x5f, 0x69, 0x6c, 0x7c, 0xac, 0xc0, 0xcc, 0xce, 0xdc}, {0x04, 0x0d, 0x1d, 0x45, 0x47, 0x49, 0x4b, 0x4c, 0x5e, 0x68, 0x6d, 0x7d, 0xad, 0xc1, 0xcd, 0xcf, 0xdd}, {0x07, 0x0e, 0x1e, 0x44, 0x46, 0x48, 0x4a, 0x4f, 0x5d, 0x6b, 0x6e, 0x7e, 0xae, 0xc2, 0xcc, 0xce, 0xde}, {0x06, 0x0f, 0x1f, 0x45, 0x47, 0x49, 0x4b, 0x4e, 0x5c, 0x6a, 0x6f, 0x7f, 0xaf, 0xc3, 0xcd, 0xcf, 0xdf}, {0x00, 0x10, 0x19, 0x43, 0x51, 0x54, 0x56, 0x58, 0x5a, 0x60, 0x70, 0x75, 0xb0, 0xc0, 0xd0, 0xd2, 0xdc}, {0x01, 0x11, 0x18, 0x42, 0x50, 0x55, 0x57, 0x59, 0x5b, 0x61, 0x71, 0x74, 0xb1, 0xc1, 0xd1, 0xd3, 0xdd}, {0x02, 0x12, 0x1b, 0x41, 0x53, 0x54, 0x56, 0x58, 0x5a, 0x62, 0x72, 0x77, 0xb2, 0xc2, 0xd0, 0xd2, 0xde}, {0x03, 0x13, 0x1a, 0x40, 0x52, 0x55, 0x57, 0x59, 0x5b, 0x63, 0x73, 0x76, 0xb3, 0xc3, 0xd1, 0xd3, 0xdf}, {0x04, 0x14, 0x1d, 0x47, 0x50, 0x52, 0x55, 0x5c, 0x5e, 0x64, 0x71, 0x74, 0xb4, 0xc4, 0xd4, 0xd6, 0xd8}, {0x05, 0x15, 0x1c, 0x46, 0x51, 0x53, 0x54, 0x5d, 0x5f, 0x65, 0x70, 0x75, 0xb5, 0xc5, 0xd5, 0xd7, 0xd9}, {0x06, 0x16, 0x1f, 0x45, 0x50, 0x52, 0x57, 0x5c, 0x5e, 0x66, 0x73, 0x76, 0xb6, 0xc6, 0xd4, 0xd6, 0xda}, {0x07, 0x17, 0x1e, 0x44, 0x51, 0x53, 0x56, 0x5d, 0x5f, 0x67, 0x72, 0x77, 0xb7, 0xc7, 0xd5, 0xd7, 0xdb}, {0x08, 0x11, 0x18, 0x4b, 0x50, 0x52, 0x59, 0x5c, 0x5e, 0x68, 0x78, 0x7d, 0xb8, 0xc8, 0xd4, 0xd8, 0xda}, {0x09, 0x10, 0x19, 0x4a, 0x51, 0x53, 0x58, 0x5d, 0x5f, 0x69, 0x79, 0x7c, 0xb9, 0xc9, 0xd5, 0xd9, 0xdb}, {0x0a, 0x13, 0x1a, 0x49, 0x50, 0x52, 0x5b, 0x5c, 0x5e, 0x6a, 0x7a, 0x7f, 0xba, 0xca, 0xd6, 0xd8, 0xda}, {0x0b, 0x12, 0x1b, 0x48, 0x51, 0x53, 0x5a, 0x5d, 0x5f, 0x6b, 0x7b, 0x7e, 0xbb, 0xcb, 0xd7, 0xd9, 0xdb}, {0x0c, 0x15, 0x1c, 0x4f, 0x54, 0x56, 0x58, 0x5a, 0x5d, 0x6c, 0x79, 0x7c, 0xbc, 0xcc, 0xd0, 0xdc, 0xde}, {0x0d, 0x14, 0x1d, 0x4e, 0x55, 0x57, 0x59, 0x5b, 0x5c, 0x6d, 0x78, 0x7d, 0xbd, 0xcd, 0xd1, 0xdd, 0xdf}, {0x0e, 0x17, 0x1e, 0x4d, 0x54, 0x56, 0x58, 0x5a, 0x5f, 0x6e, 0x7b, 0x7e, 0xbe, 0xce, 0xd2, 0xdc, 0xde}, {0x0f, 0x16, 0x1f, 0x4c, 0x55, 0x57, 0x59, 0x5b, 0x5e, 0x6f, 0x7a, 0x7f, 0xbf, 0xcf, 0xd3, 0xdd, 0xdf}, {0x20, 0x29, 0x30, 0x40, 0x45, 0x50, 0x61, 0x64, 0x66, 0x68, 0x6a, 0x73, 0x80, 0xe0, 0xe2, 0xec, 0xf0}, {0x21, 0x28, 0x31, 0x41, 0x44, 0x51, 0x60, 0x65, 0x67, 0x69, 0x6b, 0x72, 0x81, 0xe1, 0xe3, 0xed, 0xf1}, {0x22, 0x2b, 0x32, 0x42, 0x47, 0x52, 0x63, 0x64, 0x66, 0x68, 0x6a, 0x71, 0x82, 0xe0, 0xe2, 0xee, 0xf2}, {0x23, 0x2a, 0x33, 0x43, 0x46, 0x53, 0x62, 0x65, 0x67, 0x69, 0x6b, 0x70, 0x83, 0xe1, 0xe3, 0xef, 0xf3}, {0x24, 0x2d, 0x34, 0x41, 0x44, 0x54, 0x60, 0x62, 0x65, 0x6c, 0x6e, 0x77, 0x84, 0xe4, 0xe6, 0xe8, 0xf4}, {0x25, 0x2c, 0x35, 0x40, 0x45, 0x55, 0x61, 0x63, 0x64, 0x6d, 0x6f, 0x76, 0x85, 0xe5, 0xe7, 0xe9, 0xf5}, {0x26, 0x2f, 0x36, 0x43, 0x46, 0x56, 0x60, 0x62, 0x67, 0x6c, 0x6e, 0x75, 0x86, 0xe4, 0xe6, 0xea, 0xf6}, {0x27, 0x2e, 0x37, 0x42, 0x47, 0x57, 0x61, 0x63, 0x66, 0x6d, 0x6f, 0x74, 0x87, 0xe5, 0xe7, 0xeb, 0xf7}, {0x21, 0x28, 0x38, 0x48, 0x4d, 0x58, 0x60, 0x62, 0x69, 0x6c, 0x6e, 0x7b, 0x88, 0xe4, 0xe8, 0xea, 0xf8}, {0x20, 0x29, 0x39, 0x49, 0x4c, 0x59, 0x61, 0x63, 0x68, 0x6d, 0x6f, 0x7a, 0x89, 0xe5, 0xe9, 0xeb, 0xf9}, {0x23, 0x2a, 0x3a, 0x4a, 0x4f, 0x5a, 0x60, 0x62, 0x6b, 0x6c, 0x6e, 0x79, 0x8a, 0xe6, 0xe8, 0xea, 0xfa}, {0x22, 0x2b, 0x3b, 0x4b, 0x4e, 0x5b, 0x61, 0x63, 0x6a, 0x6d, 0x6f, 0x78, 0x8b, 0xe7, 0xe9, 0xeb, 0xfb}, {0x25, 0x2c, 0x3c, 0x49, 0x4c, 0x5c, 0x64, 0x66, 0x68, 0x6a, 0x6d, 0x7f, 0x8c, 0xe0, 0xec, 0xee, 0xfc}, {0x24, 0x2d, 0x3d, 0x48, 0x4d, 0x5d, 0x65, 0x67, 0x69, 0x6b, 0x6c, 0x7e, 0x8d, 0xe1, 0xed, 0xef, 0xfd}, {0x27, 0x2e, 0x3e, 0x4b, 0x4e, 0x5e, 0x64, 0x66, 0x68, 0x6a, 0x6f, 0x7d, 0x8e, 0xe2, 0xec, 0xee, 0xfe}, {0x26, 0x2f, 0x3f, 0x4a, 0x4f, 0x5f, 0x65, 0x67, 0x69, 0x6b, 0x6e, 0x7c, 0x8f, 0xe3, 0xed, 0xef, 0xff}, {0x20, 0x30, 0x39, 0x40, 0x50, 0x55, 0x63, 0x71, 0x74, 0x76, 0x78, 0x7a, 0x90, 0xe0, 0xf0, 0xf2, 0xfc}, {0x21, 0x31, 0x38, 0x41, 0x51, 0x54, 0x62, 0x70, 0x75, 0x77, 0x79, 0x7b, 0x91, 0xe1, 0xf1, 0xf3, 0xfd}, {0x22, 0x32, 0x3b, 0x42, 0x52, 0x57, 0x61, 0x73, 0x74, 0x76, 0x78, 0x7a, 0x92, 0xe2, 0xf0, 0xf2, 0xfe}, {0x23, 0x33, 0x3a, 0x43, 0x53, 0x56, 0x60, 0x72, 0x75, 0x77, 0x79, 0x7b, 0x93, 0xe3, 0xf1, 0xf3, 0xff}, {0x24, 0x34, 0x3d, 0x44, 0x51, 0x54, 0x67, 0x70, 0x72, 0x75, 0x7c, 0x7e, 0x94, 0xe4, 0xf4, 0xf6, 0xf8}, {0x25, 0x35, 0x3c, 0x45, 0x50, 0x55, 0x66, 0x71, 0x73, 0x74, 0x7d, 0x7f, 0x95, 0xe5, 0xf5, 0xf7, 0xf9}, {0x26, 0x36, 0x3f, 0x46, 0x53, 0x56, 0x65, 0x70, 0x72, 0x77, 0x7c, 0x7e, 0x96, 0xe6, 0xf4, 0xf6, 0xfa}, {0x27, 0x37, 0x3e, 0x47, 0x52, 0x57, 0x64, 0x71, 0x73, 0x76, 0x7d, 0x7f, 0x97, 0xe7, 0xf5, 0xf7, 0xfb}, {0x28, 0x31, 0x38, 0x48, 0x58, 0x5d, 0x6b, 0x70, 0x72, 0x79, 0x7c, 0x7e, 0x98, 0xe8, 0xf4, 0xf8, 0xfa}, {0x29, 0x30, 0x39, 0x49, 0x59, 0x5c, 0x6a, 0x71, 0x73, 0x78, 0x7d, 0x7f, 0x99, 0xe9, 0xf5, 0xf9, 0xfb}, {0x2a, 0x33, 0x3a, 0x4a, 0x5a, 0x5f, 0x69, 0x70, 0x72, 0x7b, 0x7c, 0x7e, 0x9a, 0xea, 0xf6, 0xf8, 0xfa}, {0x2b, 0x32, 0x3b, 0x4b, 0x5b, 0x5e, 0x68, 0x71, 0x73, 0x7a, 0x7d, 0x7f, 0x9b, 0xeb, 0xf7, 0xf9, 0xfb}, {0x2c, 0x35, 0x3c, 0x4c, 0x59, 0x5c, 0x6f, 0x74, 0x76, 0x78, 0x7a, 0x7d, 0x9c, 0xec, 0xf0, 0xfc, 0xfe}, {0x2d, 0x34, 0x3d, 0x4d, 0x58, 0x5d, 0x6e, 0x75, 0x77, 0x79, 0x7b, 0x7c, 0x9d, 0xed, 0xf1, 0xfd, 0xff}, {0x2e, 0x37, 0x3e, 0x4e, 0x5b, 0x5e, 0x6d, 0x74, 0x76, 0x78, 0x7a, 0x7f, 0x9e, 0xee, 0xf2, 0xfc, 0xfe}, {0x2f, 0x36, 0x3f, 0x4f, 0x5a, 0x5f, 0x6c, 0x75, 0x77, 0x79, 0x7b, 0x7e, 0x9f, 0xef, 0xf3, 0xfd, 0xff}, {0x00, 0x02, 0x0c, 0x10, 0x60, 0x81, 0x84, 0x86, 0x88, 0x8a, 0x93, 0xa0, 0xa5, 0xb0, 0xc0, 0xc9, 0xd0}, {0x01, 0x03, 0x0d, 0x11, 0x61, 0x80, 0x85, 0x87, 0x89, 0x8b, 0x92, 0xa1, 0xa4, 0xb1, 0xc1, 0xc8, 0xd1}, {0x00, 0x02, 0x0e, 0x12, 0x62, 0x83, 0x84, 0x86, 0x88, 0x8a, 0x91, 0xa2, 0xa7, 0xb2, 0xc2, 0xcb, 0xd2}, {0x01, 0x03, 0x0f, 0x13, 0x63, 0x82, 0x85, 0x87, 0x89, 0x8b, 0x90, 0xa3, 0xa6, 0xb3, 0xc3, 0xca, 0xd3}, {0x04, 0x06, 0x08, 0x14, 0x64, 0x80, 0x82, 0x85, 0x8c, 0x8e, 0x97, 0xa1, 0xa4, 0xb4, 0xc4, 0xcd, 0xd4}, {0x05, 0x07, 0x09, 0x15, 0x65, 0x81, 0x83, 0x84, 0x8d, 0x8f, 0x96, 0xa0, 0xa5, 0xb5, 0xc5, 0xcc, 0xd5}, {0x04, 0x06, 0x0a, 0x16, 0x66, 0x80, 0x82, 0x87, 0x8c, 0x8e, 0x95, 0xa3, 0xa6, 0xb6, 0xc6, 0xcf, 0xd6}, {0x05, 0x07, 0x0b, 0x17, 0x67, 0x81, 0x83, 0x86, 0x8d, 0x8f, 0x94, 0xa2, 0xa7, 0xb7, 0xc7, 0xce, 0xd7}, {0x04, 0x08, 0x0a, 0x18, 0x68, 0x80, 0x82, 0x89, 0x8c, 0x8e, 0x9b, 0xa8, 0xad, 0xb8, 0xc1, 0xc8, 0xd8}, {0x05, 0x09, 0x0b, 0x19, 0x69, 0x81, 0x83, 0x88, 0x8d, 0x8f, 0x9a, 0xa9, 0xac, 0xb9, 0xc0, 0xc9, 0xd9}, {0x06, 0x08, 0x0a, 0x1a, 0x6a, 0x80, 0x82, 0x8b, 0x8c, 0x8e, 0x99, 0xaa, 0xaf, 0xba, 0xc3, 0xca, 0xda}, {0x07, 0x09, 0x0b, 0x1b, 0x6b, 0x81, 0x83, 0x8a, 0x8d, 0x8f, 0x98, 0xab, 0xae, 0xbb, 0xc2, 0xcb, 0xdb}, {0x00, 0x0c, 0x0e, 0x1c, 0x6c, 0x84, 0x86, 0x88, 0x8a, 0x8d, 0x9f, 0xa9, 0xac, 0xbc, 0xc5, 0xcc, 0xdc}, {0x01, 0x0d, 0x0f, 0x1d, 0x6d, 0x85, 0x87, 0x89, 0x8b, 0x8c, 0x9e, 0xa8, 0xad, 0xbd, 0xc4, 0xcd, 0xdd}, {0x02, 0x0c, 0x0e, 0x1e, 0x6e, 0x84, 0x86, 0x88, 0x8a, 0x8f, 0x9d, 0xab, 0xae, 0xbe, 0xc7, 0xce, 0xde}, {0x03, 0x0d, 0x0f, 0x1f, 0x6f, 0x85, 0x87, 0x89, 0x8b, 0x8e, 0x9c, 0xaa, 0xaf, 0xbf, 0xc6, 0xcf, 0xdf}, {0x00, 0x10, 0x12, 0x1c, 0x70, 0x83, 0x91, 0x94, 0x96, 0x98, 0x9a, 0xa0, 0xb0, 0xb5, 0xc0, 0xd0, 0xd9}, {0x01, 0x11, 0x13, 0x1d, 0x71, 0x82, 0x90, 0x95, 0x97, 0x99, 0x9b, 0xa1, 0xb1, 0xb4, 0xc1, 0xd1, 0xd8}, {0x02, 0x10, 0x12, 0x1e, 0x72, 0x81, 0x93, 0x94, 0x96, 0x98, 0x9a, 0xa2, 0xb2, 0xb7, 0xc2, 0xd2, 0xdb}, {0x03, 0x11, 0x13, 0x1f, 0x73, 0x80, 0x92, 0x95, 0x97, 0x99, 0x9b, 0xa3, 0xb3, 0xb6, 0xc3, 0xd3, 0xda}, {0x04, 0x14, 0x16, 0x18, 0x74, 0x87, 0x90, 0x92, 0x95, 0x9c, 0x9e, 0xa4, 0xb1, 0xb4, 0xc4, 0xd4, 0xdd}, {0x05, 0x15, 0x17, 0x19, 0x75, 0x86, 0x91, 0x93, 0x94, 0x9d, 0x9f, 0xa5, 0xb0, 0xb5, 0xc5, 0xd5, 0xdc}, {0x06, 0x14, 0x16, 0x1a, 0x76, 0x85, 0x90, 0x92, 0x97, 0x9c, 0x9e, 0xa6, 0xb3, 0xb6, 0xc6, 0xd6, 0xdf}, {0x07, 0x15, 0x17, 0x1b, 0x77, 0x84, 0x91, 0x93, 0x96, 0x9d, 0x9f, 0xa7, 0xb2, 0xb7, 0xc7, 0xd7, 0xde}, {0x08, 0x14, 0x18, 0x1a, 0x78, 0x8b, 0x90, 0x92, 0x99, 0x9c, 0x9e, 0xa8, 0xb8, 0xbd, 0xc8, 0xd1, 0xd8}, {0x09, 0x15, 0x19, 0x1b, 0x79, 0x8a, 0x91, 0x93, 0x98, 0x9d, 0x9f, 0xa9, 0xb9, 0xbc, 0xc9, 0xd0, 0xd9}, {0x0a, 0x16, 0x18, 0x1a, 0x7a, 0x89, 0x90, 0x92, 0x9b, 0x9c, 0x9e, 0xaa, 0xba, 0xbf, 0xca, 0xd3, 0xda}, {0x0b, 0x17, 0x19, 0x1b, 0x7b, 0x88, 0x91, 0x93, 0x9a, 0x9d, 0x9f, 0xab, 0xbb, 0xbe, 0xcb, 0xd2, 0xdb}, {0x0c, 0x10, 0x1c, 0x1e, 0x7c, 0x8f, 0x94, 0x96, 0x98, 0x9a, 0x9d, 0xac, 0xb9, 0xbc, 0xcc, 0xd5, 0xdc}, {0x0d, 0x11, 0x1d, 0x1f, 0x7d, 0x8e, 0x95, 0x97, 0x99, 0x9b, 0x9c, 0xad, 0xb8, 0xbd, 0xcd, 0xd4, 0xdd}, {0x0e, 0x12, 0x1c, 0x1e, 0x7e, 0x8d, 0x94, 0x96, 0x98, 0x9a, 0x9f, 0xae, 0xbb, 0xbe, 0xce, 0xd7, 0xde}, {0x0f, 0x13, 0x1d, 0x1f, 0x7f, 0x8c, 0x95, 0x97, 0x99, 0x9b, 0x9e, 0xaf, 0xba, 0xbf, 0xcf, 0xd6, 0xdf}, {0x20, 0x22, 0x2c, 0x30, 0x40, 0x80, 0x85, 0x90, 0xa1, 0xa4, 0xa6, 0xa8, 0xaa, 0xb3, 0xe0, 0xe9, 0xf0}, {0x21, 0x23, 0x2d, 0x31, 0x41, 0x81, 0x84, 0x91, 0xa0, 0xa5, 0xa7, 0xa9, 0xab, 0xb2, 0xe1, 0xe8, 0xf1}, {0x20, 0x22, 0x2e, 0x32, 0x42, 0x82, 0x87, 0x92, 0xa3, 0xa4, 0xa6, 0xa8, 0xaa, 0xb1, 0xe2, 0xeb, 0xf2}, {0x21, 0x23, 0x2f, 0x33, 0x43, 0x83, 0x86, 0x93, 0xa2, 0xa5, 0xa7, 0xa9, 0xab, 0xb0, 0xe3, 0xea, 0xf3}, {0x24, 0x26, 0x28, 0x34, 0x44, 0x81, 0x84, 0x94, 0xa0, 0xa2, 0xa5, 0xac, 0xae, 0xb7, 0xe4, 0xed, 0xf4}, {0x25, 0x27, 0x29, 0x35, 0x45, 0x80, 0x85, 0x95, 0xa1, 0xa3, 0xa4, 0xad, 0xaf, 0xb6, 0xe5, 0xec, 0xf5}, {0x24, 0x26, 0x2a, 0x36, 0x46, 0x83, 0x86, 0x96, 0xa0, 0xa2, 0xa7, 0xac, 0xae, 0xb5, 0xe6, 0xef, 0xf6}, {0x25, 0x27, 0x2b, 0x37, 0x47, 0x82, 0x87, 0x97, 0xa1, 0xa3, 0xa6, 0xad, 0xaf, 0xb4, 0xe7, 0xee, 0xf7}, {0x24, 0x28, 0x2a, 0x38, 0x48, 0x88, 0x8d, 0x98, 0xa0, 0xa2, 0xa9, 0xac, 0xae, 0xbb, 0xe1, 0xe8, 0xf8}, {0x25, 0x29, 0x2b, 0x39, 0x49, 0x89, 0x8c, 0x99, 0xa1, 0xa3, 0xa8, 0xad, 0xaf, 0xba, 0xe0, 0xe9, 0xf9}, {0x26, 0x28, 0x2a, 0x3a, 0x4a, 0x8a, 0x8f, 0x9a, 0xa0, 0xa2, 0xab, 0xac, 0xae, 0xb9, 0xe3, 0xea, 0xfa}, {0x27, 0x29, 0x2b, 0x3b, 0x4b, 0x8b, 0x8e, 0x9b, 0xa1, 0xa3, 0xaa, 0xad, 0xaf, 0xb8, 0xe2, 0xeb, 0xfb}, {0x20, 0x2c, 0x2e, 0x3c, 0x4c, 0x89, 0x8c, 0x9c, 0xa4, 0xa6, 0xa8, 0xaa, 0xad, 0xbf, 0xe5, 0xec, 0xfc}, {0x21, 0x2d, 0x2f, 0x3d, 0x4d, 0x88, 0x8d, 0x9d, 0xa5, 0xa7, 0xa9, 0xab, 0xac, 0xbe, 0xe4, 0xed, 0xfd}, {0x22, 0x2c, 0x2e, 0x3e, 0x4e, 0x8b, 0x8e, 0x9e, 0xa4, 0xa6, 0xa8, 0xaa, 0xaf, 0xbd, 0xe7, 0xee, 0xfe}, {0x23, 0x2d, 0x2f, 0x3f, 0x4f, 0x8a, 0x8f, 0x9f, 0xa5, 0xa7, 0xa9, 0xab, 0xae, 0xbc, 0xe6, 0xef, 0xff}, {0x20, 0x30, 0x32, 0x3c, 0x50, 0x80, 0x90, 0x95, 0xa3, 0xb1, 0xb4, 0xb6, 0xb8, 0xba, 0xe0, 0xf0, 0xf9}, {0x21, 0x31, 0x33, 0x3d, 0x51, 0x81, 0x91, 0x94, 0xa2, 0xb0, 0xb5, 0xb7, 0xb9, 0xbb, 0xe1, 0xf1, 0xf8}, {0x22, 0x30, 0x32, 0x3e, 0x52, 0x82, 0x92, 0x97, 0xa1, 0xb3, 0xb4, 0xb6, 0xb8, 0xba, 0xe2, 0xf2, 0xfb}, {0x23, 0x31, 0x33, 0x3f, 0x53, 0x83, 0x93, 0x96, 0xa0, 0xb2, 0xb5, 0xb7, 0xb9, 0xbb, 0xe3, 0xf3, 0xfa}, {0x24, 0x34, 0x36, 0x38, 0x54, 0x84, 0x91, 0x94, 0xa7, 0xb0, 0xb2, 0xb5, 0xbc, 0xbe, 0xe4, 0xf4, 0xfd}, {0x25, 0x35, 0x37, 0x39, 0x55, 0x85, 0x90, 0x95, 0xa6, 0xb1, 0xb3, 0xb4, 0xbd, 0xbf, 0xe5, 0xf5, 0xfc}, {0x26, 0x34, 0x36, 0x3a, 0x56, 0x86, 0x93, 0x96, 0xa5, 0xb0, 0xb2, 0xb7, 0xbc, 0xbe, 0xe6, 0xf6, 0xff}, {0x27, 0x35, 0x37, 0x3b, 0x57, 0x87, 0x92, 0x97, 0xa4, 0xb1, 0xb3, 0xb6, 0xbd, 0xbf, 0xe7, 0xf7, 0xfe}, {0x28, 0x34, 0x38, 0x3a, 0x58, 0x88, 0x98, 0x9d, 0xab, 0xb0, 0xb2, 0xb9, 0xbc, 0xbe, 0xe8, 0xf1, 0xf8}, {0x29, 0x35, 0x39, 0x3b, 0x59, 0x89, 0x99, 0x9c, 0xaa, 0xb1, 0xb3, 0xb8, 0xbd, 0xbf, 0xe9, 0xf0, 0xf9}, {0x2a, 0x36, 0x38, 0x3a, 0x5a, 0x8a, 0x9a, 0x9f, 0xa9, 0xb0, 0xb2, 0xbb, 0xbc, 0xbe, 0xea, 0xf3, 0xfa}, {0x2b, 0x37, 0x39, 0x3b, 0x5b, 0x8b, 0x9b, 0x9e, 0xa8, 0xb1, 0xb3, 0xba, 0xbd, 0xbf, 0xeb, 0xf2, 0xfb}, {0x2c, 0x30, 0x3c, 0x3e, 0x5c, 0x8c, 0x99, 0x9c, 0xaf, 0xb4, 0xb6, 0xb8, 0xba, 0xbd, 0xec, 0xf5, 0xfc}, {0x2d, 0x31, 0x3d, 0x3f, 0x5d, 0x8d, 0x98, 0x9d, 0xae, 0xb5, 0xb7, 0xb9, 0xbb, 0xbc, 0xed, 0xf4, 0xfd}, {0x2e, 0x32, 0x3c, 0x3e, 0x5e, 0x8e, 0x9b, 0x9e, 0xad, 0xb4, 0xb6, 0xb8, 0xba, 0xbf, 0xee, 0xf7, 0xfe}, {0x2f, 0x33, 0x3d, 0x3f, 0x5f, 0x8f, 0x9a, 0x9f, 0xac, 0xb5, 0xb7, 0xb9, 0xbb, 0xbe, 0xef, 0xf6, 0xff}, {0x20, 0x40, 0x42, 0x4c, 0x50, 0x80, 0x89, 0x90, 0xc1, 0xc4, 0xc6, 0xc8, 0xca, 0xd3, 0xe0, 0xe5, 0xf0}, {0x21, 0x41, 0x43, 0x4d, 0x51, 0x81, 0x88, 0x91, 0xc0, 0xc5, 0xc7, 0xc9, 0xcb, 0xd2, 0xe1, 0xe4, 0xf1}, {0x22, 0x40, 0x42, 0x4e, 0x52, 0x82, 0x8b, 0x92, 0xc3, 0xc4, 0xc6, 0xc8, 0xca, 0xd1, 0xe2, 0xe7, 0xf2}, {0x23, 0x41, 0x43, 0x4f, 0x53, 0x83, 0x8a, 0x93, 0xc2, 0xc5, 0xc7, 0xc9, 0xcb, 0xd0, 0xe3, 0xe6, 0xf3}, {0x24, 0x44, 0x46, 0x48, 0x54, 0x84, 0x8d, 0x94, 0xc0, 0xc2, 0xc5, 0xcc, 0xce, 0xd7, 0xe1, 0xe4, 0xf4}, {0x25, 0x45, 0x47, 0x49, 0x55, 0x85, 0x8c, 0x95, 0xc1, 0xc3, 0xc4, 0xcd, 0xcf, 0xd6, 0xe0, 0xe5, 0xf5}, {0x26, 0x44, 0x46, 0x4a, 0x56, 0x86, 0x8f, 0x96, 0xc0, 0xc2, 0xc7, 0xcc, 0xce, 0xd5, 0xe3, 0xe6, 0xf6}, {0x27, 0x45, 0x47, 0x4b, 0x57, 0x87, 0x8e, 0x97, 0xc1, 0xc3, 0xc6, 0xcd, 0xcf, 0xd4, 0xe2, 0xe7, 0xf7}, {0x28, 0x44, 0x48, 0x4a, 0x58, 0x81, 0x88, 0x98, 0xc0, 0xc2, 0xc9, 0xcc, 0xce, 0xdb, 0xe8, 0xed, 0xf8}, {0x29, 0x45, 0x49, 0x4b, 0x59, 0x80, 0x89, 0x99, 0xc1, 0xc3, 0xc8, 0xcd, 0xcf, 0xda, 0xe9, 0xec, 0xf9}, {0x2a, 0x46, 0x48, 0x4a, 0x5a, 0x83, 0x8a, 0x9a, 0xc0, 0xc2, 0xcb, 0xcc, 0xce, 0xd9, 0xea, 0xef, 0xfa}, {0x2b, 0x47, 0x49, 0x4b, 0x5b, 0x82, 0x8b, 0x9b, 0xc1, 0xc3, 0xca, 0xcd, 0xcf, 0xd8, 0xeb, 0xee, 0xfb}, {0x2c, 0x40, 0x4c, 0x4e, 0x5c, 0x85, 0x8c, 0x9c, 0xc4, 0xc6, 0xc8, 0xca, 0xcd, 0xdf, 0xe9, 0xec, 0xfc}, {0x2d, 0x41, 0x4d, 0x4f, 0x5d, 0x84, 0x8d, 0x9d, 0xc5, 0xc7, 0xc9, 0xcb, 0xcc, 0xde, 0xe8, 0xed, 0xfd}, {0x2e, 0x42, 0x4c, 0x4e, 0x5e, 0x87, 0x8e, 0x9e, 0xc4, 0xc6, 0xc8, 0xca, 0xcf, 0xdd, 0xeb, 0xee, 0xfe}, {0x2f, 0x43, 0x4d, 0x4f, 0x5f, 0x86, 0x8f, 0x9f, 0xc5, 0xc7, 0xc9, 0xcb, 0xce, 0xdc, 0xea, 0xef, 0xff}, {0x30, 0x40, 0x50, 0x52, 0x5c, 0x80, 0x90, 0x99, 0xc3, 0xd1, 0xd4, 0xd6, 0xd8, 0xda, 0xe0, 0xf0, 0xf5}, {0x31, 0x41, 0x51, 0x53, 0x5d, 0x81, 0x91, 0x98, 0xc2, 0xd0, 0xd5, 0xd7, 0xd9, 0xdb, 0xe1, 0xf1, 0xf4}, {0x32, 0x42, 0x50, 0x52, 0x5e, 0x82, 0x92, 0x9b, 0xc1, 0xd3, 0xd4, 0xd6, 0xd8, 0xda, 0xe2, 0xf2, 0xf7}, {0x33, 0x43, 0x51, 0x53, 0x5f, 0x83, 0x93, 0x9a, 0xc0, 0xd2, 0xd5, 0xd7, 0xd9, 0xdb, 0xe3, 0xf3, 0xf6}, {0x34, 0x44, 0x54, 0x56, 0x58, 0x84, 0x94, 0x9d, 0xc7, 0xd0, 0xd2, 0xd5, 0xdc, 0xde, 0xe4, 0xf1, 0xf4}, {0x35, 0x45, 0x55, 0x57, 0x59, 0x85, 0x95, 0x9c, 0xc6, 0xd1, 0xd3, 0xd4, 0xdd, 0xdf, 0xe5, 0xf0, 0xf5}, {0x36, 0x46, 0x54, 0x56, 0x5a, 0x86, 0x96, 0x9f, 0xc5, 0xd0, 0xd2, 0xd7, 0xdc, 0xde, 0xe6, 0xf3, 0xf6}, {0x37, 0x47, 0x55, 0x57, 0x5b, 0x87, 0x97, 0x9e, 0xc4, 0xd1, 0xd3, 0xd6, 0xdd, 0xdf, 0xe7, 0xf2, 0xf7}, {0x38, 0x48, 0x54, 0x58, 0x5a, 0x88, 0x91, 0x98, 0xcb, 0xd0, 0xd2, 0xd9, 0xdc, 0xde, 0xe8, 0xf8, 0xfd}, {0x39, 0x49, 0x55, 0x59, 0x5b, 0x89, 0x90, 0x99, 0xca, 0xd1, 0xd3, 0xd8, 0xdd, 0xdf, 0xe9, 0xf9, 0xfc}, {0x3a, 0x4a, 0x56, 0x58, 0x5a, 0x8a, 0x93, 0x9a, 0xc9, 0xd0, 0xd2, 0xdb, 0xdc, 0xde, 0xea, 0xfa, 0xff}, {0x3b, 0x4b, 0x57, 0x59, 0x5b, 0x8b, 0x92, 0x9b, 0xc8, 0xd1, 0xd3, 0xda, 0xdd, 0xdf, 0xeb, 0xfb, 0xfe}, {0x3c, 0x4c, 0x50, 0x5c, 0x5e, 0x8c, 0x95, 0x9c, 0xcf, 0xd4, 0xd6, 0xd8, 0xda, 0xdd, 0xec, 0xf9, 0xfc}, {0x3d, 0x4d, 0x51, 0x5d, 0x5f, 0x8d, 0x94, 0x9d, 0xce, 0xd5, 0xd7, 0xd9, 0xdb, 0xdc, 0xed, 0xf8, 0xfd}, {0x3e, 0x4e, 0x52, 0x5c, 0x5e, 0x8e, 0x97, 0x9e, 0xcd, 0xd4, 0xd6, 0xd8, 0xda, 0xdf, 0xee, 0xfb, 0xfe}, {0x3f, 0x4f, 0x53, 0x5d, 0x5f, 0x8f, 0x96, 0x9f, 0xcc, 0xd5, 0xd7, 0xd9, 0xdb, 0xde, 0xef, 0xfa, 0xff}, {0x00, 0x60, 0x62, 0x6c, 0x70, 0xa0, 0xa9, 0xb0, 0xc0, 0xc5, 0xd0, 0xe1, 0xe4, 0xe6, 0xe8, 0xea, 0xf3}, {0x01, 0x61, 0x63, 0x6d, 0x71, 0xa1, 0xa8, 0xb1, 0xc1, 0xc4, 0xd1, 0xe0, 0xe5, 0xe7, 0xe9, 0xeb, 0xf2}, {0x02, 0x60, 0x62, 0x6e, 0x72, 0xa2, 0xab, 0xb2, 0xc2, 0xc7, 0xd2, 0xe3, 0xe4, 0xe6, 0xe8, 0xea, 0xf1}, {0x03, 0x61, 0x63, 0x6f, 0x73, 0xa3, 0xaa, 0xb3, 0xc3, 0xc6, 0xd3, 0xe2, 0xe5, 0xe7, 0xe9, 0xeb, 0xf0}, {0x04, 0x64, 0x66, 0x68, 0x74, 0xa4, 0xad, 0xb4, 0xc1, 0xc4, 0xd4, 0xe0, 0xe2, 0xe5, 0xec, 0xee, 0xf7}, {0x05, 0x65, 0x67, 0x69, 0x75, 0xa5, 0xac, 0xb5, 0xc0, 0xc5, 0xd5, 0xe1, 0xe3, 0xe4, 0xed, 0xef, 0xf6}, {0x06, 0x64, 0x66, 0x6a, 0x76, 0xa6, 0xaf, 0xb6, 0xc3, 0xc6, 0xd6, 0xe0, 0xe2, 0xe7, 0xec, 0xee, 0xf5}, {0x07, 0x65, 0x67, 0x6b, 0x77, 0xa7, 0xae, 0xb7, 0xc2, 0xc7, 0xd7, 0xe1, 0xe3, 0xe6, 0xed, 0xef, 0xf4}, {0x08, 0x64, 0x68, 0x6a, 0x78, 0xa1, 0xa8, 0xb8, 0xc8, 0xcd, 0xd8, 0xe0, 0xe2, 0xe9, 0xec, 0xee, 0xfb}, {0x09, 0x65, 0x69, 0x6b, 0x79, 0xa0, 0xa9, 0xb9, 0xc9, 0xcc, 0xd9, 0xe1, 0xe3, 0xe8, 0xed, 0xef, 0xfa}, {0x0a, 0x66, 0x68, 0x6a, 0x7a, 0xa3, 0xaa, 0xba, 0xca, 0xcf, 0xda, 0xe0, 0xe2, 0xeb, 0xec, 0xee, 0xf9}, {0x0b, 0x67, 0x69, 0x6b, 0x7b, 0xa2, 0xab, 0xbb, 0xcb, 0xce, 0xdb, 0xe1, 0xe3, 0xea, 0xed, 0xef, 0xf8}, {0x0c, 0x60, 0x6c, 0x6e, 0x7c, 0xa5, 0xac, 0xbc, 0xc9, 0xcc, 0xdc, 0xe4, 0xe6, 0xe8, 0xea, 0xed, 0xff}, {0x0d, 0x61, 0x6d, 0x6f, 0x7d, 0xa4, 0xad, 0xbd, 0xc8, 0xcd, 0xdd, 0xe5, 0xe7, 0xe9, 0xeb, 0xec, 0xfe}, {0x0e, 0x62, 0x6c, 0x6e, 0x7e, 0xa7, 0xae, 0xbe, 0xcb, 0xce, 0xde, 0xe4, 0xe6, 0xe8, 0xea, 0xef, 0xfd}, {0x0f, 0x63, 0x6d, 0x6f, 0x7f, 0xa6, 0xaf, 0xbf, 0xca, 0xcf, 0xdf, 0xe5, 0xe7, 0xe9, 0xeb, 0xee, 0xfc}, {0x10, 0x60, 0x70, 0x72, 0x7c, 0xa0, 0xb0, 0xb9, 0xc0, 0xd0, 0xd5, 0xe3, 0xf1, 0xf4, 0xf6, 0xf8, 0xfa}, {0x11, 0x61, 0x71, 0x73, 0x7d, 0xa1, 0xb1, 0xb8, 0xc1, 0xd1, 0xd4, 0xe2, 0xf0, 0xf5, 0xf7, 0xf9, 0xfb}, {0x12, 0x62, 0x70, 0x72, 0x7e, 0xa2, 0xb2, 0xbb, 0xc2, 0xd2, 0xd7, 0xe1, 0xf3, 0xf4, 0xf6, 0xf8, 0xfa}, {0x13, 0x63, 0x71, 0x73, 0x7f, 0xa3, 0xb3, 0xba, 0xc3, 0xd3, 0xd6, 0xe0, 0xf2, 0xf5, 0xf7, 0xf9, 0xfb}, {0x14, 0x64, 0x74, 0x76, 0x78, 0xa4, 0xb4, 0xbd, 0xc4, 0xd1, 0xd4, 0xe7, 0xf0, 0xf2, 0xf5, 0xfc, 0xfe}, {0x15, 0x65, 0x75, 0x77, 0x79, 0xa5, 0xb5, 0xbc, 0xc5, 0xd0, 0xd5, 0xe6, 0xf1, 0xf3, 0xf4, 0xfd, 0xff}, {0x16, 0x66, 0x74, 0x76, 0x7a, 0xa6, 0xb6, 0xbf, 0xc6, 0xd3, 0xd6, 0xe5, 0xf0, 0xf2, 0xf7, 0xfc, 0xfe}, {0x17, 0x67, 0x75, 0x77, 0x7b, 0xa7, 0xb7, 0xbe, 0xc7, 0xd2, 0xd7, 0xe4, 0xf1, 0xf3, 0xf6, 0xfd, 0xff}, {0x18, 0x68, 0x74, 0x78, 0x7a, 0xa8, 0xb1, 0xb8, 0xc8, 0xd8, 0xdd, 0xeb, 0xf0, 0xf2, 0xf9, 0xfc, 0xfe}, {0x19, 0x69, 0x75, 0x79, 0x7b, 0xa9, 0xb0, 0xb9, 0xc9, 0xd9, 0xdc, 0xea, 0xf1, 0xf3, 0xf8, 0xfd, 0xff}, {0x1a, 0x6a, 0x76, 0x78, 0x7a, 0xaa, 0xb3, 0xba, 0xca, 0xda, 0xdf, 0xe9, 0xf0, 0xf2, 0xfb, 0xfc, 0xfe}, {0x1b, 0x6b, 0x77, 0x79, 0x7b, 0xab, 0xb2, 0xbb, 0xcb, 0xdb, 0xde, 0xe8, 0xf1, 0xf3, 0xfa, 0xfd, 0xff}, {0x1c, 0x6c, 0x70, 0x7c, 0x7e, 0xac, 0xb5, 0xbc, 0xcc, 0xd9, 0xdc, 0xef, 0xf4, 0xf6, 0xf8, 0xfa, 0xfd}, {0x1d, 0x6d, 0x71, 0x7d, 0x7f, 0xad, 0xb4, 0xbd, 0xcd, 0xd8, 0xdd, 0xee, 0xf5, 0xf7, 0xf9, 0xfb, 0xfc}, {0x1e, 0x6e, 0x72, 0x7c, 0x7e, 0xae, 0xb7, 0xbe, 0xce, 0xdb, 0xde, 0xed, 0xf4, 0xf6, 0xf8, 0xfa, 0xff}, {0x1f, 0x6f, 0x73, 0x7d, 0x7f, 0xaf, 0xb6, 0xbf, 0xcf, 0xda, 0xdf, 0xec, 0xf5, 0xf7, 0xf9, 0xfb, 0xfe}}; liquid-dsp-1.3.1/src/fec/src/fec_hamming1511.c000066400000000000000000000121531317124540100206130ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "liquid.internal.h" #define DEBUG_FEC_HAMMING1511 0 // // Hamming(15,11) code // // parity bit coverage mask for encoder (collapsed version of figure // above, stripping out parity bits P1, P2, P4, P8 and only including // data bits 1:11) // // parity bit P1 x x . x x . x . x . x = .110 1101 0101 // coverage P2 x . x x . x x . . x x = .101 1011 0011 // P4 . x x x . . . x x x x = .011 1000 1111 // P8 . . . . x x x x x x x = .000 0111 1111 #define HAMMING_M1 0x06d5 // .110 1101 0101 #define HAMMING_M2 0x05b3 // .101 1011 0011 #define HAMMING_M4 0x038f // .011 1000 1111 #define HAMMING_M8 0x007f // .000 0111 1111 // parity bit coverage mask for decoder; used to compute syndromes // for decoding a received message (see first figure, above). #define HAMMING_S1 0x5555 // .101 0101 0101 0101 #define HAMMING_S2 0x3333 // .011 0011 0011 0011 #define HAMMING_S4 0x0f0f // .000 1111 0000 1111 #define HAMMING_S8 0x00ff // .000 0000 1111 1111 unsigned int fec_hamming1511_encode_symbol(unsigned int _sym_dec) { // validate input if (_sym_dec >= (1<<11)) { fprintf(stderr,"error, fec_hamming_encode(), input symbol too large\n"); exit(1); } // compute parity bits unsigned int p1 = liquid_bdotprod_uint16(_sym_dec, HAMMING_M1); unsigned int p2 = liquid_bdotprod_uint16(_sym_dec, HAMMING_M2); unsigned int p4 = liquid_bdotprod_uint16(_sym_dec, HAMMING_M4); unsigned int p8 = liquid_bdotprod_uint16(_sym_dec, HAMMING_M8); #if DEBUG_FEC_HAMMING1511 printf("parity bits (p1,p2,p4,p8) : (%1u,%1u,%1u,%1u)\n", p1, p2, p4, p8); #endif // encode symbol by inserting parity bits with data bits to // make a 15-bit symbol unsigned int sym_enc = ((_sym_dec & 0x007f) << 0) | ((_sym_dec & 0x0380) << 1) | ((_sym_dec & 0x0400) << 2) | ( p1 << 14 ) | ( p2 << 13 ) | ( p4 << 11 ) | ( p8 << 7 ); return sym_enc; } unsigned int fec_hamming1511_decode_symbol(unsigned int _sym_enc) { // validate input if (_sym_enc >= (1<<15)) { fprintf(stderr,"error, fec_hamming_decode(), input symbol too large\n"); exit(1); } // compute syndrome bits unsigned int s1 = liquid_bdotprod_uint16(_sym_enc, HAMMING_S1); unsigned int s2 = liquid_bdotprod_uint16(_sym_enc, HAMMING_S2); unsigned int s4 = liquid_bdotprod_uint16(_sym_enc, HAMMING_S4); unsigned int s8 = liquid_bdotprod_uint16(_sym_enc, HAMMING_S8); // index unsigned int z = (s8<<3) | (s4<<2) | (s2<<1) | s1; #if DEBUG_FEC_HAMMING1511 printf("syndrome bits (s1,s2,s4,s8) : (%1u,%1u,%1u,%1u)\n", s1, s2, s4, s8); printf("syndrome z : %u\n", z); #endif // flip bit at this position if (z) { if (z > 15) { // if this happens there are likely too many errors // to correct; just pass without trying to do anything fprintf(stderr,"warning, fec_hamming1511_decode_symbol(), syndrome index exceeds maximum\n"); } else { //printf("error detected!\n"); _sym_enc ^= 1 << (15-z); } } // strip data bits (x) from encoded symbol with parity bits (.) // symbol: [..x. xxx. xxxx] // 0000 0000 1111 > 0x000f // 0000 1110 0000 > 0x00e0 // 0010 0000 0000 > 0x0200 // // symbol: [ -..x .xxx .xxx xxxx] // -000 0000 0xxx xxxx > 0x007f // -000 0111 0000 0000 > 0x0700 // -001 0000 0000 0000 > 0x1000 unsigned int sym_dec = ((_sym_enc & 0x007f) ) | ((_sym_enc & 0x0700) >> 1) | ((_sym_enc & 0x1000) >> 2); return sym_dec; } liquid-dsp-1.3.1/src/fec/src/fec_hamming3126.c000066400000000000000000000173711317124540100206260ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "liquid.internal.h" #define DEBUG_FEC_HAMMING3126 0 // // (31,26) Hamming code // // parity bit coverage mask for encoder (collapsed version of figure // above, stripping out parity bits P1, P2, P4, P8, P16 and only including // data bits 1:26) // // bit position 3 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 // * * * * * * // parity bit P1 x x . x x . x . x . x x . x . x . x . x . x . x . x = ..11 0110 1010 1101 0101 0101 0101 // coverage P2 x . x x . x x . . x x . x x . . x x . . x x . . x x = ..10 1101 1001 1011 0011 0011 0011 // P4 . x x x . . . x x x x . . . x x x x . . . . x x x x = ..01 1100 0111 1000 1111 0000 1111 // P8 . . . . x x x x x x x . . . . . . . x x x x x x x x = ..00 0011 1111 1000 0000 1111 1111 // P16 . . . . . . . . . . . x x x x x x x x x x x x x x x = ..00 0000 0000 0111 1111 1111 1111 #define HAMMING_M1 0x036AD555 // ..11 0110 1010 1101 0101 0101 0101 #define HAMMING_M2 0x02D9B333 // ..10 1101 1001 1011 0011 0011 0011 #define HAMMING_M4 0x01C78F0F // ..01 1100 0111 1000 1111 0000 1111 #define HAMMING_M8 0x003F80FF // ..00 0011 1111 1000 0000 1111 1111 #define HAMMING_M16 0x00007FFF // ..00 0000 0000 0111 1111 1111 1111 // bit position 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 // * * * * * * * // parity bit P1 x . x . x . x . x . x . x . x . x . x . x . x . x . x . x . x = .101 0101 0101 0101 0101 0101 0101 0101 // coverage P2 . x x . . x x . . x x . . x x . . x x . . x x . . x x . . x x = .011 0011 0011 0011 0011 0011 0011 0011 // P4 . . . x x x x . . . . x x x x . . . . x x x x . . . . x x x x = .000 1111 0000 1111 0000 1111 0000 1111 // P8 . . . . . . . x x x x x x x x . . . . . . . . x x x x x x x x = .000 0000 1111 1111 0000 0000 1111 1111 // P16 . . . . . . . . . . . . . . . x x x x x x x x x x x x x x x x = .000 0000 0000 0000 1111 1111 1111 1111 // // parity bit coverage mask for decoder; used to compute syndromes // for decoding a received message (see figure, above). #define HAMMING_S1 0x55555555 // .101 0101 0101 0101 0101 0101 0101 0101 #define HAMMING_S2 0x33333333 // .011 0011 0011 0011 0011 0011 0011 0011 #define HAMMING_S4 0x0f0f0f0f // .000 1111 0000 1111 0000 1111 0000 1111 #define HAMMING_S8 0x00ff00ff // .000 0000 1111 1111 0000 0000 1111 1111 #define HAMMING_S16 0x0000ffff // .000 0000 0000 0000 1111 1111 1111 1111 unsigned int fec_hamming3126_encode_symbol(unsigned int _sym_dec) { // validate input if (_sym_dec >= (1<<26)) { fprintf(stderr,"error, fec_hamming_encode(), input symbol too large\n"); exit(1); } // compute parity bits unsigned int p1 = liquid_bdotprod_uint32(_sym_dec, HAMMING_M1); unsigned int p2 = liquid_bdotprod_uint32(_sym_dec, HAMMING_M2); unsigned int p4 = liquid_bdotprod_uint32(_sym_dec, HAMMING_M4); unsigned int p8 = liquid_bdotprod_uint32(_sym_dec, HAMMING_M8); unsigned int p16 = liquid_bdotprod_uint32(_sym_dec, HAMMING_M16); #if DEBUG_FEC_HAMMING printf("parity bits (p1,p2,p4,p8,p16) : (%1u,%1u,%1u,%1u,%1u)\n", p1, p2, p4, p8, p16); #endif // encode symbol by inserting parity bits with data bits to // make a 31-bit symbol unsigned int sym_enc = ((_sym_dec & 0x00007fff) << 0) | // ..00 0000 0000 0111 1111 1111 1111 ((_sym_dec & 0x003F8000) << 1) | // ..00 0011 1111 1000 0000 0000 0000 ((_sym_dec & 0x01C00000) << 2) | // ..01 1100 0000 0000 0000 0000 0000 ((_sym_dec & 0x02000000) << 3) | // ..10 0000 0000 0000 0000 0000 0000 ( p1 << 30 ) | // 30 = 31 - 1 (position of P1) ( p2 << 29 ) | // 29 = 31 - 2 (position of P2) ( p4 << 27 ) | // 27 = 31 - 4 (position of P4) ( p8 << 23 ) | // 23 = 31 - 8 (position of P8) ( p16 << 15 ); // 15 = 31 - 16 (position of P16) return sym_enc; } unsigned int fec_hamming3126_decode_symbol(unsigned int _sym_enc) { // validate input if (_sym_enc >= (1<<31)) { fprintf(stderr,"error, fec_hamming_decode(), input symbol too large\n"); exit(1); } // compute syndrome bits unsigned int s1 = liquid_bdotprod_uint32(_sym_enc, HAMMING_S1); unsigned int s2 = liquid_bdotprod_uint32(_sym_enc, HAMMING_S2); unsigned int s4 = liquid_bdotprod_uint32(_sym_enc, HAMMING_S4); unsigned int s8 = liquid_bdotprod_uint32(_sym_enc, HAMMING_S8); unsigned int s16 = liquid_bdotprod_uint32(_sym_enc, HAMMING_S16); // index unsigned int z = (s16<<4) | (s8<<3) | (s4<<2) | (s2<<1) | s1; #if DEBUG_FEC_HAMMING printf("syndrome bits (s1,s2,s4,s8,16) : (%1u,%1u,%1u,%1u,%1u)\n", s1, s2, s4, s8, s16); printf("syndrome z : %u\n", z); #endif // flip bit at this position if (z) { if (z > 31) { // if this happens there are likely too many errors // to correct; just pass without trying to do anything fprintf(stderr,"warning, fec_hamming3126_decode_symbol(), syndrome index exceeds maximum\n"); } else { //printf("error detected!\n"); _sym_enc ^= 1 << (31-z); } } // strip data bits from encoded symbol with parity bits unsigned int sym_dec = ((_sym_enc & 0x00007fff) ) | // .000 0000 0000 0000 0111 1111 1111 1111 ((_sym_enc & 0x007f0000) >> 1) | // .000 0000 0111 1111 0000 0000 0000 0000 ((_sym_enc & 0x07000000) >> 2) | // .000 0111 0000 0000 0000 0000 0000 0000 ((_sym_enc & 0x10000000) >> 3); // .001 0000 0000 0000 0000 0000 0000 0000 return sym_dec; } liquid-dsp-1.3.1/src/fec/src/fec_hamming74.c000066400000000000000000000173161317124540100204640ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // 1/2-rate (7,4) Hamming code // #include #include #include #include "liquid.internal.h" // encoder look-up table unsigned char hamming74_enc_gentab[16] = { 0x00, 0x69, 0x2a, 0x43, 0x4c, 0x25, 0x66, 0x0f, 0x70, 0x19, 0x5a, 0x33, 0x3c, 0x55, 0x16, 0x7f}; // decoder look-up table unsigned char hamming74_dec_gentab[128] = { 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x0e, 0x07, 0x00, 0x09, 0x02, 0x07, 0x04, 0x07, 0x07, 0x07, 0x00, 0x09, 0x0e, 0x0b, 0x0e, 0x0d, 0x0e, 0x0e, 0x09, 0x09, 0x0a, 0x09, 0x0c, 0x09, 0x0e, 0x07, 0x00, 0x05, 0x02, 0x0b, 0x05, 0x05, 0x06, 0x05, 0x02, 0x01, 0x02, 0x02, 0x0c, 0x05, 0x02, 0x07, 0x08, 0x0b, 0x0b, 0x0b, 0x0c, 0x05, 0x0e, 0x0b, 0x0c, 0x09, 0x02, 0x0b, 0x0c, 0x0c, 0x0c, 0x0f, 0x00, 0x03, 0x03, 0x03, 0x04, 0x0d, 0x06, 0x03, 0x04, 0x01, 0x0a, 0x03, 0x04, 0x04, 0x04, 0x07, 0x08, 0x0d, 0x0a, 0x03, 0x0d, 0x0d, 0x0e, 0x0d, 0x0a, 0x09, 0x0a, 0x0a, 0x04, 0x0d, 0x0a, 0x0f, 0x08, 0x01, 0x06, 0x03, 0x06, 0x05, 0x06, 0x06, 0x01, 0x01, 0x02, 0x01, 0x04, 0x01, 0x06, 0x0f, 0x08, 0x08, 0x08, 0x0b, 0x08, 0x0d, 0x06, 0x0f, 0x08, 0x01, 0x0a, 0x0f, 0x0c, 0x0f, 0x0f, 0x0f}; // create Hamming(7,4) codec object fec fec_hamming74_create(void * _opts) { fec q = (fec) malloc(sizeof(struct fec_s)); // set scheme q->scheme = LIQUID_FEC_HAMMING74; q->rate = fec_get_rate(q->scheme); // set internal function pointers q->encode_func = &fec_hamming74_encode; q->decode_func = &fec_hamming74_decode; q->decode_soft_func = &fec_hamming74_decode_soft; return q; } // destroy Hamming(7,4) object void fec_hamming74_destroy(fec _q) { free(_q); } // encode block of data using Hamming(7,4) encoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_dec : decoded message [size: _dec_msg_len x 1] // _msg_enc : encoded message [size: ...] void fec_hamming74_encode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_dec, unsigned char *_msg_enc) { unsigned int i; // input byte counter unsigned int k=0; // array bit index // compute encoded message length unsigned int enc_msg_len = fec_block_get_enc_msg_len(_dec_msg_len,4,7); unsigned char s0, s1; // decoded symbols unsigned char m0, m1; // encoded symbols for (i=0; i<_dec_msg_len; i++) { // strip two 4-bit symbols from input byte s0 = (_msg_dec[i] >> 4) & 0x0f; s1 = (_msg_dec[i] >> 0) & 0x0f; // encode two 7-bit symbols m0 = hamming74_enc_gentab[s0]; m1 = hamming74_enc_gentab[s1]; // pack encoded symbols into output array liquid_pack_array(_msg_enc, enc_msg_len, k, 7, m0); k += 7; liquid_pack_array(_msg_enc, enc_msg_len, k, 7, m1); k += 7; //printf(" %3u : 0x%.2x > 0x%.2x, 0x%.2x > 0x%.2x (k=%u)\n", i, s0, m0, s1, m1, k); } } // decode block of data using Hamming(7,4) decoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_enc : encoded message [size: ...] // _msg_dec : decoded message [size: _dec_msg_len x 1] // //unsigned int void fec_hamming74_decode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { unsigned int i; unsigned int k=0; // array bit index // compute encoded message length unsigned int enc_msg_len = fec_block_get_enc_msg_len(_dec_msg_len,4,7); unsigned char r0, r1; // received 7-bit symbols unsigned char s0, s1; // decoded 4-bit symbols //unsigned char num_errors=0; for (i=0; i<_dec_msg_len; i++) { // strip two 7-bit symbols from liquid_unpack_array(_msg_enc, enc_msg_len, k, 7, &r0); k += 7; liquid_unpack_array(_msg_enc, enc_msg_len, k, 7, &r1); k += 7; s0 = hamming74_dec_gentab[r0]; s1 = hamming74_dec_gentab[r1]; _msg_dec[i] = (s0 << 4) | s1; //printf(" %3u : 0x%.2x > 0x%.2x, 0x%.2x > 0x%.2x (k=%u)\n", i, r0, s0, r1, s1, k); } //return num_errors; } // decode block of data using Hamming(7,4) soft decoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_enc : encoded message [size: 8*_enc_msg_len x 1] // _msg_dec : decoded message [size: _dec_msg_len x 1] // //unsigned int void fec_hamming74_decode_soft(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { unsigned int i; unsigned int k=0; // array bit index // compute encoded message length unsigned int enc_msg_len = fec_block_get_enc_msg_len(_dec_msg_len,4,7); // decoded 4-bit symbols unsigned char s0; unsigned char s1; //unsigned char num_errors=0; for (i=0; i<_dec_msg_len; i++) { s0 = fecsoft_hamming74_decode(&_msg_enc[k ]); s1 = fecsoft_hamming74_decode(&_msg_enc[k+7]); k += 14; // pack two 4-bit symbols into one 8-bit byte _msg_dec[i] = (s0 << 4) | s1; //printf(" %3u : 0x%.2x > 0x%.2x, 0x%.2x > 0x%.2x (k=%u)\n", i, r0, s0, r1, s1, k); } assert(k == 8*enc_msg_len); //return num_errors; } // // internal methods // // soft decoding of one symbol unsigned char fecsoft_hamming74_decode(unsigned char * _soft_bits) { // find symbol with minimum distance from all 2^4 possible unsigned int d; // distance metric unsigned int dmin = 0; // minimum distance unsigned char s_hat = 0; // estimated transmitted symbol unsigned char c; // encoded symbol unsigned char s; for (s=0; s<16; s++) { // encode symbol c = hamming74_enc_gentab[s]; // compute distance metric d = 0; d += (c & 0x40) ? 255 - _soft_bits[0] : _soft_bits[0]; d += (c & 0x20) ? 255 - _soft_bits[1] : _soft_bits[1]; d += (c & 0x10) ? 255 - _soft_bits[2] : _soft_bits[2]; d += (c & 0x08) ? 255 - _soft_bits[3] : _soft_bits[3]; d += (c & 0x04) ? 255 - _soft_bits[4] : _soft_bits[4]; d += (c & 0x02) ? 255 - _soft_bits[5] : _soft_bits[5]; d += (c & 0x01) ? 255 - _soft_bits[6] : _soft_bits[6]; if (d < dmin || s==0) { s_hat = s; dmin = d; } } return s_hat; } liquid-dsp-1.3.1/src/fec/src/fec_hamming84.c000066400000000000000000000172141317124540100204620ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // 1/2-rate (8,4) Hamming code // #include #include #include #include "liquid.internal.h" // encoder look-up table unsigned char hamming84_enc_gentab[16] = { 0x00, 0xd2, 0x55, 0x87, 0x99, 0x4b, 0xcc, 0x1e, 0xe1, 0x33, 0xb4, 0x66, 0x78, 0xaa, 0x2d, 0xff}; // decoder look-up table unsigned char hamming84_dec_gentab[256] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x05, 0x05, 0x0e, 0x0e, 0x07, 0x07, 0x00, 0x00, 0x09, 0x09, 0x02, 0x02, 0x07, 0x07, 0x04, 0x04, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00, 0x09, 0x09, 0x0e, 0x0e, 0x0b, 0x0b, 0x0e, 0x0e, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x09, 0x09, 0x0c, 0x0c, 0x09, 0x09, 0x0e, 0x0e, 0x07, 0x07, 0x00, 0x00, 0x05, 0x05, 0x02, 0x02, 0x0b, 0x0b, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x05, 0x05, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x0c, 0x0c, 0x05, 0x05, 0x02, 0x02, 0x07, 0x07, 0x08, 0x08, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, 0x05, 0x05, 0x0e, 0x0e, 0x0b, 0x0b, 0x0c, 0x0c, 0x09, 0x09, 0x02, 0x02, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x0d, 0x0d, 0x06, 0x06, 0x03, 0x03, 0x04, 0x04, 0x01, 0x01, 0x0a, 0x0a, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x07, 0x08, 0x08, 0x0d, 0x0d, 0x0a, 0x0a, 0x03, 0x03, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0d, 0x0d, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x04, 0x04, 0x0d, 0x0d, 0x0a, 0x0a, 0x0f, 0x0f, 0x08, 0x08, 0x01, 0x01, 0x06, 0x06, 0x03, 0x03, 0x06, 0x06, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x04, 0x04, 0x01, 0x01, 0x06, 0x06, 0x0f, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0b, 0x0b, 0x08, 0x08, 0x0d, 0x0d, 0x06, 0x06, 0x0f, 0x0f, 0x08, 0x08, 0x01, 0x01, 0x0a, 0x0a, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f}; // create Hamming(8,4) codec object fec fec_hamming84_create(void * _opts) { fec q = (fec) malloc(sizeof(struct fec_s)); // set scheme q->scheme = LIQUID_FEC_HAMMING84; q->rate = fec_get_rate(q->scheme); // set internal function pointers q->encode_func = &fec_hamming84_encode; q->decode_func = &fec_hamming84_decode; q->decode_soft_func = &fec_hamming84_decode_soft; return q; } // destroy Hamming(8,4) object void fec_hamming84_destroy(fec _q) { free(_q); } // encode block of data using Hamming(8,4) encoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_dec : decoded message [size: 1 x _dec_msg_len] // _msg_enc : encoded message [size: 1 x 2*_dec_msg_len] void fec_hamming84_encode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_dec, unsigned char *_msg_enc) { unsigned int i, j=0; unsigned char s0, s1; for (i=0; i<_dec_msg_len; i++) { s0 = (_msg_dec[i] >> 4) & 0x0f; s1 = (_msg_dec[i] >> 0) & 0x0f; _msg_enc[j+0] = hamming84_enc_gentab[s0]; _msg_enc[j+1] = hamming84_enc_gentab[s1]; j+=2; } } // decode block of data using Hamming(8,4) decoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_enc : encoded message [size: 1 x 2*_dec_msg_len] // _msg_dec : decoded message [size: 1 x _dec_msg_len] // //unsigned int void fec_hamming84_decode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { unsigned int i; unsigned char r0, r1; // received 8-bit symbols unsigned char s0, s1; // decoded 4-bit symbols //unsigned char num_errors=0; for (i=0; i<_dec_msg_len; i++) { r0 = _msg_enc[2*i+0] & 0xff; r1 = _msg_enc[2*i+1] & 0xff; s0 = hamming84_dec_gentab[r0]; s1 = hamming84_dec_gentab[r1]; _msg_dec[i] = (s0 << 4) | s1; } //return num_errors; } // decode block of data using Hamming(8,4) soft decoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_enc : encoded message [size: 8*_enc_msg_len x 1] // _msg_dec : decoded message [size: _dec_msg_len x 1] // //unsigned int void fec_hamming84_decode_soft(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { unsigned int i; unsigned int k=0; // array bit index // compute encoded message length unsigned int enc_msg_len = fec_block_get_enc_msg_len(_dec_msg_len,4,8); // decoded 4-bit symbols unsigned char s0; unsigned char s1; //unsigned char num_errors=0; for (i=0; i<_dec_msg_len; i++) { s0 = fecsoft_hamming84_decode(&_msg_enc[k ]); s1 = fecsoft_hamming84_decode(&_msg_enc[k+8]); k += 16; // pack two 4-bit symbols into one 8-bit byte _msg_dec[i] = (s0 << 4) | s1; //printf(" %3u : 0x%.2x > 0x%.2x, 0x%.2x > 0x%.2x (k=%u)\n", i, r0, s0, r1, s1, k); } assert(k == 8*enc_msg_len); //return num_errors; } // // internal methods // // soft decoding of one symbol unsigned char fecsoft_hamming84_decode(unsigned char * _soft_bits) { // find symbol with minimum distance from all 2^4 possible unsigned int d; // distance metric unsigned int dmin = 0; // minimum distance unsigned char s_hat = 0; // estimated transmitted symbol unsigned char c; // encoded symbol unsigned char s; for (s=0; s<16; s++) { // encode symbol c = hamming84_enc_gentab[s]; // compute distance metric d = 0; d += (c & 0x80) ? 255 - _soft_bits[0] : _soft_bits[0]; d += (c & 0x40) ? 255 - _soft_bits[1] : _soft_bits[1]; d += (c & 0x20) ? 255 - _soft_bits[2] : _soft_bits[2]; d += (c & 0x10) ? 255 - _soft_bits[3] : _soft_bits[3]; d += (c & 0x08) ? 255 - _soft_bits[4] : _soft_bits[4]; d += (c & 0x04) ? 255 - _soft_bits[5] : _soft_bits[5]; d += (c & 0x02) ? 255 - _soft_bits[6] : _soft_bits[6]; d += (c & 0x01) ? 255 - _soft_bits[7] : _soft_bits[7]; if (d < dmin || s==0) { s_hat = s; dmin = d; } } return s_hat; } liquid-dsp-1.3.1/src/fec/src/fec_pass.c000066400000000000000000000037001317124540100176270ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // FEC, none/pass // #include #include #include #include "liquid.internal.h" fec fec_pass_create(void * _opts) { fec q = (fec) malloc(sizeof(struct fec_s)); q->scheme = LIQUID_FEC_NONE; q->rate = fec_get_rate(q->scheme); q->encode_func = &fec_pass_encode; q->decode_func = &fec_pass_decode; q->decode_soft_func = NULL; return q; } void fec_pass_destroy(fec _q) { free(_q); } void fec_pass_print(fec _q) { printf("fec_pass [r: %3.2f]\n", _q->rate); } void fec_pass_encode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_dec, unsigned char *_msg_enc) { memmove(_msg_enc, _msg_dec, _dec_msg_len); } void fec_pass_decode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { memmove(_msg_dec, _msg_enc, _dec_msg_len); } liquid-dsp-1.3.1/src/fec/src/fec_rep3.c000066400000000000000000000111071317124540100175320ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // FEC, repeat code // #include #include #include #include "liquid.internal.h" // create rep3 codec object fec fec_rep3_create(void * _opts) { fec q = (fec) malloc(sizeof(struct fec_s)); q->scheme = LIQUID_FEC_REP3; q->rate = fec_get_rate(q->scheme); q->encode_func = &fec_rep3_encode; q->decode_func = &fec_rep3_decode; q->decode_soft_func = &fec_rep3_decode_soft; return q; } // destroy rep3 object void fec_rep3_destroy(fec _q) { free(_q); } // print rep3 object void fec_rep3_print(fec _q) { printf("fec_rep3 [r: %3.2f]\n", _q->rate); } // encode block of data using rep3 encoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_dec : decoded message [size: 1 x _dec_msg_len] // _msg_enc : encoded message [size: 1 x 3*_dec_msg_len] void fec_rep3_encode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_dec, unsigned char *_msg_enc) { unsigned int i; for (i=0; i<3; i++) { memcpy(&_msg_enc[i*_dec_msg_len], _msg_dec, _dec_msg_len); } } // decode block of data using rep3 decoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_enc : encoded message [size: 1 x 3*_dec_msg_len] // _msg_dec : decoded message [size: 1 x _dec_msg_len] void fec_rep3_decode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { unsigned char s0, s1, s2; unsigned int i, num_errors=0; for (i=0; i<_dec_msg_len; i++) { s0 = _msg_enc[i]; s1 = _msg_enc[i + _dec_msg_len]; s2 = _msg_enc[i + 2*_dec_msg_len]; // s0 s1 s2 | y e // ------------+--------- // 0 0 0 | 0 0 // 0 0 1 | 0 1 // 0 1 0 | 0 1 // 0 1 1 | 1 1 // 1 0 0 | 0 1 // 1 0 1 | 1 1 // 1 1 0 | 1 1 // 1 1 1 | 1 0 _msg_dec[i] = (s0 & s1) | (s0 & s2) | (s1 & s2); //num_errors += (s0 ^ s1) | (s0 ^ s2) | (s1 ^ s2) ? 1 : 0; num_errors += 0; } //return num_errors; } // decode block of data using rep3 decoder (soft metrics) // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_enc : encoded message [size: 1 x 3*_dec_msg_len] // _msg_dec : decoded message [size: 1 x _dec_msg_len] void fec_rep3_decode_soft(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec) { unsigned char s0, s1, s2; unsigned int i; unsigned int j; unsigned int s_hat; //unsigned int num_errors=0; for (i=0; i<_dec_msg_len; i++) { // clear decoded message _msg_dec[i] = 0x00; for (j=0; j<8; j++) { s0 = _msg_enc[8*i + j]; s1 = _msg_enc[8*(i + _dec_msg_len) + j]; s2 = _msg_enc[8*(i + 2*_dec_msg_len) + j]; // average three symbols and make decision s_hat = (s0 + s1 + s2)/3; _msg_dec[i] |= (s_hat > LIQUID_SOFTBIT_ERASURE) ? (1 << (8-j-1)) : 0x00; } } } liquid-dsp-1.3.1/src/fec/src/fec_rep5.c000066400000000000000000000115541317124540100175420ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // FEC, repeat code // #include #include #include #include "liquid.internal.h" // create rep5 codec object fec fec_rep5_create(void * _opts) { fec q = (fec) malloc(sizeof(struct fec_s)); q->scheme = LIQUID_FEC_REP5; q->rate = fec_get_rate(q->scheme); q->encode_func = &fec_rep5_encode; q->decode_func = &fec_rep5_decode; q->decode_soft_func = &fec_rep5_decode_soft; return q; } // destroy rep5 object void fec_rep5_destroy(fec _q) { free(_q); } // print rep5 object void fec_rep5_print(fec _q) { printf("fec_rep5 [r: %3.2f]\n", _q->rate); } // encode block of data using rep5 encoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_dec : decoded message [size: 1 x _dec_msg_len] // _msg_enc : encoded message [size: 1 x 5*_dec_msg_len] void fec_rep5_encode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_dec, unsigned char *_msg_enc) { unsigned int i; for (i=0; i<5; i++) { memcpy(&_msg_enc[i*_dec_msg_len], _msg_dec, _dec_msg_len); } } // decode block of data using rep5 decoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_enc : encoded message [size: 1 x 5*_dec_msg_len] // _msg_dec : decoded message [size: 1 x _dec_msg_len] void fec_rep5_decode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { unsigned char s0, s1, s2, s3, s4; unsigned int i, num_errors=0; for (i=0; i<_dec_msg_len; i++) { s0 = _msg_enc[i ]; s1 = _msg_enc[i + _dec_msg_len]; s2 = _msg_enc[i + 2*_dec_msg_len]; s3 = _msg_enc[i + 3*_dec_msg_len]; s4 = _msg_enc[i + 4*_dec_msg_len]; // compute all triplet combinations _msg_dec[i] = (s0 & s1 & s2) | (s0 & s1 & s3) | (s0 & s1 & s4) | (s0 & s2 & s3) | (s0 & s2 & s4) | (s0 & s3 & s4) | (s1 & s2 & s3) | (s1 & s2 & s4) | (s1 & s3 & s4) | (s2 & s3 & s4); //num_errors += (s0 ^ s1) | (s0 ^ s2) | (s1 ^ s2) ? 1 : 0; num_errors += 0; } //return num_errors; } // decode block of data using rep5 decoder (soft metrics) // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_enc : encoded message [size: 1 x 5*_dec_msg_len] // _msg_dec : decoded message [size: 1 x _dec_msg_len] void fec_rep5_decode_soft(fec _q, unsigned int _dec_msg_len, unsigned char * _msg_enc, unsigned char * _msg_dec) { unsigned char s0, s1, s2, s3, s4; unsigned int i; unsigned int j; unsigned int s_hat; //unsigned int num_errors=0; for (i=0; i<_dec_msg_len; i++) { // clear decoded message _msg_dec[i] = 0x00; for (j=0; j<8; j++) { s0 = _msg_enc[8*i + j]; s1 = _msg_enc[8*(i + _dec_msg_len) + j]; s2 = _msg_enc[8*(i + 2*_dec_msg_len) + j]; s3 = _msg_enc[8*(i + 3*_dec_msg_len) + j]; s4 = _msg_enc[8*(i + 4*_dec_msg_len) + j]; // average three symbols and make decision s_hat = (s0 + s1 + s2 + s3 + s4)/5; _msg_dec[i] |= (s_hat > LIQUID_SOFTBIT_ERASURE) ? (1 << (8-j-1)) : 0x00; } } } liquid-dsp-1.3.1/src/fec/src/fec_rs.c000066400000000000000000000222531317124540100173110ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Reed-Solomon (macros) // #include #include #include #include #include "liquid.internal.h" #define VERBOSE_FEC_RS 0 #if LIBFEC_ENABLED #include "fec.h" fec fec_rs_create(fec_scheme _fs) { fec q = (fec) malloc(sizeof(struct fec_s)); q->scheme = _fs; q->rate = fec_get_rate(q->scheme); q->encode_func = &fec_rs_encode; q->decode_func = &fec_rs_decode; q->decode_soft_func = NULL; switch (q->scheme) { case LIQUID_FEC_RS_M8: fec_rs_init_p8(q); break; default: fprintf(stderr,"error: fec_rs_create(), invalid type\n"); exit(1); } // initialize basic parameters q->nn = (1 << q->symsize) - 1; q->kk = q->nn - q->nroots; // lengths q->num_dec_bytes = 0; q->rs = NULL; // allocate memory for arrays q->tblock = (unsigned char*) malloc(q->nn*sizeof(unsigned char)); q->errlocs = (int *) malloc(q->nn*sizeof(int)); q->derrlocs = (int *) malloc(q->nn*sizeof(int)); return q; } void fec_rs_destroy(fec _q) { // delete internal Reed-Solomon decoder object if (_q->rs != NULL) { free_rs_char(_q->rs); } // delete internal memory arrays free(_q->tblock); free(_q->errlocs); free(_q->derrlocs); // delete fec object free(_q); } void fec_rs_encode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_dec, unsigned char *_msg_enc) { // validate input if (_dec_msg_len == 0) { fprintf(stderr,"error: fec_rs_encode(), input lenght must be > 0\n"); exit(1); } // re-allocate resources if necessary fec_rs_setlength(_q, _dec_msg_len); unsigned int i; unsigned int n0=0; // input index unsigned int n1=0; // output index unsigned int block_size = _q->dec_block_len; for (i=0; i<_q->num_blocks; i++) { // the last block is smaller by the residual block length if (i == _q->num_blocks-1) block_size -= _q->res_block_len; // copy sequence memmove(_q->tblock, &_msg_dec[n0], block_size*sizeof(unsigned char)); // last block: we could pad end with zeros, but it's not really // necessary as these bits are going to be thrown away anyway // encode data, appending parity bits to end of sequence encode_rs_char(_q->rs, _q->tblock, &_q->tblock[_q->dec_block_len]); // copy result to output memmove(&_msg_enc[n1], _q->tblock, _q->enc_block_len*sizeof(unsigned char)); // increment counters n0 += block_size; n1 += _q->enc_block_len; } // sanity check assert( n0 == _q->num_dec_bytes ); assert( n1 == _q->num_enc_bytes ); } //unsigned int void fec_rs_decode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { // validate input if (_dec_msg_len == 0) { fprintf(stderr,"error: fec_rs_encode(), input lenght must be > 0\n"); exit(1); } // re-allocate resources if necessary fec_rs_setlength(_q, _dec_msg_len); // set erasures, error locations to zero memset(_q->errlocs, 0x00, _q->nn*sizeof(unsigned char)); memset(_q->derrlocs, 0x00, _q->nn*sizeof(unsigned char)); _q->erasures = 0; unsigned int i; unsigned int n0=0; unsigned int n1=0; unsigned int block_size = _q->dec_block_len; //int derrors; // number of decoder errors for (i=0; i<_q->num_blocks; i++) { // the last block is smaller by the residual block length if (i == _q->num_blocks-1) block_size -= _q->res_block_len; // copy sequence memmove(_q->tblock, &_msg_enc[n0], _q->enc_block_len*sizeof(unsigned char)); // decode block //derrors = decode_rs_char(_q->rs, _q->tblock, _q->derrlocs, _q->erasures); // copy result memmove(&_msg_dec[n1], _q->tblock, block_size*sizeof(unsigned char)); // increment counters n0 += _q->enc_block_len; n1 += block_size; } // sanity check assert( n0 == _q->num_enc_bytes ); assert( n1 == _q->num_dec_bytes ); } // Set dec_msg_len, re-allocating resources as necessary. Effectively, it // divides the input message into several blocks and allows the decoder to // pad each block appropraitely. // // For example : if we are using the 8-bit code, // nroots = 32 // nn = 255 // kk = 223 // Let _dec_msg_len = 1024, then // num_blocks = ceil(1024/223) // = ceil(4.5919) // = 5 // dec_block_len = ceil(1024/num_blocks) // = ceil(204.8) // = 205 // enc_block_len = dec_block_len + nroots // = 237 // res_block_len = mod(num_blocks*dec_block_len,_dec_msg_len) // = mod(5*205,1024) // = mod(1025,1024) // = 1 (cannot evenly divide input sequence) // pad = kk - dec_block_len // = 223 - 205 // = 18 // // Thus, the 1024-byte input message is broken into 5 blocks, the first // four have a length 205, and the last block has a length 204 (which is // externally padded to 205, e.g. res_block_len = 1). This code adds 32 // parity symbols, so each block is extended to 237 bytes. libfec auto- // matically extends the internal data to 255 bytes by padding with 18 // symbols. Therefore, the final output length is 237 * 5 = 1185 symbols. void fec_rs_setlength(fec _q, unsigned int _dec_msg_len) { // return if length has not changed if (_dec_msg_len == _q->num_dec_bytes) return; // reset lengths _q->num_dec_bytes = _dec_msg_len; div_t d; // compute the total number of blocks necessary: ceil(num_dec_bytes / kk) d = div(_q->num_dec_bytes, _q->kk); _q->num_blocks = d.quot + (d.rem==0 ? 0 : 1); // compute the decoded block length: ceil(num_dec_bytes / num_blocks) d = div(_dec_msg_len, _q->num_blocks); _q->dec_block_len = d.quot + (d.rem == 0 ? 0 : 1); // compute the encoded block length: dec_block_len + nroots _q->enc_block_len = _q->dec_block_len + _q->nroots; // compute the residual padding symbols in the last block: // mod(num_blocks*dec_block_len, num_dec_bytes) _q->res_block_len = (_q->num_blocks*_q->dec_block_len) % _q->num_dec_bytes; // compute the internal libfec padding factor: kk - dec_block_len _q->pad = _q->kk - _q->dec_block_len; // compute the final encoded block length: enc_block_len * num_blocks _q->num_enc_bytes = _q->enc_block_len * _q->num_blocks; #if VERBOSE_FEC_RS printf("dec_msg_len : %u\n", _q->num_dec_bytes); printf("num_blocks : %u\n", _q->num_blocks); printf("dec_block_len : %u\n", _q->dec_block_len); printf("enc_block_len : %u\n", _q->enc_block_len); printf("res_block_len : %u\n", _q->res_block_len); printf("pad : %u\n", _q->pad); printf("enc_msg_len : %u\n", _q->num_enc_bytes); #endif // delete old decoder if necessary if (_q->rs != NULL) free_rs_char(_q->rs); // Reed-Solomon specific decoding _q->rs = init_rs_char(_q->symsize, _q->genpoly, _q->fcs, _q->prim, _q->nroots, _q->pad); } // // internal // void fec_rs_init_p8(fec _q) { _q->symsize = 8; _q->genpoly = 0x11d; _q->fcs = 1; _q->prim = 1; _q->nroots = 32; } #else // LIBFEC_ENABLED fec fec_rs_create(fec_scheme _fs) { return NULL; } void fec_rs_destroy(fec _q) { } void fec_rs_encode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_dec, unsigned char *_msg_enc) { } //unsigned int void fec_rs_decode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { } #endif // LIBFEC_ENABLED liquid-dsp-1.3.1/src/fec/src/fec_secded2216.c000066400000000000000000000231661317124540100204330ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // SEC-DED (22,16) 8/11-rate forward error-correction block code // // References: // [Lin:2004] Lin, Shu and Costello, Daniel L. Jr., "Error Control // Coding," Prentice Hall, New Jersey, 2nd edition, 2004. // #include #include #include #include #include "liquid.internal.h" #define DEBUG_FEC_SECDED2216 0 // P matrix [6 x 16 bits], [6 x 2 bytes] // 1001 1001 0011 1100 : // 0011 1110 1000 1010 : // 1110 1110 0110 0000 : // 1110 0001 1101 0001 : // 0001 0011 1100 0111 : // 0100 0100 0011 1111 : unsigned char secded2216_P[12] = { 0x99, 0x3c, 0x3e, 0x8a, 0xee, 0x60, 0xe1, 0xd1, 0x13, 0xc7, 0x44, 0x3f}; // syndrome vectors for errors of weight 1 unsigned char secded2216_syndrome_w1[22] = { 0x07, 0x13, 0x23, 0x31, 0x25, 0x29, 0x0e, 0x16, 0x26, 0x1a, 0x19, 0x38, 0x32, 0x1c, 0x0d, 0x2c, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20}; // compute parity on 16-bit input unsigned char fec_secded2216_compute_parity(unsigned char * _m) { // compute encoded/transmitted message: v = m*G unsigned char parity = 0x00; // TODO : unwrap this loop unsigned int i; for (i=0; i<6; i++) { parity <<= 1; unsigned int p = liquid_c_ones[ secded2216_P[2*i+0] & _m[0] ] + liquid_c_ones[ secded2216_P[2*i+1] & _m[1] ]; parity |= p & 0x01; } return parity; } // compute syndrome on 22-bit input unsigned char fec_secded2216_compute_syndrome(unsigned char * _v) { // TODO : unwrap this loop unsigned int i; unsigned char syndrome = 0x00; for (i=0; i<6; i++) { syndrome <<= 1; unsigned int p = ( (_v[0] & (1<<(6-i-1))) ? 1 : 0 )+ liquid_c_ones[ secded2216_P[2*i+0] & _v[1] ] + liquid_c_ones[ secded2216_P[2*i+1] & _v[2] ]; syndrome |= p & 0x01; } return syndrome; } // encode symbol // _sym_dec : decoded symbol [size: 2 x 1] // _sym_enc : encoded symbol [size: 3 x 1], _sym_enc[0] has only 6 bits void fec_secded2216_encode_symbol(unsigned char * _sym_dec, unsigned char * _sym_enc) { // first six bits is parity block _sym_enc[0] = fec_secded2216_compute_parity(_sym_dec); // copy last two values _sym_enc[1] = _sym_dec[0]; _sym_enc[2] = _sym_dec[1]; } // decode symbol, returning 0/1/2 for zero/one/multiple errors // detected, respectively // _sym_enc : encoded symbol [size: 3 x 1], _sym_enc[0] has only 6 bits // _sym_dec : decoded symbol [size: 2 x 1] int fec_secded2216_decode_symbol(unsigned char * _sym_enc, unsigned char * _sym_dec) { #if 0 // validate input if (_sym_enc[0] >= (1<<6)) { fprintf(stderr,"warning, fec_secded2216_decode_symbol(), input symbol too large\n"); } #endif // estimate error vector unsigned char e_hat[3] = {0,0,0}; int syndrome_flag = fec_secded2216_estimate_ehat(_sym_enc, e_hat); // compute estimated transmit vector (last 64 bits of encoded message) // NOTE: indices take into account first element in _sym_enc and e_hat // arrays holds the parity bits _sym_dec[0] = _sym_enc[1] ^ e_hat[1]; _sym_dec[1] = _sym_enc[2] ^ e_hat[2]; #if DEBUG_FEC_SECDED2216 if (syndrome_flag == 1) { printf("secded2216_decode_symbol(): single error detected!\n"); } else if (syndrome_flag == 2) { printf("secded2216_decode_symbol(): no match found (multiple errors detected)\n"); } #endif // return syndrome flag return syndrome_flag; } // estimate error vector, returning 0/1/2 for zero/one/multiple errors // detected, respectively // _sym_enc : encoded symbol [size: 3 x 1], _sym_enc[0] has only 6 bits // _e_hat : estimated error vector [size: 3 x 1] int fec_secded2216_estimate_ehat(unsigned char * _sym_enc, unsigned char * _e_hat) { // clear output array _e_hat[0] = 0x00; _e_hat[1] = 0x00; _e_hat[2] = 0x00; // compute syndrome vector, s = r*H^T = ( H*r^T )^T unsigned char s = fec_secded2216_compute_syndrome(_sym_enc); // compute weight of s unsigned int ws = liquid_c_ones[s]; if (ws == 0) { // no errors detected return 0; } else { // estimate error location; search for syndrome with error // vector of weight one unsigned int n; // estimate error location for (n=0; n<22; n++) { if (s == secded2216_syndrome_w1[n]) { // single error detected at location 'n' div_t d = div(n,8); _e_hat[3-d.quot-1] = 1 << d.rem; return 1; } } } // no syndrome match; multiple errors detected return 2; } // create SEC-DED (22,16) codec object fec fec_secded2216_create(void * _opts) { fec q = (fec) malloc(sizeof(struct fec_s)); // set scheme q->scheme = LIQUID_FEC_SECDED2216; q->rate = fec_get_rate(q->scheme); // set internal function pointers q->encode_func = &fec_secded2216_encode; q->decode_func = &fec_secded2216_decode; q->decode_soft_func = NULL; return q; } // destroy SEC-DEC (22,16) object void fec_secded2216_destroy(fec _q) { free(_q); } // encode block of data using SEC-DEC (22,16) encoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_dec : decoded message [size: 1 x _dec_msg_len] // _msg_enc : encoded message [size: 1 x 2*_dec_msg_len] void fec_secded2216_encode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_dec, unsigned char *_msg_enc) { unsigned int i=0; // decoded byte counter unsigned int j=0; // encoded byte counter // determine remainder of input length / 8 unsigned int r = _dec_msg_len % 2; // for now simply encode as 2/3-rate codec (eat // 2 bits of parity) // TODO : make more efficient for (i=0; i<_dec_msg_len-r; i+=2) { // compute parity (6 bits) on two input bytes (16 bits) _msg_enc[j+0] = fec_secded2216_compute_parity(&_msg_dec[i]); // copy remaining two input bytes (16 bits) _msg_enc[j+1] = _msg_dec[i+0]; _msg_enc[j+2] = _msg_dec[i+1]; // increment output counter j += 3; } // if input length isn't divisible by 2, encode last few bytes if (r) { // one 16-bit symbol (decoded) unsigned char m[2] = {_msg_dec[i], 0x00}; // one 22-bit symbol (encoded) unsigned char v[3]; // encode fec_secded2216_encode_symbol(m, v); // there is no need to actually send all three bytes; // the last byte is zero and can be artificially // inserted at the decoder _msg_enc[j+0] = v[0]; _msg_enc[j+1] = v[1]; i += r; j += r+1; } assert( j == fec_get_enc_msg_length(LIQUID_FEC_SECDED2216,_dec_msg_len) ); assert( i == _dec_msg_len); } // decode block of data using SEC-DEC (22,16) decoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_enc : encoded message [size: 1 x 2*_dec_msg_len] // _msg_dec : decoded message [size: 1 x _dec_msg_len] // //unsigned int void fec_secded2216_decode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { unsigned int i=0; // decoded byte counter unsigned int j=0; // encoded byte counter // determine remainder of input length / 8 unsigned int r = _dec_msg_len % 2; for (i=0; i<_dec_msg_len-r; i+=2) { // decode straight to output fec_secded2216_decode_symbol(&_msg_enc[j], &_msg_dec[i]); j += 3; } // if input length isn't divisible by 2, decode last several bytes if (r) { // one 22-bit symbol (encoded), with last byte artifically // set to '00000000' unsigned char v[3] = {_msg_enc[j+0], _msg_enc[j+1], 0x00}; // one 16-bit symbol (decoded) unsigned char m_hat[2]; // decode symbol fec_secded2216_decode_symbol(v, m_hat); // copy just first byte to output _msg_dec[i] = m_hat[0]; i += r; j += r+1; } assert( j == fec_get_enc_msg_length(LIQUID_FEC_SECDED2216,_dec_msg_len) ); assert( i == _dec_msg_len); //return num_errors; } liquid-dsp-1.3.1/src/fec/src/fec_secded3932.c000066400000000000000000000253531317124540100204410ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // SEC-DED (39,32) forward error-correction block code // // References: // [Lin:2004] Lin, Shu and Costello, Daniel L. Jr., "Error Control // Coding," Prentice Hall, New Jersey, 2nd edition, 2004. // #include #include #include #include #include "liquid.internal.h" #define DEBUG_FEC_SECDED3932 0 // P matrix [7 x 32 bits], [7 x 4 bytes] // 1000 1010 1000 0010 0000 1111 0001 1011 // 0001 0000 0001 1111 0111 0001 0110 0001 // 0001 0110 1111 0000 1001 0010 1010 0110 // 1111 1111 0000 0001 1010 0100 0100 0100 // 0110 1100 1111 1111 0000 1000 0000 1000 // 0010 0001 0010 0100 1111 1111 1001 0000 // 1100 0001 0100 1000 0100 0000 1111 1111 unsigned char secded3932_P[28] = { 0x8a, 0x82, 0x0f, 0x1b, 0x10, 0x1f, 0x71, 0x61, 0x16, 0xf0, 0x92, 0xa6, 0xff, 0x01, 0xa4, 0x44, 0x6c, 0xff, 0x08, 0x08, 0x21, 0x24, 0xff, 0x90, 0xc1, 0x48, 0x40, 0xff}; // syndrome vectors for errors of weight 1 unsigned char secded3932_syndrome_w1[39] = { 0x61, 0x51, 0x19, 0x45, 0x43, 0x31, 0x29, 0x13, 0x62, 0x52, 0x4a, 0x46, 0x32, 0x2a, 0x23, 0x1a, 0x2c, 0x64, 0x26, 0x25, 0x34, 0x16, 0x15, 0x54, 0x0b, 0x58, 0x1c, 0x4c, 0x38, 0x0e, 0x0d, 0x49, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40}; // compute parity on 32-bit input unsigned char fec_secded3932_compute_parity(unsigned char * _m) { // compute encoded/transmitted message: v = m*G unsigned char parity = 0x00; // TODO : unwrap this loop unsigned int i; for (i=0; i<7; i++) { parity <<= 1; unsigned int p = liquid_c_ones[ secded3932_P[4*i+0] & _m[0] ] + liquid_c_ones[ secded3932_P[4*i+1] & _m[1] ] + liquid_c_ones[ secded3932_P[4*i+2] & _m[2] ] + liquid_c_ones[ secded3932_P[4*i+3] & _m[3] ]; parity |= p & 0x01; } return parity; } // compute syndrome on 39-bit input unsigned char fec_secded3932_compute_syndrome(unsigned char * _v) { // TODO : unwrap this loop unsigned int i; unsigned char syndrome = 0x00; for (i=0; i<7; i++) { syndrome <<= 1; unsigned int p = ( (_v[0] & (1<<(7-i-1))) ? 1 : 0 )+ liquid_c_ones[ secded3932_P[4*i+0] & _v[1] ] + liquid_c_ones[ secded3932_P[4*i+1] & _v[2] ] + liquid_c_ones[ secded3932_P[4*i+2] & _v[3] ] + liquid_c_ones[ secded3932_P[4*i+3] & _v[4] ]; syndrome |= p & 0x01; } return syndrome; } // encode symbol // _sym_dec : decoded symbol [size: 4 x 1] // _sym_enc : encoded symbol [size: 5 x 1], _sym_enc[0] has only 7 bits void fec_secded3932_encode_symbol(unsigned char * _sym_dec, unsigned char * _sym_enc) { // first six bits is parity block _sym_enc[0] = fec_secded3932_compute_parity(_sym_dec); // concatenate original message _sym_enc[1] = _sym_dec[0]; _sym_enc[2] = _sym_dec[1]; _sym_enc[3] = _sym_dec[2]; _sym_enc[4] = _sym_dec[3]; } // decode symbol, returning 0/1/2 for zero/one/multiple errors detected // _sym_enc : encoded symbol [size: 5 x 1], _sym_enc[0] has only 7 bits // _sym_dec : decoded symbol [size: 4 x 1] int fec_secded3932_decode_symbol(unsigned char * _sym_enc, unsigned char * _sym_dec) { #if 0 // validate input if (_sym_enc[0] >= (1<<7)) { fprintf(stderr,"warning, fec_secded3932_decode_symbol(), input symbol too large\n"); } #endif // estimate error vector unsigned char e_hat[5] = {0,0,0,0,0}; // estimated error vector int syndrome_flag = fec_secded3932_estimate_ehat(_sym_enc, e_hat); // compute estimated transmit vector (last 64 bits of encoded message) // NOTE: indices take into account first element in _sym_enc and e_hat // arrays holds the parity bits _sym_dec[0] = _sym_enc[1] ^ e_hat[1]; _sym_dec[1] = _sym_enc[2] ^ e_hat[2]; _sym_dec[2] = _sym_enc[3] ^ e_hat[3]; _sym_dec[3] = _sym_enc[4] ^ e_hat[4]; #if DEBUG_FEC_SECDED3932 if (syndrome_flag == 1) { printf("secded3932_decode_symbol(): single error detected!\n"); } else if (syndrome_flag == 2) { printf("secded3932_decode_symbol(): no match found (multiple errors detected)\n"); } #endif // return syndrome flag return syndrome_flag; } // estimate error vector, returning 0/1/2 for zero/one/multiple errors // detected, respectively // _sym_enc : encoded symbol [size: 5 x 1], _sym_enc[0] has only 6 bits // _e_hat : estimated error vector [size: 5 x 1] int fec_secded3932_estimate_ehat(unsigned char * _sym_enc, unsigned char * _e_hat) { // clear output array _e_hat[0] = 0x00; _e_hat[1] = 0x00; _e_hat[2] = 0x00; _e_hat[3] = 0x00; _e_hat[4] = 0x00; // compute syndrome vector, s = r*H^T = ( H*r^T )^T unsigned char s = fec_secded3932_compute_syndrome(_sym_enc); // compute weight of s unsigned int ws = liquid_c_ones[s]; if (ws == 0) { // no errors detected return 0; } else { // estimate error location; search for syndrome with error // vector of weight one unsigned int n; // estimate error location for (n=0; n<39; n++) { if (s == secded3932_syndrome_w1[n]) { // single error detected at location 'n' div_t d = div(n,8); _e_hat[5-d.quot-1] = 1 << d.rem; return 1; } } } // no syndrome match; multiple errors detected return 2; } // create SEC-DED (39,32) codec object fec fec_secded3932_create(void * _opts) { fec q = (fec) malloc(sizeof(struct fec_s)); // set scheme q->scheme = LIQUID_FEC_SECDED3932; q->rate = fec_get_rate(q->scheme); // set internal function pointers q->encode_func = &fec_secded3932_encode; q->decode_func = &fec_secded3932_decode; q->decode_soft_func = NULL; return q; } // destroy SEC-DEC (39,32) object void fec_secded3932_destroy(fec _q) { free(_q); } // encode block of data using SEC-DEC (39,32) encoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_dec : decoded message [size: 1 x _dec_msg_len] // _msg_enc : encoded message [size: 1 x 2*_dec_msg_len] void fec_secded3932_encode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_dec, unsigned char *_msg_enc) { unsigned int i=0; // decoded byte counter unsigned int j=0; // encoded byte counter // determine remainder of input length / 4 unsigned int r = _dec_msg_len % 4; // for now simply encode as 4/5-rate codec (eat // last parity bit) // TODO : make more efficient for (i=0; i<_dec_msg_len-r; i+=4) { // compute parity (7 bits) on two input bytes (32 bits) _msg_enc[j+0] = fec_secded3932_compute_parity(&_msg_dec[i]); // copy remaining two input bytes (32 bits) _msg_enc[j+1] = _msg_dec[i+0]; _msg_enc[j+2] = _msg_dec[i+1]; _msg_enc[j+3] = _msg_dec[i+2]; _msg_enc[j+4] = _msg_dec[i+3]; // increment output counter j += 5; } // if input length isn't divisible by 4, encode last few bytes if (r) { // one 32-bit symbol (decoded) unsigned char m[4] = {0,0,0,0}; unsigned int n; for (n=0; n #include #include #include #include "liquid.internal.h" #define DEBUG_FEC_SECDED7264 0 // P matrix [8 x 64] // 11111111 00001111 00001111 00001100 01101000 10001000 10001000 10000000 : // 11110000 11111111 00000000 11110011 01100100 01000100 01000100 01000000 : // 00110000 11110000 11111111 00001111 00000010 00100010 00100010 00100110 : // 11001111 00000000 11110000 11111111 00000001 00010001 00010001 00010110 : // 01101000 10001000 10001000 10000000 11111111 00001111 00000000 11110011 : // 01100100 01000100 01000100 01000000 11110000 11111111 00001111 00001100 : // 00000010 00100010 00100010 00100110 11001111 00000000 11111111 00001111 : // 00000001 00010001 00010001 00010110 00110000 11110000 11110000 11111111 : unsigned char secded7264_P[64] = { 0xFF, 0x0F, 0x0F, 0x0C, 0x68, 0x88, 0x88, 0x80, 0xF0, 0xFF, 0x00, 0xF3, 0x64, 0x44, 0x44, 0x40, 0x30, 0xF0, 0xFF, 0x0F, 0x02, 0x22, 0x22, 0x26, 0xCF, 0x00, 0xF0, 0xFF, 0x01, 0x11, 0x11, 0x16, 0x68, 0x88, 0x88, 0x80, 0xFF, 0x0F, 0x00, 0xF3, 0x64, 0x44, 0x44, 0x40, 0xF0, 0xFF, 0x0F, 0x0C, 0x02, 0x22, 0x22, 0x26, 0xCF, 0x00, 0xFF, 0x0F, 0x01, 0x11, 0x11, 0x16, 0x30, 0xF0, 0xF0, 0xFF}; // syndrome vectors for errors of weight 1 unsigned char secded7264_syndrome_w1[72] = { 0x0b, 0x3b, 0x37, 0x07, 0x19, 0x29, 0x49, 0x89, 0x16, 0x26, 0x46, 0x86, 0x13, 0x23, 0x43, 0x83, 0x1c, 0x2c, 0x4c, 0x8c, 0x15, 0x25, 0x45, 0x85, 0x1a, 0x2a, 0x4a, 0x8a, 0x0d, 0xcd, 0xce, 0x0e, 0x70, 0x73, 0xb3, 0xb0, 0x51, 0x52, 0x54, 0x58, 0xa1, 0xa2, 0xa4, 0xa8, 0x31, 0x32, 0x34, 0x38, 0xc1, 0xc2, 0xc4, 0xc8, 0x61, 0x62, 0x64, 0x68, 0x91, 0x92, 0x94, 0x98, 0xe0, 0xec, 0xdc, 0xd0, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; // compute parity byte on 64-byte input unsigned char fec_secded7264_compute_parity(unsigned char * _v) { // compute parity byte on message unsigned int i; unsigned char parity = 0x00; for (i=0; i<8; i++) { parity <<= 1; unsigned int p = liquid_c_ones[ secded7264_P[8*i+0] & _v[0] ] + liquid_c_ones[ secded7264_P[8*i+1] & _v[1] ] + liquid_c_ones[ secded7264_P[8*i+2] & _v[2] ] + liquid_c_ones[ secded7264_P[8*i+3] & _v[3] ] + liquid_c_ones[ secded7264_P[8*i+4] & _v[4] ] + liquid_c_ones[ secded7264_P[8*i+5] & _v[5] ] + liquid_c_ones[ secded7264_P[8*i+6] & _v[6] ] + liquid_c_ones[ secded7264_P[8*i+7] & _v[7] ]; parity |= p & 0x01; } // return parity byte return parity; } // compute syndrome on 72-bit input unsigned char fec_secded7264_compute_syndrome(unsigned char * _v) { // TODO : unwrap this loop unsigned int i; unsigned char syndrome = 0x00; for (i=0; i<8; i++) { syndrome <<= 1; // compute parity bit unsigned int p = ( (_v[0] & (1<<(8-i-1))) ? 1 : 0 ) + liquid_c_ones[ secded7264_P[8*i+0] & _v[1] ] + liquid_c_ones[ secded7264_P[8*i+1] & _v[2] ] + liquid_c_ones[ secded7264_P[8*i+2] & _v[3] ] + liquid_c_ones[ secded7264_P[8*i+3] & _v[4] ] + liquid_c_ones[ secded7264_P[8*i+4] & _v[5] ] + liquid_c_ones[ secded7264_P[8*i+5] & _v[6] ] + liquid_c_ones[ secded7264_P[8*i+6] & _v[7] ] + liquid_c_ones[ secded7264_P[8*i+7] & _v[8] ]; syndrome |= p & 0x01; } return syndrome; } void fec_secded7264_encode_symbol(unsigned char * _sym_dec, unsigned char * _sym_enc) { // compute parity on input _sym_enc[0] = fec_secded7264_compute_parity(_sym_dec); // copy input to output _sym_enc[1] = _sym_dec[0]; _sym_enc[2] = _sym_dec[1]; _sym_enc[3] = _sym_dec[2]; _sym_enc[4] = _sym_dec[3]; _sym_enc[5] = _sym_dec[4]; _sym_enc[6] = _sym_dec[5]; _sym_enc[7] = _sym_dec[6]; _sym_enc[8] = _sym_dec[7]; } // decode symbol, returning 0/1/2 for zero/one/multiple errors detected // _sym_enc : encoded symbol [size: 9 x 1] // _sym_dec : decoded symbol [size: 8 x 1] int fec_secded7264_decode_symbol(unsigned char * _sym_enc, unsigned char * _sym_dec) { // estimate error vector unsigned char e_hat[9] = {0,0,0,0,0,0,0,0,0}; int syndrome_flag = fec_secded7264_estimate_ehat(_sym_enc, e_hat); // compute estimated transmit vector (last 64 bits of encoded message) // NOTE: indices take into account first element in _sym_enc and e_hat // arrays holds the parity bits _sym_dec[0] = _sym_enc[1] ^ e_hat[1]; _sym_dec[1] = _sym_enc[2] ^ e_hat[2]; _sym_dec[2] = _sym_enc[3] ^ e_hat[3]; _sym_dec[3] = _sym_enc[4] ^ e_hat[4]; _sym_dec[4] = _sym_enc[5] ^ e_hat[5]; _sym_dec[5] = _sym_enc[6] ^ e_hat[6]; _sym_dec[6] = _sym_enc[7] ^ e_hat[7]; _sym_dec[7] = _sym_enc[8] ^ e_hat[8]; #if DEBUG_FEC_SECDED7264 if (syndrome_flag == 1) { printf("secded7264_decode_symbol(): single error detected!\n"); } else if (syndrome_flag == 2) { printf("secded7264_decode_symbol(): no match found (multiple errors detected)\n"); } #endif // return syndrome flag return syndrome_flag; } // estimate error vector, returning 0/1/2 for zero/one/multiple errors // detected, respectively // _sym_enc : encoded symbol [size: 9 x 1], // _e_hat : estimated error vector [size: 9 x 1] int fec_secded7264_estimate_ehat(unsigned char * _sym_enc, unsigned char * _e_hat) { // clear output array memset(_e_hat, 0x00, 9*sizeof(unsigned char)); // compute syndrome vector, s = r*H^T = ( H*r^T )^T unsigned char s = fec_secded7264_compute_syndrome(_sym_enc); // compute weight of s unsigned int ws = liquid_c_ones[s]; if (ws == 0) { // no errors detected return 0; } else { // estimate error location; search for syndrome with error // vector of weight one unsigned int n; // estimate error location for (n=0; n<72; n++) { if (s == secded7264_syndrome_w1[n]) { // single error detected at location 'n' div_t d = div(n,8); _e_hat[9-d.quot-1] = 1 << d.rem; return 1; } } } // no syndrome match; multiple errors detected return 2; } // create SEC-DED (72,64) codec object fec fec_secded7264_create(void * _opts) { fec q = (fec) malloc(sizeof(struct fec_s)); // set scheme q->scheme = LIQUID_FEC_SECDED7264; q->rate = fec_get_rate(q->scheme); // set internal function pointers q->encode_func = &fec_secded7264_encode; q->decode_func = &fec_secded7264_decode; q->decode_soft_func = NULL; return q; } // destroy SEC-DEC (72,64) object void fec_secded7264_destroy(fec _q) { free(_q); } // encode block of data using SEC-DEC (72,64) encoder // // _q : encoder/decoder object // _dec_msg_len : decoded message length (number of bytes) // _msg_dec : decoded message [size: 1 x _dec_msg_len] // _msg_enc : encoded message [size: 1 x 2*_dec_msg_len] void fec_secded7264_encode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_dec, unsigned char *_msg_enc) { unsigned int i=0; // decoded byte counter unsigned int j=0; // encoded byte counter unsigned char parity; // parity byte // determine remainder of input length / 8 unsigned int r = _dec_msg_len % 8; // TODO : devise more efficient way of doing this for (i=0; i<_dec_msg_len-r; i+=8) { // encode directly to output fec_secded7264_encode_symbol(&_msg_dec[i], &_msg_enc[j]); j += 9; } // if input length isn't divisible by 8, encode last few bytes if (r) { unsigned char v[8] = {0,0,0,0,0,0,0,0}; unsigned int n; for (n=0; n #include #include #include #include "liquid.internal.h" // // internal methods // // permute one iteration void interleaver_permute(unsigned char * _x, unsigned int _n, unsigned int _M, unsigned int _N); // permute one iteration (soft bit input) void interleaver_permute_soft(unsigned char * _x, unsigned int _n, unsigned int _M, unsigned int _N); // permute one iteration with mask void interleaver_permute_mask(unsigned char * _x, unsigned int _n, unsigned int _M, unsigned int _N, unsigned char _mask); // permute one iteration (soft bit input) with mask void interleaver_permute_mask_soft(unsigned char * _x, unsigned int _n, unsigned int _M, unsigned int _N, unsigned char _mask); // structured interleaver object struct interleaver_s { unsigned int n; // number of bytes unsigned int M; // row dimension unsigned int N; // col dimension // interleaving depth (number of permutations) unsigned int depth; }; // create interleaver of length _n input/output bytes interleaver interleaver_create(unsigned int _n) { interleaver q = (interleaver) malloc(sizeof(struct interleaver_s)); q->n = _n; // set internal properties q->depth = 4; // default depth to maximum // compute block dimensions q->M = 1 + (unsigned int) floorf(sqrtf(q->n)); q->N = q->n / q->M; while (q->n >= (q->M*q->N)) q->N++; // ensures M*N >= n return q; } // destroy interleaver object void interleaver_destroy(interleaver _q) { // free main object memory free(_q); } // print interleaver internals void interleaver_print(interleaver _q) { printf("interleaver [block, %u bytes] :\n", _q->n); printf(" M : %u\n", _q->M); printf(" N : %u\n", _q->N); printf(" depth : %u\n", _q->depth); } // set depth (number of internal iterations) void interleaver_set_depth(interleaver _q, unsigned int _depth) { _q->depth = _depth; } // execute forward interleaver (encoder) // _q : interleaver object // _msg_dec : decoded (un-interleaved) message // _msg_enc : encoded (interleaved) message void interleaver_encode(interleaver _q, unsigned char * _msg_dec, unsigned char * _msg_enc) { // copy data to output memmove(_msg_enc, _msg_dec, _q->n); if (_q->depth > 0) interleaver_permute(_msg_enc, _q->n, _q->M, _q->N); if (_q->depth > 1) interleaver_permute_mask(_msg_enc, _q->n, _q->M, _q->N+2, 0x0f); if (_q->depth > 2) interleaver_permute_mask(_msg_enc, _q->n, _q->M, _q->N+4, 0x55); if (_q->depth > 3) interleaver_permute_mask(_msg_enc, _q->n, _q->M, _q->N+8, 0x33); } // execute forward interleaver (encoder) on soft bits // _q : interleaver object // _msg_dec : decoded (un-interleaved) message // _msg_enc : encoded (interleaved) message void interleaver_encode_soft(interleaver _q, unsigned char * _msg_dec, unsigned char * _msg_enc) { // copy data to output memmove(_msg_enc, _msg_dec, 8*_q->n); if (_q->depth > 0) interleaver_permute_soft(_msg_enc, _q->n, _q->M, _q->N); if (_q->depth > 1) interleaver_permute_mask_soft(_msg_enc, _q->n, _q->M, _q->N+2, 0x0f); if (_q->depth > 2) interleaver_permute_mask_soft(_msg_enc, _q->n, _q->M, _q->N+4, 0x55); if (_q->depth > 3) interleaver_permute_mask_soft(_msg_enc, _q->n, _q->M, _q->N+8, 0x33); } // execute reverse interleaver (decoder) // _q : interleaver object // _msg_enc : encoded (interleaved) message // _msg_dec : decoded (un-interleaved) message void interleaver_decode(interleaver _q, unsigned char * _msg_enc, unsigned char * _msg_dec) { // copy data to output memmove(_msg_dec, _msg_enc, _q->n); if (_q->depth > 3) interleaver_permute_mask(_msg_dec, _q->n, _q->M, _q->N+8, 0x33); if (_q->depth > 2) interleaver_permute_mask(_msg_dec, _q->n, _q->M, _q->N+4, 0x55); if (_q->depth > 1) interleaver_permute_mask(_msg_dec, _q->n, _q->M, _q->N+2, 0x0f); if (_q->depth > 0) interleaver_permute(_msg_dec, _q->n, _q->M, _q->N); } // execute reverse interleaver (decoder) on soft bits // _q : interleaver object // _msg_enc : encoded (interleaved) message // _msg_dec : decoded (un-interleaved) message void interleaver_decode_soft(interleaver _q, unsigned char * _msg_enc, unsigned char * _msg_dec) { // copy data to output memmove(_msg_dec, _msg_enc, 8*_q->n); if (_q->depth > 3) interleaver_permute_mask_soft(_msg_dec, _q->n, _q->M, _q->N+8, 0x33); if (_q->depth > 2) interleaver_permute_mask_soft(_msg_dec, _q->n, _q->M, _q->N+4, 0x55); if (_q->depth > 1) interleaver_permute_mask_soft(_msg_dec, _q->n, _q->M, _q->N+2, 0x0f); if (_q->depth > 0) interleaver_permute_soft(_msg_dec, _q->n, _q->M, _q->N); } // // internal permutation methods // // permute one iteration void interleaver_permute(unsigned char * _x, unsigned int _n, unsigned int _M, unsigned int _N) { unsigned int i; unsigned int j; unsigned int m=0; unsigned int n=_n/3; unsigned int n2=_n/2; unsigned char tmp; for (i=0; i=n2); // swap indices tmp = _x[2*j+1]; _x[2*j+1] = _x[2*i+0]; _x[2*i+0] = tmp; } } // permute one iteration (soft bit input) void interleaver_permute_soft(unsigned char * _x, unsigned int _n, unsigned int _M, unsigned int _N) { unsigned int i; unsigned int j; unsigned int m=0; unsigned int n=_n/3; unsigned int n2=_n/2; unsigned char tmp[8]; for (i=0; i=n2); // swap soft bits at indices memmove( tmp, &_x[8*(2*j+1)], 8); memmove( &_x[8*(2*j+1)], &_x[8*(2*i+0)], 8); memmove( &_x[8*(2*i+0)], tmp, 8); } //printf("\n"); } // permute one iteration with mask void interleaver_permute_mask(unsigned char * _x, unsigned int _n, unsigned int _M, unsigned int _N, unsigned char _mask) { unsigned int i; unsigned int j; unsigned int m=0; unsigned int n=_n/3; unsigned int n2=_n/2; unsigned char tmp0; unsigned char tmp1; for (i=0; i=n2); // swap indices, applying mask tmp0 = (_x[2*i+0] & (~_mask)) | (_x[2*j+1] & ( _mask)); tmp1 = (_x[2*i+0] & ( _mask)) | (_x[2*j+1] & (~_mask)); _x[2*i+0] = tmp0; _x[2*j+1] = tmp1; } } // permute one iteration (soft bit input) void interleaver_permute_mask_soft(unsigned char * _x, unsigned int _n, unsigned int _M, unsigned int _N, unsigned char _mask) { unsigned int i; unsigned int j; unsigned int k; unsigned int m=0; unsigned int n=_n/3; unsigned int n2=_n/2; unsigned char tmp; for (i=0; i=n2); // swap bits matching the mask for (k=0; k<8; k++) { if ( (_mask >> (8-k-1)) & 0x01 ) { tmp = _x[8*(2*j+1)+k]; _x[8*(2*j+1)+k] = _x[8*(2*i+0)+k]; _x[8*(2*i+0)+k] = tmp; } } } //printf("\n"); } liquid-dsp-1.3.1/src/fec/src/packetizer.c000066400000000000000000000305601317124540100202110ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Packetizer // #include #include #include #include "liquid.internal.h" // reallocate memory for buffers void packetizer_realloc_buffers(packetizer _p, unsigned int _len); // computes the number of encoded bytes after packetizing // // _n : number of uncoded input bytes // _crc : error-detecting scheme // _fec0 : inner forward error-correction code // _fec1 : outer forward error-correction code unsigned int packetizer_compute_enc_msg_len(unsigned int _n, int _crc, int _fec0, int _fec1) { unsigned int k = _n + crc_get_length(_crc); unsigned int n0 = fec_get_enc_msg_length(_fec0, k); unsigned int n1 = fec_get_enc_msg_length(_fec1, n0); return n1; } // computes the number of decoded bytes before packetizing // // _k : number of encoded bytes // _crc : error-detecting scheme // _fec0 : inner forward error-correction code // _fec1 : outer forward error-correction code unsigned int packetizer_compute_dec_msg_len(unsigned int _k, int _crc, int _fec0, int _fec1) { unsigned int n_hat = 0; unsigned int k_hat = 0; // check for zero-length packet // TODO : implement faster method while (k_hat < _k) { // compute encoded packet length k_hat = packetizer_compute_enc_msg_len(n_hat, _crc, _fec0, _fec1); // if (k_hat == _k) return n_hat; else if (k_hat > _k) return n_hat; // TODO : check this special condition else n_hat++; } return 0; } // create packetizer object // // _n : number of uncoded intput bytes // _crc : error-detecting scheme // _fec0 : inner forward error-correction code // _fec1 : outer forward error-correction code packetizer packetizer_create(unsigned int _n, int _crc, int _fec0, int _fec1) { packetizer p = (packetizer) malloc(sizeof(struct packetizer_s)); p->msg_len = _n; p->packet_len = packetizer_compute_enc_msg_len(_n, _crc, _fec0, _fec1); p->check = _crc; p->crc_length = crc_get_length(p->check); // allocate memory for buffers (scale by 8 for soft decoding) p->buffer_len = p->packet_len; p->buffer_0 = (unsigned char*) malloc(8*p->buffer_len); p->buffer_1 = (unsigned char*) malloc(8*p->buffer_len); // create plan p->plan_len = 2; p->plan = (struct fecintlv_plan*) malloc((p->plan_len)*sizeof(struct fecintlv_plan)); // set schemes unsigned int i; unsigned int n0 = _n + p->crc_length; for (i=0; iplan_len; i++) { // set schemes p->plan[i].fs = (i==0) ? _fec0 : _fec1; // compute lengths p->plan[i].dec_msg_len = n0; p->plan[i].enc_msg_len = fec_get_enc_msg_length(p->plan[i].fs, p->plan[i].dec_msg_len); // create objects p->plan[i].f = fec_create(p->plan[i].fs, NULL); p->plan[i].q = interleaver_create(p->plan[i].enc_msg_len); // set interleaver depth to zero if no error correction scheme // is applied to this plan if (p->plan[i].fs == LIQUID_FEC_NONE) interleaver_set_depth(p->plan[i].q, 0); // update length n0 = p->plan[i].enc_msg_len; } return p; } // re-create packetizer object // // _p : initialz packetizer object // _n : number of uncoded intput bytes // _crc : error-detecting scheme // _fec0 : inner forward error-correction code // _fec1 : outer forward error-correction code packetizer packetizer_recreate(packetizer _p, unsigned int _n, int _crc, int _fec0, int _fec1) { if (_p == NULL) { // packetizer was never created return packetizer_create(_n, _crc, _fec0, _fec1); } // check values if (_p->msg_len == _n && _p->check == _crc && _p->plan[0].fs == _fec0 && _p->plan[1].fs == _fec1 ) { // no change; return input pointer return _p; } // something has changed; destroy old object and create new one // TODO : rather than completely destroying object, only change values that are necessary packetizer_destroy(_p); return packetizer_create(_n,_crc,_fec0,_fec1); } // destroy packetizer object void packetizer_destroy(packetizer _p) { // free fec, interleaver objects unsigned int i; for (i=0; i<_p->plan_len; i++) { fec_destroy(_p->plan[i].f); interleaver_destroy(_p->plan[i].q); }; // free plan free(_p->plan); // free buffers free(_p->buffer_0); free(_p->buffer_1); // free packetizer object free(_p); } // print packetizer object internals void packetizer_print(packetizer _p) { printf("packetizer [dec: %u, enc: %u]\n", _p->msg_len, _p->packet_len); printf(" : crc %-10u %-10u %-16s\n", _p->msg_len, _p->msg_len + _p->crc_length, crc_scheme_str[_p->check][0]); unsigned int i; for (i=0; i<_p->plan_len; i++) { printf("%4u : fec %-10u %-10u %-16s\n", i, _p->plan[i].dec_msg_len, _p->plan[i].enc_msg_len, fec_scheme_str[_p->plan[i].fs][1]); } } // get decoded message length unsigned int packetizer_get_dec_msg_len(packetizer _p) { return _p->msg_len; } // get encoded message length unsigned int packetizer_get_enc_msg_len(packetizer _p) { return _p->packet_len; } crc_scheme packetizer_get_crc(packetizer _p) { return _p->check; } fec_scheme packetizer_get_fec0(packetizer _p) { return _p->plan[0].fs; } fec_scheme packetizer_get_fec1(packetizer _p) { return _p->plan[1].fs; } // Execute the packetizer on an input message // // _p : packetizer object // _msg : input message (uncoded bytes) // _pkt : encoded output message void packetizer_encode(packetizer _p, const unsigned char * _msg, unsigned char * _pkt) { unsigned int i; // copy input message to internal buffer[0] (or initialize to zeros) if (_msg != NULL) { // copy user-defined input memmove(_p->buffer_0, _msg, _p->msg_len); } else { // initialize with zeros memset(_p->buffer_0, 0x00, _p->msg_len); } // compute crc, append to buffer unsigned int key = crc_generate_key(_p->check, _p->buffer_0, _p->msg_len); for (i=0; i<_p->crc_length; i++) { // append byte to buffer _p->buffer_0[_p->msg_len+_p->crc_length-i-1] = key & 0xff; // shift key by 8 bits key >>= 8; } // whiten input sequence scramble_data(_p->buffer_0, _p->msg_len + _p->crc_length); // execute fec/interleaver plans for (i=0; i<_p->plan_len; i++) { // run the encoder: buffer[0] > buffer[1] fec_encode(_p->plan[i].f, _p->plan[i].dec_msg_len, _p->buffer_0, _p->buffer_1); // run the interleaver: buffer[1] > buffer[0] interleaver_encode(_p->plan[i].q, _p->buffer_1, _p->buffer_0); } // copy result to output memmove(_pkt, _p->buffer_0, _p->packet_len); } // Execute the packetizer to decode an input message, return validity // check of resulting data // // _p : packetizer object // _pkt : input message (coded bytes) // _msg : decoded output message int packetizer_decode(packetizer _p, const unsigned char * _pkt, unsigned char * _msg) { // copy coded message to internal buffer[0] memmove(_p->buffer_0, _pkt, _p->packet_len); // execute fec/interleaver plans unsigned int i; for (i=_p->plan_len; i>0; i--) { // run the de-interleaver: buffer[0] > buffer[1] interleaver_decode(_p->plan[i-1].q, _p->buffer_0, _p->buffer_1); // run the decoder: buffer[1] > buffer[0] fec_decode(_p->plan[i-1].f, _p->plan[i-1].dec_msg_len, _p->buffer_1, _p->buffer_0); } // remove sequence whitening unscramble_data(_p->buffer_0, _p->msg_len + _p->crc_length); // strip crc, validate message unsigned int key = 0; for (i=0; i<_p->crc_length; i++) { key <<= 8; key |= _p->buffer_0[_p->msg_len+i]; } // copy result to output memmove(_msg, _p->buffer_0, _p->msg_len); // return crc validity return crc_validate_message(_p->check, _p->buffer_0, _p->msg_len, key); } // Execute the packetizer to decode an input message, return validity // check of resulting data // // _p : packetizer object // _pkt : input message (coded soft bits) // _msg : decoded output message int packetizer_decode_soft(packetizer _p, const unsigned char * _pkt, unsigned char * _msg) { // copy coded message to internal buffer[0] memmove(_p->buffer_0, _pkt, 8*_p->packet_len); // // decode outer level using soft decoding // // run the de-interleaver: buffer[0] > buffer[1] interleaver_decode_soft(_p->plan[1].q, _p->buffer_0, _p->buffer_1); // run the decoder: buffer[1] > buffer[0] fec_decode_soft(_p->plan[1].f, _p->plan[1].dec_msg_len, _p->buffer_1, _p->buffer_0); // // decode inner level using hard decoding // // run the de-interleaver: buffer[0] > buffer[1] interleaver_decode(_p->plan[0].q, _p->buffer_0, _p->buffer_1); // run the decoder: buffer[1] > buffer[0] fec_decode(_p->plan[0].f, _p->plan[0].dec_msg_len, _p->buffer_1, _p->buffer_0); // remove sequence whitening unscramble_data(_p->buffer_0, _p->msg_len + _p->crc_length); // strip crc, validate message unsigned int key = 0; unsigned int i; for (i=0; i<_p->crc_length; i++) { key <<= 8; key |= _p->buffer_0[_p->msg_len+i]; } // copy result to output memmove(_msg, _p->buffer_0, _p->msg_len); // return crc validity return crc_validate_message(_p->check, _p->buffer_0, _p->msg_len, key); } void packetizer_set_scheme(packetizer _p, int _fec0, int _fec1) { // } // // internal methods // void packetizer_realloc_buffers(packetizer _p, unsigned int _len) { _p->buffer_len = _len; _p->buffer_0 = (unsigned char*) realloc(_p->buffer_0, _p->buffer_len); _p->buffer_1 = (unsigned char*) realloc(_p->buffer_1, _p->buffer_len); } liquid-dsp-1.3.1/src/fec/src/sumproduct.c000066400000000000000000000150251317124540100202540ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // sumproduct.c // // floating-point implementation of the sum-product algorithm // #include #include #include #include "liquid.internal.h" #define DEBUG_SUMPRODUCT 0 // phi(x) = -logf( tanhf( x/2 ) ) float sumproduct_phi(float _x) { return -logf(tanhf(_x/2.0f + 1e-12)); } // iterate over the sum-product algorithm: // returns 1 if parity checks, 0 otherwise // _m : rows // _n : cols // _H : sparse binary parity check matrix [size: _m x _n] // _LLR : received signal (soft bits, LLR) [size: _n x 1] // _c_hat : estimated transmitted signal [size: _n x 1] // _max_steps : maximum number of steps before bailing int fec_sumproduct(unsigned int _m, unsigned int _n, smatrixb _H, float * _LLR, unsigned char * _c_hat, unsigned int _max_steps) { // TODO : validate input if (_n == 0 || _m == 0) { fprintf(stderr,"error: fec_sumproduct(), matrix dimensions cannot be zero\n"); exit(1); } // internal variables unsigned int num_iterations = 0; float Lq[_m*_n]; float Lr[_m*_n]; float Lc[_n]; float LQ[_n]; unsigned char parity[_m]; unsigned int i; unsigned int j; int parity_pass; int continue_running = 1; // initialize Lq with log-likelihood values for (i=0; i<_n; i++) Lc[i] = _LLR[i]; //Lc[i] = 2.0f * _y[i] / (sigma*sigma); for (j=0; j<_m; j++) { for (i=0; i<_n; i++) { Lq[j*_n+i] = smatrixb_get(_H,j,i) ? Lc[i] : 0.0f; } } #if DEBUG_SUMPRODUCT // print Lc matrixf_print(Lc,1,_n); #endif // TODO : run multiple iterations while (continue_running) { #if DEBUG_SUMPRODUCT // printf("\n"); printf("************* iteration %u ****************\n", num_iterations); #endif // step sum-product algorithm //parity_pass = fec_sumproduct_step(_H,_m,_n,_c_hat,Lq,Lr,Lc,LQ,parity); parity_pass = fec_sumproduct_step(_m,_n,_H,_c_hat,Lq,Lr,Lc,LQ,parity); // update... num_iterations++; if (parity_pass || num_iterations == _max_steps) continue_running = 0; } return parity_pass; } // sum-product algorithm, returns 1 if parity checks, 0 otherwise // _m : rows // _n : cols // _H : sparse binary parity check matrix [size: _m x _n] // _c_hat : estimated transmitted signal [size: _n x 1] // // internal state arrays // _Lq : [size: _m x _n] // _Lr : [size: _m x _n] // _Lc : [size: _n x 1] // _LQ : [size: _n x 1] // _parity : _H * _c_hat [size: _m x 1] int fec_sumproduct_step(unsigned int _m, unsigned int _n, smatrixb _H, unsigned char * _c_hat, float * _Lq, float * _Lr, float * _Lc, float * _LQ, unsigned char * _parity) { unsigned int i; unsigned int j; unsigned int ip; unsigned int jp; float alpha_prod; float phi_sum; int parity_pass; // compute Lr for (i=0; i<_n; i++) { for (j=0; j<_m; j++) { alpha_prod = 1.0f; phi_sum = 0.0f; for (ip=0; ip<_n; ip++) { //if (_H[j*_n+ip]==1 && i != ip) { if (smatrixb_get(_H,j,ip)==1 && i != ip) { float alpha = _Lq[j*_n+ip] > 0.0f ? 1.0f : -1.0f; float beta = fabsf(_Lq[j*_n+ip]); phi_sum += sumproduct_phi(beta); alpha_prod *= alpha; } } _Lr[j*_n+i] = alpha_prod * sumproduct_phi(phi_sum); } } #if DEBUG_SUMPRODUCT // print Lq matrixf_print(_Lq,_m,_n); // print Lr matrixf_print(_Lr,_m,_n); #endif // compute next iteration of Lq for (i=0; i<_n; i++) { for (j=0; j<_m; j++) { // initialize with LLR _Lq[j*_n+i] = _Lc[i]; for (jp=0; jp<_m; jp++) { //if (_H[jp*_n+i]==1 && j != jp) if (smatrixb_get(_H,jp,i)==1 && j != jp) _Lq[j*_n+i] += _Lr[jp*_n+i]; } } } #if DEBUG_SUMPRODUCT // print Lq matrixf_print(_Lq,_m,_n); #endif // compute LQ for (i=0; i<_n; i++) { _LQ[i] = _Lc[i]; // initialize with LLR value for (j=0; j<_m; j++) { //if (_H[j*_n+i]==1) if (smatrixb_get(_H,j,i)==1) _LQ[i] += _Lr[j*_n+i]; } } #if DEBUG_SUMPRODUCT // print LQ matrixf_print(_LQ,1,_n); #endif // compute hard-decoded value for (i=0; i<_n; i++) _c_hat[i] = _LQ[i] < 0.0f ? 1 : 0; // compute parity check: p = H*c_hat smatrixb_vmul(_H, _c_hat, _parity); // check parity parity_pass = 1; for (j=0; j<_m; j++) { if (_parity[j]) parity_pass = 0; } #if DEBUG_SUMPRODUCT // print hard-decision output printf(" : c hat = ["); for (i=0; i<_n; i++) printf(" %1u", _c_hat[i]); printf(" ], "); // print parity printf("parity = ["); for (j=0; j<_m; j++) printf(" %1u", _parity[j]); printf(" ], "); printf(" (%s)\n", parity_pass ? "pass" : "FAIL"); #endif return parity_pass; } liquid-dsp-1.3.1/src/fec/tests/000077500000000000000000000000001317124540100162535ustar00rootroot00000000000000liquid-dsp-1.3.1/src/fec/tests/crc_autotest.c000066400000000000000000000064101317124540100211170ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "autotest/autotest.h" #include "liquid.h" // // AUTOTEST: reverse byte // void autotest_reverse_byte() { // 0110 0010 unsigned char b = 0x62; // 0100 0110 unsigned char r = 0x46; // CONTEND_EQUALITY(liquid_reverse_byte(b),r); } // // AUTOTEST: reverse uint16_t // void autotest_reverse_uint16() { // 1111 0111 0101 1001 unsigned int b = 0xF759; // 1001 1010 1110 1111 unsigned int r = 0x9AEF; // CONTEND_EQUALITY(liquid_reverse_uint16(b),r); } // // AUTOTEST: reverse uint32_t // void autotest_reverse_uint32() { // 0110 0010 1101 1001 0011 1011 1111 0000 unsigned int b = 0x62D93BF0; // 0000 1111 1101 1100 1001 1011 0100 0110 unsigned int r = 0x0FDC9B46; // CONTEND_EQUALITY(liquid_reverse_uint32(b),r); } // // autotest helper function // void validate_crc(crc_scheme _check, unsigned int _n) { unsigned int i; // generate pseudo-random data unsigned char data[_n]; msequence ms = msequence_create_default(9); for (i=0; i<_n; i++) data[i] = msequence_generate_symbol(ms,8); msequence_destroy(ms); // generate key unsigned int key = crc_generate_key(_check, data, _n); // contend data/key are valid CONTEND_EXPRESSION(crc_validate_message(_check, data, _n, key)); // unsigned char data_corrupt[_n]; unsigned int j; for (i=0; i<_n; i++) { for (j=0; j<8; j++) { // copy original data sequence memmove(data_corrupt, data, _n*sizeof(unsigned char)); // flip bit j at byte i data[i] ^= (1 << j); // contend data/key are invalid CONTEND_EXPRESSION(crc_validate_message(_check, data, _n, key)==0); } } } // // AUTOTESTS : validate error-detection tests // void autotest_checksum() { validate_crc(LIQUID_CRC_CHECKSUM, 16); } void autotest_crc8() { validate_crc(LIQUID_CRC_8, 16); } void autotest_crc16() { validate_crc(LIQUID_CRC_16, 64); } void autotest_crc24() { validate_crc(LIQUID_CRC_24, 64); } void autotest_crc32() { validate_crc(LIQUID_CRC_32, 64); } liquid-dsp-1.3.1/src/fec/tests/fec_autotest.c000066400000000000000000000123131317124540100211040ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "autotest/autotest.h" #include "liquid.internal.h" // Helper function to keep code base small void fec_test_codec(fec_scheme _fs, unsigned int _n, void * _opts) { #if !LIBFEC_ENABLED if ( _fs == LIQUID_FEC_CONV_V27 || _fs == LIQUID_FEC_CONV_V29 || _fs == LIQUID_FEC_CONV_V39 || _fs == LIQUID_FEC_CONV_V615 || _fs == LIQUID_FEC_CONV_V27P23 || _fs == LIQUID_FEC_CONV_V27P34 || _fs == LIQUID_FEC_CONV_V27P45 || _fs == LIQUID_FEC_CONV_V27P56 || _fs == LIQUID_FEC_CONV_V27P67 || _fs == LIQUID_FEC_CONV_V27P78 || _fs == LIQUID_FEC_CONV_V29P23 || _fs == LIQUID_FEC_CONV_V29P34 || _fs == LIQUID_FEC_CONV_V29P45 || _fs == LIQUID_FEC_CONV_V29P56 || _fs == LIQUID_FEC_CONV_V29P67 || _fs == LIQUID_FEC_CONV_V29P78 || _fs == LIQUID_FEC_RS_M8) { AUTOTEST_WARN("convolutional, Reed-Solomon codes unavailable (install libfec)\n"); return; } #endif // generate fec object fec q = fec_create(_fs,_opts); // create arrays unsigned int n_enc = fec_get_enc_msg_length(_fs,_n); unsigned char msg[_n]; // original message unsigned char msg_enc[n_enc]; // encoded message unsigned char msg_dec[_n]; // decoded message // initialze message unsigned int i; for (i=0; i<_n; i++) { msg[i] = rand() & 0xff; msg_dec[i] = 0; } // encode message fec_encode(q,_n,msg,msg_enc); // channel: add single error msg_enc[0] ^= 0x01; // decode message fec_decode(q,_n,msg_enc,msg_dec); // validate output CONTEND_SAME_DATA(msg,msg_dec,_n); // clean up objects fec_destroy(q); } // // AUTOTESTS: basic encode/decode functionality // // repeat codes void autotest_fec_r3() { fec_test_codec(LIQUID_FEC_REP3, 64, NULL); } void autotest_fec_r5() { fec_test_codec(LIQUID_FEC_REP5, 64, NULL); } // Hamming block codes void autotest_fec_h74() { fec_test_codec(LIQUID_FEC_HAMMING74, 64, NULL); } void autotest_fec_h84() { fec_test_codec(LIQUID_FEC_HAMMING84, 64, NULL); } void autotest_fec_h128() { fec_test_codec(LIQUID_FEC_HAMMING128, 64, NULL); } // Golay block codes void autotest_fec_g2412() { fec_test_codec(LIQUID_FEC_GOLAY2412, 64, NULL); } // SEC-DED block codecs void autotest_fec_secded2216() { fec_test_codec(LIQUID_FEC_SECDED2216, 64, NULL); } void autotest_fec_secded3932() { fec_test_codec(LIQUID_FEC_SECDED3932, 64, NULL); } void autotest_fec_secded7264() { fec_test_codec(LIQUID_FEC_SECDED7264, 64, NULL); } // convolutional codes void autotest_fec_v27() { fec_test_codec(LIQUID_FEC_CONV_V27, 64, NULL); } void autotest_fec_v29() { fec_test_codec(LIQUID_FEC_CONV_V29, 64, NULL); } void autotest_fec_v39() { fec_test_codec(LIQUID_FEC_CONV_V39, 64, NULL); } void autotest_fec_v615() { fec_test_codec(LIQUID_FEC_CONV_V615, 64, NULL); } // convolutional codes (punctured) void autotest_fec_v27p23() { fec_test_codec(LIQUID_FEC_CONV_V27P23, 64, NULL); } void autotest_fec_v27p34() { fec_test_codec(LIQUID_FEC_CONV_V27P34, 64, NULL); } void autotest_fec_v27p45() { fec_test_codec(LIQUID_FEC_CONV_V27P45, 64, NULL); } void autotest_fec_v27p56() { fec_test_codec(LIQUID_FEC_CONV_V27P56, 64, NULL); } void autotest_fec_v27p67() { fec_test_codec(LIQUID_FEC_CONV_V27P67, 64, NULL); } void autotest_fec_v27p78() { fec_test_codec(LIQUID_FEC_CONV_V27P78, 64, NULL); } void autotest_fec_v29p23() { fec_test_codec(LIQUID_FEC_CONV_V29P23, 64, NULL); } void autotest_fec_v29p34() { fec_test_codec(LIQUID_FEC_CONV_V29P34, 64, NULL); } void autotest_fec_v29p45() { fec_test_codec(LIQUID_FEC_CONV_V29P45, 64, NULL); } void autotest_fec_v29p56() { fec_test_codec(LIQUID_FEC_CONV_V29P56, 64, NULL); } void autotest_fec_v29p67() { fec_test_codec(LIQUID_FEC_CONV_V29P67, 64, NULL); } void autotest_fec_v29p78() { fec_test_codec(LIQUID_FEC_CONV_V29P78, 64, NULL); } // Reed-Solomon block codes void autotest_fec_rs8() { fec_test_codec(LIQUID_FEC_RS_M8, 64, NULL); } liquid-dsp-1.3.1/src/fec/tests/fec_golay2412_autotest.c000066400000000000000000000067021317124540100226150ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "autotest/autotest.h" #include "liquid.internal.h" // generate random error vector with 'n' ones; // maybe not efficient but effective unsigned int golay2412_generate_error_vector(unsigned int _n) { if (_n > 24) { fprintf(stderr,"error: golay2412_generate_error_vector(), cannot generate more than 24 errors\n"); exit(1); } unsigned int i; unsigned int error_locations[24]; for (i=0; i<24; i++) error_locations[i] = 0; unsigned int t=0; for (i=0; i<_n; i++) { do { // generate random error location t = rand() % 24; // check error location } while (error_locations[t]); error_locations[t] = 1; } // generate error vector unsigned int e = 0; for (i=0; i<24; i++) e |= error_locations[i] ? (1 << i) : 0; return e; } // // AUTOTEST: Golay(24,12) codec // void autotest_golay2412_codec() { unsigned int num_trials=50; // number of symbol trials unsigned int num_errors; // number of errors unsigned int i; for (num_errors=0; num_errors<=3; num_errors++) { for (i=0; i #include #include "autotest/autotest.h" #include "liquid.internal.h" // // AUTOTEST: Hamming (12,8) codec // void autotest_hamming128_codec() { unsigned int n=8; // unsigned int k=12; // unsigned int i; // index of bit to corrupt for (i=0; i #include #include "autotest/autotest.h" #include "liquid.internal.h" // // AUTOTEST: Hamming (15,11) codec // void autotest_hamming1511_codec() { unsigned int n=11; // unsigned int k=15; // unsigned int i; // index of bit to corrupt for (i=0; i #include #include "autotest/autotest.h" #include "liquid.internal.h" // // AUTOTEST: Hamming (31,26) codec // void autotest_hamming3126_codec() { unsigned int n=26; // unsigned int k=31; // unsigned int i; // index of bit to corrupt for (i=0; i #include #include #include "autotest/autotest.h" #include "liquid.internal.h" // // AUTOTEST: Reed-Solomon codecs // void autotest_reedsolomon_223_255() { #if !LIBFEC_ENABLED printf("warning: Reed-Solomon codes unavailable\n"); return; #endif unsigned int dec_msg_len = 223; // compute and test encoded message length unsigned int enc_msg_len = fec_get_enc_msg_length(LIQUID_FEC_RS_M8,dec_msg_len); CONTEND_EQUALITY( enc_msg_len, 255 ); // create arrays unsigned char msg_org[dec_msg_len]; // original message unsigned char msg_enc[enc_msg_len]; // encoded message unsigned char msg_rec[enc_msg_len]; // received message unsigned char msg_dec[dec_msg_len]; // decoded message // initialize original message unsigned int i; for (i=0; i #include #include "autotest/autotest.h" #include "liquid.internal.h" // // AUTOTEST: SEC-DEC (22,16) codec (no errors) // void autotest_secded2216_codec_e0() { // generate symbol unsigned char sym_org[2]; sym_org[0] = rand() & 0xffff; sym_org[1] = rand() & 0xffff; // encoded symbol unsigned char sym_enc[3]; fec_secded2216_encode_symbol(sym_org, sym_enc); // decoded symbol unsigned char sym_dec[2]; fec_secded2216_decode_symbol(sym_enc, sym_dec); // validate data are the same CONTEND_EQUALITY(sym_org[0], sym_dec[0]); CONTEND_EQUALITY(sym_org[1], sym_dec[1]); } // // AUTOTEST: SEC-DEC (22,16) codec (single error) // void autotest_secded2216_codec_e1() { unsigned int k; // error location for (k=0; k<22; k++) { // generate symbol unsigned char sym_org[2]; sym_org[0] = rand() & 0xffff; sym_org[1] = rand() & 0xffff; // encoded symbol unsigned char sym_enc[3]; fec_secded2216_encode_symbol(sym_org, sym_enc); // generate error vector (single error) unsigned char e[3] = {0,0,0}; div_t d = div(k,8); e[3-d.quot-1] = 1 << d.rem; // received symbol unsigned char sym_rec[3]; sym_rec[0] = sym_enc[0] ^ e[0]; sym_rec[1] = sym_enc[1] ^ e[1]; sym_rec[2] = sym_enc[2] ^ e[2]; // decoded symbol unsigned char sym_dec[2]; fec_secded2216_decode_symbol(sym_rec, sym_dec); // validate data are the same CONTEND_EQUALITY(sym_org[0], sym_dec[0]); CONTEND_EQUALITY(sym_org[1], sym_dec[1]); } } // // AUTOTEST: SEC-DEC (22,16) codec (double error detection) // void autotest_secded2216_codec_e2() { // total combinations of double errors: nchoosek(22,2) = 231 unsigned int j; unsigned int k; for (j=0; j<21; j++) { if (liquid_autotest_verbose) printf("***** %2u *****\n", j); for (k=0; k<22-j-1; k++) { // generate symbol unsigned char sym_org[2]; sym_org[0] = rand() & 0xffff; sym_org[1] = rand() & 0xffff; // encoded symbol unsigned char sym_enc[3]; fec_secded2216_encode_symbol(sym_org, sym_enc); // generate error vector (single error) unsigned char e[3] = {0,0,0}; div_t dj = div(j,8); e[3-dj.quot-1] |= 1 << dj.rem; div_t dk = div(k+j+1,8); e[3-dk.quot-1] |= 1 << dk.rem; // received symbol unsigned char sym_rec[3]; sym_rec[0] = sym_enc[0] ^ e[0]; sym_rec[1] = sym_enc[1] ^ e[1]; sym_rec[2] = sym_enc[2] ^ e[2]; // decoded symbol unsigned char sym_dec[2]; int syndrome_flag = fec_secded2216_decode_symbol(sym_rec, sym_dec); if (liquid_autotest_verbose) { // print error vector printf("%3u, e = ", k); liquid_print_bitstring(e[0], 6); liquid_print_bitstring(e[1], 8); liquid_print_bitstring(e[2], 8); printf(" flag=%2d\n", syndrome_flag); } // validate syndrome flag is '2' CONTEND_EQUALITY(syndrome_flag, 2); } } } liquid-dsp-1.3.1/src/fec/tests/fec_secded3932_autotest.c000066400000000000000000000121051317124540100227330ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "autotest/autotest.h" #include "liquid.internal.h" // // AUTOTEST: SEC-DEC (39,32) codec (no errors) // void autotest_secded3932_codec_e0() { // generate symbol unsigned char sym_org[4]; sym_org[0] = rand() & 0xffff; sym_org[1] = rand() & 0xffff; sym_org[2] = rand() & 0xffff; sym_org[3] = rand() & 0xffff; // encoded symbol unsigned char sym_enc[5]; fec_secded3932_encode_symbol(sym_org, sym_enc); // decoded symbol unsigned char sym_dec[4]; fec_secded3932_decode_symbol(sym_enc, sym_dec); // validate data are the same CONTEND_EQUALITY(sym_org[0], sym_dec[0]); CONTEND_EQUALITY(sym_org[1], sym_dec[1]); CONTEND_EQUALITY(sym_org[2], sym_dec[2]); CONTEND_EQUALITY(sym_org[3], sym_dec[3]); } // // AUTOTEST: SEC-DEC (39,32) codec (single error) // void autotest_secded3932_codec_e1() { unsigned int k; // error location for (k=0; k<39; k++) { // generate symbol unsigned char sym_org[4]; sym_org[0] = rand() & 0xffff; sym_org[1] = rand() & 0xffff; sym_org[2] = rand() & 0xffff; sym_org[3] = rand() & 0xffff; // encoded symbol unsigned char sym_enc[5]; fec_secded3932_encode_symbol(sym_org, sym_enc); // generate error vector (single error) unsigned char e[5] = {0,0,0,0,0}; div_t d = div(k,8); e[5-d.quot-1] = 1 << d.rem; // received symbol unsigned char sym_rec[5]; sym_rec[0] = sym_enc[0] ^ e[0]; sym_rec[1] = sym_enc[1] ^ e[1]; sym_rec[2] = sym_enc[2] ^ e[2]; sym_rec[3] = sym_enc[3] ^ e[3]; sym_rec[4] = sym_enc[4] ^ e[4]; // decoded symbol unsigned char sym_dec[4]; fec_secded3932_decode_symbol(sym_rec, sym_dec); // validate data are the same CONTEND_EQUALITY(sym_org[0], sym_dec[0]); CONTEND_EQUALITY(sym_org[1], sym_dec[1]); CONTEND_EQUALITY(sym_org[2], sym_dec[2]); CONTEND_EQUALITY(sym_org[3], sym_dec[3]); } } // // AUTOTEST: SEC-DEC (39,32) codec (double error detection) // void autotest_secded3932_codec_e2() { // total combinations of double errors: nchoosek(39,2) = 741 unsigned int j; unsigned int k; for (j=0; j<39-1; j++) { if (liquid_autotest_verbose) printf("***** %2u *****\n", j); for (k=0; k<39-1-j; k++) { // generate symbol unsigned char sym_org[4]; sym_org[0] = rand() & 0xffff; sym_org[1] = rand() & 0xffff; sym_org[2] = rand() & 0xffff; sym_org[3] = rand() & 0xffff; // encoded symbol unsigned char sym_enc[5]; fec_secded3932_encode_symbol(sym_org, sym_enc); // generate error vector (single error) unsigned char e[5] = {0,0,0,0,0}; div_t dj = div(j,8); e[5-dj.quot-1] |= 1 << dj.rem; div_t dk = div(k+j+1,8); e[5-dk.quot-1] |= 1 << dk.rem; // received symbol unsigned char sym_rec[5]; sym_rec[0] = sym_enc[0] ^ e[0]; sym_rec[1] = sym_enc[1] ^ e[1]; sym_rec[2] = sym_enc[2] ^ e[2]; sym_rec[3] = sym_enc[3] ^ e[3]; sym_rec[4] = sym_enc[4] ^ e[4]; // decoded symbol unsigned char sym_dec[4]; int syndrome_flag = fec_secded3932_decode_symbol(sym_rec, sym_dec); if (liquid_autotest_verbose) { // print error vector printf("%3u, e = ", k); liquid_print_bitstring(e[0], 7); liquid_print_bitstring(e[1], 8); liquid_print_bitstring(e[2], 8); liquid_print_bitstring(e[3], 8); liquid_print_bitstring(e[4], 8); printf(" flag=%2d\n", syndrome_flag); } // validate syndrome flag is '2' CONTEND_EQUALITY(syndrome_flag, 2); } } } liquid-dsp-1.3.1/src/fec/tests/fec_secded7264_autotest.c000066400000000000000000000126641317124540100227470ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "autotest/autotest.h" #include "liquid.internal.h" // // AUTOTEST: SEC-DEC (72,64) codec (no errors) // void autotest_secded7264_codec_e0() { // arrays unsigned char sym_org[8]; // original symbol unsigned char sym_enc[9]; // encoded symbol unsigned char sym_dec[8]; // decoded symbol // generate symbol sym_org[0] = rand() & 0xff; sym_org[1] = rand() & 0xff; sym_org[2] = rand() & 0xff; sym_org[3] = rand() & 0xff; sym_org[4] = rand() & 0xff; sym_org[5] = rand() & 0xff; sym_org[6] = rand() & 0xff; sym_org[7] = rand() & 0xff; // encoded symbol fec_secded7264_encode_symbol(sym_org, sym_enc); // decoded symbol fec_secded7264_decode_symbol(sym_enc, sym_dec); // validate data are the same CONTEND_EQUALITY(sym_org[0], sym_dec[0]); CONTEND_EQUALITY(sym_org[1], sym_dec[1]); CONTEND_EQUALITY(sym_org[2], sym_dec[2]); CONTEND_EQUALITY(sym_org[3], sym_dec[3]); CONTEND_EQUALITY(sym_org[4], sym_dec[4]); CONTEND_EQUALITY(sym_org[5], sym_dec[5]); CONTEND_EQUALITY(sym_org[6], sym_dec[6]); CONTEND_EQUALITY(sym_org[7], sym_dec[7]); } // // AUTOTEST: SEC-DEC (72,64) codec (single error) // void autotest_secded7264_codec_e1() { // arrays unsigned char sym_org[8]; // original symbol unsigned char sym_enc[9]; // encoded symbol unsigned char e[9]; // error vector unsigned char sym_rec[9]; // received symbol unsigned char sym_dec[8]; // decoded symbol unsigned int i; unsigned int k; // error location for (k=0; k<72; k++) { // generate symbol for (i=0; i<8; i++) sym_org[i] = rand() & 0xff; // encoded symbol fec_secded7264_encode_symbol(sym_org, sym_enc); // generate error vector (single error) for (i=0; i<9; i++) e[i] = 0; div_t d = div(k,8); e[9-d.quot-1] = 1 << d.rem; // flip bit at index k // received symbol for (i=0; i<9; i++) sym_rec[i] = sym_enc[i] ^ e[i]; // decoded symbol fec_secded7264_decode_symbol(sym_rec, sym_dec); // validate data are the same for (i=0; i<8; i++) CONTEND_EQUALITY(sym_org[i], sym_dec[i]); } } // // AUTOTEST: SEC-DEC (72,64) codec (double error detection) // void autotest_secded7264_codec_e2() { // total combinations of double errors: nchoosek(72,2) = 2556 // arrays unsigned char sym_org[8]; // original symbol unsigned char sym_enc[9]; // encoded symbol unsigned char e[9]; // error vector unsigned char sym_rec[9]; // received symbol unsigned char sym_dec[8]; // decoded symbol unsigned int i; unsigned int j; unsigned int k; for (j=0; j<72-1; j++) { #if 0 if (liquid_autotest_verbose) printf("***** %2u *****\n", j); #endif for (k=0; k<72-1-j; k++) { // generate symbol for (i=0; i<8; i++) sym_org[i] = rand() & 0xff; // encoded symbol fec_secded7264_encode_symbol(sym_org, sym_enc); // generate error vector (single error) for (i=0; i<9; i++) e[i] = 0; div_t dj = div(j,8); e[9-dj.quot-1] |= 1 << dj.rem; div_t dk = div(k+j+1,8); e[9-dk.quot-1] |= 1 << dk.rem; // received symbol for (i=0; i<9; i++) sym_rec[i] = sym_enc[i] ^ e[i]; // decoded symbol int syndrome_flag = fec_secded7264_decode_symbol(sym_rec, sym_dec); #if 0 if (liquid_autotest_verbose) { // print error vector printf("%3u, e = ", k); liquid_print_bitstring(e[0], 8); liquid_print_bitstring(e[1], 8); liquid_print_bitstring(e[2], 8); liquid_print_bitstring(e[3], 8); liquid_print_bitstring(e[4], 8); liquid_print_bitstring(e[5], 8); liquid_print_bitstring(e[6], 8); liquid_print_bitstring(e[7], 8); liquid_print_bitstring(e[8], 8); printf(" flag=%2d\n", syndrome_flag); } #endif // validate syndrome flag is '2' CONTEND_EQUALITY(syndrome_flag, 2); } } } liquid-dsp-1.3.1/src/fec/tests/fec_soft_autotest.c000066400000000000000000000132621317124540100221430ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "autotest/autotest.h" #include "liquid.internal.h" // Test soft-decoding of a particular coding scheme // (helper function to keep code base small) void fec_test_soft_codec(fec_scheme _fs, unsigned int _n, void * _opts) { #if !LIBFEC_ENABLED if ( _fs == LIQUID_FEC_CONV_V27 || _fs == LIQUID_FEC_CONV_V29 || _fs == LIQUID_FEC_CONV_V39 || _fs == LIQUID_FEC_CONV_V615 || _fs == LIQUID_FEC_CONV_V27P23 || _fs == LIQUID_FEC_CONV_V27P34 || _fs == LIQUID_FEC_CONV_V27P45 || _fs == LIQUID_FEC_CONV_V27P56 || _fs == LIQUID_FEC_CONV_V27P67 || _fs == LIQUID_FEC_CONV_V27P78 || _fs == LIQUID_FEC_CONV_V29P23 || _fs == LIQUID_FEC_CONV_V29P34 || _fs == LIQUID_FEC_CONV_V29P45 || _fs == LIQUID_FEC_CONV_V29P56 || _fs == LIQUID_FEC_CONV_V29P67 || _fs == LIQUID_FEC_CONV_V29P78 || _fs == LIQUID_FEC_RS_M8) { AUTOTEST_WARN("convolutional, Reed-Solomon codes unavailable (install libfec)\n"); return; } #endif // generate fec object fec q = fec_create(_fs,_opts); // create arrays unsigned int n_enc = fec_get_enc_msg_length(_fs,_n); unsigned char msg[_n]; // original message unsigned char msg_enc[n_enc]; // encoded message unsigned char msg_soft[8*n_enc]; // encoded message (soft bits) unsigned char msg_dec[_n]; // decoded message // initialze message unsigned int i; for (i=0; i<_n; i++) { msg[i] = rand() & 0xff; msg_dec[i] = 0; } // encode message fec_encode(q, _n, msg, msg_enc); // convert to soft bits for (i=0; i #include "autotest/autotest.h" #include "liquid.h" // // AUTOTESTS: interleave/deinterleave // void interleaver_test_hard(unsigned int _n) { unsigned int i; unsigned char x[_n]; unsigned char y[_n]; unsigned char z[_n]; for (i=0; i<_n; i++) x[i] = rand() & 0xFF; // create interleaver object interleaver q = interleaver_create(_n); interleaver_encode(q,x,y); interleaver_decode(q,y,z); CONTEND_SAME_DATA(x, z, _n); // destroy interleaver object interleaver_destroy(q); } // // AUTOTESTS: interleave/deinterleave (soft) // void interleaver_test_soft(unsigned int _n) { unsigned int i; unsigned char x[8*_n]; unsigned char y[8*_n]; unsigned char z[8*_n]; for (i=0; i<8*_n; i++) x[i] = rand() & 0xFF; // create interleaver object interleaver q = interleaver_create(_n); interleaver_encode_soft(q,x,y); interleaver_decode_soft(q,y,z); CONTEND_SAME_DATA(x, z, 8*_n); // destroy interleaver object interleaver_destroy(q); } void autotest_interleaver_hard_8() { interleaver_test_hard(8 ); } void autotest_interleaver_hard_16() { interleaver_test_hard(16 ); } void autotest_interleaver_hard_64() { interleaver_test_hard(64 ); } void autotest_interleaver_hard_256() { interleaver_test_hard(256 ); } void autotest_interleaver_soft_8() { interleaver_test_soft(8 ); } void autotest_interleaver_soft_16() { interleaver_test_soft(16 ); } void autotest_interleaver_soft_64() { interleaver_test_soft(64 ); } void autotest_interleaver_soft_256() { interleaver_test_soft(256 ); } liquid-dsp-1.3.1/src/fec/tests/packetizer_autotest.c000066400000000000000000000047011317124540100225120ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.h" // Help function to keep code base small void packetizer_test_codec(unsigned int _n, crc_scheme _crc, fec_scheme _fec0, fec_scheme _fec1) { unsigned char msg_tx[_n]; unsigned char msg_rx[_n]; unsigned int pkt_len = packetizer_compute_enc_msg_len(_n,_crc,_fec0,_fec1); unsigned char packet[pkt_len]; // create object packetizer p = packetizer_create(_n,_crc,_fec0,_fec1); if (liquid_autotest_verbose) packetizer_print(p); // initialize data unsigned int i; for (i=0; i<_n; i++) { msg_tx[i] = i % 256; msg_rx[i] = 0; } // encode/decode packet packetizer_encode(p, msg_tx, packet); int crc_pass = packetizer_decode(p, packet, msg_rx); CONTEND_SAME_DATA(msg_tx, msg_rx, _n); CONTEND_EQUALITY(crc_pass, 1); // clean up objects packetizer_destroy(p); } // // AUTOTESTS // void autotest_packetizer_n16_0_0() { packetizer_test_codec(16, LIQUID_CRC_32, LIQUID_FEC_NONE, LIQUID_FEC_NONE); } void autotest_packetizer_n16_0_1() { packetizer_test_codec(16, LIQUID_CRC_32, LIQUID_FEC_NONE, LIQUID_FEC_REP3); } void autotest_packetizer_n16_0_2() { packetizer_test_codec(16, LIQUID_CRC_32, LIQUID_FEC_NONE, LIQUID_FEC_HAMMING74); } liquid-dsp-1.3.1/src/fft/000077500000000000000000000000001317124540100151335ustar00rootroot00000000000000liquid-dsp-1.3.1/src/fft/bench/000077500000000000000000000000001317124540100162125ustar00rootroot00000000000000liquid-dsp-1.3.1/src/fft/bench/fft_composite_benchmark.c000066400000000000000000000405071317124540100232370ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fft_composite_benchmark.c : benchmark FFTs of 'composite' length (not // prime, not of form 2^m) // #include #include #include #include "liquid.h" #include "src/fft/bench/fft_runbench.h" // composite numbers void benchmark_fft_6 LIQUID_FFT_BENCHMARK_API( 6, LIQUID_FFT_FORWARD) void benchmark_fft_9 LIQUID_FFT_BENCHMARK_API( 9, LIQUID_FFT_FORWARD) void benchmark_fft_10 LIQUID_FFT_BENCHMARK_API( 10, LIQUID_FFT_FORWARD) void benchmark_fft_12 LIQUID_FFT_BENCHMARK_API( 12, LIQUID_FFT_FORWARD) void benchmark_fft_14 LIQUID_FFT_BENCHMARK_API( 14, LIQUID_FFT_FORWARD) void benchmark_fft_15 LIQUID_FFT_BENCHMARK_API( 15, LIQUID_FFT_FORWARD) void benchmark_fft_18 LIQUID_FFT_BENCHMARK_API( 18, LIQUID_FFT_FORWARD) void benchmark_fft_20 LIQUID_FFT_BENCHMARK_API( 20, LIQUID_FFT_FORWARD) void benchmark_fft_21 LIQUID_FFT_BENCHMARK_API( 21, LIQUID_FFT_FORWARD) void benchmark_fft_22 LIQUID_FFT_BENCHMARK_API( 22, LIQUID_FFT_FORWARD) void benchmark_fft_24 LIQUID_FFT_BENCHMARK_API( 24, LIQUID_FFT_FORWARD) void benchmark_fft_25 LIQUID_FFT_BENCHMARK_API( 25, LIQUID_FFT_FORWARD) void benchmark_fft_26 LIQUID_FFT_BENCHMARK_API( 26, LIQUID_FFT_FORWARD) void benchmark_fft_27 LIQUID_FFT_BENCHMARK_API( 27, LIQUID_FFT_FORWARD) void benchmark_fft_28 LIQUID_FFT_BENCHMARK_API( 28, LIQUID_FFT_FORWARD) void benchmark_fft_30 LIQUID_FFT_BENCHMARK_API( 30, LIQUID_FFT_FORWARD) void benchmark_fft_33 LIQUID_FFT_BENCHMARK_API( 33, LIQUID_FFT_FORWARD) void benchmark_fft_34 LIQUID_FFT_BENCHMARK_API( 34, LIQUID_FFT_FORWARD) void benchmark_fft_35 LIQUID_FFT_BENCHMARK_API( 35, LIQUID_FFT_FORWARD) void benchmark_fft_36 LIQUID_FFT_BENCHMARK_API( 36, LIQUID_FFT_FORWARD) void benchmark_fft_38 LIQUID_FFT_BENCHMARK_API( 38, LIQUID_FFT_FORWARD) void benchmark_fft_39 LIQUID_FFT_BENCHMARK_API( 39, LIQUID_FFT_FORWARD) void benchmark_fft_40 LIQUID_FFT_BENCHMARK_API( 40, LIQUID_FFT_FORWARD) void benchmark_fft_42 LIQUID_FFT_BENCHMARK_API( 42, LIQUID_FFT_FORWARD) void benchmark_fft_44 LIQUID_FFT_BENCHMARK_API( 44, LIQUID_FFT_FORWARD) void benchmark_fft_45 LIQUID_FFT_BENCHMARK_API( 45, LIQUID_FFT_FORWARD) void benchmark_fft_46 LIQUID_FFT_BENCHMARK_API( 46, LIQUID_FFT_FORWARD) void benchmark_fft_48 LIQUID_FFT_BENCHMARK_API( 48, LIQUID_FFT_FORWARD) void benchmark_fft_49 LIQUID_FFT_BENCHMARK_API( 49, LIQUID_FFT_FORWARD) void benchmark_fft_50 LIQUID_FFT_BENCHMARK_API( 50, LIQUID_FFT_FORWARD) void benchmark_fft_51 LIQUID_FFT_BENCHMARK_API( 51, LIQUID_FFT_FORWARD) void benchmark_fft_52 LIQUID_FFT_BENCHMARK_API( 52, LIQUID_FFT_FORWARD) void benchmark_fft_54 LIQUID_FFT_BENCHMARK_API( 54, LIQUID_FFT_FORWARD) void benchmark_fft_55 LIQUID_FFT_BENCHMARK_API( 55, LIQUID_FFT_FORWARD) void benchmark_fft_56 LIQUID_FFT_BENCHMARK_API( 56, LIQUID_FFT_FORWARD) void benchmark_fft_57 LIQUID_FFT_BENCHMARK_API( 57, LIQUID_FFT_FORWARD) void benchmark_fft_58 LIQUID_FFT_BENCHMARK_API( 58, LIQUID_FFT_FORWARD) void benchmark_fft_60 LIQUID_FFT_BENCHMARK_API( 60, LIQUID_FFT_FORWARD) void benchmark_fft_62 LIQUID_FFT_BENCHMARK_API( 62, LIQUID_FFT_FORWARD) void benchmark_fft_63 LIQUID_FFT_BENCHMARK_API( 63, LIQUID_FFT_FORWARD) void benchmark_fft_65 LIQUID_FFT_BENCHMARK_API( 65, LIQUID_FFT_FORWARD) void benchmark_fft_66 LIQUID_FFT_BENCHMARK_API( 66, LIQUID_FFT_FORWARD) void benchmark_fft_68 LIQUID_FFT_BENCHMARK_API( 68, LIQUID_FFT_FORWARD) void benchmark_fft_69 LIQUID_FFT_BENCHMARK_API( 69, LIQUID_FFT_FORWARD) void benchmark_fft_70 LIQUID_FFT_BENCHMARK_API( 70, LIQUID_FFT_FORWARD) void benchmark_fft_72 LIQUID_FFT_BENCHMARK_API( 72, LIQUID_FFT_FORWARD) void benchmark_fft_74 LIQUID_FFT_BENCHMARK_API( 74, LIQUID_FFT_FORWARD) void benchmark_fft_75 LIQUID_FFT_BENCHMARK_API( 75, LIQUID_FFT_FORWARD) void benchmark_fft_76 LIQUID_FFT_BENCHMARK_API( 76, LIQUID_FFT_FORWARD) void benchmark_fft_77 LIQUID_FFT_BENCHMARK_API( 77, LIQUID_FFT_FORWARD) void benchmark_fft_78 LIQUID_FFT_BENCHMARK_API( 78, LIQUID_FFT_FORWARD) void benchmark_fft_80 LIQUID_FFT_BENCHMARK_API( 80, LIQUID_FFT_FORWARD) void benchmark_fft_81 LIQUID_FFT_BENCHMARK_API( 81, LIQUID_FFT_FORWARD) void benchmark_fft_82 LIQUID_FFT_BENCHMARK_API( 82, LIQUID_FFT_FORWARD) void benchmark_fft_84 LIQUID_FFT_BENCHMARK_API( 84, LIQUID_FFT_FORWARD) void benchmark_fft_85 LIQUID_FFT_BENCHMARK_API( 85, LIQUID_FFT_FORWARD) void benchmark_fft_86 LIQUID_FFT_BENCHMARK_API( 86, LIQUID_FFT_FORWARD) void benchmark_fft_87 LIQUID_FFT_BENCHMARK_API( 87, LIQUID_FFT_FORWARD) void benchmark_fft_88 LIQUID_FFT_BENCHMARK_API( 88, LIQUID_FFT_FORWARD) void benchmark_fft_90 LIQUID_FFT_BENCHMARK_API( 90, LIQUID_FFT_FORWARD) void benchmark_fft_91 LIQUID_FFT_BENCHMARK_API( 91, LIQUID_FFT_FORWARD) void benchmark_fft_92 LIQUID_FFT_BENCHMARK_API( 92, LIQUID_FFT_FORWARD) void benchmark_fft_93 LIQUID_FFT_BENCHMARK_API( 93, LIQUID_FFT_FORWARD) void benchmark_fft_94 LIQUID_FFT_BENCHMARK_API( 94, LIQUID_FFT_FORWARD) void benchmark_fft_95 LIQUID_FFT_BENCHMARK_API( 95, LIQUID_FFT_FORWARD) void benchmark_fft_96 LIQUID_FFT_BENCHMARK_API( 96, LIQUID_FFT_FORWARD) void benchmark_fft_98 LIQUID_FFT_BENCHMARK_API( 98, LIQUID_FFT_FORWARD) void benchmark_fft_99 LIQUID_FFT_BENCHMARK_API( 99, LIQUID_FFT_FORWARD) void benchmark_fft_100 LIQUID_FFT_BENCHMARK_API( 100, LIQUID_FFT_FORWARD) void benchmark_fft_102 LIQUID_FFT_BENCHMARK_API( 102, LIQUID_FFT_FORWARD) void benchmark_fft_104 LIQUID_FFT_BENCHMARK_API( 104, LIQUID_FFT_FORWARD) void benchmark_fft_105 LIQUID_FFT_BENCHMARK_API( 105, LIQUID_FFT_FORWARD) void benchmark_fft_106 LIQUID_FFT_BENCHMARK_API( 106, LIQUID_FFT_FORWARD) void benchmark_fft_108 LIQUID_FFT_BENCHMARK_API( 108, LIQUID_FFT_FORWARD) void benchmark_fft_110 LIQUID_FFT_BENCHMARK_API( 110, LIQUID_FFT_FORWARD) void benchmark_fft_111 LIQUID_FFT_BENCHMARK_API( 111, LIQUID_FFT_FORWARD) void benchmark_fft_112 LIQUID_FFT_BENCHMARK_API( 112, LIQUID_FFT_FORWARD) void benchmark_fft_114 LIQUID_FFT_BENCHMARK_API( 114, LIQUID_FFT_FORWARD) void benchmark_fft_115 LIQUID_FFT_BENCHMARK_API( 115, LIQUID_FFT_FORWARD) void benchmark_fft_116 LIQUID_FFT_BENCHMARK_API( 116, LIQUID_FFT_FORWARD) void benchmark_fft_117 LIQUID_FFT_BENCHMARK_API( 117, LIQUID_FFT_FORWARD) void benchmark_fft_118 LIQUID_FFT_BENCHMARK_API( 118, LIQUID_FFT_FORWARD) void benchmark_fft_119 LIQUID_FFT_BENCHMARK_API( 119, LIQUID_FFT_FORWARD) void benchmark_fft_120 LIQUID_FFT_BENCHMARK_API( 120, LIQUID_FFT_FORWARD) void benchmark_fft_121 LIQUID_FFT_BENCHMARK_API( 121, LIQUID_FFT_FORWARD) void benchmark_fft_122 LIQUID_FFT_BENCHMARK_API( 122, LIQUID_FFT_FORWARD) void benchmark_fft_123 LIQUID_FFT_BENCHMARK_API( 123, LIQUID_FFT_FORWARD) void benchmark_fft_124 LIQUID_FFT_BENCHMARK_API( 124, LIQUID_FFT_FORWARD) void benchmark_fft_125 LIQUID_FFT_BENCHMARK_API( 125, LIQUID_FFT_FORWARD) void benchmark_fft_126 LIQUID_FFT_BENCHMARK_API( 126, LIQUID_FFT_FORWARD) void benchmark_fft_129 LIQUID_FFT_BENCHMARK_API( 129, LIQUID_FFT_FORWARD) void benchmark_fft_130 LIQUID_FFT_BENCHMARK_API( 130, LIQUID_FFT_FORWARD) void benchmark_fft_132 LIQUID_FFT_BENCHMARK_API( 132, LIQUID_FFT_FORWARD) void benchmark_fft_133 LIQUID_FFT_BENCHMARK_API( 133, LIQUID_FFT_FORWARD) void benchmark_fft_134 LIQUID_FFT_BENCHMARK_API( 134, LIQUID_FFT_FORWARD) void benchmark_fft_135 LIQUID_FFT_BENCHMARK_API( 135, LIQUID_FFT_FORWARD) void benchmark_fft_136 LIQUID_FFT_BENCHMARK_API( 136, LIQUID_FFT_FORWARD) void benchmark_fft_138 LIQUID_FFT_BENCHMARK_API( 138, LIQUID_FFT_FORWARD) void benchmark_fft_140 LIQUID_FFT_BENCHMARK_API( 140, LIQUID_FFT_FORWARD) void benchmark_fft_141 LIQUID_FFT_BENCHMARK_API( 141, LIQUID_FFT_FORWARD) void benchmark_fft_142 LIQUID_FFT_BENCHMARK_API( 142, LIQUID_FFT_FORWARD) void benchmark_fft_143 LIQUID_FFT_BENCHMARK_API( 143, LIQUID_FFT_FORWARD) void benchmark_fft_144 LIQUID_FFT_BENCHMARK_API( 144, LIQUID_FFT_FORWARD) void benchmark_fft_145 LIQUID_FFT_BENCHMARK_API( 145, LIQUID_FFT_FORWARD) void benchmark_fft_146 LIQUID_FFT_BENCHMARK_API( 146, LIQUID_FFT_FORWARD) void benchmark_fft_147 LIQUID_FFT_BENCHMARK_API( 147, LIQUID_FFT_FORWARD) void benchmark_fft_148 LIQUID_FFT_BENCHMARK_API( 148, LIQUID_FFT_FORWARD) void benchmark_fft_150 LIQUID_FFT_BENCHMARK_API( 150, LIQUID_FFT_FORWARD) void benchmark_fft_152 LIQUID_FFT_BENCHMARK_API( 152, LIQUID_FFT_FORWARD) void benchmark_fft_153 LIQUID_FFT_BENCHMARK_API( 153, LIQUID_FFT_FORWARD) void benchmark_fft_154 LIQUID_FFT_BENCHMARK_API( 154, LIQUID_FFT_FORWARD) void benchmark_fft_155 LIQUID_FFT_BENCHMARK_API( 155, LIQUID_FFT_FORWARD) void benchmark_fft_156 LIQUID_FFT_BENCHMARK_API( 156, LIQUID_FFT_FORWARD) void benchmark_fft_158 LIQUID_FFT_BENCHMARK_API( 158, LIQUID_FFT_FORWARD) void benchmark_fft_159 LIQUID_FFT_BENCHMARK_API( 159, LIQUID_FFT_FORWARD) void benchmark_fft_160 LIQUID_FFT_BENCHMARK_API( 160, LIQUID_FFT_FORWARD) void benchmark_fft_161 LIQUID_FFT_BENCHMARK_API( 161, LIQUID_FFT_FORWARD) void benchmark_fft_162 LIQUID_FFT_BENCHMARK_API( 162, LIQUID_FFT_FORWARD) void benchmark_fft_164 LIQUID_FFT_BENCHMARK_API( 164, LIQUID_FFT_FORWARD) void benchmark_fft_165 LIQUID_FFT_BENCHMARK_API( 165, LIQUID_FFT_FORWARD) void benchmark_fft_166 LIQUID_FFT_BENCHMARK_API( 166, LIQUID_FFT_FORWARD) void benchmark_fft_168 LIQUID_FFT_BENCHMARK_API( 168, LIQUID_FFT_FORWARD) void benchmark_fft_169 LIQUID_FFT_BENCHMARK_API( 169, LIQUID_FFT_FORWARD) void benchmark_fft_170 LIQUID_FFT_BENCHMARK_API( 170, LIQUID_FFT_FORWARD) void benchmark_fft_171 LIQUID_FFT_BENCHMARK_API( 171, LIQUID_FFT_FORWARD) void benchmark_fft_172 LIQUID_FFT_BENCHMARK_API( 172, LIQUID_FFT_FORWARD) void benchmark_fft_174 LIQUID_FFT_BENCHMARK_API( 174, LIQUID_FFT_FORWARD) void benchmark_fft_175 LIQUID_FFT_BENCHMARK_API( 175, LIQUID_FFT_FORWARD) void benchmark_fft_176 LIQUID_FFT_BENCHMARK_API( 176, LIQUID_FFT_FORWARD) void benchmark_fft_177 LIQUID_FFT_BENCHMARK_API( 177, LIQUID_FFT_FORWARD) void benchmark_fft_178 LIQUID_FFT_BENCHMARK_API( 178, LIQUID_FFT_FORWARD) void benchmark_fft_180 LIQUID_FFT_BENCHMARK_API( 180, LIQUID_FFT_FORWARD) void benchmark_fft_182 LIQUID_FFT_BENCHMARK_API( 182, LIQUID_FFT_FORWARD) void benchmark_fft_183 LIQUID_FFT_BENCHMARK_API( 183, LIQUID_FFT_FORWARD) void benchmark_fft_184 LIQUID_FFT_BENCHMARK_API( 184, LIQUID_FFT_FORWARD) void benchmark_fft_185 LIQUID_FFT_BENCHMARK_API( 185, LIQUID_FFT_FORWARD) void benchmark_fft_186 LIQUID_FFT_BENCHMARK_API( 186, LIQUID_FFT_FORWARD) void benchmark_fft_187 LIQUID_FFT_BENCHMARK_API( 187, LIQUID_FFT_FORWARD) void benchmark_fft_188 LIQUID_FFT_BENCHMARK_API( 188, LIQUID_FFT_FORWARD) void benchmark_fft_189 LIQUID_FFT_BENCHMARK_API( 189, LIQUID_FFT_FORWARD) void benchmark_fft_190 LIQUID_FFT_BENCHMARK_API( 190, LIQUID_FFT_FORWARD) void benchmark_fft_192 LIQUID_FFT_BENCHMARK_API( 192, LIQUID_FFT_FORWARD) void benchmark_fft_194 LIQUID_FFT_BENCHMARK_API( 194, LIQUID_FFT_FORWARD) void benchmark_fft_195 LIQUID_FFT_BENCHMARK_API( 195, LIQUID_FFT_FORWARD) void benchmark_fft_196 LIQUID_FFT_BENCHMARK_API( 196, LIQUID_FFT_FORWARD) void benchmark_fft_198 LIQUID_FFT_BENCHMARK_API( 198, LIQUID_FFT_FORWARD) void benchmark_fft_200 LIQUID_FFT_BENCHMARK_API( 200, LIQUID_FFT_FORWARD) void benchmark_fft_201 LIQUID_FFT_BENCHMARK_API( 201, LIQUID_FFT_FORWARD) void benchmark_fft_202 LIQUID_FFT_BENCHMARK_API( 202, LIQUID_FFT_FORWARD) void benchmark_fft_203 LIQUID_FFT_BENCHMARK_API( 203, LIQUID_FFT_FORWARD) void benchmark_fft_204 LIQUID_FFT_BENCHMARK_API( 204, LIQUID_FFT_FORWARD) void benchmark_fft_205 LIQUID_FFT_BENCHMARK_API( 205, LIQUID_FFT_FORWARD) void benchmark_fft_206 LIQUID_FFT_BENCHMARK_API( 206, LIQUID_FFT_FORWARD) void benchmark_fft_207 LIQUID_FFT_BENCHMARK_API( 207, LIQUID_FFT_FORWARD) void benchmark_fft_208 LIQUID_FFT_BENCHMARK_API( 208, LIQUID_FFT_FORWARD) void benchmark_fft_209 LIQUID_FFT_BENCHMARK_API( 209, LIQUID_FFT_FORWARD) void benchmark_fft_210 LIQUID_FFT_BENCHMARK_API( 210, LIQUID_FFT_FORWARD) void benchmark_fft_212 LIQUID_FFT_BENCHMARK_API( 212, LIQUID_FFT_FORWARD) void benchmark_fft_213 LIQUID_FFT_BENCHMARK_API( 213, LIQUID_FFT_FORWARD) void benchmark_fft_214 LIQUID_FFT_BENCHMARK_API( 214, LIQUID_FFT_FORWARD) void benchmark_fft_215 LIQUID_FFT_BENCHMARK_API( 215, LIQUID_FFT_FORWARD) void benchmark_fft_216 LIQUID_FFT_BENCHMARK_API( 216, LIQUID_FFT_FORWARD) void benchmark_fft_217 LIQUID_FFT_BENCHMARK_API( 217, LIQUID_FFT_FORWARD) void benchmark_fft_218 LIQUID_FFT_BENCHMARK_API( 218, LIQUID_FFT_FORWARD) void benchmark_fft_219 LIQUID_FFT_BENCHMARK_API( 219, LIQUID_FFT_FORWARD) void benchmark_fft_220 LIQUID_FFT_BENCHMARK_API( 220, LIQUID_FFT_FORWARD) void benchmark_fft_221 LIQUID_FFT_BENCHMARK_API( 221, LIQUID_FFT_FORWARD) void benchmark_fft_222 LIQUID_FFT_BENCHMARK_API( 222, LIQUID_FFT_FORWARD) void benchmark_fft_224 LIQUID_FFT_BENCHMARK_API( 224, LIQUID_FFT_FORWARD) void benchmark_fft_225 LIQUID_FFT_BENCHMARK_API( 225, LIQUID_FFT_FORWARD) void benchmark_fft_226 LIQUID_FFT_BENCHMARK_API( 226, LIQUID_FFT_FORWARD) void benchmark_fft_228 LIQUID_FFT_BENCHMARK_API( 228, LIQUID_FFT_FORWARD) void benchmark_fft_230 LIQUID_FFT_BENCHMARK_API( 230, LIQUID_FFT_FORWARD) void benchmark_fft_231 LIQUID_FFT_BENCHMARK_API( 231, LIQUID_FFT_FORWARD) void benchmark_fft_232 LIQUID_FFT_BENCHMARK_API( 232, LIQUID_FFT_FORWARD) void benchmark_fft_234 LIQUID_FFT_BENCHMARK_API( 234, LIQUID_FFT_FORWARD) void benchmark_fft_235 LIQUID_FFT_BENCHMARK_API( 235, LIQUID_FFT_FORWARD) void benchmark_fft_236 LIQUID_FFT_BENCHMARK_API( 236, LIQUID_FFT_FORWARD) void benchmark_fft_237 LIQUID_FFT_BENCHMARK_API( 237, LIQUID_FFT_FORWARD) void benchmark_fft_238 LIQUID_FFT_BENCHMARK_API( 238, LIQUID_FFT_FORWARD) void benchmark_fft_240 LIQUID_FFT_BENCHMARK_API( 240, LIQUID_FFT_FORWARD) void benchmark_fft_242 LIQUID_FFT_BENCHMARK_API( 242, LIQUID_FFT_FORWARD) void benchmark_fft_243 LIQUID_FFT_BENCHMARK_API( 243, LIQUID_FFT_FORWARD) void benchmark_fft_244 LIQUID_FFT_BENCHMARK_API( 244, LIQUID_FFT_FORWARD) void benchmark_fft_245 LIQUID_FFT_BENCHMARK_API( 245, LIQUID_FFT_FORWARD) void benchmark_fft_246 LIQUID_FFT_BENCHMARK_API( 246, LIQUID_FFT_FORWARD) void benchmark_fft_247 LIQUID_FFT_BENCHMARK_API( 247, LIQUID_FFT_FORWARD) void benchmark_fft_248 LIQUID_FFT_BENCHMARK_API( 248, LIQUID_FFT_FORWARD) void benchmark_fft_249 LIQUID_FFT_BENCHMARK_API( 249, LIQUID_FFT_FORWARD) void benchmark_fft_250 LIQUID_FFT_BENCHMARK_API( 250, LIQUID_FFT_FORWARD) void benchmark_fft_252 LIQUID_FFT_BENCHMARK_API( 252, LIQUID_FFT_FORWARD) void benchmark_fft_253 LIQUID_FFT_BENCHMARK_API( 253, LIQUID_FFT_FORWARD) void benchmark_fft_254 LIQUID_FFT_BENCHMARK_API( 254, LIQUID_FFT_FORWARD) void benchmark_fft_255 LIQUID_FFT_BENCHMARK_API( 255, LIQUID_FFT_FORWARD) liquid-dsp-1.3.1/src/fft/bench/fft_prime_benchmark.c000066400000000000000000000213321317124540100223440ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fft_prime_benchmark.c : benchmark FFTs of prime length // #include #include #include #include "liquid.h" #include "src/fft/bench/fft_runbench.h" // prime numbers void benchmark_fft_3 LIQUID_FFT_BENCHMARK_API( 3, LIQUID_FFT_FORWARD) void benchmark_fft_5 LIQUID_FFT_BENCHMARK_API( 5, LIQUID_FFT_FORWARD) void benchmark_fft_7 LIQUID_FFT_BENCHMARK_API( 7, LIQUID_FFT_FORWARD) void benchmark_fft_11 LIQUID_FFT_BENCHMARK_API( 11, LIQUID_FFT_FORWARD) void benchmark_fft_13 LIQUID_FFT_BENCHMARK_API( 13, LIQUID_FFT_FORWARD) void benchmark_fft_17 LIQUID_FFT_BENCHMARK_API( 17, LIQUID_FFT_FORWARD) void benchmark_fft_19 LIQUID_FFT_BENCHMARK_API( 19, LIQUID_FFT_FORWARD) void benchmark_fft_23 LIQUID_FFT_BENCHMARK_API( 23, LIQUID_FFT_FORWARD) void benchmark_fft_29 LIQUID_FFT_BENCHMARK_API( 29, LIQUID_FFT_FORWARD) void benchmark_fft_31 LIQUID_FFT_BENCHMARK_API( 31, LIQUID_FFT_FORWARD) void benchmark_fft_37 LIQUID_FFT_BENCHMARK_API( 37, LIQUID_FFT_FORWARD) void benchmark_fft_41 LIQUID_FFT_BENCHMARK_API( 41, LIQUID_FFT_FORWARD) void benchmark_fft_43 LIQUID_FFT_BENCHMARK_API( 43, LIQUID_FFT_FORWARD) void benchmark_fft_47 LIQUID_FFT_BENCHMARK_API( 47, LIQUID_FFT_FORWARD) void benchmark_fft_53 LIQUID_FFT_BENCHMARK_API( 53, LIQUID_FFT_FORWARD) void benchmark_fft_59 LIQUID_FFT_BENCHMARK_API( 59, LIQUID_FFT_FORWARD) void benchmark_fft_61 LIQUID_FFT_BENCHMARK_API( 61, LIQUID_FFT_FORWARD) void benchmark_fft_67 LIQUID_FFT_BENCHMARK_API( 67, LIQUID_FFT_FORWARD) void benchmark_fft_71 LIQUID_FFT_BENCHMARK_API( 71, LIQUID_FFT_FORWARD) void benchmark_fft_73 LIQUID_FFT_BENCHMARK_API( 73, LIQUID_FFT_FORWARD) void benchmark_fft_79 LIQUID_FFT_BENCHMARK_API( 79, LIQUID_FFT_FORWARD) void benchmark_fft_83 LIQUID_FFT_BENCHMARK_API( 83, LIQUID_FFT_FORWARD) void benchmark_fft_89 LIQUID_FFT_BENCHMARK_API( 89, LIQUID_FFT_FORWARD) void benchmark_fft_97 LIQUID_FFT_BENCHMARK_API( 97, LIQUID_FFT_FORWARD) void benchmark_fft_101 LIQUID_FFT_BENCHMARK_API( 101, LIQUID_FFT_FORWARD) void benchmark_fft_103 LIQUID_FFT_BENCHMARK_API( 103, LIQUID_FFT_FORWARD) void benchmark_fft_107 LIQUID_FFT_BENCHMARK_API( 107, LIQUID_FFT_FORWARD) void benchmark_fft_109 LIQUID_FFT_BENCHMARK_API( 109, LIQUID_FFT_FORWARD) void benchmark_fft_113 LIQUID_FFT_BENCHMARK_API( 113, LIQUID_FFT_FORWARD) void benchmark_fft_127 LIQUID_FFT_BENCHMARK_API( 127, LIQUID_FFT_FORWARD) void benchmark_fft_131 LIQUID_FFT_BENCHMARK_API( 131, LIQUID_FFT_FORWARD) void benchmark_fft_137 LIQUID_FFT_BENCHMARK_API( 137, LIQUID_FFT_FORWARD) void benchmark_fft_139 LIQUID_FFT_BENCHMARK_API( 139, LIQUID_FFT_FORWARD) void benchmark_fft_149 LIQUID_FFT_BENCHMARK_API( 149, LIQUID_FFT_FORWARD) void benchmark_fft_151 LIQUID_FFT_BENCHMARK_API( 151, LIQUID_FFT_FORWARD) void benchmark_fft_157 LIQUID_FFT_BENCHMARK_API( 157, LIQUID_FFT_FORWARD) void benchmark_fft_163 LIQUID_FFT_BENCHMARK_API( 163, LIQUID_FFT_FORWARD) void benchmark_fft_167 LIQUID_FFT_BENCHMARK_API( 167, LIQUID_FFT_FORWARD) void benchmark_fft_173 LIQUID_FFT_BENCHMARK_API( 173, LIQUID_FFT_FORWARD) void benchmark_fft_179 LIQUID_FFT_BENCHMARK_API( 179, LIQUID_FFT_FORWARD) void benchmark_fft_181 LIQUID_FFT_BENCHMARK_API( 181, LIQUID_FFT_FORWARD) void benchmark_fft_191 LIQUID_FFT_BENCHMARK_API( 191, LIQUID_FFT_FORWARD) void benchmark_fft_193 LIQUID_FFT_BENCHMARK_API( 193, LIQUID_FFT_FORWARD) void benchmark_fft_197 LIQUID_FFT_BENCHMARK_API( 197, LIQUID_FFT_FORWARD) void benchmark_fft_199 LIQUID_FFT_BENCHMARK_API( 199, LIQUID_FFT_FORWARD) void benchmark_fft_211 LIQUID_FFT_BENCHMARK_API( 211, LIQUID_FFT_FORWARD) void benchmark_fft_223 LIQUID_FFT_BENCHMARK_API( 223, LIQUID_FFT_FORWARD) void benchmark_fft_227 LIQUID_FFT_BENCHMARK_API( 227, LIQUID_FFT_FORWARD) void benchmark_fft_229 LIQUID_FFT_BENCHMARK_API( 229, LIQUID_FFT_FORWARD) void benchmark_fft_233 LIQUID_FFT_BENCHMARK_API( 233, LIQUID_FFT_FORWARD) void benchmark_fft_239 LIQUID_FFT_BENCHMARK_API( 239, LIQUID_FFT_FORWARD) void benchmark_fft_241 LIQUID_FFT_BENCHMARK_API( 241, LIQUID_FFT_FORWARD) void benchmark_fft_251 LIQUID_FFT_BENCHMARK_API( 251, LIQUID_FFT_FORWARD) void benchmark_fft_257 LIQUID_FFT_BENCHMARK_API( 257, LIQUID_FFT_FORWARD) void benchmark_fft_263 LIQUID_FFT_BENCHMARK_API( 263, LIQUID_FFT_FORWARD) void benchmark_fft_269 LIQUID_FFT_BENCHMARK_API( 269, LIQUID_FFT_FORWARD) void benchmark_fft_271 LIQUID_FFT_BENCHMARK_API( 271, LIQUID_FFT_FORWARD) void benchmark_fft_277 LIQUID_FFT_BENCHMARK_API( 277, LIQUID_FFT_FORWARD) void benchmark_fft_281 LIQUID_FFT_BENCHMARK_API( 281, LIQUID_FFT_FORWARD) void benchmark_fft_283 LIQUID_FFT_BENCHMARK_API( 283, LIQUID_FFT_FORWARD) void benchmark_fft_293 LIQUID_FFT_BENCHMARK_API( 293, LIQUID_FFT_FORWARD) void benchmark_fft_307 LIQUID_FFT_BENCHMARK_API( 307, LIQUID_FFT_FORWARD) void benchmark_fft_311 LIQUID_FFT_BENCHMARK_API( 311, LIQUID_FFT_FORWARD) void benchmark_fft_313 LIQUID_FFT_BENCHMARK_API( 313, LIQUID_FFT_FORWARD) void benchmark_fft_317 LIQUID_FFT_BENCHMARK_API( 317, LIQUID_FFT_FORWARD) void benchmark_fft_331 LIQUID_FFT_BENCHMARK_API( 331, LIQUID_FFT_FORWARD) void benchmark_fft_337 LIQUID_FFT_BENCHMARK_API( 337, LIQUID_FFT_FORWARD) void benchmark_fft_347 LIQUID_FFT_BENCHMARK_API( 347, LIQUID_FFT_FORWARD) void benchmark_fft_349 LIQUID_FFT_BENCHMARK_API( 349, LIQUID_FFT_FORWARD) void benchmark_fft_353 LIQUID_FFT_BENCHMARK_API( 353, LIQUID_FFT_FORWARD) void benchmark_fft_359 LIQUID_FFT_BENCHMARK_API( 359, LIQUID_FFT_FORWARD) void benchmark_fft_367 LIQUID_FFT_BENCHMARK_API( 367, LIQUID_FFT_FORWARD) void benchmark_fft_373 LIQUID_FFT_BENCHMARK_API( 373, LIQUID_FFT_FORWARD) void benchmark_fft_379 LIQUID_FFT_BENCHMARK_API( 379, LIQUID_FFT_FORWARD) void benchmark_fft_383 LIQUID_FFT_BENCHMARK_API( 383, LIQUID_FFT_FORWARD) void benchmark_fft_389 LIQUID_FFT_BENCHMARK_API( 389, LIQUID_FFT_FORWARD) void benchmark_fft_397 LIQUID_FFT_BENCHMARK_API( 397, LIQUID_FFT_FORWARD) void benchmark_fft_401 LIQUID_FFT_BENCHMARK_API( 401, LIQUID_FFT_FORWARD) void benchmark_fft_409 LIQUID_FFT_BENCHMARK_API( 409, LIQUID_FFT_FORWARD) void benchmark_fft_419 LIQUID_FFT_BENCHMARK_API( 419, LIQUID_FFT_FORWARD) void benchmark_fft_421 LIQUID_FFT_BENCHMARK_API( 421, LIQUID_FFT_FORWARD) void benchmark_fft_431 LIQUID_FFT_BENCHMARK_API( 431, LIQUID_FFT_FORWARD) void benchmark_fft_433 LIQUID_FFT_BENCHMARK_API( 433, LIQUID_FFT_FORWARD) void benchmark_fft_439 LIQUID_FFT_BENCHMARK_API( 439, LIQUID_FFT_FORWARD) void benchmark_fft_443 LIQUID_FFT_BENCHMARK_API( 443, LIQUID_FFT_FORWARD) void benchmark_fft_449 LIQUID_FFT_BENCHMARK_API( 449, LIQUID_FFT_FORWARD) void benchmark_fft_457 LIQUID_FFT_BENCHMARK_API( 457, LIQUID_FFT_FORWARD) void benchmark_fft_461 LIQUID_FFT_BENCHMARK_API( 461, LIQUID_FFT_FORWARD) void benchmark_fft_463 LIQUID_FFT_BENCHMARK_API( 463, LIQUID_FFT_FORWARD) void benchmark_fft_467 LIQUID_FFT_BENCHMARK_API( 467, LIQUID_FFT_FORWARD) void benchmark_fft_479 LIQUID_FFT_BENCHMARK_API( 479, LIQUID_FFT_FORWARD) void benchmark_fft_487 LIQUID_FFT_BENCHMARK_API( 487, LIQUID_FFT_FORWARD) void benchmark_fft_491 LIQUID_FFT_BENCHMARK_API( 491, LIQUID_FFT_FORWARD) void benchmark_fft_499 LIQUID_FFT_BENCHMARK_API( 499, LIQUID_FFT_FORWARD) void benchmark_fft_503 LIQUID_FFT_BENCHMARK_API( 503, LIQUID_FFT_FORWARD) void benchmark_fft_509 LIQUID_FFT_BENCHMARK_API( 509, LIQUID_FFT_FORWARD) liquid-dsp-1.3.1/src/fft/bench/fft_r2r_benchmark.c000066400000000000000000000074051317124540100217420ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fft_r2r_benchmark.h // // Real even/odd FFT benchmarks (discrete cosine/sine transforms) // #include #include "liquid.h" #define LIQUID_FFT_R2R_BENCH_API(N,K) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { fft_r2r_bench(_start, _finish, _num_iterations, N, K); } // Helper function to keep code base small void fft_r2r_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _n, int _kind) { // initialize arrays, plan float x[_n], y[_n]; int _flags = 0; fftplan p = fft_create_plan_r2r_1d(_n, x, y, _kind, _flags); unsigned long int i; // initialize input with random values for (i=0; i<_n; i++) x[i] = randnf(); // scale number of iterations to keep execution time // relatively linear *_num_iterations /= _n * _n; *_num_iterations *= 10; *_num_iterations += 1; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { fft_execute(p); fft_execute(p); fft_execute(p); fft_execute(p); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; fft_destroy_plan(p); } // Radix-2 void benchmark_fft_REDFT00_128 LIQUID_FFT_R2R_BENCH_API(128, LIQUID_FFT_REDFT00) void benchmark_fft_REDFT01_128 LIQUID_FFT_R2R_BENCH_API(128, LIQUID_FFT_REDFT01) void benchmark_fft_REDFT10_128 LIQUID_FFT_R2R_BENCH_API(128, LIQUID_FFT_REDFT10) void benchmark_fft_REDFT11_128 LIQUID_FFT_R2R_BENCH_API(128, LIQUID_FFT_REDFT11) void benchmark_fft_RODFT00_128 LIQUID_FFT_R2R_BENCH_API(128, LIQUID_FFT_RODFT00) void benchmark_fft_RODFT01_128 LIQUID_FFT_R2R_BENCH_API(128, LIQUID_FFT_RODFT01) void benchmark_fft_RODFT10_128 LIQUID_FFT_R2R_BENCH_API(128, LIQUID_FFT_RODFT10) void benchmark_fft_RODFT11_128 LIQUID_FFT_R2R_BENCH_API(128, LIQUID_FFT_RODFT11) // prime number void benchmark_fft_REDFT00_127 LIQUID_FFT_R2R_BENCH_API(127, LIQUID_FFT_REDFT00) void benchmark_fft_REDFT01_127 LIQUID_FFT_R2R_BENCH_API(127, LIQUID_FFT_REDFT01) void benchmark_fft_REDFT10_127 LIQUID_FFT_R2R_BENCH_API(127, LIQUID_FFT_REDFT10) void benchmark_fft_REDFT11_127 LIQUID_FFT_R2R_BENCH_API(127, LIQUID_FFT_REDFT11) void benchmark_fft_RODFT00_127 LIQUID_FFT_R2R_BENCH_API(127, LIQUID_FFT_RODFT00) void benchmark_fft_RODFT01_127 LIQUID_FFT_R2R_BENCH_API(127, LIQUID_FFT_RODFT01) void benchmark_fft_RODFT10_127 LIQUID_FFT_R2R_BENCH_API(127, LIQUID_FFT_RODFT10) void benchmark_fft_RODFT11_127 LIQUID_FFT_R2R_BENCH_API(127, LIQUID_FFT_RODFT11) liquid-dsp-1.3.1/src/fft/bench/fft_radix2_benchmark.c000066400000000000000000000047631317124540100224320ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fft_radix2_benchmark.c : benchmark FFTs of length 2^m // #include #include #include #include "liquid.h" #include "src/fft/bench/fft_runbench.h" // power-of-two transforms void benchmark_fft_2 LIQUID_FFT_BENCHMARK_API(2, LIQUID_FFT_FORWARD) void benchmark_fft_4 LIQUID_FFT_BENCHMARK_API(4, LIQUID_FFT_FORWARD) void benchmark_fft_8 LIQUID_FFT_BENCHMARK_API(8, LIQUID_FFT_FORWARD) void benchmark_fft_16 LIQUID_FFT_BENCHMARK_API(16, LIQUID_FFT_FORWARD) void benchmark_fft_32 LIQUID_FFT_BENCHMARK_API(32, LIQUID_FFT_FORWARD) void benchmark_fft_64 LIQUID_FFT_BENCHMARK_API(64, LIQUID_FFT_FORWARD) void benchmark_fft_128 LIQUID_FFT_BENCHMARK_API(128, LIQUID_FFT_FORWARD) void benchmark_fft_256 LIQUID_FFT_BENCHMARK_API(256, LIQUID_FFT_FORWARD) void benchmark_fft_512 LIQUID_FFT_BENCHMARK_API(512, LIQUID_FFT_FORWARD) void benchmark_fft_1024 LIQUID_FFT_BENCHMARK_API(1024, LIQUID_FFT_FORWARD) void benchmark_fft_2048 LIQUID_FFT_BENCHMARK_API(2048, LIQUID_FFT_FORWARD) void benchmark_fft_4096 LIQUID_FFT_BENCHMARK_API(4096, LIQUID_FFT_FORWARD) void benchmark_fft_8192 LIQUID_FFT_BENCHMARK_API(8192, LIQUID_FFT_FORWARD) void benchmark_fft_16384 LIQUID_FFT_BENCHMARK_API(16384, LIQUID_FFT_FORWARD) void benchmark_fft_32768 LIQUID_FFT_BENCHMARK_API(32768, LIQUID_FFT_FORWARD) liquid-dsp-1.3.1/src/fft/bench/fft_runbench.c000066400000000000000000000045621317124540100210300ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fft_runbench.c : benchmark execution program // #include #include #include #include "liquid.h" // Helper function to keep code base small void fft_runbench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _nfft, int _direction) { // initialize arrays, plan float complex * x = (float complex *) malloc(_nfft*sizeof(float complex)); float complex * y = (float complex *) malloc(_nfft*sizeof(float complex)); int _method = 0; fftplan q = fft_create_plan(_nfft, x, y, _direction, _method); unsigned long int i; // initialize input with random values for (i=0; i<_nfft; i++) x[i] = randnf() + randnf()*_Complex_I; // scale number of iterations to keep execution time // relatively linear *_num_iterations /= _nfft; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { fft_execute(q); fft_execute(q); fft_execute(q); fft_execute(q); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; fft_destroy_plan(q); free(x); free(y); } liquid-dsp-1.3.1/src/fft/bench/fft_runbench.h000066400000000000000000000034611317124540100210320ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fft_runbench.h : benchmark execution program declaration // #ifndef __FFT_RUNBENCH_H__ #define __FFT_RUNBENCH_H__ #include #define LIQUID_FFT_BENCHMARK_API(NFFT,D) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { fft_runbench(_start, _finish, _num_iterations, NFFT, D); } // Helper function to keep code base small void fft_runbench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _nfft, int _direction); #endif // __FFT_RUNBENCH_H__ liquid-dsp-1.3.1/src/fft/src/000077500000000000000000000000001317124540100157225ustar00rootroot00000000000000liquid-dsp-1.3.1/src/fft/src/asgram.c000066400000000000000000000164311317124540100173450ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2017 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // asgram (ASCII spectrogram) // #include #include #include #include #include #include "liquid.internal.h" struct ASGRAM(_s) { unsigned int nfft; // transform size (display) unsigned int nfftp; // transform size (processing) unsigned int p; // over-sampling rate SPGRAM() periodogram; // spectral periodogram object TC * X; // spectral periodogram output float * psd; // power spectral density float levels[10]; // threshold for signal levels char levelchar[10]; // characters representing levels unsigned int num_levels; // number of levels float div; // dB per division float ref; // dB reference value }; // create asgram object with size _nfft ASGRAM() ASGRAM(_create)(unsigned int _nfft) { // validate input if (_nfft < 2) { fprintf(stderr,"error: asgram%s_create(), fft size must be at least 2\n", EXTENSION); exit(1); } // create main object ASGRAM() q = (ASGRAM()) malloc(sizeof(struct ASGRAM(_s))); q->nfft = _nfft; // derived values q->p = 4; // over-sampling rate q->nfftp = q->nfft * q->p; // allocate memory for PSD estimate q->X = (TC * ) malloc((q->nfftp)*sizeof(TC) ); q->psd = (float *) malloc((q->nfftp)*sizeof(float)); // create spectral periodogram object q->periodogram = SPGRAM(_create)(q->nfftp,LIQUID_WINDOW_HANN,q->nfft,q->nfft/2); // power spectral density levels q->num_levels = 10; ASGRAM(_set_display)(q," .,-+*&NM#"); ASGRAM(_set_scale)(q, 0.0f, 10.0f); return q; } // destroy asgram object void ASGRAM(_destroy)(ASGRAM() _q) { // destroy spectral periodogram object SPGRAM(_destroy)(_q->periodogram); // free PSD estimate array free(_q->X); free(_q->psd); // free main object memory free(_q); } // resets the internal state of the asgram object void ASGRAM(_reset)(ASGRAM() _q) { SPGRAM(_reset)(_q->periodogram); } // set scale and offset for spectrogram // _q : asgram object // _ref : signal reference level [dB] // _div : signal division [dB] void ASGRAM(_set_scale)(ASGRAM() _q, float _ref, float _div) { if (_div <= 0.0f) { fprintf(stderr,"ASGRAM(_set_scale)(), div must be greater than zero\n"); exit(1); } _q->ref = _ref; _q->div = _div; unsigned int i; for (i=0; i<_q->num_levels; i++) _q->levels[i] = _q->ref + i*_q->div; } // set display characters for output string // _q : asgram object // _ascii : 10-character display, default: " .,-+*&NM#" void ASGRAM(_set_display)(ASGRAM() _q, const char * _ascii) { unsigned int i; for (i=0; i<10; i++) { if (_ascii[i] == '\0') { fprintf(stderr,"warning: asgram%s_set_display(), invalid use of null character\n", EXTENSION); _q->levelchar[i] = '?'; } else { _q->levelchar[i] = _ascii[i]; } } } // push a single sample into the asgram object // _q : asgram object // _x : input buffer [size: _n x 1] // _n : input buffer length void ASGRAM(_push)(ASGRAM() _q, TI _x) { // push sample into internal spectral periodogram SPGRAM(_push)(_q->periodogram, _x); } // write a block of samples to the asgram object // _q : asgram object // _x : input buffer [size: _n x 1] // _n : input buffer length void ASGRAM(_write)(ASGRAM() _q, TI * _x, unsigned int _n) { // write samples to internal spectral periodogram SPGRAM(_write)(_q->periodogram, _x, _n); } // compute spectral periodogram output from current buffer contents // _q : ascii spectrogram object // _ascii : output ASCII string [size: _nfft x 1] // _peakval : value at peak (returned value) // _peakfreq : frequency at peak (returned value) void ASGRAM(_execute)(ASGRAM() _q, char * _ascii, float * _peakval, float * _peakfreq) { // check number of transforms if (SPGRAM(_get_num_transforms)(_q->periodogram)==0) { memset(_ascii,' ',_q->nfft); *_peakval = 0.0f; *_peakfreq = 0.0f; return; } // execute spectral periodogram SPGRAM(_get_psd)(_q->periodogram, _q->psd); SPGRAM(_reset)(_q->periodogram); unsigned int i; unsigned int j; // find peak for (i=0; i<_q->nfftp; i++) { if (i==0 || _q->psd[i] > *_peakval) { *_peakval = _q->psd[i]; *_peakfreq = (float)(i) / (float)(_q->nfftp) - 0.5f; } } // down-sample from nfft*p frequency bins to just nfft by retaining // one value (e.g. maximum or average) over range. for (i=0; i<_q->nfft; i++) { #if 0 // find maximum within 'p' samples float psd_val = 0.0f; for (j=0; j<_q->p; j++) { unsigned int index = (_q->p*i) + j; psd_val = (j==0 || _q->psd[index] > psd_val) ? _q->psd[index] : psd_val; } #else // find average over 'p' samples float psd_val = 0.0f; for (j=0; j<_q->p; j++) psd_val += _q->psd[(_q->p*i) + j]; psd_val /= (float)(_q->p); #endif // determine ascii level (which character to use) _ascii[i] = _q->levelchar[0]; for (j=0; j<_q->num_levels; j++) { if ( psd_val > _q->levels[j] ) _ascii[i] = _q->levelchar[j]; } } // append null character to end of string //_ascii[i] = '\0'; } // compute spectral periodogram output from current buffer // contents and print standard format to stdout void ASGRAM(_print)(ASGRAM() _q) { float maxval; float maxfreq; char ascii[_q->nfft+1]; ascii[_q->nfft] = '\0'; // append null character to end of string // execute the spectrogram ASGRAM(_execute)(_q, ascii, &maxval, &maxfreq); // print the spectrogram to stdout printf(" > %s < pk%5.1f dB [%5.2f]\n", ascii, maxval, maxfreq); } liquid-dsp-1.3.1/src/fft/src/dct_execute.c000066400000000000000000000061351317124540100203670ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // DCT : Discrete Cosine Transforms // #include #include #include "liquid.internal.h" // DCT-I void FFT(_execute_REDFT00)(FFT(plan) _q) { // ugly, slow method unsigned int i,k; float n_inv = 1.0f / (float)(_q->nfft-1); float phi; for (i=0; i<_q->nfft; i++) { T x0 = _q->xr[0]; // first element T xn = _q->xr[_q->nfft-1]; // last element _q->yr[i] = 0.5f*( x0 + (i%2 ? -xn : xn)); for (k=1; k<_q->nfft-1; k++) { phi = M_PI*n_inv*((float)k)*((float)i); _q->yr[i] += _q->xr[k]*cosf(phi); } // compensate for discrepancy _q->yr[i] *= 2.0f; } } // DCT-II (regular 'dct') void FFT(_execute_REDFT10)(FFT(plan) _q) { // ugly, slow method unsigned int i,k; float n_inv = 1.0f / (float)_q->nfft; float phi; for (i=0; i<_q->nfft; i++) { _q->yr[i] = 0.0f; for (k=0; k<_q->nfft; k++) { phi = M_PI*n_inv*((float)k + 0.5f)*i; _q->yr[i] += _q->xr[k]*cosf(phi); } // compensate for discrepancy _q->yr[i] *= 2.0f; } } // DCT-III (regular 'idct') void FFT(_execute_REDFT01)(FFT(plan) _q) { // ugly, slow method unsigned int i,k; float n_inv = 1.0f / (float)_q->nfft; float phi; for (i=0; i<_q->nfft; i++) { _q->yr[i] = _q->xr[0]*0.5f; for (k=1; k<_q->nfft; k++) { phi = M_PI*n_inv*((float)i + 0.5f)*k; _q->yr[i] += _q->xr[k]*cosf(phi); } // compensate for discrepancy _q->yr[i] *= 2.0f; } } // DCT-IV void FFT(_execute_REDFT11)(FFT(plan) _q) { // ugly, slow method unsigned int i,k; float n_inv = 1.0f / (float)(_q->nfft); float phi; for (i=0; i<_q->nfft; i++) { _q->yr[i] = 0.0f; for (k=0; k<_q->nfft; k++) { phi = M_PI*n_inv*((float)k+0.5f)*((float)i+0.5f); _q->yr[i] += _q->xr[k]*cosf(phi); } // compensate for discrepancy _q->yr[i] *= 2.0f; } } liquid-dsp-1.3.1/src/fft/src/fct_execute.c000066400000000000000000000063031317124540100203660ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fct_exeucte.c // // FCT : Fast (Discrete) Cosine Transforms // #include #include #include "liquid.internal.h" // // DCT-I // // // DCT-II (regular 'dct') // void FFT(_execute_REDFT10_fftn)(FFT(plan) _p) { unsigned int i; unsigned int r = _p->n % 2; unsigned int L = (_p->n - r)/2; // precondition fft for (i=0; ixc[i] = _p->xr[2*i+0]; _p->xc[_p->n-i-1] = _p->xr[2*i+1]; } // check for odd condition if (r==1) _p->xc[L] = _p->xr[2*L]; // execute fft, storing result in _p->yc FFT(_execute)(_p->internal_plan); // post-condition output for (i=0; i<_p->n; i++) _p->yr[i] = 2.0f*crealf(_p->yc[i]*cexpf(-_Complex_I*0.5f*M_PI*i/((float)_p->n))); } // // DCT-III (regular 'idct') // void FFT(_execute_REDFT01_fftn)(FFT(plan) _p) { unsigned int i; unsigned int r = _p->n % 2; unsigned int L = (_p->n - r)/2; // precondition fft for (i=0; i<_p->n; i++) _p->xc[i] = _p->xr[i] * cexpf(_Complex_I*0.5f*M_PI*i/((float)_p->n)); // execute fft, storing result in _p->yc FFT(_execute)(_p->internal_plan); // post-condition output for (i=0; iyr[2*i ] = 2.0f * crealf( _p->yc[i] ); _p->yr[2*i+1] = 2.0f * crealf( _p->yc[_p->n-i-1] ); } // check for odd condition if (r==1) _p->yr[2*L] = 2.0f * crealf( _p->yc[L] ); } // // DCT-IV // void FFT(_execute_REDFT11_fft4n)(FFT(plan) _p) { // NOTE: this method is only faster if n >= 64 and is radix-2 unsigned int i; // precondition fft for (i=0; i<_p->n; i++) { _p->xc[0*(_p->n) + i] = _p->xr[i]; _p->xc[1*(_p->n) + i] = -_p->xr[_p->n-i-1]; _p->xc[2*(_p->n) + i] = -_p->xr[i]; _p->xc[3*(_p->n) + i] = _p->xr[_p->n-i-1]; } // execute fft, storing result in _p->yc FFT(_execute)(_p->internal_plan); // post-condition output for (i=0; i<_p->n; i++) { float theta = 0.5 * M_PI * ((float)i + 0.5) / ((float)_p->n); _p->yr[i] = 0.5f*crealf(_p->yc[2*i+1]*cexpf(-_Complex_I*theta)); } } liquid-dsp-1.3.1/src/fft/src/fft_common.c000066400000000000000000000272321317124540100202230ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fft_common.c : common utilities specific to precision // #include #include #include "liquid.internal.h" struct FFT(plan_s) { // common data unsigned int nfft; // fft size TC * x; // input array pointer (not allocated) TC * y; // output array pointer (not allocated) int direction; // forward/reverse int flags; liquid_fft_type type; // type of transform liquid_fft_method method; // transform method // 'execute' function pointer FFT(_execute_t) * execute; // real even/odd DFT parameters (DCT/DST) T * xr; // input array (real) T * yr; // output array (real) // common data structure shared between specific FFT algorithms union { // DFT struct { TC * twiddle; // twiddle factors DOTPROD() * dotprod; // inner dot products } dft; // radix-2 transform data struct { unsigned int m; // log2(nfft) unsigned int * index_rev; // reversed indices TC * twiddle; // twiddle factors } radix2; // recursive mixed-radix transform data: // - compute 'Q' FFTs of size 'P' // - apply twiddle factors // - compute 'P' FFTs of size 'Q' // - transpose result struct { unsigned int P; // first FFT size unsigned int Q; // second FFT size TC * x; // input buffer (copied) TC * t0; // temporary buffer (small FFT input) TC * t1; // temporary buffer (small FFT output) TC * twiddle; // twiddle factors FFT(plan) fft_P; // sub-transform of size P FFT(plan) fft_Q; // sub-transform of size Q } mixedradix; // Rader's algorithm for computing FFTs of prime length struct { unsigned int * seq; // transformation sequence, size: nfft-1 TC * R; // DFT of sequence { exp(-j*2*pi*g^i/nfft }, size: nfft-1 TC * x_prime; // sub-transform time-domain buffer TC * X_prime; // sub-transform freq-domain buffer FFT(plan) fft; // sub-FFT of size nfft-1 FFT(plan) ifft; // sub-IFFT of size nfft-1 } rader; // Rader's alternate algorithm for computing FFTs of prime length struct { unsigned int nfft_prime; unsigned int * seq; // transformation sequence, size: nfft_prime TC * R; // DFT of sequence { exp(-j*2*pi*g^i/nfft }, size: nfft_prime TC * x_prime; // sub-transform time-domain buffer TC * X_prime; // sub-transform freq-domain buffer FFT(plan) fft; // sub-FFT of size nfft_prime FFT(plan) ifft; // sub-IFFT of size nfft_prime } rader2; } data; }; // create FFT plan, regular complex one-dimensional transform // _nfft : FFT size // _x : input array [size: _nfft x 1] // _y : output array [size: _nfft x 1] // _dir : fft direction: {LIQUID_FFT_FORWARD, LIQUID_FFT_BACKWARD} // _flags : fft method FFT(plan) FFT(_create_plan)(unsigned int _nfft, TC * _x, TC * _y, int _dir, int _flags) { // determine best method for execution // TODO : check flags and allow user override liquid_fft_method method = liquid_fft_estimate_method(_nfft); // initialize fft based on method switch (method) { case LIQUID_FFT_METHOD_RADIX2: // use radix-2 decimation-in-time method return FFT(_create_plan_radix2)(_nfft, _x, _y, _dir, _flags); case LIQUID_FFT_METHOD_MIXED_RADIX: // use Cooley-Tukey mixed-radix algorithm return FFT(_create_plan_mixed_radix)(_nfft, _x, _y, _dir, _flags); case LIQUID_FFT_METHOD_RADER: // use Rader's algorithm for FFTs of prime length return FFT(_create_plan_rader)(_nfft, _x, _y, _dir, _flags); case LIQUID_FFT_METHOD_RADER2: // use Rader's algorithm for FFTs of prime length return FFT(_create_plan_rader2)(_nfft, _x, _y, _dir, _flags); case LIQUID_FFT_METHOD_DFT: // use slow DFT return FFT(_create_plan_dft)(_nfft, _x, _y, _dir, _flags); case LIQUID_FFT_METHOD_UNKNOWN: default: fprintf(stderr,"error: fft_create_plan(), unknown/invalid fft method\n"); exit(1); } return NULL; } // destroy FFT plan void FFT(_destroy_plan)(FFT(plan) _q) { switch (_q->type) { // complex one-dimensional transforms case LIQUID_FFT_FORWARD: case LIQUID_FFT_BACKWARD: switch (_q->method) { case LIQUID_FFT_METHOD_DFT: FFT(_destroy_plan_dft)(_q); return; case LIQUID_FFT_METHOD_RADIX2: FFT(_destroy_plan_radix2)(_q); return; case LIQUID_FFT_METHOD_MIXED_RADIX: FFT(_destroy_plan_mixed_radix)(_q); return; case LIQUID_FFT_METHOD_RADER: FFT(_destroy_plan_rader)(_q); return; case LIQUID_FFT_METHOD_RADER2: FFT(_destroy_plan_rader2)(_q); return; case LIQUID_FFT_METHOD_UNKNOWN: default: fprintf(stderr,"error: fft_destroy_plan(), unknown/invalid fft method\n"); exit(1); } break; // discrete cosine transforms case LIQUID_FFT_REDFT00: case LIQUID_FFT_REDFT10: case LIQUID_FFT_REDFT01: case LIQUID_FFT_REDFT11: // discrete sine transforms case LIQUID_FFT_RODFT00: case LIQUID_FFT_RODFT10: case LIQUID_FFT_RODFT01: case LIQUID_FFT_RODFT11: FFT(_destroy_plan_r2r_1d)(_q); break; // modified discrete cosine transform case LIQUID_FFT_MDCT: break; case LIQUID_FFT_IMDCT: break; case LIQUID_FFT_UNKNOWN: default: fprintf(stderr,"error: fft_destroy_plan(), unknown/invalid fft type\n"); exit(1); } } // print FFT plan void FFT(_print_plan)(FFT(plan) _q) { switch (_q->type) { // complex one-dimensional transforms case LIQUID_FFT_FORWARD: case LIQUID_FFT_BACKWARD: printf("fft plan [%s], n=%u, ", _q->direction == LIQUID_FFT_FORWARD ? "forward" : "reverse", _q->nfft); switch (_q->method) { case LIQUID_FFT_METHOD_DFT: printf("DFT\n"); break; case LIQUID_FFT_METHOD_RADIX2: printf("Radix-2\n"); break; case LIQUID_FFT_METHOD_MIXED_RADIX: printf("Cooley-Tukey\n"); break; case LIQUID_FFT_METHOD_RADER: printf("Rader (Type I)\n"); break; case LIQUID_FFT_METHOD_RADER2: printf("Rader (Type II)\n"); break; case LIQUID_FFT_METHOD_UNKNOWN: default: fprintf(stderr,"error: fft_destroy_plan(), unknown/invalid fft method\n"); exit(1); } // print recursive plan FFT(_print_plan_recursive)(_q, 0); break; // discrete cosine transforms case LIQUID_FFT_REDFT00: case LIQUID_FFT_REDFT10: case LIQUID_FFT_REDFT01: case LIQUID_FFT_REDFT11: // discrete sine transforms case LIQUID_FFT_RODFT00: case LIQUID_FFT_RODFT10: case LIQUID_FFT_RODFT01: case LIQUID_FFT_RODFT11: FFT(_print_plan)(_q); break; // modified discrete cosine transform case LIQUID_FFT_MDCT: break; case LIQUID_FFT_IMDCT: break; case LIQUID_FFT_UNKNOWN: default: fprintf(stderr,"error: fft_print_plan(), unknown/invalid fft type\n"); exit(1); } } // print FFT plan (recursively) void FFT(_print_plan_recursive)(FFT(plan) _q, unsigned int _level) { // print indentation based on recursion level unsigned int i; for (i=0; i<_level; i++) printf(" "); printf("%u, ", _q->nfft); switch (_q->method) { case LIQUID_FFT_METHOD_DFT: printf("DFT\n"); break; case LIQUID_FFT_METHOD_RADIX2: printf("Radix-2\n"); break; case LIQUID_FFT_METHOD_MIXED_RADIX: // two internal transforms printf("Cooley-Tukey mixed radix, Q=%u, P=%u\n", _q->data.mixedradix.Q, _q->data.mixedradix.P); FFT(_print_plan_recursive)(_q->data.mixedradix.fft_Q, _level+1); FFT(_print_plan_recursive)(_q->data.mixedradix.fft_P, _level+1); break; case LIQUID_FFT_METHOD_RADER: printf("Rader (Type-II), nfft-prime=%u\n", _q->nfft-1); FFT(_print_plan_recursive)(_q->data.rader.fft, _level+1); break; case LIQUID_FFT_METHOD_RADER2: printf("Rader (Type-II), nfft-prime=%u\n", _q->data.rader2.nfft_prime); FFT(_print_plan_recursive)(_q->data.rader2.fft, _level+1); break; case LIQUID_FFT_METHOD_UNKNOWN: printf("(unknown)\n"); break; default: printf("(unknown)\n"); break; } } // execute fft void FFT(_execute)(FFT(plan) _q) { // invoke internal function pointer _q->execute(_q); } // perform n-point FFT allocating plan internally // _nfft : fft size // _x : input array [size: _nfft x 1] // _y : output array [size: _nfft x 1] // _dir : fft direction: LIQUID_FFT_{FORWARD,BACKWARD} // _flags : fft flags void FFT(_run)(unsigned int _nfft, TC * _x, TC * _y, int _dir, int _flags) { // create plan FFT(plan) plan = FFT(_create_plan)(_nfft, _x, _y, _dir, _flags); // execute fft FFT(_execute)(plan); // destroy plan FFT(_destroy_plan)(plan); } // perform real n-point FFT allocating plan internally // _nfft : fft size // _x : input array [size: _nfft x 1] // _y : output array [size: _nfft x 1] // _type : fft type, e.g. LIQUID_FFT_REDFT10 // _flags : fft flags void FFT(_r2r_1d_run)(unsigned int _nfft, T * _x, T * _y, int _type, int _flags) { // create plan FFT(plan) plan = FFT(_create_plan_r2r_1d)(_nfft, _x, _y, _type, _flags); // execute fft FFT(_execute)(plan); // destroy plan FFT(_destroy_plan)(plan); } // perform _n-point FFT shift void FFT(_shift)(TC *_x, unsigned int _n) { unsigned int i, n2; if (_n%2) n2 = (_n-1)/2; else n2 = _n/2; TC tmp; for (i=0; i #include #include #include "liquid.internal.h" // create FFT plan for regular DFT // _nfft : FFT size // _x : input array [size: _nfft x 1] // _y : output array [size: _nfft x 1] // _dir : fft direction: {LIQUID_FFT_FORWARD, LIQUID_FFT_BACKWARD} // _method : fft method FFT(plan) FFT(_create_plan_dft)(unsigned int _nfft, TC * _x, TC * _y, int _dir, int _flags) { // allocate plan and initialize all internal arrays to NULL FFT(plan) q = (FFT(plan)) malloc(sizeof(struct FFT(plan_s))); q->nfft = _nfft; q->x = _x; q->y = _y; q->flags = _flags; q->type = (_dir == LIQUID_FFT_FORWARD) ? LIQUID_FFT_FORWARD : LIQUID_FFT_BACKWARD; q->direction = (_dir == LIQUID_FFT_FORWARD) ? LIQUID_FFT_FORWARD : LIQUID_FFT_BACKWARD; q->method = LIQUID_FFT_METHOD_DFT; q->data.dft.twiddle = NULL; q->data.dft.dotprod = NULL; // check size, use specific codelet for small DFTs if (q->nfft == 2) q->execute = FFT(_execute_dft_2); else if (q->nfft == 3) q->execute = FFT(_execute_dft_3); else if (q->nfft == 4) q->execute = FFT(_execute_dft_4); else if (q->nfft == 5) q->execute = FFT(_execute_dft_5); else if (q->nfft == 6) q->execute = FFT(_execute_dft_6); else if (q->nfft == 7) q->execute = FFT(_execute_dft_7); else if (q->nfft == 8) q->execute = FFT(_execute_dft_8); else if (q->nfft == 16) q->execute = FFT(_execute_dft_16); else { q->execute = FFT(_execute_dft); // initialize twiddle factors q->data.dft.twiddle = (TC *) malloc(q->nfft * sizeof(TC)); // create dotprod objects q->data.dft.dotprod = (DOTPROD()*) malloc(q->nfft * sizeof(DOTPROD())); // create dotprod objects // twiddles: exp(-j*2*pi*W/n), W= // 0 0 0 0 0... // 0 1 2 3 4... // 0 2 4 6 8... // 0 3 6 9 12... // ... // Note that first row/column is zero, no multiplication necessary. // Create dotprod for first row anyway because it's still faster... unsigned int i; unsigned int k; T d = (q->direction == LIQUID_FFT_FORWARD) ? -1.0 : 1.0; for (i=0; infft; i++) { // initialize twiddle factors // NOTE: no need to compute first twiddle because exp(-j*2*pi*0) = 1 for (k=1; knfft; k++) q->data.dft.twiddle[k-1] = cexpf(_Complex_I*d*2*M_PI*(T)(k*i) / (T)(q->nfft)); // create dotprod object q->data.dft.dotprod[i] = DOTPROD(_create)(q->data.dft.twiddle, q->nfft-1); } } return q; } // destroy FFT plan void FFT(_destroy_plan_dft)(FFT(plan) _q) { // free twiddle factors if (_q->data.dft.twiddle != NULL) free(_q->data.dft.twiddle); // free dotprod objects if (_q->data.dft.dotprod != NULL) { unsigned int i; for (i=0; i<_q->nfft; i++) DOTPROD(_destroy)(_q->data.dft.dotprod[i]); // free dotprod array free(_q->data.dft.dotprod); } // free main object memory free(_q); } // execute DFT (slow but functionally correct) void FFT(_execute_dft)(FFT(plan) _q) { unsigned int i; unsigned int nfft = _q->nfft; #if 0 // DC value is sum of input _q->y[0] = _q->x[0]; for (i=1; iy[0] += _q->x[i]; // compute remaining DFT values unsigned int k; for (i=1; iy[i] = _q->x[0]; for (k=1; ky[i] += _q->x[k] * _q->data.dft.twiddle[(i*k)%_q->nfft]; } } #else // use vector dot products // NOTE: no need to compute first multiplication because exp(-j*2*pi*0) = 1 for (i=0; idata.dft.dotprod[i], &_q->x[1], &_q->y[i]); _q->y[i] += _q->x[0]; } #endif } // // codelets for small DFTs // // void FFT(_execute_dft_2)(FFT(plan) _q) { _q->y[0] = _q->x[0] + _q->x[1]; _q->y[1] = _q->x[0] - _q->x[1]; } // void FFT(_execute_dft_3)(FFT(plan) _q) { #if 0 // NOTE: not as fast as other method, but perhaps useful for // fixed-point algorithm // x = a + jb // y = c + jd // We want to compute both x*y and x*conj(y) with as few // multiplications as possible. If we define // k1 = a*(c+d); // k2 = d*(a+b); // k3 = c*(b-a); // k4 = b*(c+d); // then // x*y = (k1-k2) + j(k1+k3) // x*conj(y) = (k4-k3) + j(k4-k2) T a, b; // c=real(g)=-0.5, d=imag(g)=-sqrt(3)/2 T k1, k2, k3, k4; // compute both _q->x[1]*g and _q->x[1]*conj(g) with only 4 real multiplications a = crealf(_q->x[1]); b = cimagf(_q->x[1]); //k1 = a*(-0.5f + -0.866025403784439f); k1 = -1.36602540378444f*a; k2 = -0.866025403784439f*( a + b); k3 = -0.5f*( b - a); //k4 = b*(-0.5f + -0.866025403784439f); k4 = -1.36602540378444f*b; TC ta1 = (k1-k2) + _Complex_I*(k1+k3); // TC tb1 = (k4-k3) + _Complex_I*(k4-k2); // // compute both _q->x[2]*g and _q->x[2]*conj(g) with only 4 real multiplications a = crealf(_q->x[2]); b = cimagf(_q->x[2]); //k1 = a*(-0.5f + -0.866025403784439f); k1 = -1.36602540378444f*a; k2 = -0.866025403784439f*( a + b); k3 = -0.5f*( b - a); //k4 = b*(-0.5f + -0.866025403784439f); k4 = -1.36602540378444f*b; TC ta2 = (k1-k2) + _Complex_I*(k1+k3); // TC tb2 = (k4-k3) + _Complex_I*(k4-k2); // // set return values _q->y[0] = _q->x[0] + _q->x[1] + _q->x[2]; if (_q->direction == LIQUID_FFT_FORWARD) { _q->y[1] = _q->x[0] + ta1 + tb2; _q->y[2] = _q->x[0] + tb1 + ta2; } else { _q->y[1] = _q->x[0] + tb1 + ta2; _q->y[2] = _q->x[0] + ta1 + tb2; } #else TC g = -0.5f - _Complex_I*0.866025403784439; // sqrt(3)/2 _q->y[0] = _q->x[0] + _q->x[1] + _q->x[2]; TC ta = _q->x[0] + _q->x[1]*g + _q->x[2]*conjf(g); TC tb = _q->x[0] + _q->x[1]*conjf(g) + _q->x[2]*g; // set return values if (_q->direction == LIQUID_FFT_FORWARD) { _q->y[1] = ta; _q->y[2] = tb; } else { _q->y[1] = tb; _q->y[2] = ta; } #endif } // void FFT(_execute_dft_4)(FFT(plan) _q) { TC yp; TC * x = _q->x; TC * y = _q->y; // index reversal y[0] = x[0]; y[1] = x[2]; y[2] = x[1]; y[3] = x[3]; // k0 = 0, k1=1 yp = y[1]; y[1] = y[0] - yp; y[0] = y[0] + yp; // k0 = 2, k1=3 yp = y[3]; y[3] = y[2] - yp; y[2] = y[2] + yp; // k0 = 0, k1=2 yp = y[2]; y[2] = y[0] - yp; y[0] = y[0] + yp; // k0 = 1, k1=3 yp = cimagf(y[3]) - _Complex_I*crealf(y[3]); if (_q->direction == LIQUID_FFT_BACKWARD) yp = -yp; y[3] = y[1] - yp; y[1] = y[1] + yp; } // void FFT(_execute_dft_5)(FFT(plan) _q) { TC * x = _q->x; TC * y = _q->y; // DC value is sum of inputs y[0] = x[0] + x[1] + x[2] + x[3] + x[4]; // exp(-j*2*pi*1/5) TC g0 = 0.309016994374947 - 0.951056516295154*_Complex_I; // exp(-j*2*pi*2/5) TC g1 = -0.809016994374947 - 0.587785252292473*_Complex_I; if (_q->direction == LIQUID_FFT_BACKWARD) { g0 = conjf(g0); g1 = conjf(g1); } TC g0_conj = conjf(g0); TC g1_conj = conjf(g1); y[1] = x[0] + x[1]*g0 + x[2]*g1 + x[3]*g1_conj + x[4]*g0_conj; y[2] = x[0] + x[1]*g1 + x[2]*g0_conj + x[3]*g0 + x[4]*g1_conj; y[3] = x[0] + x[1]*g1_conj + x[2]*g0 + x[3]*g0_conj + x[4]*g1; y[4] = x[0] + x[1]*g0_conj + x[2]*g1_conj + x[3]*g1 + x[4]*g0; } // void FFT(_execute_dft_6)(FFT(plan) _q) { TC * x = _q->x; TC * y = _q->y; // DC value is sum of inputs y[0] = x[0] + x[1] + x[2] + x[3] + x[4] + x[5]; // exp(-j*2*pi*1/6) = 1/2 - j*sqrt(3)/2 TC g = 0.5 - 0.866025403784439*_Complex_I; TC g1, g2, g4, g5; if (_q->direction == LIQUID_FFT_FORWARD) { g1 = g; // exp(-j*2*pi*1/6) g2 = -conjf(g); // exp(-j*2*pi*2/6) g4 = -g; // exp(-j*2*pi*4/6) g5 = conjf(g); // exp(-j*2*pi*5/6) } else { g1 = conjf(g); // exp( j*2*pi*1/6) g2 = -g; // exp( j*2*pi*2/6) g4 = -conjf(g); // exp( j*2*pi*4/6) g5 = g; // exp( j*2*pi*5/6) } y[1] = x[0] + x[1]*g1 + x[2]*g2 - x[3] + x[4]*g4 + x[5]*g5; y[2] = x[0] + x[1]*g2 + x[2]*g4 + x[3] + x[4]*g2 + x[5]*g4; y[3] = x[0] - x[1] + x[2] - x[3] + x[4] - x[5]; y[4] = x[0] + x[1]*g4 + x[2]*g2 + x[3] + x[4]*g4 + x[5]*g2; y[5] = x[0] + x[1]*g5 + x[2]*g4 - x[3] + x[4]*g2 + x[5]*g1; } // void FFT(_execute_dft_7)(FFT(plan) _q) { TC * x = _q->x; TC * y = _q->y; // DC value is sum of inputs y[0] = x[0] + x[1] + x[2] + x[3] + x[4] + x[5] + x[6]; // initialize twiddle factors TC g1 = 0.623489801858734 - 0.781831482468030 * _Complex_I; // exp(-j*2*pi*1/7) TC g2 = -0.222520933956314 - 0.974927912181824 * _Complex_I; // exp(-j*2*pi*2/7) TC g3 = -0.900968867902419 - 0.433883739117558 * _Complex_I; // exp(-j*2*pi*3/7) if (_q->direction == LIQUID_FFT_FORWARD) { } else { g1 = conjf(g1); // exp(+j*2*pi*1/7) g2 = conjf(g2); // exp(+j*2*pi*2/7) g3 = conjf(g3); // exp(+j*2*pi*3/7) } TC g4 = conjf(g3); TC g5 = conjf(g2); TC g6 = conjf(g1); y[1] = x[0] + x[1]*g1 + x[2]*g2 + x[3]*g3 + x[4]*g4 + x[5]*g5 + x[6]*g6; y[2] = x[0] + x[1]*g2 + x[2]*g4 + x[3]*g6 + x[4]*g1 + x[5]*g3 + x[6]*g5; y[3] = x[0] + x[1]*g3 + x[2]*g6 + x[3]*g2 + x[4]*g5 + x[5]*g1 + x[6]*g4; y[4] = x[0] + x[1]*g4 + x[2]*g1 + x[3]*g5 + x[4]*g2 + x[5]*g6 + x[6]*g3; y[5] = x[0] + x[1]*g5 + x[2]*g3 + x[3]*g1 + x[4]*g6 + x[5]*g4 + x[6]*g2; y[6] = x[0] + x[1]*g6 + x[2]*g5 + x[3]*g4 + x[4]*g3 + x[5]*g2 + x[6]*g1; } // void FFT(_execute_dft_8)(FFT(plan) _q) { TC yp; TC * x = _q->x; TC * y = _q->y; // fft or ifft? int fft = _q->direction == LIQUID_FFT_FORWARD ? 1 : 0; // index reversal y[0] = x[0]; y[1] = x[4]; y[2] = x[2]; y[3] = x[6]; y[4] = x[1]; y[5] = x[5]; y[6] = x[3]; y[7] = x[7]; // i=0 yp = y[1]; y[1] = y[0]-yp; y[0] += yp; yp = y[3]; y[3] = y[2]-yp; y[2] += yp; yp = y[5]; y[5] = y[4]-yp; y[4] += yp; yp = y[7]; y[7] = y[6]-yp; y[6] += yp; // i=1 yp = y[2]; y[2] = y[0]-yp; y[0] += yp; yp = y[6]; y[6] = y[4]-yp; y[4] += yp; if (fft) yp = cimagf(y[3]) - crealf(y[3])*_Complex_I; else yp = -cimagf(y[3]) + crealf(y[3])*_Complex_I; y[3] = y[1]-yp; y[1] += yp; if (fft) yp = cimagf(y[7]) - crealf(y[7])*_Complex_I; else yp = -cimagf(y[7]) + crealf(y[7])*_Complex_I; y[7] = y[5]-yp; y[5] += yp; // i=2 yp = y[4]; y[4] = y[0]-yp; y[0] += yp; if (fft) yp = y[5]*(M_SQRT1_2 - M_SQRT1_2*_Complex_I); else yp = y[5]*(M_SQRT1_2 + M_SQRT1_2*_Complex_I); y[5] = y[1]-yp; y[1] += yp; if (fft) yp = cimagf(y[6]) - crealf(y[6])*_Complex_I; else yp = -cimagf(y[6]) + crealf(y[6])*_Complex_I; y[6] = y[2]-yp; y[2] += yp; if (fft) yp = y[7]*(-M_SQRT1_2 - M_SQRT1_2*_Complex_I); else yp = y[7]*(-M_SQRT1_2 + M_SQRT1_2*_Complex_I); y[7] = y[3]-yp; y[3] += yp; } // void FFT(_execute_dft_16)(FFT(plan) _q) { TC yp; TC * x = _q->x; TC * y = _q->y; // fft or ifft? int fft = _q->direction == LIQUID_FFT_FORWARD ? 1 : 0; // index reversal y[ 0] = x[ 0]; y[ 1] = x[ 8]; y[ 2] = x[ 4]; y[ 3] = x[12]; y[ 4] = x[ 2]; y[ 5] = x[10]; y[ 6] = x[ 6]; y[ 7] = x[14]; y[ 8] = x[ 1]; y[ 9] = x[ 9]; y[10] = x[ 5]; y[11] = x[13]; y[12] = x[ 3]; y[13] = x[11]; y[14] = x[ 7]; y[15] = x[15]; // i=0 yp = y[ 1]; y[ 1] = y[ 0] - yp; y[ 0] += yp; yp = y[ 3]; y[ 3] = y[ 2] - yp; y[ 2] += yp; yp = y[ 5]; y[ 5] = y[ 4] - yp; y[ 4] += yp; yp = y[ 7]; y[ 7] = y[ 6] - yp; y[ 6] += yp; yp = y[ 9]; y[ 9] = y[ 8] - yp; y[ 8] += yp; yp = y[11]; y[11] = y[10] - yp; y[10] += yp; yp = y[13]; y[13] = y[12] - yp; y[12] += yp; yp = y[15]; y[15] = y[14] - yp; y[14] += yp; // i=1 yp = y[ 2]; y[ 2] = y[ 0] - yp; y[ 0] += yp; yp = y[ 6]; y[ 6] = y[ 4] - yp; y[ 4] += yp; yp = y[10]; y[10] = y[ 8] - yp; y[ 8] += yp; yp = y[14]; y[14] = y[12] - yp; y[12] += yp; if (fft) { yp = -y[ 3]*_Complex_I; y[ 3] = y[ 1] - yp; y[ 1] += yp; yp = -y[ 7]*_Complex_I; y[ 7] = y[ 5] - yp; y[ 5] += yp; yp = -y[11]*_Complex_I; y[11] = y[ 9] - yp; y[ 9] += yp; yp = -y[15]*_Complex_I; y[15] = y[13] - yp; y[13] += yp; } else { yp = y[ 3]*_Complex_I; y[ 3] = y[ 1] - yp; y[ 1] += yp; yp = y[ 7]*_Complex_I; y[ 7] = y[ 5] - yp; y[ 5] += yp; yp = y[11]*_Complex_I; y[11] = y[ 9] - yp; y[ 9] += yp; yp = y[15]*_Complex_I; y[15] = y[13] - yp; y[13] += yp; } // i=2 yp = y[ 4]; y[ 4] = y[ 0] - yp; y[ 0] += yp; yp = y[12]; y[12] = y[ 8] - yp; y[ 8] += yp; if (fft) { yp = y[ 5]*( 0.70710677 + _Complex_I* -0.70710677); y[ 5] = y[ 1] - yp; y[ 1] += yp; yp = y[13]*( 0.70710677 + _Complex_I* -0.70710677); y[13] = y[ 9] - yp; y[ 9] += yp; yp = -y[ 6]*_Complex_I; y[ 6] = y[ 2] - yp; y[ 2] += yp; yp = -y[14]*_Complex_I; y[14] = y[10] - yp; y[10] += yp; yp = y[ 7]*( -0.70710677 + _Complex_I* -0.70710677); y[ 7] = y[ 3] - yp; y[ 3] += yp; yp = y[15]*( -0.70710677 + _Complex_I* -0.70710677); y[15] = y[11] - yp; y[11] += yp; } else { yp = y[ 5]*( 0.70710677 - _Complex_I* -0.70710677); y[ 5] = y[ 1] - yp; y[ 1] += yp; yp = y[13]*( 0.70710677 - _Complex_I* -0.70710677); y[13] = y[ 9] - yp; y[ 9] += yp; yp = y[ 6]*_Complex_I; y[ 6] = y[ 2] - yp; y[ 2] += yp; yp = y[14]*_Complex_I; y[14] = y[10] - yp; y[10] += yp; yp = y[ 7]*( -0.70710677 - _Complex_I* -0.70710677); y[ 7] = y[ 3] - yp; y[ 3] += yp; yp = y[15]*( -0.70710677 - _Complex_I* -0.70710677); y[15] = y[11] - yp; y[11] += yp; } // i=3 yp = y[ 8]; y[ 8] = y[ 0] - yp; y[ 0] += yp; if (fft) { yp = y[ 9]*( 0.92387950 + _Complex_I* -0.38268346); y[ 9] = y[ 1] - yp; y[ 1] += yp; yp = y[10]*( 0.70710677 + _Complex_I* -0.70710677); y[10] = y[ 2] - yp; y[ 2] += yp; yp = y[11]*( 0.38268343 + _Complex_I* -0.92387950); y[11] = y[ 3] - yp; y[ 3] += yp; yp = -y[12]*_Complex_I; y[12] = y[ 4] - yp; y[ 4] += yp; yp = y[13]*( -0.38268340 + _Complex_I* -0.92387956); y[13] = y[ 5] - yp; y[ 5] += yp; yp = y[14]*( -0.70710677 + _Complex_I* -0.70710677); y[14] = y[ 6] - yp; y[ 6] += yp; yp = y[15]*( -0.92387950 + _Complex_I* -0.38268349); y[15] = y[ 7] - yp; y[ 7] += yp; } else { yp = y[ 9]*( 0.92387950 - _Complex_I* -0.38268346); y[ 9] = y[ 1] - yp; y[ 1] += yp; yp = y[10]*( 0.70710677 - _Complex_I* -0.70710677); y[10] = y[ 2] - yp; y[ 2] += yp; yp = y[11]*( 0.38268343 - _Complex_I* -0.92387950); y[11] = y[ 3] - yp; y[ 3] += yp; yp = y[12]*_Complex_I; y[12] = y[ 4] - yp; y[ 4] += yp; yp = y[13]*( -0.38268340 - _Complex_I* -0.92387956); y[13] = y[ 5] - yp; y[ 5] += yp; yp = y[14]*( -0.70710677 - _Complex_I* -0.70710677); y[14] = y[ 6] - yp; y[ 6] += yp; yp = y[15]*( -0.92387950 - _Complex_I* -0.38268349); y[15] = y[ 7] - yp; y[ 7] += yp; } } liquid-dsp-1.3.1/src/fft/src/fft_mixed_radix.c000066400000000000000000000201451317124540100212240ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fft_mixed_radix.c : definitions for mixed-radix transforms using // the Cooley-Tukey algorithm // #include #include #include #include #include "liquid.internal.h" #define FFT_DEBUG_MIXED_RADIX 0 // create FFT plan for regular DFT // _nfft : FFT size // _x : input array [size: _nfft x 1] // _y : output array [size: _nfft x 1] // _dir : fft direction: {LIQUID_FFT_FORWARD, LIQUID_FFT_BACKWARD} // _method : fft method FFT(plan) FFT(_create_plan_mixed_radix)(unsigned int _nfft, TC * _x, TC * _y, int _dir, int _flags) { // allocate plan and initialize all internal arrays to NULL FFT(plan) q = (FFT(plan)) malloc(sizeof(struct FFT(plan_s))); q->nfft = _nfft; q->x = _x; q->y = _y; q->flags = _flags; q->type = (_dir == LIQUID_FFT_FORWARD) ? LIQUID_FFT_FORWARD : LIQUID_FFT_BACKWARD; q->direction = (_dir == LIQUID_FFT_FORWARD) ? LIQUID_FFT_FORWARD : LIQUID_FFT_BACKWARD; q->method = LIQUID_FFT_METHOD_MIXED_RADIX; q->execute = FFT(_execute_mixed_radix); // find first 'prime' factor of _nfft unsigned int i; unsigned int Q = FFT(_estimate_mixed_radix)(_nfft); if (Q==0) { fprintf(stderr,"error: fft_create_plan_mixed_radix(), _nfft=%u is prime\n", _nfft); exit(1); } else if ( (_nfft % Q) != 0 ) { fprintf(stderr,"error: fft_create_plan_mixed_radix(), _nfft=%u is not divisible by Q=%u\n", _nfft, Q); exit(1); } // set mixed-radix data unsigned int P = q->nfft / Q; q->data.mixedradix.Q = Q; q->data.mixedradix.P = P; // allocate memory for buffers unsigned int t_len = Q > P ? Q : P; q->data.mixedradix.t0 = (TC *) malloc(t_len * sizeof(TC)); q->data.mixedradix.t1 = (TC *) malloc(t_len * sizeof(TC)); // allocate memory for input buffers q->data.mixedradix.x = (TC *) malloc(q->nfft * sizeof(TC)); // create P-point FFT plan q->data.mixedradix.fft_P = FFT(_create_plan)(q->data.mixedradix.P, q->data.mixedradix.t0, q->data.mixedradix.t1, q->direction, q->flags); // create Q-point FFT plan q->data.mixedradix.fft_Q = FFT(_create_plan)(q->data.mixedradix.Q, q->data.mixedradix.t0, q->data.mixedradix.t1, q->direction, q->flags); // initialize twiddle factors, indices for mixed-radix transforms // TODO : only allocate necessary twiddle factors q->data.mixedradix.twiddle = (TC *) malloc(q->nfft * sizeof(TC)); T d = (q->direction == LIQUID_FFT_FORWARD) ? -1.0 : 1.0; for (i=0; infft; i++) q->data.mixedradix.twiddle[i] = cexpf(_Complex_I*d*2*M_PI*(T)i / (T)(q->nfft)); return q; } // destroy FFT plan void FFT(_destroy_plan_mixed_radix)(FFT(plan) _q) { // destroy sub-plans FFT(_destroy_plan)(_q->data.mixedradix.fft_P); FFT(_destroy_plan)(_q->data.mixedradix.fft_Q); // free data specific to mixed-radix transforms free(_q->data.mixedradix.t0); free(_q->data.mixedradix.t1); free(_q->data.mixedradix.x); free(_q->data.mixedradix.twiddle); // free main object memory free(_q); } // execute mixed-radix FFT void FFT(_execute_mixed_radix)(FFT(plan) _q) { // set internal constants unsigned int P = _q->data.mixedradix.P; // first FFT size unsigned int Q = _q->data.mixedradix.Q; // second FFT size // set pointers TC * t0 = _q->data.mixedradix.t0; // small FFT input buffer TC * t1 = _q->data.mixedradix.t1; // small FFT output buffer TC * x = _q->data.mixedradix.x; // full input buffer (data copied) TC * twiddle = _q->data.mixedradix.twiddle; // twiddle factors // copy input to internal buffer memmove(x, _q->x, _q->nfft*sizeof(TC)); unsigned int i; unsigned int k; // compute 'Q' DFTs of size 'P' #if FFT_DEBUG_MIXED_RADIX printf("computing %u DFTs of size %u\n", Q, P); #endif for (i=0; idata.mixedradix.fft_P); // copy back to input, applying twiddle factors for (k=0; kdata.mixedradix.fft_Q); // copy and transpose for (k=0; ky[k*P+i] = t1[k]; #if DEBUG printf("i=%3u/%3u\n", i, P); for (k=0; ky[k*P+i]), cimagf(_q->y[k*P+i])); #endif } } // strategize as to best radix to use unsigned int FFT(_estimate_mixed_radix)(unsigned int _nfft) { // compute factors of _nfft unsigned int factors[LIQUID_MAX_FACTORS]; unsigned int num_factors; liquid_factor(_nfft, factors, &num_factors); // check if _nfft is prime if (num_factors < 2) { fprintf(stderr,"warning: fft_estimate_mixed_radix(), %u is prime\n", _nfft); return 0; } // if _nfft has many factors of 2, retain for later in favor of // radix2 sub-fft method unsigned int num_factors_2 = 0; unsigned int i; for (i=0; i 0) { #if 0 // check if there are _only_ factors of 2 if (num_factors_2 == num_factors) { // return Q = 2^(ceil(num_factors_2 / 2)) // example: nfft = 128 = 2^7, return Q=2^4 = 16 return 1 << ((num_factors_2 + (num_factors_2%2))/2); } // return 2^num_factors_2 return 1 << num_factors_2; #else // use codelets if ( (_nfft%16)==0 ) return 16; if ( (_nfft% 8)==0 ) return 8; else if ( (_nfft% 4)==0 ) return 4; else return 2; #endif } // return next largest prime factor return factors[0]; } liquid-dsp-1.3.1/src/fft/src/fft_r2r_1d.c000066400000000000000000000156531317124540100200300ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fft_r2r_1d.c : real-to-real methods (DCT/DST) // #include #include #include #include "liquid.internal.h" // create DCT/DST plan // _nfft : FFT size // _x : input array [size: _nfft x 1] // _y : output array [size: _nfft x 1] // _type : type (e.g. LIQUID_FFT_REDFT00) // _method : fft method FFT(plan) FFT(_create_plan_r2r_1d)(unsigned int _nfft, T * _x, T * _y, int _type, int _flags) { // allocate plan and initialize all internal arrays to NULL FFT(plan) q = (FFT(plan)) malloc(sizeof(struct FFT(plan_s))); q->nfft = _nfft; q->xr = _x; q->yr = _y; q->type = _type; q->flags = _flags; // TODO : use separate 'method' for real-to-real types //q->method = LIQUID_FFT_METHOD_NONE; switch (q->type) { case LIQUID_FFT_REDFT00: q->execute = &FFT(_execute_REDFT00); break; // DCT-I case LIQUID_FFT_REDFT10: q->execute = &FFT(_execute_REDFT10); break; // DCT-II case LIQUID_FFT_REDFT01: q->execute = &FFT(_execute_REDFT01); break; // DCT-III case LIQUID_FFT_REDFT11: q->execute = &FFT(_execute_REDFT11); break; // DCT-IV case LIQUID_FFT_RODFT00: q->execute = &FFT(_execute_RODFT00); break; // DST-I case LIQUID_FFT_RODFT10: q->execute = &FFT(_execute_RODFT10); break; // DST-II case LIQUID_FFT_RODFT01: q->execute = &FFT(_execute_RODFT01); break; // DST-III case LIQUID_FFT_RODFT11: q->execute = &FFT(_execute_RODFT11); break; // DST-IV default: fprintf(stderr,"error: fft_create_plan_r2r_1d(), invalid type, %d\n", q->type); exit(1); } return q; } // destroy real-to-real transform plan void FFT(_destroy_plan_r2r_1d)(FFT(plan) _q) { // free main object memory free(_q); } // print real-to-real transform plan void FFT(_print_plan_r2r_1d)(FFT(plan) _q) { printf("real-to-real transform...\n"); // TODO: print actual transform type } // // DCT : Discrete Cosine Transforms // // DCT-I void FFT(_execute_REDFT00)(FFT(plan) _q) { // ugly, slow method unsigned int i,k; float n_inv = 1.0f / (float)(_q->nfft-1); float phi; for (i=0; i<_q->nfft; i++) { T x0 = _q->xr[0]; // first element T xn = _q->xr[_q->nfft-1]; // last element _q->yr[i] = 0.5f*( x0 + (i%2 ? -xn : xn)); for (k=1; k<_q->nfft-1; k++) { phi = M_PI*n_inv*((float)k)*((float)i); _q->yr[i] += _q->xr[k]*cosf(phi); } // compensate for discrepancy _q->yr[i] *= 2.0f; } } // DCT-II (regular 'dct') void FFT(_execute_REDFT10)(FFT(plan) _q) { // ugly, slow method unsigned int i,k; float n_inv = 1.0f / (float)_q->nfft; float phi; for (i=0; i<_q->nfft; i++) { _q->yr[i] = 0.0f; for (k=0; k<_q->nfft; k++) { phi = M_PI*n_inv*((float)k + 0.5f)*i; _q->yr[i] += _q->xr[k]*cosf(phi); } // compensate for discrepancy _q->yr[i] *= 2.0f; } } // DCT-III (regular 'idct') void FFT(_execute_REDFT01)(FFT(plan) _q) { // ugly, slow method unsigned int i,k; float n_inv = 1.0f / (float)_q->nfft; float phi; for (i=0; i<_q->nfft; i++) { _q->yr[i] = _q->xr[0]*0.5f; for (k=1; k<_q->nfft; k++) { phi = M_PI*n_inv*((float)i + 0.5f)*k; _q->yr[i] += _q->xr[k]*cosf(phi); } // compensate for discrepancy _q->yr[i] *= 2.0f; } } // DCT-IV void FFT(_execute_REDFT11)(FFT(plan) _q) { // ugly, slow method unsigned int i,k; float n_inv = 1.0f / (float)(_q->nfft); float phi; for (i=0; i<_q->nfft; i++) { _q->yr[i] = 0.0f; for (k=0; k<_q->nfft; k++) { phi = M_PI*n_inv*((float)k+0.5f)*((float)i+0.5f); _q->yr[i] += _q->xr[k]*cosf(phi); } // compensate for discrepancy _q->yr[i] *= 2.0f; } } // // DST : Discrete Sine Transforms // // DST-I void FFT(_execute_RODFT00)(FFT(plan) _q) { // ugly, slow method unsigned int i,k; float n_inv = 1.0f / (float)(_q->nfft+1); float phi; for (i=0; i<_q->nfft; i++) { _q->yr[i] = 0.0f; for (k=0; k<_q->nfft; k++) { phi = M_PI*n_inv*(float)((k+1)*(i+1)); _q->yr[i] += _q->xr[k]*sinf(phi); } // compensate for discrepancy _q->yr[i] *= 2.0f; } } // DST-II void FFT(_execute_RODFT10)(FFT(plan) _q) { // ugly, slow method unsigned int i,k; float n_inv = 1.0f / (float)(_q->nfft); float phi; for (i=0; i<_q->nfft; i++) { _q->yr[i] = 0.0f; for (k=0; k<_q->nfft; k++) { phi = M_PI*n_inv*((float)k+0.5f)*(i+1); _q->yr[i] += _q->xr[k]*sinf(phi); } // compensate for discrepancy _q->yr[i] *= 2.0f; } } // DST-III void FFT(_execute_RODFT01)(FFT(plan) _q) { // ugly, slow method unsigned int i,k; float n_inv = 1.0f / (float)(_q->nfft); float phi; for (i=0; i<_q->nfft; i++) { _q->yr[i] = ((i%2)==0 ? 0.5f : -0.5f) * _q->xr[_q->nfft-1]; for (k=0; k<_q->nfft-1; k++) { phi = M_PI*n_inv*((float)k+1)*((float)i+0.5f); _q->yr[i] += _q->xr[k]*sinf(phi); } // compensate for discrepancy _q->yr[i] *= 2.0f; } } // DST-IV void FFT(_execute_RODFT11)(FFT(plan) _q) { // ugly, slow method unsigned int i,k; float n_inv = 1.0f / (float)(_q->nfft); float phi; for (i=0; i<_q->nfft; i++) { _q->yr[i] = 0.0f; for (k=0; k<_q->nfft; k++) { phi = M_PI*n_inv*((float)k+0.5f)*((float)i+0.5f); _q->yr[i] += _q->xr[k]*sinf(phi); } // compensate for discrepancy _q->yr[i] *= 2.0f; } } liquid-dsp-1.3.1/src/fft/src/fft_rader.c000066400000000000000000000135321317124540100200260ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fft_rader.c : definitions for transforms of prime length using // Rader's algorithm // // References: // [Rader:1968] Charles M. Rader, "Discrete Fourier Transforms When // the Number of Data Samples Is Prime," Proceedings of the IEEE, // vol. 56, number 6, pp. 1107--1108, June 1968 // #include #include #include #include #include "liquid.internal.h" #define FFT_DEBUG_RADER 0 // create FFT plan for regular DFT // _nfft : FFT size // _x : input array [size: _nfft x 1] // _y : output array [size: _nfft x 1] // _dir : fft direction: {LIQUID_FFT_FORWARD, LIQUID_FFT_BACKWARD} // _method : fft method FFT(plan) FFT(_create_plan_rader)(unsigned int _nfft, TC * _x, TC * _y, int _dir, int _flags) { // allocate plan and initialize all internal arrays to NULL FFT(plan) q = (FFT(plan)) malloc(sizeof(struct FFT(plan_s))); q->nfft = _nfft; q->x = _x; q->y = _y; q->flags = _flags; q->type = (_dir == LIQUID_FFT_FORWARD) ? LIQUID_FFT_FORWARD : LIQUID_FFT_BACKWARD; q->direction = (_dir == LIQUID_FFT_FORWARD) ? LIQUID_FFT_FORWARD : LIQUID_FFT_BACKWARD; q->method = LIQUID_FFT_METHOD_RADER; q->execute = FFT(_execute_rader); // allocate memory for sub-transforms q->data.rader.x_prime = (TC*)malloc((q->nfft-1)*sizeof(TC)); q->data.rader.X_prime = (TC*)malloc((q->nfft-1)*sizeof(TC)); // create sub-FFT of size nfft-1 q->data.rader.fft = FFT(_create_plan)(q->nfft-1, q->data.rader.x_prime, q->data.rader.X_prime, LIQUID_FFT_FORWARD, q->flags); // create sub-IFFT of size nfft-1 q->data.rader.ifft = FFT(_create_plan)(q->nfft-1, q->data.rader.X_prime, q->data.rader.x_prime, LIQUID_FFT_BACKWARD, q->flags); // compute primitive root of nfft unsigned int g = liquid_primitive_root_prime(q->nfft); // create and initialize sequence q->data.rader.seq = (unsigned int *)malloc((q->nfft-1)*sizeof(unsigned int)); unsigned int i; for (i=0; infft-1; i++) q->data.rader.seq[i] = liquid_modpow(g, i+1, q->nfft); // compute DFT of sequence { exp(-j*2*pi*g^i/nfft }, size: nfft-1 // NOTE: R[0] = -1, |R[k]| = sqrt(nfft) for k != 0 // (use newly-created FFT plan of length nfft-1) T d = (q->direction == LIQUID_FFT_FORWARD) ? -1.0 : 1.0; for (i=0; infft-1; i++) q->data.rader.x_prime[i] = cexpf(_Complex_I*d*2*M_PI*q->data.rader.seq[i]/(T)(q->nfft)); FFT(_execute)(q->data.rader.fft); // copy result to R q->data.rader.R = (TC*)malloc((q->nfft-1)*sizeof(TC)); memmove(q->data.rader.R, q->data.rader.X_prime, (q->nfft-1)*sizeof(TC)); // return main object return q; } // destroy FFT plan void FFT(_destroy_plan_rader)(FFT(plan) _q) { // free data specific to Rader's algorithm free(_q->data.rader.seq); // sequence free(_q->data.rader.R); // pre-computed transform of exp(j*2*pi*seq) free(_q->data.rader.x_prime); // sub-transform input array free(_q->data.rader.X_prime); // sub-transform output array FFT(_destroy_plan)(_q->data.rader.fft); FFT(_destroy_plan)(_q->data.rader.ifft); // free main object memory free(_q); } // execute Rader's algorithm void FFT(_execute_rader)(FFT(plan) _q) { unsigned int i; // compute DFT of permuted sequence, size: nfft-1 for (i=0; i<_q->nfft-1; i++) { // reverse sequence unsigned int k = _q->data.rader.seq[_q->nfft-1-i-1]; _q->data.rader.x_prime[i] = _q->x[k]; } // compute sub-FFT // equivalent to: FFT(_run)(_q->nfft-1, xp, Xp, LIQUID_FFT_FORWARD, 0); FFT(_execute)(_q->data.rader.fft); // compute inverse FFT of product for (i=0; i<_q->nfft-1; i++) _q->data.rader.X_prime[i] *= _q->data.rader.R[i]; // compute sub-IFFT // equivalent to: FFT(_run)(_q->nfft-1, Xp, xp, LIQUID_FFT_BACKWARD, 0); FFT(_execute)(_q->data.rader.ifft); // set DC value _q->y[0] = 0.0f; for (i=0; i<_q->nfft; i++) _q->y[0] += _q->x[i]; // reverse permute result, scale, and add offset x[0] for (i=0; i<_q->nfft-1; i++) { unsigned int k = _q->data.rader.seq[i]; _q->y[k] = _q->data.rader.x_prime[i] / (T)(_q->nfft-1) + _q->x[0]; } } liquid-dsp-1.3.1/src/fft/src/fft_rader2.c000066400000000000000000000200631317124540100201050ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fft_rader2.c : definitions for transforms of prime length using // Rader's alternate algorithm // // References: // [Rader:1968] Charles M. Rader, "Discrete Fourier Transforms When // the Number of Data Samples Is Prime," Proceedings of the IEEE, // vol. 56, number 6, pp. 1107--1108, June 1968 // #include #include #include #include "liquid.internal.h" #define FFT_DEBUG_RADER 0 // create FFT plan // _nfft : FFT size // _x : input array [size: _nfft x 1] // _y : output array [size: _nfft x 1] // _dir : fft direction: {LIQUID_FFT_FORWARD, LIQUID_FFT_BACKWARD} // _method : fft method FFT(plan) FFT(_create_plan_rader2)(unsigned int _nfft, TC * _x, TC * _y, int _dir, int _flags) { // allocate plan and initialize all internal arrays to NULL FFT(plan) q = (FFT(plan)) malloc(sizeof(struct FFT(plan_s))); q->nfft = _nfft; q->x = _x; q->y = _y; q->flags = _flags; q->type = (_dir == LIQUID_FFT_FORWARD) ? LIQUID_FFT_FORWARD : LIQUID_FFT_BACKWARD; q->direction = (_dir == LIQUID_FFT_FORWARD) ? LIQUID_FFT_FORWARD : LIQUID_FFT_BACKWARD; q->method = LIQUID_FFT_METHOD_RADER2; q->execute = FFT(_execute_rader2); unsigned int i; // compute primitive root of nfft unsigned int g = liquid_primitive_root_prime(q->nfft); // create and initialize sequence q->data.rader2.seq = (unsigned int *)malloc((q->nfft-1)*sizeof(unsigned int)); for (i=0; infft-1; i++) q->data.rader2.seq[i] = liquid_modpow(g, i+1, q->nfft); #if 0 // compute larger FFT length greater than 2*nfft-4 // NOTE: while any length greater than 2*nfft-4 will work, use // nfft_prime as smallest 'simple' FFT (mostly small factors) // // TODO: devise better score (fewer factors is better) // score(n) = n / sum(factors(n).^2) float gamma_max = 0.0f; // score unsigned int nfft_prime_opt = 0; unsigned int num_steps = 10;// + q->nfft; for (i=1; i<=num_steps; i++) { unsigned int n_hat = 2*q->nfft - 4 + i; // compute factors unsigned int k; unsigned int num_factors = 0; unsigned int m = n_hat; float gamma = 0.0f; do { for (k=2; k<=m; k++) { if ( (m % k) == 0) { m /= k; num_factors++; gamma += k*k; break; } } } while (m > 1); // compute score: //float gamma = (float)n_hat / (float)num_factors; //float gamma = 1e3f * (float)num_factors / (float)n_hat; gamma = (float)n_hat / gamma; if (gamma > gamma_max) { gamma_max = gamma; nfft_prime_opt = n_hat; } } q->data.rader2.nfft_prime = nfft_prime_opt; #else // compute larger FFT length greater than 2*nfft-4 // NOTE: while any length greater than 2*nfft-4 will work, use // nfft_prime = 2 ^ nextpow2( 2*nfft - 4 ) to enable // radix-2 transform unsigned int m=0; q->data.rader2.nfft_prime = (2*q->nfft-4)-1; while (q->data.rader2.nfft_prime > 0) { q->data.rader2.nfft_prime >>= 1; m++; } q->data.rader2.nfft_prime = 1 << m; #endif //printf("nfft_prime = %u\n", q->data.rader2.nfft_prime); // assert(nfft_prime > 2*nfft-4) // allocate memory for sub-transforms q->data.rader2.x_prime = (TC*)malloc((q->data.rader2.nfft_prime)*sizeof(TC)); q->data.rader2.X_prime = (TC*)malloc((q->data.rader2.nfft_prime)*sizeof(TC)); // create sub-FFT of size nfft-1 q->data.rader2.fft = FFT(_create_plan)(q->data.rader2.nfft_prime, q->data.rader2.x_prime, q->data.rader2.X_prime, LIQUID_FFT_FORWARD, q->flags); // create sub-IFFT of size nfft-1 q->data.rader2.ifft = FFT(_create_plan)(q->data.rader2.nfft_prime, q->data.rader2.X_prime, q->data.rader2.x_prime, LIQUID_FFT_BACKWARD, q->flags); // compute DFT of sequence { exp(-j*2*pi*g^i/nfft }, size: nfft_prime // NOTE: R[0] = -1, |R[k]| = sqrt(nfft) for k != 0 // (use newly-created FFT plan of length nfft_prime) T d = (q->direction == LIQUID_FFT_FORWARD) ? -1.0 : 1.0; for (i=0; idata.rader2.nfft_prime; i++) q->data.rader2.x_prime[i] = cexpf(_Complex_I*d*2*M_PI*q->data.rader2.seq[i%(q->nfft-1)]/(T)(q->nfft)); FFT(_execute)(q->data.rader2.fft); // copy result to R q->data.rader2.R = (TC*)malloc(q->data.rader2.nfft_prime*sizeof(TC)); memmove(q->data.rader2.R, q->data.rader2.X_prime, q->data.rader2.nfft_prime*sizeof(TC)); // return main object return q; } // destroy FFT plan void FFT(_destroy_plan_rader2)(FFT(plan) _q) { // free data specific to Rader's algorithm free(_q->data.rader2.seq); // sequence free(_q->data.rader2.R); // pre-computed transform of exp(j*2*pi*seq) free(_q->data.rader2.x_prime); // sub-transform input array free(_q->data.rader2.X_prime); // sub-transform output array FFT(_destroy_plan)(_q->data.rader2.fft); FFT(_destroy_plan)(_q->data.rader2.ifft); // free main object memory free(_q); } // execute Rader's algorithm void FFT(_execute_rader2)(FFT(plan) _q) { unsigned int i; // set pointers to internal buffers TC * xp = _q->data.rader2.x_prime; TC * Xp = _q->data.rader2.X_prime; TC * R = _q->data.rader2.R; unsigned int * seq = _q->data.rader2.seq; // set constant values unsigned int nfft_prime = _q->data.rader2.nfft_prime; // compute nfft_prime-length DFT of permuted sequence with // nfft_prime-nfft+1 zeros inserted after first element xp[0] = _q->x[ seq[_q->nfft-2] ]; for (i=0; infft+1; i++) xp[i+1] = 0.0f; for (i=1; i<_q->nfft-1; i++) { // reverse sequence unsigned int k = seq[_q->nfft-1-i-1]; xp[i+nfft_prime-_q->nfft+1] = _q->x[k]; } FFT(_execute)(_q->data.rader2.fft); // compute inverse FFT of product // compute nfft_prime-length inverse FFT of product for (i=0; idata.rader2.ifft); // set DC value _q->y[0] = 0.0f; for (i=0; i<_q->nfft; i++) _q->y[0] += _q->x[i]; // reverse permute result, scale, and add offset x[0] for (i=0; i<_q->nfft-1; i++) { unsigned int k = seq[i]; _q->y[k] = xp[i] / (T)(nfft_prime) + _q->x[0]; } } liquid-dsp-1.3.1/src/fft/src/fft_radix2.c000066400000000000000000000110101317124540100201070ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fft_radix2.c : definitions for transforms of the form 2^m // #include #include #include #include "liquid.internal.h" // create FFT plan for regular DFT // _nfft : FFT size // _x : input array [size: _nfft x 1] // _y : output array [size: _nfft x 1] // _dir : fft direction: {LIQUID_FFT_FORWARD, LIQUID_FFT_BACKWARD} // _method : fft method FFT(plan) FFT(_create_plan_radix2)(unsigned int _nfft, TC * _x, TC * _y, int _dir, int _flags) { // allocate plan and initialize all internal arrays to NULL FFT(plan) q = (FFT(plan)) malloc(sizeof(struct FFT(plan_s))); q->nfft = _nfft; q->x = _x; q->y = _y; q->flags = _flags; q->type = (_dir == LIQUID_FFT_FORWARD) ? LIQUID_FFT_FORWARD : LIQUID_FFT_BACKWARD; q->direction = (_dir == LIQUID_FFT_FORWARD) ? LIQUID_FFT_FORWARD : LIQUID_FFT_BACKWARD; q->method = LIQUID_FFT_METHOD_RADIX2; q->execute = FFT(_execute_radix2); // initialize twiddle factors, indices for radix-2 transforms q->data.radix2.m = liquid_msb_index(q->nfft) - 1; // m = log2(nfft) q->data.radix2.index_rev = (unsigned int *) malloc((q->nfft)*sizeof(unsigned int)); unsigned int i; for (i=0; infft; i++) q->data.radix2.index_rev[i] = fft_reverse_index(i,q->data.radix2.m); // initialize twiddle factors q->data.radix2.twiddle = (TC *) malloc(q->nfft * sizeof(TC)); T d = (q->direction == LIQUID_FFT_FORWARD) ? -1.0 : 1.0; for (i=0; infft; i++) q->data.radix2.twiddle[i] = cexpf(_Complex_I*d*2*M_PI*(T)i / (T)(q->nfft)); return q; } // destroy FFT plan void FFT(_destroy_plan_radix2)(FFT(plan) _q) { // free data specific to radix-2 transforms free(_q->data.radix2.index_rev); free(_q->data.radix2.twiddle); // free main object memory free(_q); } // execute radix-2 FFT void FFT(_execute_radix2)(FFT(plan) _q) { // swap values unsigned int i,j,k; // unroll loop unsigned int nfft4 = (_q->nfft>>2)<<2; // floor(_nfft/4) for (i=0; iy[i ] = _q->x[ _q->data.radix2.index_rev[i ] ]; _q->y[i+1] = _q->x[ _q->data.radix2.index_rev[i+1] ]; _q->y[i+2] = _q->x[ _q->data.radix2.index_rev[i+2] ]; _q->y[i+3] = _q->x[ _q->data.radix2.index_rev[i+3] ]; } #if 0 // clean up remaining // NOTE : this only happens when _nfft=2 because we know (_nfft%4)==0 otherwise for ( ; i<_q->nfft; i++) _q->y[i] = _q->x[ _q->data.radix2.index_rev[i] ]; #endif TC yp; TC *y=_q->y; unsigned int n1 = 0; unsigned int n2 = 1; TC t; // twiddle value unsigned int stride = _q->nfft; unsigned int twiddle_index; for (i=0; i<_q->data.radix2.m; i++) { n1 = n2; n2 *= 2; stride >>= 1; twiddle_index = 0; for (j=0; jdata.radix2.twiddle[twiddle_index]; twiddle_index = (twiddle_index + stride) % _q->nfft; for (k=j; k<_q->nfft; k+=n2) { // NOTE: most computation is with the multiplication in next line yp = y[k+n1]*t; y[k+n1] = y[k] - yp; y[k] += yp; } } } } liquid-dsp-1.3.1/src/fft/src/fft_utilities.c000066400000000000000000000061501317124540100207420ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fft_utilities.c : common utilities not specific to precision // #include #include #include #include "liquid.internal.h" // determine best FFT method based on size liquid_fft_method liquid_fft_estimate_method(unsigned int _nfft) { if (_nfft == 0) { // invalid length fprintf(stderr,"error: liquid_fft_estimate_method(), fft size must be > 0\n"); return LIQUID_FFT_METHOD_UNKNOWN; } else if (_nfft <= 8 || _nfft==11 || _nfft==13 || _nfft==16 || _nfft==17) { // use simple DFT return LIQUID_FFT_METHOD_DFT; } else if (fft_is_radix2(_nfft)) { // transform is of the form 2^m #if 0 // use radix-2 algorithm return LIQUID_FFT_METHOD_RADIX2; #else // acutally, prefer Cooley-Tukey algorithm return LIQUID_FFT_METHOD_MIXED_RADIX; #endif } else if (liquid_is_prime(_nfft)) { // prefer Rader's alternate method (using radix-2 transform) // unless _nfft-1 is also radix2 // TODO : also prefer Rader-I if _nfft-1 is mostly factors of 2 if ( fft_is_radix2(_nfft-1) ) return LIQUID_FFT_METHOD_RADER; else return LIQUID_FFT_METHOD_RADER2; } // last resort //return LIQUID_FFT_METHOD_DFT; // use slow DFT method return LIQUID_FFT_METHOD_MIXED_RADIX; // use mixed radix method } // is input radix-2? int fft_is_radix2(unsigned int _n) { // check to see if _n is radix 2 unsigned int i; unsigned int d=0; unsigned int m=0; unsigned int t=_n; for (i=0; i<8*sizeof(unsigned int); i++) { d += (t & 1); // count bits, radix-2 if d==1 if (!m && (t&1)) m = i; // count lagging zeros, effectively log2(n) t >>= 1; } return (d == 1) ? 1 : 0; } // reverse _n-bit index _i unsigned int fft_reverse_index(unsigned int _i, unsigned int _n) { unsigned int j=0, k; for (k=0; k<_n; k++) { j <<= 1; j |= ( _i & 1 ); _i >>= 1; } return j; } liquid-dsp-1.3.1/src/fft/src/fftf.c000066400000000000000000000042331317124540100170150ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // FFT API: floating-point (single precision) // #include "liquid.internal.h" // Macro definitions #define FFT(name) LIQUID_CONCAT(fft,name) #define DOTPROD(name) LIQUID_CONCAT(dotprod_cccf,name) #define T float /* primitive type */ #define TC float complex /* primitive type (complex) */ #define PRINTVAL_T(X,F) PRINTVAL_FLOAT(X,F) #define PRINTVAL_TC(X,F) PRINTVAL_CFLOAT(X,F) // include main files #include "fft_common.c" // common source must come first (object definition) #include "fft_dft.c" // FFT definitions for DFT #include "fft_radix2.c" // FFT definitions for radix-2 transforms #include "fft_mixed_radix.c" // FFT definitions for mixed-radix transforms (Cooley-Tukey) #include "fft_rader.c" // FFT definitions for transforms of prime length (Rader's algorithm) #include "fft_rader2.c" // FFT definitions for transforms of prime length (Rader's alternate algorithm) #include "fft_r2r_1d.c" // real-to-real definitions (DCT/DST) liquid-dsp-1.3.1/src/fft/src/spgram.c000066400000000000000000000330701317124540100173620ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2017 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // spgram (spectral periodogram) // #include #include #include #include #include #include #include "liquid.internal.h" struct SPGRAM(_s) { // options unsigned int nfft; // FFT length int wtype; // window type unsigned int window_len; // window length unsigned int delay; // delay between transforms [samples] float alpha; // spectrum smoothing filter: feedforward parameter float gamma; // spectrum smoothing filter: feedback parameter int accumulate; // accumulate? or use time-average WINDOW() buffer; // input buffer TC * buf_time; // pointer to input array (allocated) TC * buf_freq; // output fft (allocated) T * w; // tapering window [size: window_len x 1] FFT_PLAN fft; // FFT plan // psd accumulation T * psd; // accumulated power spectral density estimate (linear) unsigned int sample_timer; // countdown to transform uint64_t num_samples; // total number of samples since reset uint64_t num_samples_total; // total number of samples since start uint64_t num_transforms; // total number of transforms since reset uint64_t num_transforms_total; // total number of transforms since start }; // // internal methods // // compute spectral periodogram output (complex values) // from current buffer contents void SPGRAM(_step)(SPGRAM() _q); // create spgram object // _nfft : FFT size // _wtype : window type, e.g. LIQUID_WINDOW_HAMMING // _window_len : window length // _delay : delay between transforms, _delay > 0 SPGRAM() SPGRAM(_create)(unsigned int _nfft, int _wtype, unsigned int _window_len, unsigned int _delay) { // validate input if (_nfft < 2) { fprintf(stderr,"error: spgram%s_create(), fft size must be at least 2\n", EXTENSION); exit(1); } else if (_window_len > _nfft) { fprintf(stderr,"error: spgram%s_create(), window size cannot exceed fft size\n", EXTENSION); exit(1); } else if (_window_len == 0) { fprintf(stderr,"error: spgram%s_create(), window size must be greater than zero\n", EXTENSION); exit(1); } else if (_wtype == LIQUID_WINDOW_KBD && _window_len % 2) { fprintf(stderr,"error: spgram%s_create(), KBD window length must be even\n", EXTENSION); exit(1); } else if (_delay == 0) { fprintf(stderr,"error: spgram%s_create(), delay must be greater than 0\n", EXTENSION); exit(1); } // allocate memory for main object SPGRAM() q = (SPGRAM()) malloc(sizeof(struct SPGRAM(_s))); // set input parameters q->nfft = _nfft; q->wtype = _wtype; q->window_len = _window_len; q->delay = _delay; // set object for full accumulation SPGRAM(_set_alpha)(q, -1.0f); // create FFT arrays, object q->buf_time = (TC*) malloc((q->nfft)*sizeof(TC)); q->buf_freq = (TC*) malloc((q->nfft)*sizeof(TC)); q->psd = (T *) malloc((q->nfft)*sizeof(T )); q->fft = FFT_CREATE_PLAN(q->nfft, q->buf_time, q->buf_freq, FFT_DIR_FORWARD, FFT_METHOD); // create buffer q->buffer = WINDOW(_create)(q->window_len); // create window q->w = (T*) malloc((q->window_len)*sizeof(T)); unsigned int i; unsigned int n = q->window_len; float beta = 10.0f; float zeta = 3.0f; for (i=0; iwtype) { case LIQUID_WINDOW_HAMMING: q->w[i] = hamming(i,n); break; case LIQUID_WINDOW_HANN: q->w[i] = hann(i,n); break; case LIQUID_WINDOW_BLACKMANHARRIS: q->w[i] = blackmanharris(i,n); break; case LIQUID_WINDOW_BLACKMANHARRIS7: q->w[i] = blackmanharris7(i,n); break; case LIQUID_WINDOW_KAISER: q->w[i] = kaiser(i,n,beta,0); break; case LIQUID_WINDOW_FLATTOP: q->w[i] = flattop(i,n); break; case LIQUID_WINDOW_TRIANGULAR: q->w[i] = triangular(i,n,n); break; case LIQUID_WINDOW_RCOSTAPER: q->w[i] = liquid_rcostaper_windowf(i,n/3,n); break; case LIQUID_WINDOW_KBD: q->w[i] = liquid_kbd(i,n,zeta); break; default: fprintf(stderr,"error: spgram%s_create(), invalid window\n", EXTENSION); exit(1); } } // scale by window magnitude, FFT size float g = 0.0f; for (i=0; iwindow_len; i++) g += q->w[i] * q->w[i]; g = M_SQRT2 / ( sqrtf(g / q->window_len) * sqrtf((float)(q->nfft)) ); // scale window and copy for (i=0; iwindow_len; i++) q->w[i] = g * q->w[i]; // reset the spgram object q->num_samples_total = 0; q->num_transforms_total = 0; SPGRAM(_reset)(q); // return new object return q; } // create default spgram object (Kaiser-Bessel window) SPGRAM() SPGRAM(_create_default)(unsigned int _nfft) { // validate input if (_nfft < 2) { fprintf(stderr,"error: spgram%s_create_default(), fft size must be at least 2\n", EXTENSION); exit(1); } return SPGRAM(_create)(_nfft, LIQUID_WINDOW_KAISER, _nfft/2, _nfft/4); } // destroy spgram object void SPGRAM(_destroy)(SPGRAM() _q) { // free allocated memory free(_q->buf_time); free(_q->buf_freq); free(_q->w); free(_q->psd); WINDOW(_destroy)(_q->buffer); FFT_DESTROY_PLAN(_q->fft); // free main object free(_q); } // clears the internal state of the spgram object, but not // the internal buffer void SPGRAM(_clear)(SPGRAM() _q) { // clear FFT input unsigned int i; for (i=0; i<_q->nfft; i++) _q->buf_time[i] = 0.0f; // reset counters _q->sample_timer = _q->delay; _q->num_transforms = 0; _q->num_samples = 0; // clear PSD accumulation for (i=0; i<_q->nfft; i++) _q->psd[i] = 0.0f; } // reset the spgram object to its original state completely void SPGRAM(_reset)(SPGRAM() _q) { // reset spgram object except for the window buffer SPGRAM(_clear)(_q); // clear the window buffer WINDOW(_reset)(_q->buffer); } // prints the spgram object's parameters void SPGRAM(_print)(SPGRAM() _q) { printf("spgram%s: nfft=%u, window=%u, delay=%u\n", EXTENSION, _q->nfft, _q->window_len, _q->delay); } // set forgetting factor int SPGRAM(_set_alpha)(SPGRAM() _q, float _alpha) { // validate input if (_alpha != -1 && (_alpha < 0.0f || _alpha > 1.0f)) { fprintf(stderr,"warning: spgram%s_set_alpha(), alpha must be in {-1,[0,1]}\n", EXTENSION); return -1; } // set accumulation flag appropriately _q->accumulate = (_alpha == -1.0f) ? 1 : 0; if (_q->accumulate) { _q->alpha = 1.0f; _q->gamma = 1.0f; } else { _q->alpha = _alpha; _q->gamma = 1.0f - _q->alpha; } return 0; } // get FFT size unsigned int SPGRAM(_get_nfft)(SPGRAM() _q) { return _q->nfft; } // get window length unsigned int SPGRAM(_get_window_len)(SPGRAM() _q) { return _q->window_len; } // get delay between transforms unsigned int SPGRAM(_get_delay)(SPGRAM() _q) { return _q->delay; } // get number of samples processed since reset uint64_t SPGRAM(_get_num_samples)(SPGRAM() _q) { return _q->num_samples; } // get number of samples processed since start uint64_t SPGRAM(_get_num_samples_total)(SPGRAM() _q) { return _q->num_samples_total; } // get number of transforms processed since reset uint64_t SPGRAM(_get_num_transforms)(SPGRAM() _q) { return _q->num_transforms; } // get number of transforms processed since start uint64_t SPGRAM(_get_num_transforms_total)(SPGRAM() _q) { return _q->num_transforms_total; } // push a single sample into the spgram object // _q : spgram object // _x : input sample void SPGRAM(_push)(SPGRAM() _q, TI _x) { // push sample into internal window WINDOW(_push)(_q->buffer, _x); // update counters _q->num_samples++; _q->num_samples_total++; // adjust timer _q->sample_timer--; if (_q->sample_timer) return; // reset timer and step through computation _q->sample_timer = _q->delay; SPGRAM(_step)(_q); } // write a block of samples to the spgram object // _q : spgram object // _x : input buffer [size: _n x 1] // _n : input buffer length void SPGRAM(_write)(SPGRAM() _q, TI * _x, unsigned int _n) { #if 0 // write a block of samples to the internal window WINDOW(_write)(_q->buffer, _x, _n); #else // TODO: be smarter about how to write and execute samples unsigned int i; for (i=0; i<_n; i++) SPGRAM(_push)(_q, _x[i]); #endif } // compute spectral periodogram output from current buffer contents // _q : spgram object void SPGRAM(_step)(SPGRAM() _q) { unsigned int i; // read buffer, copy to FFT input (applying window) // TODO: use SIMD extensions to speed this up TI * rc; WINDOW(_read)(_q->buffer, &rc); for (i=0; i<_q->window_len; i++) _q->buf_time[i] = rc[i] * _q->w[i]; // execute fft on _q->buf_time and store result in _q->buf_freq FFT_EXECUTE(_q->fft); // accumulate output for (i=0; i<_q->nfft; i++) { T v = crealf( _q->buf_freq[i] * conjf(_q->buf_freq[i]) ); if (_q->num_transforms == 0) _q->psd[i] = v; else _q->psd[i] = _q->gamma*_q->psd[i] + _q->alpha*v; } _q->num_transforms++; _q->num_transforms_total++; } // compute spectral periodogram output (fft-shifted values // in dB) from current buffer contents // _q : spgram object // _X : output spectrum [size: _nfft x 1] void SPGRAM(_get_psd)(SPGRAM() _q, T * _X) { // compute magnitude in dB and run FFT shift unsigned int i; unsigned int nfft_2 = _q->nfft / 2; T scale = _q->accumulate ? -10*log10f(_q->num_transforms) : 0.0f; // TODO: adjust scale if infinite integration for (i=0; i<_q->nfft; i++) { unsigned int k = (i + nfft_2) % _q->nfft; _X[i] = 10*log10f(_q->psd[k]+1e-6f) + scale; } } // export gnuplot file // _q : spgram object // _filename : input buffer [size: _n x 1] int SPGRAM(_export_gnuplot)(SPGRAM() _q, const char * _filename) { FILE * fid = fopen(_filename,"w"); if (fid == NULL) { fprintf(stderr,"error: spgram%s_export_gnuplot(), could not open '%s' for writing\n", EXTENSION, _filename); return -1; } fprintf(fid,"# %s : auto-generated file\n", _filename); fprintf(fid,"reset\n"); fprintf(fid,"set terminal png size 1200,800 enhanced font 'Verdana,10'\n"); fprintf(fid,"set output '%s.png'\n", _filename); fprintf(fid,"set xrange [-0.5:0.5]\n"); fprintf(fid,"set autoscale y\n"); fprintf(fid,"set xlabel 'Noramlized Frequency'\n"); fprintf(fid,"set ylabel 'Power Spectral Density'\n"); fprintf(fid,"set style line 12 lc rgb '#404040' lt 0 lw 1\n"); fprintf(fid,"set grid xtics ytics\n"); fprintf(fid,"set grid front ls 12\n"); fprintf(fid,"set style fill transparent solid 0.2\n"); fprintf(fid,"set nokey\n"); fprintf(fid,"plot '-' w filledcurves x1 lt 1 lw 2 lc rgb '#004080'\n"); // export spectrum data T * psd = (T*) malloc(_q->nfft * sizeof(T)); SPGRAM(_get_psd)(_q, psd); unsigned int i; for (i=0; i<_q->nfft; i++) fprintf(fid," %12.8f %12.8f\n", (float)i/(float)(_q->nfft)-0.5f, (float)(psd[i])); free(psd); fprintf(fid,"e\n"); // close it up fclose(fid); return 0; } // // object-independent methods // // estimate spectrum on input signal // _nfft : FFT size // _x : input signal [size: _n x 1] // _n : input signal length // _psd : output spectrum, [size: _nfft x 1] void SPGRAM(_estimate_psd)(unsigned int _nfft, TI * _x, unsigned int _n, T * _psd) { // create object SPGRAM() q = SPGRAM(_create_default)(_nfft); // run spectral estimate on entire sequence SPGRAM(_write)(q, _x, _n); // get PSD estimate SPGRAM(_get_psd)(q, _psd); // destroy object SPGRAM(_destroy)(q); } liquid-dsp-1.3.1/src/fft/src/spgramcf.c000066400000000000000000000040301317124540100176650ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // spectral periodogram API: complex floating-point // #include "liquid.internal.h" // naming extensions (useful for print statements) #define EXTENSION "cf" // name-mangling macros #define ASGRAM(name) LIQUID_CONCAT(asgramcf,name) #define SPGRAM(name) LIQUID_CONCAT(spgramcf,name) #define SPWATERFALL(name) LIQUID_CONCAT(spwaterfallcf,name) #define WINDOW(name) LIQUID_CONCAT(windowcf,name) #define FFT(name) LIQUID_CONCAT(fft,name) #define T float // primitive type (real) #define TC float complex // primitive type (complex) #define TI float complex // input type #define TI_COMPLEX 1 #define PRINTVAL_T(X,F) PRINTVAL_FLOAT(X,F) #define PRINTVAL_TC(X,F) PRINTVAL_CFLOAT(X,F) #define PRINTVAL_TI(X,F) PRINTVAL_CFLOAT(X,F) // source files #include "asgram.c" #include "spgram.c" #include "spwaterfall.c" liquid-dsp-1.3.1/src/fft/src/spgramf.c000066400000000000000000000040221317124540100175230ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // spectral periodogram API: complex floating-point // #include "liquid.internal.h" // naming extensions (useful for print statements) #define EXTENSION "f" // name-mangling macros #define ASGRAM(name) LIQUID_CONCAT(asgramf,name) #define SPGRAM(name) LIQUID_CONCAT(spgramf,name) #define SPWATERFALL(name) LIQUID_CONCAT(spwaterfallf,name) #define WINDOW(name) LIQUID_CONCAT(windowf,name) #define FFT(name) LIQUID_CONCAT(fft,name) #define T float // primitive type (real) #define TC float complex // primitive type (complex) #define TI float // input type #define TI_COMPLEX 0 #define PRINTVAL_T(X,F) PRINTVAL_FLOAT(X,F) #define PRINTVAL_TC(X,F) PRINTVAL_CFLOAT(X,F) #define PRINTVAL_TI(X,F) PRINTVAL_FLOAT(X,F) // source files #include "asgram.c" #include "spgram.c" #include "spwaterfall.c" liquid-dsp-1.3.1/src/fft/src/spwaterfall.c000066400000000000000000000313261317124540100204170ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2017 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // spwaterfall (spectral periodogram waterfall) // #include #include #include #include #include #include #include "liquid.internal.h" struct SPWATERFALL(_s) { // options unsigned int nfft; // FFT length unsigned int time; // minimum time buffer SPGRAM() periodogram; // spectral periodogram object // buffers T * psd; // time/frequency buffer [nfft x 2*time] unsigned int index_time; // time index for writing to buffer unsigned int rollover; // number of FFTs to take before writing to output }; // // internal methods // // compute spectral periodogram output (complex values) from internal periodogram object void SPWATERFALL(_step)(SPWATERFALL() _q); // consolidate buffer by taking log-average of two separate spectral estimates in time void SPWATERFALL(_consolidate_buffer)(SPWATERFALL() _q); // export files int SPWATERFALL(_export_bin)(SPWATERFALL() _q, const char * _filename_base); int SPWATERFALL(_export_gnu)(SPWATERFALL() _q, const char * _filename_base); // create spwaterfall object // _nfft : FFT size // _wtype : window type, e.g. LIQUID_WINDOW_HAMMING // _window_len : window length // _delay : delay between transforms, _delay > 0 SPWATERFALL() SPWATERFALL(_create)(unsigned int _nfft, int _wtype, unsigned int _window_len, unsigned int _delay, unsigned int _time) { // validate input if (_nfft < 2) { fprintf(stderr,"error: spwaterfall%s_create(), fft size must be at least 2\n", EXTENSION); exit(1); } else if (_window_len > _nfft) { fprintf(stderr,"error: spwaterfall%s_create(), window size cannot exceed fft size\n", EXTENSION); exit(1); } else if (_window_len == 0) { fprintf(stderr,"error: spwaterfall%s_create(), window size must be greater than zero\n", EXTENSION); exit(1); } else if (_wtype == LIQUID_WINDOW_KBD && _window_len % 2) { fprintf(stderr,"error: spwaterfall%s_create(), KBD window length must be even\n", EXTENSION); exit(1); } else if (_delay == 0) { fprintf(stderr,"error: spwaterfall%s_create(), delay must be greater than 0\n", EXTENSION); exit(1); } else if (_time == 0) { fprintf(stderr,"error: spwaterfall%s_create(), time must be greater than 0\n", EXTENSION); exit(1); } // allocate memory for main object SPWATERFALL() q = (SPWATERFALL()) malloc(sizeof(struct SPWATERFALL(_s))); // set input parameters q->nfft = _nfft; q->time = _time; // create buffer to hold aggregated power spectral density // NOTE: the buffer is two-dimensional time/frequency grid that is two times // 'nfft' and 'time' to account for log-average consolidation each time // the buffer gets filled q->psd = (T*) malloc( 2 * q->nfft * q->time * sizeof(T)); // create spectral periodogram object q->periodogram = SPGRAM(_create)(_nfft, _wtype, _window_len, _delay); // reset the object SPWATERFALL(_reset)(q); // return new object return q; } // create default spwaterfall object (Kaiser-Bessel window) SPWATERFALL() SPWATERFALL(_create_default)(unsigned int _nfft, unsigned int _time) { // validate input if (_nfft < 2) { fprintf(stderr,"error: spwaterfall%s_create_default(), fft size must be at least 2\n", EXTENSION); exit(1); } else if (_time < 2) { fprintf(stderr,"error: spwaterfall%s_create_default(), fft size must be at least 2\n", EXTENSION); exit(1); } return SPWATERFALL(_create)(_nfft, LIQUID_WINDOW_KAISER, _nfft/2, _nfft/4, _time); } // destroy spwaterfall object void SPWATERFALL(_destroy)(SPWATERFALL() _q) { // free allocated memory free(_q->psd); // destroy internal spectral periodogram object SPGRAM(_destroy)(_q->periodogram); // free main object free(_q); } // clears the internal state of the spwaterfall object, but not // the internal buffer void SPWATERFALL(_clear)(SPWATERFALL() _q) { memset(_q->psd, 0x00, 2*_q->nfft*_q->time*sizeof(T)); _q->index_time = 0; } // reset the spwaterfall object to its original state completely void SPWATERFALL(_reset)(SPWATERFALL() _q) { SPWATERFALL(_clear)(_q); _q->rollover = 1; } // prints the spwaterfall object's parameters void SPWATERFALL(_print)(SPWATERFALL() _q) { printf("spwaterfall%s: nfft=%u, time=%u\n", EXTENSION, _q->nfft, _q->time); } // push a single sample into the spwaterfall object // _q : spwaterfall object // _x : input sample void SPWATERFALL(_push)(SPWATERFALL() _q, TI _x) { SPGRAM(_push)(_q->periodogram, _x); SPWATERFALL(_step)(_q); } // write a block of samples to the spwaterfall object // _q : spwaterfall object // _x : input buffer [size: _n x 1] // _n : input buffer length void SPWATERFALL(_write)(SPWATERFALL() _q, TI * _x, unsigned int _n) { // TODO: be smarter about how to write and execute samples unsigned int i; for (i=0; i<_n; i++) SPWATERFALL(_push)(_q, _x[i]); } // export output files // _q : spwaterfall object // _filename_base : base filename int SPWATERFALL(_export)(SPWATERFALL() _q, const char * _filename_base) { return SPWATERFALL(_export_bin)(_q, _filename_base) + SPWATERFALL(_export_gnu)(_q, _filename_base); } // compute spectral periodogram output from current buffer contents // _q : spwaterfall object void SPWATERFALL(_step)(SPWATERFALL() _q) { // determine if we need to extract PSD estimate from periodogram if (SPGRAM(_get_num_transforms)(_q->periodogram) >= _q->rollover) { //printf("index : %u\n", _q->index_time); // get PSD estimate from periodogram object, placing result in // proper location in internal buffer SPGRAM(_get_psd)(_q->periodogram, _q->psd + _q->nfft*_q->index_time); // soft reset of internal state, counters SPGRAM(_clear)(_q->periodogram); // increment buffer counter _q->index_time++; // determine if buffer is full and we need to consolidate buffer if (_q->index_time == 2*_q->time) SPWATERFALL(_consolidate_buffer)(_q); } } // consolidate buffer by taking log-average of two separate spectral estimates in time // _q : spwaterfall object void SPWATERFALL(_consolidate_buffer)(SPWATERFALL() _q) { // assert(_q->index_time == 2*_q->time); printf("consolidating... (rollover = %10u, total samples : %16llu, index : %u)\n", _q->rollover, SPGRAM(_get_num_samples_total)(_q->periodogram), _q->index_time); unsigned int i; // time index unsigned int k; // freq index for (i=0; i<_q->time; i++) { for (k=0; k<_q->nfft; k++) { // compute median T v0 = _q->psd[ (2*i + 0)*_q->nfft + k ]; T v1 = _q->psd[ (2*i + 1)*_q->nfft + k ]; // keep log average (only need double buffer for this, not triple buffer) _q->psd[ i*_q->nfft + k ] = logf(0.5f*(expf(v0) + expf(v1))); } } // update time index _q->index_time = _q->time; // update rollover counter _q->rollover *= 2; } // export gnuplot file // _q : spwaterfall object // _filename : input buffer [size: _n x 1] int SPWATERFALL(_export_bin)(SPWATERFALL() _q, const char * _filename_base) { // add '.bin' extension to base int n = strlen(_filename_base); char filename[n+5]; sprintf(filename,"%s.bin", _filename_base); // open output file for writing FILE * fid = fopen(filename,"w"); if (fid == NULL) { fprintf(stderr,"error: spwaterfall%s_export_bin(), could not open '%s' for writing\n", EXTENSION, filename); return -1; } unsigned int i; // write header float nfftf = (float)(_q->nfft); fwrite(&nfftf, sizeof(float), 1, fid); for (i=0; i<_q->nfft; i++) { float f = (float)i/nfftf - 0.5f; fwrite(&f, sizeof(float), 1, fid); } // write output spectral estimate // TODO: force converstion from type 'T' to type 'float' uint64_t total_samples = SPGRAM(_get_num_samples_total)(_q->periodogram); for (i=0; i<_q->index_time; i++) { float n = (float)i / (float)(_q->index_time) * (float)total_samples; fwrite(&n, sizeof(float), 1, fid); fwrite(&_q->psd[i*_q->nfft], sizeof(float), _q->nfft, fid); } // close it up fclose(fid); printf("results written to %s\n", filename); return 0; } // export gnuplot file // _q : spwaterfall object // _filename : input buffer [size: _n x 1] int SPWATERFALL(_export_gnu)(SPWATERFALL() _q, const char * _filename_base) { // add '.bin' extension to base int n = strlen(_filename_base); char filename[n+5]; sprintf(filename,"%s.gnu", _filename_base); // open output file for writing FILE * fid = fopen(filename,"w"); if (fid == NULL) { fprintf(stderr,"error: spwaterfall%s_export_gnu(), could not open '%s' for writing\n", EXTENSION, filename); return -1; } // scale to thousands, millions, billions (etc.) automatically uint64_t total_samples = SPGRAM(_get_num_samples_total)(_q->periodogram); char units = ' '; float scale = 1.0f; if (total_samples < 4e3 ) { units = ' '; scale = 1e-0f; } else if (total_samples < 4e6 ) { units = 'k'; scale = 1e-3f; } else if (total_samples < 4e9 ) { units = 'M'; scale = 1e-6f; } else if (total_samples < 4e12) { units = 'G'; scale = 1e-9f; } else if (total_samples < 4e15) { units = 'T'; scale = 1e-12f; } else { units = 'P'; scale = 1e-15f; } fprintf(fid,"#!/usr/bin/gnuplot\n"); fprintf(fid,"reset\n"); fprintf(fid,"set terminal png size 800,800 enhanced font 'Verdana,10'\n"); fprintf(fid,"set output '%s.png'\n", _filename_base); fprintf(fid,"unset key\n"); fprintf(fid,"set style line 11 lc rgb '#808080' lt 1\n"); fprintf(fid,"set border 3 front ls 11\n"); fprintf(fid,"set style line 12 lc rgb '#888888' lt 0 lw 1\n"); fprintf(fid,"set grid front ls 12\n"); fprintf(fid,"set tics nomirror out scale 0.75\n"); fprintf(fid,"set xrange [-0.5:0.5]\n"); fprintf(fid,"set yrange [0:%f]\n", (float)(total_samples-1)*scale); fprintf(fid,"set xlabel 'Normalized Frequency [f/F_s]'\n"); fprintf(fid,"set ylabel 'Sample Index'\n"); fprintf(fid,"set format y '%%.0f %c'\n", units); fprintf(fid,"# disable colorbar tics\n"); fprintf(fid,"set cbtics scale 0\n"); fprintf(fid,"set palette negative defined ( \\\n"); fprintf(fid," 0 '#D53E4F',\\\n"); fprintf(fid," 1 '#F46D43',\\\n"); fprintf(fid," 2 '#FDAE61',\\\n"); fprintf(fid," 3 '#FEE08B',\\\n"); fprintf(fid," 4 '#E6F598',\\\n"); fprintf(fid," 5 '#ABDDA4',\\\n"); fprintf(fid," 6 '#66C2A5',\\\n"); fprintf(fid," 7 '#3288BD' )\n"); fprintf(fid,"\n"); fprintf(fid,"plot '%s.bin' u 1:($2*%e):3 binary matrix with image\n", _filename_base, scale); fclose(fid); // close it up printf("results written to %s\n", filename); printf("index time : %u\n", _q->index_time); printf("rollover : %u\n", _q->rollover); printf("total transforms : %llu\n", SPGRAM(_get_num_transforms_total)(_q->periodogram)); return 0; } liquid-dsp-1.3.1/src/fft/tests/000077500000000000000000000000001317124540100162755ustar00rootroot00000000000000liquid-dsp-1.3.1/src/fft/tests/data/000077500000000000000000000000001317124540100172065ustar00rootroot00000000000000liquid-dsp-1.3.1/src/fft/tests/data/fft_data_10.c000066400000000000000000000043371317124540100214310ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 10-point transform // #include float complex fft_test_x10[] = { -0.380648737020 + 1.003981780953*_Complex_I, 1.031511152163 + -2.625896014009*_Complex_I, -1.083239396623 + 1.646877001105*_Complex_I, 0.951587457487 + -0.004983138281*_Complex_I, 0.407589360084 + 0.345698641918*_Complex_I, 0.549291472049 + 0.542579734652*_Complex_I, -0.911825526748 + 1.282009726257*_Complex_I, -0.617849040964 + 0.696673367751*_Complex_I, 1.097501043733 + 1.373947311009*_Complex_I, 0.848713422957 + -0.738252787172*_Complex_I}; float complex fft_test_y10[] = { 1.892631207117 + 3.522635624182*_Complex_I, -1.167216826866 + -3.158947047615*_Complex_I, -0.019614668329 + 1.291770408491*_Complex_I, -3.842057814631 + -1.668342848977*_Complex_I, -2.323082893679 + 1.200058008683*_Complex_I, -3.633877720265 + 7.782393298301*_Complex_I, 0.649048218143 + 6.997144832999*_Complex_I, 1.025423884758 + 1.907666229150*_Complex_I, 0.644231811894 + -5.278801296330*_Complex_I, 2.968027431661 + -2.555759399357*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_120.c000066400000000000000000000317321317124540100215120ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 120-point transform // #include float complex fft_test_x120[] = { -2.933561116248 + 0.585802030432*_Complex_I, 0.996149474765 + -0.621353657548*_Complex_I, -0.262138535383 + 0.974643272654*_Complex_I, -1.483709823026 + -1.654326811798*_Complex_I, 0.009105914718 + -0.801453728867*_Complex_I, 1.480357059658 + -0.231135073122*_Complex_I, -0.580765210290 + 1.288460832776*_Complex_I, 0.485467815383 + 0.439565460988*_Complex_I, -1.010673740947 + -0.691639979516*_Complex_I, -0.525003222625 + -0.639606200048*_Complex_I, -0.806916915589 + 0.103762356730*_Complex_I, -0.399336315292 + 0.323161793208*_Complex_I, 0.111455618955 + 0.487552495249*_Complex_I, 0.523592233718 + 0.565527718910*_Complex_I, -0.181781072708 + 0.927375893986*_Complex_I, -0.427811932504 + -1.730760015952*_Complex_I, 0.722234655868 + -0.528518032448*_Complex_I, 0.327894303730 + 1.078490369290*_Complex_I, -0.365985637484 + -0.829110156759*_Complex_I, -1.230443935235 + 1.168892009209*_Complex_I, -0.497547601907 + -1.884812736460*_Complex_I, -0.188693666275 + -0.388189056130*_Complex_I, 1.581490442848 + -0.773206675201*_Complex_I, -0.276904037052 + -1.607191981281*_Complex_I, 0.869586527848 + 2.279865113156*_Complex_I, 2.280976663440 + -0.491932963519*_Complex_I, -0.972146414270 + 1.317390598922*_Complex_I, 0.752226877706 + 0.307325301979*_Complex_I, -2.176688443840 + -0.178238348418*_Complex_I, 0.603808804599 + -1.024869177311*_Complex_I, 1.637709885855 + 1.283852424020*_Complex_I, 0.766867282671 + -2.390532794299*_Complex_I, -0.803164170514 + -0.738964307326*_Complex_I, -0.217928168834 + -1.591138647698*_Complex_I, 0.044558930462 + -0.585819999208*_Complex_I, 0.185461763498 + 0.190876001378*_Complex_I, -0.887233966458 + 0.932582089649*_Complex_I, -1.388038826042 + 0.114934886174*_Complex_I, 0.079732100731 + 0.150414346304*_Complex_I, 1.215962906658 + 0.864185821675*_Complex_I, -0.889642609373 + -0.510424427491*_Complex_I, 0.243053087540 + -1.438563895787*_Complex_I, -0.409793881375 + 0.157176601902*_Complex_I, -1.193700035506 + -0.866457731187*_Complex_I, 1.192127022305 + -0.584612994505*_Complex_I, -0.387515835212 + 1.536461365714*_Complex_I, -0.853256362306 + -0.633564682282*_Complex_I, -0.152836605296 + -0.219510310627*_Complex_I, -1.151934152005 + 0.171485405414*_Complex_I, -0.010116218440 + 0.914918482762*_Complex_I, -1.686537878154 + 0.779331814618*_Complex_I, 0.673793112643 + 0.566118503412*_Complex_I, -0.143701669515 + -0.556780150872*_Complex_I, -0.845847069767 + 0.686668013963*_Complex_I, -1.147722980640 + -0.455850082513*_Complex_I, 1.310965019946 + -0.268939336441*_Complex_I, 0.641191445468 + 0.065635531845*_Complex_I, 0.790297755545 + 0.898978586598*_Complex_I, -1.539239983789 + 1.569958337837*_Complex_I, -1.042534751831 + -1.615908992141*_Complex_I, 0.848219334777 + 1.570278962754*_Complex_I, 0.768312422101 + 1.168572048009*_Complex_I, -0.119617114473 + 0.018922768020*_Complex_I, 0.463083556040 + -0.289189219121*_Complex_I, -2.334868450076 + 0.543186130761*_Complex_I, -0.859810016516 + -0.073915244925*_Complex_I, -0.986571365561 + 0.653098182477*_Complex_I, 0.522451913274 + -0.042046367028*_Complex_I, 0.106640796179 + -0.069187996590*_Complex_I, 1.052892113567 + 0.678469397559*_Complex_I, -0.698384198090 + 0.402405190110*_Complex_I, -0.274412699197 + 0.194991340203*_Complex_I, 0.154775651261 + -1.748234046267*_Complex_I, -0.373611252309 + 0.759957440236*_Complex_I, 0.307971942775 + 0.177025819034*_Complex_I, 1.127535219986 + -0.133866569607*_Complex_I, -0.780872981180 + -1.914809677751*_Complex_I, 0.097809503845 + -0.311527508403*_Complex_I, -1.338663250568 + -0.272131094279*_Complex_I, -1.774506466862 + 0.189947566984*_Complex_I, -0.108910232947 + -1.104077803690*_Complex_I, 0.700684038217 + 0.489503255191*_Complex_I, 1.723390943656 + -0.653061888020*_Complex_I, -0.307392508631 + -0.487335518704*_Complex_I, -1.351222246370 + -0.276340698500*_Complex_I, 0.554657638847 + 1.969266502927*_Complex_I, -0.693153982211 + -0.117977636798*_Complex_I, -0.639852935555 + 0.539350932011*_Complex_I, 0.774200449083 + 1.123041486424*_Complex_I, -2.046058231062 + -0.457644959516*_Complex_I, -1.606346330196 + -1.560038496690*_Complex_I, -1.701087998893 + 1.670050065045*_Complex_I, 0.443897868781 + 0.379995716985*_Complex_I, 0.193958078518 + 0.643773547931*_Complex_I, -1.527640156621 + 1.266495146511*_Complex_I, 0.259186234049 + -0.465035554366*_Complex_I, -0.385562205417 + -1.015469771575*_Complex_I, -1.871226440588 + 0.185126256408*_Complex_I, 0.542445571049 + -0.431681611434*_Complex_I, 0.214440313475 + -0.338588753334*_Complex_I, 0.163385540462 + -0.222892296796*_Complex_I, 0.477872198487 + -0.578917341564*_Complex_I, -1.258436301493 + -0.335313659938*_Complex_I, 0.310183724816 + -1.538340991002*_Complex_I, 0.315711034668 + 0.372755872975*_Complex_I, -0.832316134028 + 0.846715050479*_Complex_I, 1.810572502100 + -0.747188365112*_Complex_I, -1.238997433684 + 2.921109879602*_Complex_I, -1.359334420871 + 1.137914515456*_Complex_I, -1.735544412609 + 0.353972290274*_Complex_I, -1.967071931759 + 1.720943408177*_Complex_I, 0.175659653421 + 0.673882179212*_Complex_I, 0.566435305275 + 1.086122584518*_Complex_I, -0.685557294027 + 0.440265086848*_Complex_I, 1.232868086689 + -0.376035944159*_Complex_I, 0.031017508722 + -1.091694970471*_Complex_I, 0.153454665192 + -0.387812357268*_Complex_I, 0.055087132749 + 0.121934454858*_Complex_I, -1.641857455950 + -0.680302798653*_Complex_I, -0.235668947578 + -0.276093078030*_Complex_I}; float complex fft_test_y120[] = { -26.130540532441 + 2.500301372380*_Complex_I, -8.384737785882 + -11.493299680300*_Complex_I, -10.815843993705 + 1.373214442809*_Complex_I, -3.468316057471 + -0.197988490875*_Complex_I, -8.468015203881 + 4.172305025792*_Complex_I, -6.972140924378 + -19.059978062591*_Complex_I, 12.894909733921 + -14.674650174719*_Complex_I, 6.217174828182 + -4.198857679111*_Complex_I, -3.038713671007 + 11.416582830167*_Complex_I, -5.889009032363 + 2.623087027225*_Complex_I, 4.415856321129 + 20.520368038723*_Complex_I, -7.596161829888 + -9.011449139900*_Complex_I, -22.967094572900 + -14.281559182333*_Complex_I, -13.103802451651 + 2.098170225144*_Complex_I, -5.815320588822 + 10.518428726478*_Complex_I, -1.290859552698 + -5.007381379220*_Complex_I, 10.503332312095 + -13.128075179264*_Complex_I, -0.995307687739 + 6.404055459139*_Complex_I, -7.098602985708 + 2.406450947955*_Complex_I, -5.425368507411 + 31.439384831310*_Complex_I, -4.531419053887 + -0.173481154479*_Complex_I, 9.402659099609 + 3.570607998710*_Complex_I, 10.130149004652 + -16.694138931142*_Complex_I, -2.197851988961 + 2.938436935104*_Complex_I, 5.864606545918 + -13.199247801155*_Complex_I, 12.427931476763 + -14.442851189707*_Complex_I, -0.346878049148 + -2.649522091233*_Complex_I, -6.110432016865 + 10.576069646496*_Complex_I, 29.337845632961 + -5.226538341924*_Complex_I, -5.530434871933 + -6.791491806236*_Complex_I, 12.511893544960 + -9.883054566598*_Complex_I, -13.522823191342 + 3.402811573476*_Complex_I, -6.949602446599 + -2.976747287959*_Complex_I, -13.604769865716 + -21.208579208314*_Complex_I, -2.667739313157 + 7.095560898932*_Complex_I, -4.030948890524 + -4.275911410965*_Complex_I, -1.538455879764 + 0.859913764271*_Complex_I, -1.597640929072 + 9.198642244462*_Complex_I, 3.258927941252 + 3.681214115496*_Complex_I, -27.177542272720 + -9.835919044876*_Complex_I, 2.137018426012 + 5.951425737520*_Complex_I, -9.328564597213 + -8.189268926052*_Complex_I, -15.202874868646 + -10.830493804699*_Complex_I, -14.141307626573 + 6.069950543455*_Complex_I, 23.789715337183 + -0.149207303988*_Complex_I, 1.018819274801 + 23.160092205105*_Complex_I, 0.160728240887 + 25.021802134125*_Complex_I, -27.292399750004 + -12.724069599967*_Complex_I, -11.090997281400 + 7.909805227447*_Complex_I, -12.632686116172 + 4.297788877667*_Complex_I, -10.947166654332 + -7.342984066688*_Complex_I, -12.526588806117 + 6.326089996957*_Complex_I, 7.848075855545 + 5.822833656652*_Complex_I, 4.463550473312 + -2.355918199764*_Complex_I, -3.359730942688 + -1.811340237346*_Complex_I, -16.045827623056 + -11.927425635813*_Complex_I, -17.191945449780 + 14.640840260710*_Complex_I, 5.723503979540 + -3.333396073843*_Complex_I, -7.212762063453 + -0.426026153122*_Complex_I, -8.371988589537 + -1.588815189476*_Complex_I, -16.721024926709 + 1.223543596227*_Complex_I, 21.500278405653 + 15.014414278563*_Complex_I, -12.998260008435 + 6.823922119636*_Complex_I, -11.969924059222 + -6.475357643023*_Complex_I, -3.880671177744 + 23.295158190426*_Complex_I, -1.615932730740 + 9.161241055173*_Complex_I, 6.743423357908 + 4.077889764270*_Complex_I, -8.491295100234 + -14.590167909493*_Complex_I, -4.050564794383 + -0.332576254078*_Complex_I, -7.563666582981 + -0.491929778422*_Complex_I, 5.325292014900 + 13.120067752469*_Complex_I, 17.266746589948 + -1.749739091662*_Complex_I, 9.016685746645 + -6.656805505959*_Complex_I, -8.457355300299 + -4.003222916857*_Complex_I, -31.407914776214 + -9.344158206903*_Complex_I, -8.003020240767 + -1.945349879704*_Complex_I, 10.679124047221 + 1.579265510278*_Complex_I, 7.576096581517 + -20.019004345583*_Complex_I, 5.425463900123 + -6.332000571240*_Complex_I, -11.713907656105 + 7.443366839954*_Complex_I, -0.593664650946 + 6.790006366701*_Complex_I, 10.381068180108 + -7.397393197217*_Complex_I, 0.455908842424 + 7.373964657268*_Complex_I, -8.378432107508 + 18.256672106713*_Complex_I, -24.128536613056 + 5.444870431684*_Complex_I, 8.421822254234 + -9.806814459804*_Complex_I, 7.173520639058 + 9.565811687718*_Complex_I, -6.236143277340 + 6.409295846945*_Complex_I, -5.379127157610 + -7.097598602556*_Complex_I, 0.992816214134 + 1.184456111668*_Complex_I, -8.630312793127 + -3.752996076907*_Complex_I, -0.458097520531 + 10.469419461305*_Complex_I, 3.184993888854 + 4.049136044816*_Complex_I, 2.080876935294 + -9.778155908324*_Complex_I, -12.941818037027 + 3.242798433849*_Complex_I, -6.524522778987 + 2.497157598131*_Complex_I, 3.225741204857 + 15.546794796319*_Complex_I, -6.079247610512 + -13.728424650306*_Complex_I, -4.960232908834 + 10.931039387444*_Complex_I, -2.558877649510 + 10.755632383919*_Complex_I, -19.611477019565 + 5.785472297267*_Complex_I, 21.866745387027 + -15.392995894737*_Complex_I, 16.349317592240 + 12.469152896354*_Complex_I, -9.294214354347 + 3.922833779556*_Complex_I, 13.879970160908 + 7.328114738105*_Complex_I, 2.651592361533 + -7.170628973597*_Complex_I, -5.253905486354 + 2.891157258399*_Complex_I, -8.491348558042 + 11.767371163610*_Complex_I, -0.986424222839 + 12.293687558243*_Complex_I, -16.973656701850 + -4.692292471582*_Complex_I, -10.242186370330 + 14.766563852584*_Complex_I, -5.961461862786 + 15.202716060356*_Complex_I, -8.983395642462 + -16.343883875645*_Complex_I, -10.094160152160 + -8.605909997569*_Complex_I, -2.538579712014 + -14.632787859230*_Complex_I, 10.260131998695 + -4.124613468367*_Complex_I, 5.155214364436 + -0.647489300204*_Complex_I, -7.821333192327 + -15.606994193249*_Complex_I, 4.093578304649 + 15.462757600992*_Complex_I, 4.765467299654 + 7.963215307045*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_130.c000066400000000000000000000337021317124540100215120ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 130-point transform // #include float complex fft_test_x130[] = { 2.295593731681 + 0.411874155977*_Complex_I, 0.867233010936 + 2.391238924231*_Complex_I, -0.979511815183 + 0.113140414722*_Complex_I, 0.077578424280 + 1.186610948031*_Complex_I, -1.071528198235 + 0.804300526324*_Complex_I, 2.564018851452 + -0.310561947705*_Complex_I, -0.950972074792 + 0.436022224496*_Complex_I, 0.329631038192 + -0.396044027241*_Complex_I, -0.862183775613 + 0.927159525327*_Complex_I, -1.059508389407 + 0.941689902943*_Complex_I, 0.561615143764 + 0.096377911775*_Complex_I, 0.534738747717 + 0.825200677825*_Complex_I, 0.532672479322 + -1.976151133815*_Complex_I, -1.310581230339 + 0.002609415320*_Complex_I, -0.093941505596 + 0.905920914198*_Complex_I, 0.925525275182 + 1.564605784264*_Complex_I, -0.117943104365 + -0.166904851246*_Complex_I, -0.009619069574 + 1.676338431134*_Complex_I, -1.367286699092 + 1.175301759986*_Complex_I, -0.053699588910 + 1.515076774609*_Complex_I, -0.070846548150 + -1.323601968188*_Complex_I, 1.796443691981 + -2.011926920619*_Complex_I, 0.493444077774 + -0.231926417128*_Complex_I, 0.426102034457 + -0.966613330823*_Complex_I, -0.403283890205 + 0.570936153832*_Complex_I, 0.339532677572 + -2.038175992612*_Complex_I, 0.202689295315 + 0.573201095278*_Complex_I, -0.571885221166 + -1.275661165797*_Complex_I, -0.794196427625 + 0.423266616492*_Complex_I, -1.259472882356 + 0.532748103823*_Complex_I, 0.578465509624 + 0.826666605971*_Complex_I, -0.185287664847 + 1.746937914937*_Complex_I, 0.763423434636 + 2.020182432630*_Complex_I, 0.086623435989 + 0.431914895390*_Complex_I, 1.507900753669 + 0.056290417021*_Complex_I, -0.032809671097 + 0.098620827398*_Complex_I, 1.816125083125 + 0.081663531528*_Complex_I, 0.214492964742 + -0.162240129055*_Complex_I, 0.189647728207 + -1.547086817248*_Complex_I, -0.273499165641 + -0.552833918252*_Complex_I, 0.118280846537 + 2.716796709548*_Complex_I, 0.771040737403 + 2.763544783033*_Complex_I, -1.225097272428 + 0.386568340878*_Complex_I, -0.106529445935 + 2.317399662638*_Complex_I, -0.309752877128 + 0.781864233638*_Complex_I, -0.382242026751 + 0.530778535695*_Complex_I, 2.187686178145 + -1.629696212455*_Complex_I, -0.796121964339 + 1.212447992147*_Complex_I, 0.483902967137 + -1.761611437465*_Complex_I, 0.078193155045 + -0.695682313346*_Complex_I, -0.586826944592 + 0.119088984700*_Complex_I, 0.105215960567 + 1.605824117591*_Complex_I, -1.096678506319 + 0.626271388642*_Complex_I, -1.393844336696 + 0.006228875154*_Complex_I, -0.563177155438 + -0.137367111477*_Complex_I, 0.009064659930 + 0.774248879600*_Complex_I, 0.116957909967 + -0.374512247987*_Complex_I, 0.139602276134 + 1.196173350261*_Complex_I, 2.212769662630 + 0.374920897734*_Complex_I, 0.016527615895 + 0.361537040940*_Complex_I, -0.121813458827 + -1.829691824294*_Complex_I, -1.177075906748 + 0.142539646960*_Complex_I, 0.036310389827 + 1.045967306206*_Complex_I, -0.065389592517 + -1.807892452763*_Complex_I, -1.387880762495 + 0.171082957785*_Complex_I, -0.561065052343 + -1.260326041796*_Complex_I, 0.640813649741 + -1.777293190718*_Complex_I, -0.854417690416 + 2.237007530372*_Complex_I, -0.547722791713 + -2.330803396241*_Complex_I, 0.241170879004 + -0.617927403601*_Complex_I, 1.149285559687 + -0.376338314437*_Complex_I, -0.611492918690 + 2.047469301403*_Complex_I, 1.187263678013 + -0.165876393098*_Complex_I, 0.165257041186 + 1.672015729392*_Complex_I, -0.994770290926 + -0.351786586669*_Complex_I, -0.899279932248 + 0.810204064241*_Complex_I, -0.989604008277 + -0.119746717438*_Complex_I, -0.645537324969 + 0.353174690969*_Complex_I, -0.170329112065 + 0.085003743875*_Complex_I, -0.622581542228 + 0.035852829902*_Complex_I, 1.027721243658 + -1.009164344833*_Complex_I, -0.512899325586 + 1.422707083000*_Complex_I, -1.537474288640 + 0.734758277184*_Complex_I, 0.300068603056 + -0.844600037520*_Complex_I, 1.173177814994 + 0.474849978182*_Complex_I, 1.994390672833 + 0.274156356539*_Complex_I, -0.395247012804 + 1.046793121497*_Complex_I, 0.111209493599 + -1.063639370387*_Complex_I, 0.804028185695 + -2.330860293474*_Complex_I, -0.790484315366 + -2.043033932357*_Complex_I, -1.938436910347 + 0.005399210558*_Complex_I, -2.213763088095 + -0.050657389028*_Complex_I, -1.085606481444 + -1.672620738363*_Complex_I, 0.114374573479 + -0.314566566070*_Complex_I, -0.334479316133 + -0.269357185023*_Complex_I, -0.405597270856 + -1.024425491739*_Complex_I, -0.268446228006 + 0.625273024277*_Complex_I, 0.114305720338 + 0.091667406850*_Complex_I, 0.458271491171 + 0.893733272049*_Complex_I, 2.164470970876 + -0.008479990723*_Complex_I, 2.534318741148 + -0.513177256373*_Complex_I, 1.349837294176 + 0.730739449071*_Complex_I, 0.178600395004 + 0.598903569881*_Complex_I, 0.999820793703 + 0.023280883440*_Complex_I, 2.567157231145 + 2.857783095653*_Complex_I, 1.121937084722 + -0.127318755949*_Complex_I, -1.476481512156 + 0.438739152692*_Complex_I, 0.102675413849 + -1.072173994008*_Complex_I, 1.753108769750 + -1.363923993462*_Complex_I, -0.329713403173 + -0.836197629494*_Complex_I, 0.053237332369 + -0.316007225300*_Complex_I, 1.094272758407 + 0.154099319830*_Complex_I, 1.120647617053 + 2.290453172159*_Complex_I, -0.909112485707 + -0.663394681024*_Complex_I, 0.427832898254 + 0.948020241699*_Complex_I, 0.346684378724 + 1.412486035318*_Complex_I, -0.142628142360 + 0.034555947923*_Complex_I, 0.329645857287 + 2.194959848150*_Complex_I, -0.914476449793 + 0.031998423787*_Complex_I, 3.135765246395 + -1.497430797101*_Complex_I, 1.209028626447 + -0.686517697463*_Complex_I, 0.379503693068 + -0.842990842120*_Complex_I, -0.660923599405 + -0.501650971018*_Complex_I, 0.299565764767 + 1.443185673085*_Complex_I, -0.436332705510 + -0.166601489288*_Complex_I, 0.671417018091 + 1.996886835639*_Complex_I, -0.357759632151 + -0.399361979644*_Complex_I, 1.113330373199 + -0.350135780628*_Complex_I, -0.281958991560 + -0.356378430727*_Complex_I, 1.134108928078 + -2.092860871008*_Complex_I}; float complex fft_test_y130[] = { 14.378246546427 + 16.821529859589*_Complex_I, 27.857066272618 + 13.571899136472*_Complex_I, -15.456704775735 + 12.690273582209*_Complex_I, -8.753035425840 + 7.321557750269*_Complex_I, 28.113754727138 + -12.547913966687*_Complex_I, 10.563681172036 + 7.127854603059*_Complex_I, -6.710153682806 + 1.534074734434*_Complex_I, -0.152583781138 + 1.608751427720*_Complex_I, 9.516727413961 + -11.938945268968*_Complex_I, 11.591596283751 + 29.464218232945*_Complex_I, -1.861083239337 + 0.048807386609*_Complex_I, 13.530879033363 + -18.257581820108*_Complex_I, -11.904116745072 + -21.233551918127*_Complex_I, 25.195023350250 + -2.967265398356*_Complex_I, 11.563020359283 + -8.938209578954*_Complex_I, -2.212982769038 + 20.141015933481*_Complex_I, 9.560556874374 + 25.805352474019*_Complex_I, 9.352588131212 + -7.076490204727*_Complex_I, 19.915109002940 + 6.825454682895*_Complex_I, 9.736225779794 + -4.099017628979*_Complex_I, 10.036798782148 + 4.863204800610*_Complex_I, -5.027402703494 + 4.645951171953*_Complex_I, 0.722099014183 + 4.901713974497*_Complex_I, 12.341913244180 + 4.734214019087*_Complex_I, 6.490076890583 + -14.694265064166*_Complex_I, 18.468325287177 + -3.754877637942*_Complex_I, 30.687354000703 + 1.981540291860*_Complex_I, -17.305129028905 + 1.869860221279*_Complex_I, 3.696020771673 + -4.871064988434*_Complex_I, 15.580947342376 + 22.519564496626*_Complex_I, 3.848144651945 + -1.781612409800*_Complex_I, 8.942942784269 + -3.602301409947*_Complex_I, -7.765663555408 + -0.625063385554*_Complex_I, -19.365854088060 + -1.898384733722*_Complex_I, 22.654736737697 + -31.009432894736*_Complex_I, 8.366067634071 + 17.695248714554*_Complex_I, 13.661573039778 + 5.489335650118*_Complex_I, 7.965893046432 + 0.920878507501*_Complex_I, -6.773323972099 + -8.838093482259*_Complex_I, 18.008424231247 + 0.970453153687*_Complex_I, 3.616219743282 + -7.106399136439*_Complex_I, 4.354625182855 + 6.303312903302*_Complex_I, 2.152940232565 + 10.856400632985*_Complex_I, 9.549358562936 + 3.736001577178*_Complex_I, -23.393358100356 + -6.204075948816*_Complex_I, 15.508680212133 + 8.577949641991*_Complex_I, -7.063921889490 + -9.211630834511*_Complex_I, 21.009705406653 + -6.517205812361*_Complex_I, 15.423888702704 + 0.981999687774*_Complex_I, 28.573348594219 + 5.383290022507*_Complex_I, 15.304347003446 + 27.118709596573*_Complex_I, 14.142070126013 + 6.277279353863*_Complex_I, 1.625323780309 + -9.187451801090*_Complex_I, 8.830870090341 + 18.810210753448*_Complex_I, -0.345015176149 + -9.619976818810*_Complex_I, 7.341484437606 + -0.732292583861*_Complex_I, 8.958852700478 + -10.587428450375*_Complex_I, 3.882707974052 + -17.745844755612*_Complex_I, -8.873303252125 + -15.211822737393*_Complex_I, -6.167534400705 + 10.214589494545*_Complex_I, -20.228656724261 + 17.585629744635*_Complex_I, 10.933318198559 + 14.370328231006*_Complex_I, -8.461977401717 + -11.180604276190*_Complex_I, -9.616742566226 + -24.903826036989*_Complex_I, -11.411472927768 + 17.575007330620*_Complex_I, -2.685486674198 + -14.771303637127*_Complex_I, -25.251618764170 + 6.826824013717*_Complex_I, -6.299724034225 + -16.396112316751*_Complex_I, -7.265214784934 + -5.565409121926*_Complex_I, -6.640524692135 + 0.521019036698*_Complex_I, 16.214262242728 + 2.209865277239*_Complex_I, -5.045705495784 + 7.246063716170*_Complex_I, 12.635656398329 + 5.953408206671*_Complex_I, 7.826253258739 + 10.349167227222*_Complex_I, 2.088937948255 + -5.121963022405*_Complex_I, -11.873961874446 + 14.994764484717*_Complex_I, 22.398422820899 + 6.844715327780*_Complex_I, -12.730924558399 + -11.992318329822*_Complex_I, 13.524168525742 + -4.729670042115*_Complex_I, 1.202484810688 + -1.663460844124*_Complex_I, -1.947874132965 + 1.302757622556*_Complex_I, -20.543601027337 + 12.258518226726*_Complex_I, -3.137767302170 + -2.981480633371*_Complex_I, -7.975513140256 + -16.485317151074*_Complex_I, 8.810596349659 + 6.332990185486*_Complex_I, -6.161246346457 + 5.235039382005*_Complex_I, 2.843534766863 + -4.617409607122*_Complex_I, -4.073520680077 + -5.879651303740*_Complex_I, -2.171553918002 + -2.554595714543*_Complex_I, -6.693230033855 + -4.317974300454*_Complex_I, 2.510552087942 + 5.009469541979*_Complex_I, -19.083210256655 + 5.125864403228*_Complex_I, 0.411198384867 + 2.018760355265*_Complex_I, -9.315948091880 + -15.753105210356*_Complex_I, 7.665007791183 + 19.339077441185*_Complex_I, 17.992904291137 + 1.608531544860*_Complex_I, 7.252549051948 + 5.185390374966*_Complex_I, -3.402294497131 + 15.472029335175*_Complex_I, -10.304002604604 + -3.412309568194*_Complex_I, 3.576347909571 + -16.980789801741*_Complex_I, -14.889487424902 + -0.293460269814*_Complex_I, -2.329133331489 + 15.570197654593*_Complex_I, -4.321477736813 + 4.956074608145*_Complex_I, 3.632694634916 + 11.871283520762*_Complex_I, 2.290904837875 + -0.771528125573*_Complex_I, 36.996035166517 + -1.073727284586*_Complex_I, 6.227709813318 + -9.761528406472*_Complex_I, -2.515872122268 + 0.034234272997*_Complex_I, 4.552755682518 + -9.370352932646*_Complex_I, 9.004603455113 + 4.753018490255*_Complex_I, 0.440587766505 + 16.114787576668*_Complex_I, -28.634077387281 + -5.605910818928*_Complex_I, -5.160190484618 + -11.779239644678*_Complex_I, -17.819659704355 + 0.062857325389*_Complex_I, -14.769191642874 + -0.223091433159*_Complex_I, 2.070190617098 + -3.834976376660*_Complex_I, -3.825400452939 + -5.056722468813*_Complex_I, -15.844519611706 + -11.255119227692*_Complex_I, 25.546454083988 + 2.033450780777*_Complex_I, 25.208964212648 + -18.608412069091*_Complex_I, -30.422847814837 + -18.350779470779*_Complex_I, 15.095434571838 + 20.530536309828*_Complex_I, 1.789608009331 + 28.248536173054*_Complex_I, -12.951533049636 + 6.950006423363*_Complex_I, 8.717234868692 + -32.148462751388*_Complex_I, 7.386347991900 + 3.651733560911*_Complex_I, -12.562312227509 + 3.070991373115*_Complex_I, -0.069804711953 + 1.802309211709*_Complex_I, 1.176122484348 + -14.149959691947*_Complex_I, 5.353573748142 + 0.564676076929*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_157.c000066400000000000000000000411161317124540100215210ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 157-point transform // #include float complex fft_test_x157[] = { 0.257182749425 + 0.221924222343*_Complex_I, 1.678933476985 + 1.690438801569*_Complex_I, -0.370453539748 + -0.279443271284*_Complex_I, -0.425568170028 + -0.346884537719*_Complex_I, 0.025131704106 + 0.368626953376*_Complex_I, -0.013250700538 + 0.876875327290*_Complex_I, 0.935964221688 + -0.003996500003*_Complex_I, 0.697482794970 + 0.169890786221*_Complex_I, -0.672758751419 + -0.529033743727*_Complex_I, -0.103638614252 + 0.221443696028*_Complex_I, -0.365208618659 + -0.660189374984*_Complex_I, 0.148416173585 + -0.919145673704*_Complex_I, -0.015366679279 + -0.943544155661*_Complex_I, 1.622323455798 + 0.481254671673*_Complex_I, -0.438594792675 + 0.487727000762*_Complex_I, 1.590594341984 + -0.549613288902*_Complex_I, -0.917184623744 + -2.221026339765*_Complex_I, -1.617744928538 + 1.593484682047*_Complex_I, -0.989508283152 + -0.094108203222*_Complex_I, 0.852090994091 + -2.231080010685*_Complex_I, -0.400903430450 + -0.366248303051*_Complex_I, -0.125211983197 + -1.455734382818*_Complex_I, 1.947225389836 + 0.980175860892*_Complex_I, -1.398014729095 + 0.014318572276*_Complex_I, -0.771114386583 + 0.544211573481*_Complex_I, 0.126434853618 + -0.465319924891*_Complex_I, 0.952552119580 + 2.799409645314*_Complex_I, 0.745539772546 + 0.038782344125*_Complex_I, 0.629464449611 + -1.544746925900*_Complex_I, -1.430974620188 + -1.148543279148*_Complex_I, -0.550191215098 + -1.044145048363*_Complex_I, -0.616171694097 + -1.252745889547*_Complex_I, 0.988808988108 + -1.602725943935*_Complex_I, -0.607710796313 + 0.518971475013*_Complex_I, 0.771090806997 + -0.385515422626*_Complex_I, 0.825512088357 + 0.474459769075*_Complex_I, -0.291745809631 + -0.149808656805*_Complex_I, -1.958415654055 + 0.651147959844*_Complex_I, -0.778182389479 + -0.780881485990*_Complex_I, -2.015821535479 + -0.050499463828*_Complex_I, 0.887353255055 + -1.214230826942*_Complex_I, -0.096317891587 + 0.761206139060*_Complex_I, -1.062009284735 + -0.271266211836*_Complex_I, 1.423990266183 + 1.335814455222*_Complex_I, -0.847479948365 + 2.671530186606*_Complex_I, -1.345728311726 + -0.634481496676*_Complex_I, -0.797816703427 + 0.502757855534*_Complex_I, -0.464673266498 + 0.116721201943*_Complex_I, 0.203062847770 + 0.561494795746*_Complex_I, 0.033909266352 + -0.261380019453*_Complex_I, -0.658056423237 + 1.281296865326*_Complex_I, 0.941736081602 + 1.987602839317*_Complex_I, -0.423846356775 + -1.241587960307*_Complex_I, -0.393324168712 + 0.737043249313*_Complex_I, -1.944403782443 + -0.943905358441*_Complex_I, -0.528242253913 + 1.908236422266*_Complex_I, 1.452295322067 + -0.869099055081*_Complex_I, -1.120053624869 + 0.850800785935*_Complex_I, 0.365006117743 + -0.347073388222*_Complex_I, -1.980724188697 + 1.747266666168*_Complex_I, 1.558965406397 + 0.725116188824*_Complex_I, -1.050340476177 + 0.477386287145*_Complex_I, 0.078299549695 + -1.166209184146*_Complex_I, 0.666177598254 + -1.881539760701*_Complex_I, -0.553008717374 + 0.112063233224*_Complex_I, -1.542438669400 + -0.905459946121*_Complex_I, -0.540183077595 + -0.653405677927*_Complex_I, 0.093096056538 + 1.658838310544*_Complex_I, -0.070743442866 + -0.474238998458*_Complex_I, -1.057268947675 + 0.965366634327*_Complex_I, -0.084404481306 + 0.516458044167*_Complex_I, 0.415540467796 + -0.571894574983*_Complex_I, -0.495234089660 + 0.103235766156*_Complex_I, 0.464768365021 + 0.651070663181*_Complex_I, -1.478301866530 + -1.246265840883*_Complex_I, -0.810080291321 + -0.090687751615*_Complex_I, 1.597727768491 + -1.303542260713*_Complex_I, 0.899193648643 + 0.101515082173*_Complex_I, -1.275261212066 + -1.670150745367*_Complex_I, -0.067477528818 + 0.082676448878*_Complex_I, -0.593487795772 + 1.015383261914*_Complex_I, -0.195143706875 + 0.197795648282*_Complex_I, 1.470101318427 + -1.090920995443*_Complex_I, 3.099635934834 + 0.418783664178*_Complex_I, 0.517928899798 + -0.515604023095*_Complex_I, -0.699637334030 + 0.411968031541*_Complex_I, 0.238527504044 + -1.024932943805*_Complex_I, 1.067350706566 + -1.185403362126*_Complex_I, 1.013271318338 + 0.881471326676*_Complex_I, 0.004430604182 + -0.799775043761*_Complex_I, 0.351524389294 + 0.780435439706*_Complex_I, 0.106334238498 + 0.458736063427*_Complex_I, -0.008723581305 + 2.334855897709*_Complex_I, -0.486030470423 + -0.237085023857*_Complex_I, -0.752315645429 + 0.905584767839*_Complex_I, -0.578103821311 + 1.125629982729*_Complex_I, -0.948197773007 + -0.457632138151*_Complex_I, 0.742229639059 + 0.271160961106*_Complex_I, -0.773931821655 + -0.314444247010*_Complex_I, -1.490298210738 + 0.035980837847*_Complex_I, 0.199618338445 + 0.632691460449*_Complex_I, -0.234261424994 + -1.443456519632*_Complex_I, 0.463236279099 + 0.303140551137*_Complex_I, 0.292524617190 + -0.043026971072*_Complex_I, 0.046692677937 + 1.116783220186*_Complex_I, -1.861132210698 + 0.261380583838*_Complex_I, -0.341148975896 + -0.470343064889*_Complex_I, -0.671470989909 + 0.007947245970*_Complex_I, -0.534160841208 + -0.124549058301*_Complex_I, 0.487094311512 + -0.314353890072*_Complex_I, -0.403442115448 + -0.857412221358*_Complex_I, 1.085529198882 + -0.386892824664*_Complex_I, 0.591555113309 + 0.384947041491*_Complex_I, -0.516471791207 + -0.646903850947*_Complex_I, -0.216099520865 + 0.030923700983*_Complex_I, -2.362722198570 + 2.187609191074*_Complex_I, -2.996234948353 + 1.169329942024*_Complex_I, 0.398987017180 + 1.432369958192*_Complex_I, -0.321543239403 + -1.079202616493*_Complex_I, 0.155932087142 + 0.283226593654*_Complex_I, -0.149566717019 + 2.000037448099*_Complex_I, -0.505275327391 + -0.592114971901*_Complex_I, 0.712863240336 + -0.919212613392*_Complex_I, 2.561694455976 + -0.315857229465*_Complex_I, -0.401098664528 + -1.414850199386*_Complex_I, 1.068811040362 + -0.520713203914*_Complex_I, -0.928756706401 + -1.036472849545*_Complex_I, 0.731918541008 + 2.246056257734*_Complex_I, -1.087622423230 + -1.271134991425*_Complex_I, 0.747682565630 + 1.167376255945*_Complex_I, 0.823139516666 + 0.417274248065*_Complex_I, 0.488604293527 + -0.768657162242*_Complex_I, -1.566207330521 + -0.520510590335*_Complex_I, 0.286432330277 + -0.603250643993*_Complex_I, 0.685025047143 + -0.939995698866*_Complex_I, 0.955471389243 + -0.323428744209*_Complex_I, -1.169027438782 + -0.175653814544*_Complex_I, -0.284005159687 + 0.460772145706*_Complex_I, -0.310159212214 + -1.720418494846*_Complex_I, 0.305232638909 + -0.090314073904*_Complex_I, 0.190795117789 + -0.467619419555*_Complex_I, -0.905744042954 + -1.143116395802*_Complex_I, 0.392128587570 + 2.286798561832*_Complex_I, -1.315880319405 + -1.432434182558*_Complex_I, 1.007683317172 + -0.154461360928*_Complex_I, 0.474642520199 + 0.729416858430*_Complex_I, -0.679375823140 + -2.856682284668*_Complex_I, -0.687426016158 + -1.023213289303*_Complex_I, -0.022785229613 + 0.698739170753*_Complex_I, -0.643221050022 + 1.444057111513*_Complex_I, 0.149585673645 + -0.602773170360*_Complex_I, 0.389853409146 + -0.949003645210*_Complex_I, -1.115251553217 + -0.405311422912*_Complex_I, 0.228569355271 + -0.486849085232*_Complex_I, -0.140823347089 + -0.328067722810*_Complex_I, 1.388787822068 + -2.267147899079*_Complex_I, 0.939124099904 + -0.563609820499*_Complex_I}; float complex fft_test_y157[] = { -13.721520175468 + -9.568907767571*_Complex_I, 8.721468524756 + -10.198063416643*_Complex_I, 15.060716782723 + -14.846901712846*_Complex_I, -11.623905596583 + 16.650835292293*_Complex_I, 19.695072317931 + -11.298461808236*_Complex_I, 1.838122765692 + 7.179001252206*_Complex_I, 8.145195639028 + -10.634659386087*_Complex_I, 13.033783220459 + 19.061682407788*_Complex_I, -3.959970595745 + -7.333783752376*_Complex_I, 17.086993536942 + -6.079044767515*_Complex_I, 10.491053572778 + -4.514192461667*_Complex_I, 6.064025221921 + 10.332579887094*_Complex_I, -3.762638600928 + 10.624543304629*_Complex_I, -1.847856432273 + -8.006182372781*_Complex_I, 41.710087074031 + 2.242012124979*_Complex_I, 8.362552928082 + -0.431571425998*_Complex_I, -2.684280607792 + -19.646530227003*_Complex_I, -5.355855356382 + -4.457469415514*_Complex_I, -7.411106913072 + 24.950544746191*_Complex_I, 16.058416814462 + 7.398904353701*_Complex_I, 4.287192732400 + -11.227843680234*_Complex_I, -1.117925486982 + 24.330611594547*_Complex_I, 3.444591991920 + 32.326680862100*_Complex_I, 17.351475510592 + -7.023399927552*_Complex_I, -0.243462815765 + 5.525094059061*_Complex_I, 1.824464191173 + -10.437625350692*_Complex_I, 0.863195259259 + 8.286510583962*_Complex_I, -2.958971801726 + -14.975362935027*_Complex_I, 9.706578069666 + 2.274491450388*_Complex_I, 18.904225667531 + 9.156322125243*_Complex_I, 1.847919083204 + 22.188095024380*_Complex_I, -4.136288117963 + -22.092021747680*_Complex_I, 4.703234992916 + 0.532501901615*_Complex_I, -3.030532632664 + -11.313921121067*_Complex_I, 1.091146775351 + 7.577427645200*_Complex_I, 3.975634530789 + 10.604839429746*_Complex_I, 12.752600166339 + 7.600696307234*_Complex_I, 15.977675567158 + 16.362460714763*_Complex_I, -0.020172843559 + 3.858168994446*_Complex_I, -14.397449821557 + 12.915383581435*_Complex_I, 15.101543348628 + -23.907576345828*_Complex_I, -1.954273280892 + 13.597214533352*_Complex_I, -8.025138226552 + 3.693906127107*_Complex_I, -10.663001711599 + 11.720999651550*_Complex_I, -1.917368345264 + -19.036649221044*_Complex_I, 4.152821868650 + -8.488773546805*_Complex_I, -24.343188706355 + -10.538612575861*_Complex_I, 12.414685926300 + 16.068084980361*_Complex_I, 2.673733474235 + -8.293379374130*_Complex_I, 9.339757855123 + 0.779105093141*_Complex_I, 34.385020257627 + -8.910778839680*_Complex_I, 13.686080719584 + -2.468581114278*_Complex_I, -0.105352104096 + -7.123485160682*_Complex_I, -26.981218401390 + 13.727259016390*_Complex_I, -6.504207057579 + 3.268522185903*_Complex_I, 7.577558748754 + 2.965812787302*_Complex_I, -22.926267985360 + 4.630017422388*_Complex_I, -8.347022143339 + 1.975527870103*_Complex_I, 3.060029390078 + -21.656262254959*_Complex_I, 9.637126253972 + -7.538708825218*_Complex_I, -13.130853679756 + -18.805264312027*_Complex_I, -16.821204438708 + 4.950740394033*_Complex_I, 22.988677066759 + -1.571260161915*_Complex_I, 1.406205876954 + 12.062599478139*_Complex_I, -28.514716646160 + 7.993271146497*_Complex_I, -0.907689305572 + 0.456303536916*_Complex_I, -3.571030267866 + -4.518597998420*_Complex_I, -11.957457146313 + -19.766437913007*_Complex_I, -5.413654003898 + -1.754632161022*_Complex_I, -9.175989023330 + -7.046783981905*_Complex_I, -4.258428526498 + -16.319730685668*_Complex_I, -8.132160224937 + -1.537755723079*_Complex_I, 15.156793468505 + 10.343087291076*_Complex_I, 25.761505476002 + 3.887909686471*_Complex_I, 21.853951697775 + -12.770771455381*_Complex_I, -14.242421455518 + 2.407693112009*_Complex_I, -13.467445303389 + -29.036488998230*_Complex_I, -9.305071893547 + 2.506212475888*_Complex_I, 22.323867850705 + -4.075769716056*_Complex_I, -5.679643000649 + -3.670620943265*_Complex_I, -13.769169134408 + 13.834529429033*_Complex_I, -12.414956903750 + -16.194735699494*_Complex_I, -2.005403979995 + -11.362528318332*_Complex_I, 7.730155179299 + 9.255875770335*_Complex_I, 15.051941677947 + -3.828126836044*_Complex_I, -21.086873877673 + 12.717384691065*_Complex_I, 22.428970474249 + 14.741806815196*_Complex_I, 2.480130753861 + -23.039122194478*_Complex_I, -10.903771391849 + -13.412743738585*_Complex_I, 6.147006915635 + 13.690721935985*_Complex_I, -20.616357511746 + -17.845769868478*_Complex_I, -8.402987902554 + 3.410410123270*_Complex_I, 10.582061652995 + 4.348210154826*_Complex_I, 15.024788596168 + -5.782083339001*_Complex_I, 8.689851678442 + 35.535383742654*_Complex_I, -4.132601952228 + -0.321739745032*_Complex_I, -19.197163106392 + 3.413027621621*_Complex_I, -5.794327856223 + -7.331102283615*_Complex_I, -6.543417534351 + -1.677934031582*_Complex_I, 7.329352169488 + -4.324029036611*_Complex_I, -25.477673544286 + -10.789721951286*_Complex_I, -0.912644707297 + -9.637940446228*_Complex_I, 4.037691841333 + 3.096945310047*_Complex_I, -5.847674330905 + 13.938407689472*_Complex_I, 10.812159378022 + 2.497873869651*_Complex_I, 5.034733833406 + 20.614345199846*_Complex_I, 9.197163204775 + 3.499527690970*_Complex_I, -11.061382406800 + 3.269075618163*_Complex_I, -2.869327440190 + -17.824719429904*_Complex_I, -16.473833296088 + -7.487202778068*_Complex_I, 6.310496423938 + 5.004751989728*_Complex_I, -6.079010956757 + 18.024756582815*_Complex_I, -4.356220575254 + -2.205381751597*_Complex_I, -8.493558121870 + -3.869308590719*_Complex_I, 7.159973070917 + 6.849733506562*_Complex_I, 17.405411913875 + -3.643915205170*_Complex_I, 1.342183355448 + 0.252403128806*_Complex_I, 2.470554720768 + 3.325864954849*_Complex_I, 3.304540368971 + -7.701906570289*_Complex_I, -41.203455184368 + 12.817592975767*_Complex_I, -20.058954711820 + 19.878752053751*_Complex_I, 9.046175416813 + 11.732938261288*_Complex_I, -0.786044861883 + 17.615815760165*_Complex_I, -3.027566374297 + 11.824558467687*_Complex_I, -3.793394817088 + 4.309384254386*_Complex_I, -15.395453276032 + -6.476272377854*_Complex_I, 2.993318695808 + 20.818567190739*_Complex_I, -21.109827170023 + -18.433989642597*_Complex_I, -7.427193578999 + -4.496310454720*_Complex_I, 13.462176439125 + -14.456554646582*_Complex_I, 2.860309865551 + 0.813195406900*_Complex_I, -16.705039250487 + 5.416257334069*_Complex_I, 12.149530796231 + 5.677739145239*_Complex_I, 10.883522142352 + -2.048976821145*_Complex_I, 33.919769198703 + 14.546697989253*_Complex_I, -0.080428049883 + -5.729314964055*_Complex_I, -1.382967825489 + -0.843240827862*_Complex_I, -14.258739687335 + -4.164415134916*_Complex_I, -11.232537602109 + 13.450368521399*_Complex_I, 6.475674985073 + -6.229640995099*_Complex_I, 9.211806090883 + -7.267971548561*_Complex_I, -14.365301190661 + 8.987964911736*_Complex_I, -11.266093935597 + -15.954781116216*_Complex_I, -18.499836430748 + -8.923649916614*_Complex_I, 31.090884321227 + 2.260100309627*_Complex_I, -7.383545212516 + 10.553116472713*_Complex_I, 1.165337529929 + -1.083672004639*_Complex_I, 1.026784219611 + -16.203749347621*_Complex_I, -0.529416311921 + -8.707703034115*_Complex_I, -9.657893357311 + 12.096083541637*_Complex_I, -15.285477594802 + 4.224467463110*_Complex_I, 16.595393096965 + 1.232758856522*_Complex_I, 10.380238903621 + -5.473695910884*_Complex_I, -5.199124871644 + 14.427071924858*_Complex_I, -10.919624558299 + 16.105413828801*_Complex_I, 15.081167155045 + -6.737986374676*_Complex_I, 5.602666437487 + -19.846630500695*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_16.c000066400000000000000000000054671317124540100214440ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 16-point transform // #include float complex fft_test_x16[] = { -1.772146047027 + 0.295934658602*_Complex_I, -1.433777343858 + -0.874041962217*_Complex_I, -0.388629405392 + 0.611030474954*_Complex_I, -0.492539890742 + 1.007726724574*_Complex_I, 0.494699992643 + -1.725668238103*_Complex_I, 0.572982289851 + 0.061642401846*_Complex_I, -0.574974496567 + 0.909843544187*_Complex_I, 0.733687565510 + 0.447433079732*_Complex_I, 0.308242485351 + -1.532252262483*_Complex_I, 1.207949830231 + -0.953543898451*_Complex_I, 0.640048909719 + -1.022371047059*_Complex_I, -0.241879356643 + -0.462432765300*_Complex_I, -0.435900183311 + 0.856847254979*_Complex_I, 0.577243720893 + 0.220786650383*_Complex_I, 1.263302572543 + 1.444493924498*_Complex_I, 1.911070541506 + -1.906912076526*_Complex_I}; float complex fft_test_y16[] = { 2.369381184706 + -2.621483536381*_Complex_I, -2.618054253504 + 4.676728363894*_Complex_I, -2.946376269367 + 0.522273546089*_Complex_I, 2.120729100677 + 4.308004588255*_Complex_I, -2.975823103566 + -3.062195121072*_Complex_I, -3.932696300262 + 3.143967424649*_Complex_I, -0.247865075327 + 5.467645213372*_Complex_I, 3.887448941709 + 5.439788616063*_Complex_I, -3.300093528791 + 2.297200155534*_Complex_I, -4.008939493163 + 4.239020717646*_Complex_I, -5.630386554230 + -0.383449644305*_Complex_I, -0.707551950987 + 2.197968388714*_Complex_I, -1.713879561730 + -5.034075846097*_Complex_I, -8.091926054909 + -8.469369525668*_Complex_I, 2.733814414891 + -7.076455598181*_Complex_I, -3.292118248586 + -0.910613204873*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_17.c000066400000000000000000000056331317124540100214400ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 17-point transform // #include float complex fft_test_x17[] = { -0.655587921776 + -0.863886550358*_Complex_I, -1.070139919529 + -2.370656605854*_Complex_I, 1.167384281127 + 0.116747569575*_Complex_I, 1.105640858428 + -1.226141009276*_Complex_I, -0.349562744440 + -0.005953723423*_Complex_I, 0.655312446998 + 1.594642817084*_Complex_I, -0.230495501721 + -0.272806523691*_Complex_I, 0.731764183318 + -0.732380509571*_Complex_I, -0.953609619255 + 1.102615917395*_Complex_I, -0.496898865182 + -1.822920499315*_Complex_I, -2.052948327746 + -0.382334768518*_Complex_I, 1.062783811112 + 0.673250838256*_Complex_I, -0.142175503751 + 0.542432325176*_Complex_I, 1.108087524611 + -0.029888173999*_Complex_I, -0.164259605567 + -1.184782100304*_Complex_I, -0.236452649938 + -0.998080495482*_Complex_I, -0.197908967423 + -0.229518503722*_Complex_I}; float complex fft_test_y17[] = { -0.719066520735 + -6.089659996026*_Complex_I, 1.821427336790 + -5.621144218242*_Complex_I, -6.173678834923 + -4.525807530343*_Complex_I, -1.549626337288 + 0.314087328771*_Complex_I, -5.136370472539 + 4.327372264632*_Complex_I, -0.105170126419 + -2.207231016009*_Complex_I, -5.750228396460 + 3.094152945701*_Complex_I, 0.618725077794 + 3.278602823446*_Complex_I, -0.888646366224 + -3.887677672776*_Complex_I, 3.905822192802 + 7.933139073811*_Complex_I, -1.522365359136 + 0.172605279098*_Complex_I, 8.552784050577 + -3.105361200836*_Complex_I, -1.598265822441 + -5.532288727983*_Complex_I, 1.151099028128 + -2.046469788513*_Complex_I, 0.253410312032 + 6.386316111258*_Complex_I, -4.676752932337 + -4.421634395132*_Complex_I, 0.671908500186 + -2.755072636947*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_192.c000066400000000000000000000477721317124540100215360ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 192-point transform // #include float complex fft_test_x192[] = { -0.570749076040 + 1.623496753738*_Complex_I, -0.801441214588 + -0.237768079755*_Complex_I, -1.136144657269 + 0.367681411439*_Complex_I, -0.021881616373 + -1.310767380444*_Complex_I, -1.897076967315 + -0.151633764169*_Complex_I, -0.065089420065 + 0.179240807290*_Complex_I, -0.459561140285 + 0.186362705450*_Complex_I, -1.459184572831 + -0.172507317719*_Complex_I, 0.768770035801 + -0.603405455907*_Complex_I, -0.445592790811 + -0.545504111400*_Complex_I, -1.133095461256 + 0.347109313928*_Complex_I, 0.680343842697 + 0.984380778227*_Complex_I, 1.434274246060 + -0.455280274247*_Complex_I, 1.367719846389 + -0.017753112833*_Complex_I, -1.036796157162 + 0.202926093122*_Complex_I, -0.608495290895 + 1.377505175242*_Complex_I, 0.677352983170 + 0.522913747818*_Complex_I, 0.829598919707 + -0.238489026179*_Complex_I, 1.658006740638 + 1.321959544651*_Complex_I, -1.813019197848 + -1.379543844064*_Complex_I, -0.105360926209 + 0.770250719958*_Complex_I, 0.950326938828 + -0.839058539588*_Complex_I, 1.158809729841 + -0.647245275247*_Complex_I, -0.360439558788 + -0.056522073112*_Complex_I, -0.729658576111 + -0.230389217591*_Complex_I, -0.147264114233 + -0.844995936147*_Complex_I, 3.006061814772 + 0.324561093094*_Complex_I, 0.421672171136 + -1.045335631843*_Complex_I, 1.450421276223 + -1.809661507608*_Complex_I, 0.112589736618 + -0.680553655537*_Complex_I, -0.962866997971 + 0.051225992580*_Complex_I, -0.069473575656 + 0.412572221634*_Complex_I, 0.807441882459 + -0.390366883673*_Complex_I, 0.494922478167 + 0.666273714397*_Complex_I, 0.534063543949 + 0.216473899855*_Complex_I, 0.115686515954 + -1.150016410968*_Complex_I, -0.911950154175 + -1.906708901788*_Complex_I, 0.035013270272 + 1.560677880077*_Complex_I, -0.689521651706 + -0.963904151064*_Complex_I, -1.140202975221 + -0.076069898430*_Complex_I, -0.246077937761 + 0.616853881528*_Complex_I, -0.251792408901 + -0.385289165959*_Complex_I, 0.144732608298 + -0.544232656456*_Complex_I, 0.716079834835 + 0.154716467884*_Complex_I, -0.454600091317 + -0.778823717821*_Complex_I, -0.004009391933 + 0.239803231190*_Complex_I, 0.128608781578 + 0.252750485610*_Complex_I, -0.104121384913 + -1.189000295448*_Complex_I, 0.242846644961 + 0.081301007736*_Complex_I, 1.450965500668 + 0.361778385840*_Complex_I, -0.190106534680 + 0.071804478293*_Complex_I, 0.420793349874 + 1.491145034929*_Complex_I, 2.460108883286 + 0.757779280601*_Complex_I, -0.825692579645 + -0.596573882891*_Complex_I, 0.671589132843 + 1.011087599399*_Complex_I, 1.284648906257 + -0.045814861627*_Complex_I, -0.760224555847 + -0.722324468953*_Complex_I, -1.322063665211 + -2.308468943382*_Complex_I, 2.293407378555 + 0.010203054084*_Complex_I, 0.055649061121 + -2.002674185757*_Complex_I, -0.282775998354 + -1.935193634195*_Complex_I, 1.737107472308 + -1.107578165456*_Complex_I, -0.235741548678 + -0.486998315145*_Complex_I, -0.270131100153 + -2.340452003512*_Complex_I, -1.145976320980 + 1.671478612533*_Complex_I, 1.046314822557 + 0.182117686556*_Complex_I, -0.745497599782 + -0.723373842151*_Complex_I, -0.511430521736 + -0.669552224448*_Complex_I, 0.619398807961 + -0.051926233859*_Complex_I, 0.650768664429 + -0.054337533084*_Complex_I, -0.377066273366 + 0.748578490695*_Complex_I, 0.868445500849 + -1.916678793529*_Complex_I, -0.745634363305 + 2.968322096526*_Complex_I, 1.601642204548 + -1.815842464572*_Complex_I, -0.110280900762 + -0.375012568050*_Complex_I, 1.082989689805 + 0.615940836645*_Complex_I, 0.285506402216 + 0.273198983697*_Complex_I, 0.277214797147 + 1.771337438831*_Complex_I, 0.165028606876 + -0.704451808040*_Complex_I, 0.317894159247 + 0.492665087928*_Complex_I, 0.601574563612 + -0.904521376193*_Complex_I, -0.642798244158 + 0.327271328047*_Complex_I, 0.011482342139 + -0.787115819239*_Complex_I, 0.244096373806 + 0.152569770967*_Complex_I, 0.178980665283 + 0.813856965670*_Complex_I, 1.492787787643 + -0.413137630323*_Complex_I, -1.122949408956 + -0.730572761342*_Complex_I, 0.096736426284 + -0.623125567869*_Complex_I, -0.054054998356 + 0.102181208006*_Complex_I, 0.016144101863 + -0.139709667178*_Complex_I, 1.323423360215 + -1.218385808067*_Complex_I, 1.225801036168 + 1.825795241395*_Complex_I, 1.773877495557 + 0.364293281834*_Complex_I, -1.266134039437 + 0.099487732018*_Complex_I, -0.417581296163 + 0.343715046363*_Complex_I, 0.505757022167 + -0.500849213570*_Complex_I, 0.968334906502 + -0.526257684744*_Complex_I, 0.333143774360 + 0.396107354791*_Complex_I, -0.506358896777 + -0.087644984012*_Complex_I, 1.324525846569 + 1.494077333636*_Complex_I, -0.951951460363 + 0.994211347018*_Complex_I, -2.692462733023 + -0.697601652243*_Complex_I, -1.072637853655 + 1.879429345687*_Complex_I, -0.193163794476 + 1.344807479696*_Complex_I, -0.036468538711 + -2.246890819337*_Complex_I, 0.123890932473 + -1.171359056597*_Complex_I, 1.614167761632 + -0.084861961160*_Complex_I, 0.813475153805 + -1.363244160675*_Complex_I, -0.751043379055 + -0.001003534113*_Complex_I, -1.127244933655 + 0.033479567244*_Complex_I, 0.120947403072 + 0.172712059551*_Complex_I, -0.650772252959 + 1.321513948454*_Complex_I, 1.305164416475 + -0.787832375788*_Complex_I, -0.312608725354 + -0.233463073219*_Complex_I, -0.754485246213 + -0.132782409884*_Complex_I, 1.522953329225 + 0.109222954313*_Complex_I, -0.495952414190 + 0.544687157445*_Complex_I, 0.506640354547 + -1.676292292327*_Complex_I, 0.495984603346 + 0.705582611126*_Complex_I, 0.555362258234 + 1.175515543993*_Complex_I, -1.380515094250 + 0.427692852149*_Complex_I, 0.003538138035 + 1.425908489255*_Complex_I, 1.062943493718 + 1.079328766594*_Complex_I, 0.035769210794 + 0.546944179639*_Complex_I, -1.009393498146 + -0.836699998466*_Complex_I, -1.299667858035 + -1.876603335383*_Complex_I, 1.400213634255 + -1.094331065468*_Complex_I, -0.978532602360 + -1.133768146514*_Complex_I, -0.126022453004 + -0.548218141207*_Complex_I, -0.459386774097 + -1.142543752432*_Complex_I, -0.634282978000 + 0.401478043588*_Complex_I, 0.536619631169 + -0.637851111890*_Complex_I, -2.177417556650 + -0.582755642600*_Complex_I, 1.956859485192 + 0.756502126757*_Complex_I, -1.033248608338 + 0.083674820018*_Complex_I, 0.361227297522 + 0.246987978580*_Complex_I, 0.200321461901 + 0.997822511718*_Complex_I, -1.130355402825 + -0.097176654080*_Complex_I, 1.384768698791 + -0.772817911874*_Complex_I, 0.926525539860 + 0.145277765291*_Complex_I, -0.540081956252 + 0.372734113022*_Complex_I, 0.327046375183 + 1.452638689757*_Complex_I, -0.402162597503 + -0.571759031309*_Complex_I, 1.213886497238 + 0.862378057918*_Complex_I, -0.024799349445 + -0.640880433466*_Complex_I, 0.605895117723 + 1.040856615204*_Complex_I, 0.875424648817 + -1.747168830682*_Complex_I, 1.792252094005 + 1.449436965826*_Complex_I, -0.058686051876 + 0.024079540685*_Complex_I, -1.197793455172 + 0.076528126740*_Complex_I, -1.451475019825 + 2.506331331519*_Complex_I, 0.115177207244 + 0.581887944455*_Complex_I, -0.894760295667 + 0.941285480086*_Complex_I, 0.167847546335 + 0.113650691315*_Complex_I, 0.580138910850 + 1.482400230136*_Complex_I, -0.638693285492 + 0.706252192544*_Complex_I, -0.679198255352 + -0.864392741247*_Complex_I, 0.309224287292 + 0.802306837308*_Complex_I, 0.089371278986 + -1.059876744659*_Complex_I, 1.352756771804 + -0.303374747952*_Complex_I, 0.142478845463 + 1.679379378038*_Complex_I, -0.307104681980 + -1.525241010787*_Complex_I, 0.947136026136 + -0.176290475474*_Complex_I, -0.191221819400 + 0.872369793925*_Complex_I, -0.694209420142 + 0.251537117440*_Complex_I, 1.193931121456 + 0.364438121717*_Complex_I, 0.364530798418 + 0.953151437736*_Complex_I, -2.204969193002 + 0.591100538765*_Complex_I, 1.152638435048 + 0.423855010290*_Complex_I, -0.190087319373 + -0.236280077579*_Complex_I, -0.959025701481 + -1.046604614844*_Complex_I, -0.059036610250 + 0.757806508323*_Complex_I, 1.193828263334 + 0.991816149312*_Complex_I, -0.644717162130 + 0.685130498159*_Complex_I, 0.386929662859 + 0.246269623980*_Complex_I, 0.747830541986 + -0.853860497506*_Complex_I, 0.563215051840 + -1.553462734011*_Complex_I, -0.411175328612 + 0.338710437150*_Complex_I, -1.017739241999 + -0.234632452129*_Complex_I, -2.270318833952 + 0.624001888473*_Complex_I, 0.530109233459 + -3.021054334701*_Complex_I, -0.733212401282 + 0.337380481817*_Complex_I, 0.686400469100 + 1.434988023046*_Complex_I, -1.537557685024 + 0.266727612837*_Complex_I, 2.377907246279 + -0.647849557308*_Complex_I, 1.588677766399 + -0.611004042543*_Complex_I, 0.547569751159 + -0.942144527428*_Complex_I, -0.489770632777 + -1.190329237689*_Complex_I, -0.588811442748 + 1.025069940138*_Complex_I, -0.380574882230 + -1.193424193517*_Complex_I, -2.719012193329 + -0.412270955448*_Complex_I, 1.447794971270 + 0.160429136252*_Complex_I}; float complex fft_test_y192[] = { 11.637079481157 + -8.771861743960*_Complex_I, -26.395324212554 + -12.523034709229*_Complex_I, -13.199274560613 + 4.197128353434*_Complex_I, 2.770319150971 + -22.367461652042*_Complex_I, 0.642915300037 + 6.363791329048*_Complex_I, -1.448465724858 + 11.100404880196*_Complex_I, -6.231101627932 + -0.711426629573*_Complex_I, 6.572370237538 + -9.008077010635*_Complex_I, 7.543400860435 + 28.757508480923*_Complex_I, -17.693058117854 + -14.497870123296*_Complex_I, -18.350699894294 + 19.700720310742*_Complex_I, -22.388250522169 + 7.667843634853*_Complex_I, 14.220360999832 + 11.088627215515*_Complex_I, 14.686986747880 + 4.769183572180*_Complex_I, -16.224161466491 + 18.657410968166*_Complex_I, -5.561225898629 + 0.059313803898*_Complex_I, 13.221567254519 + -8.899219750894*_Complex_I, -20.776362788232 + -12.895144971233*_Complex_I, 16.702761314442 + -1.206621684382*_Complex_I, 1.152218624052 + 10.429943215921*_Complex_I, 1.406407090905 + -25.487932735618*_Complex_I, 5.058858691359 + 14.007031493308*_Complex_I, 3.915927218401 + -3.143885706619*_Complex_I, 0.511679691204 + 7.640849778701*_Complex_I, -9.519895102966 + -18.415287292132*_Complex_I, 2.876304518596 + 20.969442045845*_Complex_I, 7.342107433201 + -12.347059316472*_Complex_I, -0.618433952859 + 25.041216941337*_Complex_I, 0.580421597502 + -14.237985250543*_Complex_I, 8.771852508251 + 0.733917062704*_Complex_I, 3.782207555074 + 16.248301038041*_Complex_I, -8.524579539709 + 9.295327847229*_Complex_I, -4.768100090762 + -10.116200145201*_Complex_I, 5.053774488844 + -2.415715341537*_Complex_I, 14.309532012096 + -0.424419688667*_Complex_I, 12.756379146573 + 5.032080306349*_Complex_I, 34.330424118154 + 10.117580842288*_Complex_I, -5.753681073486 + -1.411149381440*_Complex_I, 1.264859359146 + 4.528836925970*_Complex_I, -2.586666114372 + 13.851391335293*_Complex_I, -1.713098457415 + 20.890928009489*_Complex_I, -13.434363693601 + 24.394077211392*_Complex_I, -10.022671324009 + 17.664609245348*_Complex_I, -1.725934813257 + 1.891913667017*_Complex_I, 9.110355361482 + -0.179266402064*_Complex_I, -6.803970453739 + 1.078079859350*_Complex_I, 15.245357404619 + -16.002907380848*_Complex_I, 18.798658922559 + -8.909897678113*_Complex_I, -9.340116247154 + -1.125951004947*_Complex_I, 3.688509570515 + -32.689986273951*_Complex_I, 0.407888797988 + 12.869443175340*_Complex_I, 11.996274048535 + -2.662751606922*_Complex_I, 7.018158515976 + 28.262862824837*_Complex_I, 7.922722654625 + 14.250007388651*_Complex_I, 2.975237590008 + -10.603333565612*_Complex_I, 0.455653895495 + 1.453939650391*_Complex_I, -9.066906825176 + 25.796872875146*_Complex_I, -0.918183225634 + -10.468224002255*_Complex_I, -0.142851335912 + 22.780663054656*_Complex_I, 2.282086213671 + 29.891813625626*_Complex_I, 7.221536839959 + 7.770574674805*_Complex_I, -37.398067728397 + -1.105557754066*_Complex_I, -17.142633714292 + 6.118620955162*_Complex_I, -6.477664567284 + -7.690396365101*_Complex_I, 16.982767357512 + -18.131798098394*_Complex_I, 1.080785945291 + 16.906857138491*_Complex_I, 0.599451587747 + 26.081775902564*_Complex_I, -0.978816302785 + 5.925677319285*_Complex_I, 10.210787997091 + -9.910196007357*_Complex_I, -19.147402098057 + -2.498686289732*_Complex_I, 21.966256137493 + -22.859882129197*_Complex_I, -15.265643040019 + -4.426471861527*_Complex_I, 12.929479693820 + 22.330642231752*_Complex_I, 2.740221347659 + 24.061774049828*_Complex_I, -14.562401185320 + -19.628678597306*_Complex_I, 20.997689192967 + 5.792733814018*_Complex_I, 5.119546713501 + 3.964059886246*_Complex_I, -1.928221405609 + -6.512384434671*_Complex_I, -2.156293329162 + 7.753329775994*_Complex_I, -3.573953149890 + -9.239991326571*_Complex_I, -13.630949945730 + -8.106005746278*_Complex_I, 12.825262070728 + -4.660266138913*_Complex_I, -1.891349427851 + 9.400617516536*_Complex_I, -18.076150879307 + 22.373408216149*_Complex_I, -15.956268983268 + -21.975317374526*_Complex_I, 0.164201332756 + 24.388112510894*_Complex_I, -4.597078387934 + 7.039522987551*_Complex_I, -12.697120797033 + 9.467372419639*_Complex_I, 0.666493946055 + 16.398714904237*_Complex_I, 14.501434995333 + -1.201151824518*_Complex_I, -5.674281705139 + 5.888174371162*_Complex_I, -20.163201241601 + -1.818438322864*_Complex_I, -30.219423076971 + -13.719313314399*_Complex_I, -13.990403694826 + 2.714807784298*_Complex_I, 11.250768761115 + 3.628822569150*_Complex_I, -0.733728572049 + 2.948828784375*_Complex_I, -3.826671819253 + 4.571602216696*_Complex_I, 23.522991447544 + -2.821207413423*_Complex_I, 5.182638636295 + -2.280239804828*_Complex_I, -14.978530389737 + 34.007674915178*_Complex_I, 12.067946114665 + -7.231592873495*_Complex_I, -18.036308190888 + -1.167944458385*_Complex_I, -14.570445828147 + 33.703221498009*_Complex_I, -14.355007896334 + 8.624163479423*_Complex_I, -12.522417307559 + 2.964999959389*_Complex_I, 1.285831266251 + 17.486913574970*_Complex_I, -18.400444537057 + 10.275105944079*_Complex_I, -10.798107010917 + -9.398928074828*_Complex_I, -3.735870933695 + -3.928195596167*_Complex_I, -28.347786532915 + -4.087804201121*_Complex_I, 22.446246894740 + -3.314141727023*_Complex_I, -12.595391479166 + -20.525839403734*_Complex_I, -28.712938572605 + -6.003936755853*_Complex_I, 28.019514492138 + -30.082449455145*_Complex_I, -11.209466775921 + 26.443062244454*_Complex_I, 1.207579305184 + 15.519647647646*_Complex_I, -4.037012632720 + -7.499501325179*_Complex_I, 10.741743378262 + 10.026834979238*_Complex_I, 18.870849049565 + 11.960677218574*_Complex_I, 5.853418449079 + -7.462260554939*_Complex_I, 4.335224360674 + 3.129860437677*_Complex_I, 12.605242126520 + 4.554248036599*_Complex_I, -16.969702130369 + -29.534520407430*_Complex_I, -6.120705955107 + -4.482591730189*_Complex_I, -12.926535006552 + -1.874171675105*_Complex_I, 14.665201057893 + -1.128035925962*_Complex_I, 24.051538767781 + -15.958257482748*_Complex_I, 19.820057240718 + -22.152759047970*_Complex_I, -24.058042894391 + 13.729789221856*_Complex_I, 19.182753493650 + -1.045899761274*_Complex_I, 7.427878004795 + -14.645722900400*_Complex_I, 0.354829774210 + -28.351378771571*_Complex_I, -0.079617808212 + 3.973765307882*_Complex_I, -0.956500599215 + -15.489797280577*_Complex_I, 0.762491009085 + -25.453122941666*_Complex_I, -11.840853996701 + 12.962212817110*_Complex_I, 35.495866538641 + 9.686565151838*_Complex_I, -0.038469688004 + 4.392742866312*_Complex_I, -19.123338054473 + 2.775599118392*_Complex_I, -11.096274610813 + 9.852185716742*_Complex_I, 15.297635548840 + -11.871123303123*_Complex_I, -20.554975892285 + 3.876667437210*_Complex_I, 35.623881203832 + -7.111604836972*_Complex_I, -6.116783490647 + 6.858127980009*_Complex_I, 7.214111046309 + -6.503534651808*_Complex_I, 13.222866709925 + 14.222914198476*_Complex_I, 7.177684846410 + 4.449199979110*_Complex_I, 8.704887882540 + 13.440615520893*_Complex_I, 3.880333256992 + -21.379125009121*_Complex_I, 7.048477459126 + -5.798390953651*_Complex_I, -2.887754540526 + 0.926387706089*_Complex_I, -4.738508647891 + 1.592531834771*_Complex_I, -29.140442148645 + 1.326408413819*_Complex_I, -17.686809708344 + 9.306299214767*_Complex_I, -11.287941537086 + 18.573964519700*_Complex_I, -14.430331062949 + 20.500648002089*_Complex_I, 5.833514963456 + -0.787459203485*_Complex_I, 6.996874871331 + 4.372973087460*_Complex_I, 10.606258817386 + -15.371196814824*_Complex_I, 7.173199494850 + -3.739254103514*_Complex_I, 0.650868123207 + 1.129252104053*_Complex_I, 2.934818232673 + -15.452697731691*_Complex_I, 5.965230433753 + 25.063178506013*_Complex_I, 23.622843424435 + -9.618416072703*_Complex_I, 7.156185469219 + 3.585963809070*_Complex_I, -5.732158086481 + -13.452361329340*_Complex_I, -9.590479206366 + -9.053169128213*_Complex_I, 2.000269872570 + -9.513605072784*_Complex_I, 11.315627899677 + 22.817996942644*_Complex_I, 12.413894814140 + 13.626175038709*_Complex_I, 29.172874942325 + 1.484706508481*_Complex_I, 0.015766090270 + 4.368571218197*_Complex_I, 15.563774953007 + 4.894512943893*_Complex_I, -11.842691536265 + 35.592965762670*_Complex_I, -12.994473369362 + 2.698888313132*_Complex_I, 8.754669228150 + 11.235443005907*_Complex_I, -10.328265749913 + 2.323163803747*_Complex_I, -13.439572075998 + 13.889640848681*_Complex_I, -3.977518922953 + 0.690204512797*_Complex_I, -10.800653995412 + -6.554357023667*_Complex_I, -11.525124988298 + -20.660565069742*_Complex_I, 19.162721444200 + 9.408214211732*_Complex_I, -0.088361438150 + -0.665881998403*_Complex_I, -18.557501816859 + -12.065202621962*_Complex_I, 8.534483256201 + 9.270859667546*_Complex_I, 10.095451307996 + -11.066538969502*_Complex_I, -21.844145113512 + -28.094981179422*_Complex_I, -19.202996015641 + 7.054377546211*_Complex_I, -15.529186020599 + 7.476299951687*_Complex_I, -18.157842430552 + -5.316780213393*_Complex_I, -5.293208686973 + -3.663831551237*_Complex_I, 10.661425533836 + 11.243445036012*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_2.c000066400000000000000000000026741317124540100213540ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 2-point transform // #include float complex fft_test_x2[] = { -0.442695266914 + -1.176601139920*_Complex_I, 0.164300702210 + 0.941269951205*_Complex_I}; float complex fft_test_y2[] = { -0.278394564704 + -0.235331188715*_Complex_I, -0.606995969123 + -2.117871091124*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_20.c000066400000000000000000000063071317124540100214310ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 20-point transform // #include float complex fft_test_x20[] = { -0.138174469322 + -0.274748504122*_Complex_I, -1.227476709426 + 0.905279873773*_Complex_I, -0.940584818722 + -0.463678927507*_Complex_I, -0.327372793730 + 0.441537277752*_Complex_I, 0.086812488375 + 1.122322318862*_Complex_I, -0.100645730164 + -0.142102548176*_Complex_I, -0.339607323410 + -0.632982556339*_Complex_I, -1.122342071583 + -0.361529677196*_Complex_I, -0.394764118785 + 1.317868322379*_Complex_I, 0.885025645922 + 0.277662260330*_Complex_I, -0.937809434341 + -0.464711897028*_Complex_I, -0.316998490158 + 0.688777215432*_Complex_I, 0.649526607014 + 0.181558179235*_Complex_I, 0.780299241568 + -0.070192359053*_Complex_I, 1.932600474030 + -0.136400805574*_Complex_I, -0.216121187682 + -0.461249755715*_Complex_I, 0.926223942818 + -0.028529590209*_Complex_I, 1.602135289481 + 1.434596371731*_Complex_I, 1.623836928491 + -1.265873017618*_Complex_I, 1.568843067308 + -0.364404259258*_Complex_I}; float complex fft_test_y20[] = { 3.993406537683 + 1.703197921701*_Complex_I, 3.008874212687 + 7.663142996950*_Complex_I, -1.159042365700 + 3.282695683450*_Complex_I, 0.903124379379 + 1.428002755716*_Complex_I, -1.572075523393 + 4.283883169775*_Complex_I, 2.253301421641 + 2.928788716985*_Complex_I, 3.534976344610 + 2.383761115026*_Complex_I, 1.326813143543 + 3.111834244207*_Complex_I, -3.988701280111 + -0.677308408606*_Complex_I, -1.984004176890 + -4.401380983625*_Complex_I, 0.942714014611 + -2.993550877540*_Complex_I, 2.448617718798 + -1.195359461640*_Complex_I, -3.328697057289 + -4.221639306000*_Complex_I, 4.287827550431 + 1.139111429335*_Complex_I, -4.013398939947 + -0.677595378939*_Complex_I, -2.670924173537 + 7.635447143438*_Complex_I, -2.067686784436 + -7.802196902076*_Complex_I, -1.972088145081 + -6.957222482710*_Complex_I, -3.101333982661 + -2.675851028288*_Complex_I, 0.394807719219 + -9.452730429599*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_21.c000066400000000000000000000064531317124540100214340ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 21-point transform // #include float complex fft_test_x21[] = { -0.292459060095 + -0.918931582987*_Complex_I, -1.517033866291 + -0.323416256164*_Complex_I, -1.482752904272 + 0.244611310478*_Complex_I, 0.319915998225 + -0.315947516079*_Complex_I, -0.304653265396 + 1.887596128705*_Complex_I, 0.411043591735 + -0.374178478358*_Complex_I, 0.462233294747 + 0.181705549666*_Complex_I, -0.053584030277 + -1.645170622140*_Complex_I, -0.503521485275 + 0.734911625473*_Complex_I, -0.425967471739 + 0.316306288806*_Complex_I, 0.824866046500 + -0.830071277629*_Complex_I, 1.806337286696 + -0.766132673126*_Complex_I, 0.620721751355 + 0.965491952308*_Complex_I, -2.440640280723 + -0.836336433610*_Complex_I, -0.620347474921 + -1.385103078296*_Complex_I, -0.195316065403 + 0.051333260777*_Complex_I, -0.448853815719 + 1.473820485114*_Complex_I, 0.468718174491 + -0.133593056210*_Complex_I, -0.912579674279 + 0.093239456860*_Complex_I, -0.060107647935 + -1.182219308121*_Complex_I, -1.630393758159 + -1.763218511036*_Complex_I}; float complex fft_test_y21[] = { -5.974374656733 + -4.525302735571*_Complex_I, -3.602445825195 + -3.324518378407*_Complex_I, 1.072414517043 + -2.680697729601*_Complex_I, -2.544321267300 + -3.718686381182*_Complex_I, 7.073007677928 + -0.865187973747*_Complex_I, -4.293690988707 + 8.225140969655*_Complex_I, 6.571053045547 + -6.857090522238*_Complex_I, 4.072721192387 + 4.943421889232*_Complex_I, 0.156147391740 + -4.066681194313*_Complex_I, -0.307481517626 + -5.479113972476*_Complex_I, -3.514186056563 + 2.187768615743*_Complex_I, 6.761786041122 + 2.434424093260*_Complex_I, 6.161936098710 + 2.932845658178*_Complex_I, -0.983132976608 + 2.475188613552*_Complex_I, 0.631299782782 + 0.701473074392*_Complex_I, -0.667672994573 + -2.853889888582*_Complex_I, -1.447661658880 + 2.115483689466*_Complex_I, 4.415160634353 + 1.955631737971*_Complex_I, -10.003872665072 + -7.143199142087*_Complex_I, -2.863331203221 + -6.794540372208*_Complex_I, -6.854994833120 + 1.039966706231*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_22.c000066400000000000000000000066171317124540100214370ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 22-point transform // #include float complex fft_test_x22[] = { 1.005393906711 + 1.012308570546*_Complex_I, 1.688071880070 + 1.150240841419*_Complex_I, 0.683345289428 + -0.062623351865*_Complex_I, 0.155361503274 + -0.795786088580*_Complex_I, -1.820284248422 + 1.218801819999*_Complex_I, 0.628547514320 + -0.973049954879*_Complex_I, 1.065280228237 + 0.036573157841*_Complex_I, -2.060385212897 + 0.046192542979*_Complex_I, -1.013657698873 + 0.781474907362*_Complex_I, 0.375646814842 + 1.554324770487*_Complex_I, 0.891369658302 + -0.161096019710*_Complex_I, -1.068796361214 + 0.437936260633*_Complex_I, 2.551818984217 + -0.855823653619*_Complex_I, 1.902986665335 + 0.173617409071*_Complex_I, 0.782297326663 + 1.157416587734*_Complex_I, 1.408853663828 + -0.360396487397*_Complex_I, -1.133068299545 + 0.494376224047*_Complex_I, -0.644483632405 + -0.024946520734*_Complex_I, -1.906331676937 + 0.114276645380*_Complex_I, -0.607040125764 + 0.926527519920*_Complex_I, 0.405414441208 + 0.272172965895*_Complex_I, 0.522244149054 + 0.024648904750*_Complex_I}; float complex fft_test_y22[] = { 3.812584769431 + 6.167167051279*_Complex_I, -2.048551145080 + 1.920025824226*_Complex_I, 6.865239600362 + -6.254294174522*_Complex_I, 6.680188302485 + 7.175301698042*_Complex_I, 0.336985685391 + -2.472221525673*_Complex_I, 2.704578846644 + -1.072297553521*_Complex_I, -5.869735761695 + 0.406925054472*_Complex_I, 7.260505946731 + 4.415111182242*_Complex_I, 1.284910248555 + -1.935024971881*_Complex_I, 1.066939615916 + -8.084240769565*_Complex_I, -5.103441669518 + 4.459170611366*_Complex_I, -0.789428947455 + 1.848548655941*_Complex_I, -2.925771543223 + -0.333175332942*_Complex_I, 8.231473045218 + -1.322435498403*_Complex_I, -2.591866662060 + 5.216079561352*_Complex_I, -0.164183264077 + -4.464934113704*_Complex_I, -10.152302601435 + 2.776060476179*_Complex_I, -1.546651996340 + 8.030006620400*_Complex_I, 2.238990051464 + -2.081025590453*_Complex_I, 2.420796442681 + -1.572310054104*_Complex_I, 11.406980883199 + 10.003031983787*_Complex_I, -0.999573899550 + -0.554680582506*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_24.c000066400000000000000000000071271317124540100214360ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 24-point transform // #include float complex fft_test_x24[] = { -1.420307293620 + 0.936847943063*_Complex_I, -0.496969771953 + 0.590714565032*_Complex_I, -1.354677361467 + -2.010032405560*_Complex_I, -0.345483299359 + 0.404926987051*_Complex_I, 0.689486222452 + -0.768259750193*_Complex_I, -1.549641684121 + -0.858118594125*_Complex_I, 0.420175234777 + -0.280408837681*_Complex_I, -2.217262854791 + -0.375004631542*_Complex_I, -1.198653374297 + 0.900261122326*_Complex_I, 0.329725819477 + 0.014746627154*_Complex_I, 0.045545673584 + -0.712071131515*_Complex_I, -0.495265874931 + -0.922857927267*_Complex_I, 0.628733326629 + 0.643883091672*_Complex_I, 0.331696680042 + -1.105791987558*_Complex_I, 0.515399107713 + -0.438177945625*_Complex_I, 0.183533661425 + -0.031372217136*_Complex_I, -0.276753781687 + 0.187288341292*_Complex_I, 0.177067067896 + -0.017072068523*_Complex_I, -0.269294774259 + 0.299567125253*_Complex_I, 0.691280106543 + -0.285429769347*_Complex_I, -0.478959763653 + 0.592471601549*_Complex_I, 0.731469600041 + -1.116061252131*_Complex_I, 0.506952261982 + -1.310440154883*_Complex_I, -0.131823537621 + 1.440176198054*_Complex_I}; float complex fft_test_y24[] = { -4.984028609200 + -4.220215070640*_Complex_I, -4.250507506099 + 6.724208699822*_Complex_I, 0.057360770043 + 0.512716211712*_Complex_I, -3.908279516708 + 6.693724296623*_Complex_I, -1.890450979255 + 6.088953815148*_Complex_I, -1.373512942118 + 4.739496879303*_Complex_I, -4.642576156472 + 5.105686189601*_Complex_I, -2.584328440882 + 1.728098263528*_Complex_I, 0.744531943959 + 0.135606499920*_Complex_I, -0.971959807211 + -7.134164325953*_Complex_I, 0.738417588646 + -0.940988007706*_Complex_I, -0.528146358843 + -0.272559882858*_Complex_I, 0.599319565507 + 0.302073070033*_Complex_I, -3.856916042162 + -10.635041786616*_Complex_I, -5.293262572847 + -3.982011344991*_Complex_I, -4.348687900619 + 2.460786763911*_Complex_I, 5.015153490569 + 6.700996972453*_Complex_I, 0.389766514080 + -0.278393532462*_Complex_I, 0.801466543459 + 8.782425209839*_Complex_I, 3.623555226700 + -0.026142755609*_Complex_I, -3.328686450422 + 0.591920646925*_Complex_I, -5.710969715584 + 4.204863120029*_Complex_I, 2.683867262111 + -0.108391775481*_Complex_I, -1.068500953539 + -4.689297523031*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_26.c000066400000000000000000000074371317124540100214440ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 26-point transform // #include float complex fft_test_x26[] = { -1.513790990128 + 0.450104660529*_Complex_I, -0.609587704775 + 0.200963343771*_Complex_I, 1.150854971928 + -0.979670346844*_Complex_I, 0.676761753784 + -0.390760850862*_Complex_I, 0.025326431025 + 0.226613394038*_Complex_I, -0.877894422758 + 0.377687762743*_Complex_I, 0.016945667503 + -0.414424826825*_Complex_I, 0.671396901344 + 1.014597796222*_Complex_I, 1.620562100771 + -0.445584464270*_Complex_I, -0.621912682345 + 0.523347355420*_Complex_I, -1.722706628967 + -1.473722873869*_Complex_I, 1.604125850850 + -0.595523792175*_Complex_I, 2.695969244871 + -0.740444785313*_Complex_I, -1.837539349404 + -0.402987576873*_Complex_I, 0.643703593669 + -0.530984627964*_Complex_I, 0.745985203740 + -1.158124796569*_Complex_I, 0.492860315079 + 0.183477887101*_Complex_I, -0.715219690752 + -0.979086251385*_Complex_I, 0.179883358483 + 0.236135674483*_Complex_I, 0.196402574786 + -1.059380996958*_Complex_I, 0.069933652344 + 0.829344522775*_Complex_I, 0.325146685501 + -1.266467132602*_Complex_I, -1.839777223485 + -0.327473446299*_Complex_I, 1.778506841624 + -1.571433253340*_Complex_I, 1.002599293378 + 0.297630901673*_Complex_I, -1.821267785996 + 1.027493831629*_Complex_I}; float complex fft_test_y26[] = { 2.337267962069 + -6.968672891765*_Complex_I, -1.374144569280 + 2.440460452235*_Complex_I, 0.293963382503 + -1.014603415840*_Complex_I, -5.808647515741 + 2.932080281412*_Complex_I, -3.954391977726 + 4.050421232706*_Complex_I, -10.434029005073 + -2.430379478773*_Complex_I, -14.396971442054 + 7.561455425624*_Complex_I, 4.801073402095 + -7.297832464880*_Complex_I, -6.451827528493 + -1.778154888801*_Complex_I, 7.694740702469 + -3.586296872724*_Complex_I, 0.830361317715 + -4.000025563805*_Complex_I, 2.193823341792 + 2.627715132519*_Complex_I, 5.557050661872 + 3.023112572307*_Complex_I, 3.307459610871 + 1.590676230192*_Complex_I, -12.118932653799 + -2.054113664628*_Complex_I, 5.893155083845 + -6.130479717222*_Complex_I, 1.236890091413 + -1.250300895885*_Complex_I, 6.703265906214 + 0.834044438577*_Complex_I, -7.565202099594 + 2.208332250508*_Complex_I, 3.230245599909 + 6.555949348851*_Complex_I, -7.293883944894 + -3.228615872305*_Complex_I, -4.814526866453 + 4.783901741180*_Complex_I, -0.579907911716 + 5.262229129419*_Complex_I, -0.768605942699 + 3.726121287503*_Complex_I, -1.461710271209 + -1.198541330006*_Complex_I, -6.415081077369 + 5.044238707360*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_3.c000066400000000000000000000030401317124540100213410ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 3-point transform // #include float complex fft_test_x3[] = { -0.757661328095 + 0.655250200055*_Complex_I, -1.262964116539 + 0.804288531547*_Complex_I, 0.075727215016 + -0.825503865060*_Complex_I}; float complex fft_test_y3[] = { -1.944898229617 + 0.634034866542*_Complex_I, 1.247398741022 + 1.825198567765*_Complex_I, -1.575484495691 + -0.493482834141*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_30.c000066400000000000000000000102571317124540100214310ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 30-point transform // #include float complex fft_test_x30[] = { 1.383958311928 + 1.009063372834*_Complex_I, 0.656943839727 + -0.201492142788*_Complex_I, -1.263185461543 + -0.762235271683*_Complex_I, -0.279286295800 + 0.737833309276*_Complex_I, 0.061984731638 + 0.232640465778*_Complex_I, 0.078974781535 + 0.151163978562*_Complex_I, -0.067264854607 + -1.701011326832*_Complex_I, -2.367250035232 + -0.675654408115*_Complex_I, 0.901831068347 + -2.291740807507*_Complex_I, -0.685180193104 + 0.640309251420*_Complex_I, -0.865870302577 + -0.234993063029*_Complex_I, 0.394411867502 + -1.629554965527*_Complex_I, -0.163205564173 + 0.199656642882*_Complex_I, 0.561129126184 + 2.875025531619*_Complex_I, -1.191762025326 + 0.544473782291*_Complex_I, 0.808768695645 + 1.055445062240*_Complex_I, -0.145391531392 + -0.095884441741*_Complex_I, 1.006538762836 + -0.724775764669*_Complex_I, 2.116364610835 + -2.412759658708*_Complex_I, 0.210526780948 + 1.338479312378*_Complex_I, 0.722177277886 + 1.447742766425*_Complex_I, 0.148533332865 + 0.262381546261*_Complex_I, -1.337190861421 + 1.251733062365*_Complex_I, -0.346555962201 + -0.012481387193*_Complex_I, 1.400932749094 + -0.360556660035*_Complex_I, 0.479524006659 + -0.777208683834*_Complex_I, -0.525976158853 + -0.155146817266*_Complex_I, -1.237887495307 + 0.159614688084*_Complex_I, 0.526429110861 + -1.368405705104*_Complex_I, -0.688995272873 + 0.833548127008*_Complex_I}; float complex fft_test_y30[] = { 0.294027040082 + -0.664790204608*_Complex_I, -7.251086654153 + 1.930700457878*_Complex_I, 4.192769230897 + 1.789725983362*_Complex_I, 11.197367573831 + 3.254783235859*_Complex_I, -10.053118996304 + -1.739286933243*_Complex_I, 10.012405959748 + -4.383419562391*_Complex_I, -1.293134786584 + 8.917417869363*_Complex_I, 3.828158834339 + 7.240756714477*_Complex_I, 2.213781017086 + -3.491740260928*_Complex_I, -11.803330439118 + 1.771364969478*_Complex_I, 9.272563287802 + 0.848929030951*_Complex_I, -0.497098653141 + -0.996109950789*_Complex_I, -3.419412966566 + -7.252273855897*_Complex_I, -3.013334143526 + -1.690385014079*_Complex_I, 8.340586193744 + 1.433397080247*_Complex_I, 2.813635161314 + -8.730057114052*_Complex_I, 0.460908379865 + 1.518681481090*_Complex_I, -5.717851959043 + -2.820174393000*_Complex_I, 8.168927986272 + 11.157813415293*_Complex_I, 2.879730739941 + 1.551007915618*_Complex_I, 0.710609564242 + -1.414210144075*_Complex_I, 5.664928404839 + 12.624792285877*_Complex_I, -4.559435692794 + 5.128817112052*_Complex_I, 3.020061485600 + 2.317084746039*_Complex_I, 9.287256582183 + 1.097899941841*_Complex_I, 4.921470505274 + -5.250097784974*_Complex_I, 5.775306053035 + 5.396588308077*_Complex_I, -8.507611683876 + 0.041180219148*_Complex_I, 3.499272220645 + 8.240657702592*_Complex_I, 1.080399112219 + -7.557152066173*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_317.c000066400000000000000000001003161317124540100215150ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 317-point transform // #include float complex fft_test_x317[] = { 0.554097588235 + 0.674837317416*_Complex_I, 0.530737753317 + -0.079409691311*_Complex_I, 0.132225792019 + -2.683942671459*_Complex_I, -0.433831796385 + -0.644436889896*_Complex_I, 0.531193579547 + -0.234132120154*_Complex_I, 0.372970050685 + 0.234590738463*_Complex_I, 0.469189910453 + 1.347839137560*_Complex_I, 1.407357556116 + -0.732654574714*_Complex_I, -0.892419998715 + 1.232301421325*_Complex_I, -2.097695896055 + 0.374300022370*_Complex_I, 0.841647143326 + 1.509643189344*_Complex_I, 2.033126977287 + -0.280107016121*_Complex_I, 0.436605233661 + -0.542582266432*_Complex_I, -0.564143476179 + -1.316474379263*_Complex_I, 1.205813790177 + 0.314460438693*_Complex_I, -0.290370012573 + -0.142559201647*_Complex_I, 0.389754456864 + 0.846145131479*_Complex_I, 1.072733277575 + 0.217097105341*_Complex_I, -0.530701360675 + 0.621669741612*_Complex_I, -0.747465971012 + -1.217065085995*_Complex_I, 0.285811246522 + -0.575506757253*_Complex_I, 1.731868270921 + -1.695420723201*_Complex_I, 2.062026927380 + -0.467312976619*_Complex_I, -0.238522083883 + 0.733481847031*_Complex_I, 0.962605683108 + -0.932743731262*_Complex_I, -0.244109153061 + 0.048909057472*_Complex_I, -0.521908701077 + -0.335290348825*_Complex_I, -0.224377634061 + 0.812682493510*_Complex_I, -0.808168093175 + -2.606743537297*_Complex_I, -0.383229234780 + 0.204386340920*_Complex_I, -1.604057984500 + 0.282386325516*_Complex_I, 1.123689375175 + 0.294576201783*_Complex_I, 1.045506847212 + 0.558518419936*_Complex_I, 0.444874000589 + 0.832776075751*_Complex_I, 0.381774427538 + 0.783400026120*_Complex_I, 0.591805517099 + 0.899143948342*_Complex_I, 0.995508244414 + -0.835798382940*_Complex_I, -2.173146523457 + 0.954135191444*_Complex_I, 2.429109028004 + 0.404032043829*_Complex_I, -0.642851155627 + -0.253033059825*_Complex_I, -0.960201285491 + -0.932974674369*_Complex_I, 0.052794955676 + 0.070183835184*_Complex_I, -0.122786042744 + 0.417387287207*_Complex_I, 0.200201640049 + -0.342343750496*_Complex_I, 0.152601120150 + 0.746938165561*_Complex_I, -0.720582709452 + 1.464296507060*_Complex_I, 0.286243449065 + -0.356130710199*_Complex_I, -0.855441109470 + 0.260173089323*_Complex_I, 1.241960323905 + -1.220424835146*_Complex_I, 0.410436718259 + -0.915784426815*_Complex_I, -0.608754986761 + 1.196797063902*_Complex_I, 0.842595164718 + 1.776375320466*_Complex_I, 0.461313891161 + 0.132552548247*_Complex_I, -1.038934516657 + -0.503009712801*_Complex_I, -0.174516309894 + -1.414963943166*_Complex_I, -1.312041533200 + 0.350893580013*_Complex_I, 0.208956667743 + -0.958786287939*_Complex_I, 0.803660420194 + 1.011070131954*_Complex_I, 2.165017913712 + -1.468093310734*_Complex_I, 1.129645943719 + 0.537365498647*_Complex_I, -1.595984272966 + -0.203122161061*_Complex_I, 1.001865195124 + -1.388137201018*_Complex_I, 0.824523455412 + 0.399895307714*_Complex_I, 1.390174301291 + 2.631574565038*_Complex_I, -0.950205283612 + -1.131255194597*_Complex_I, 1.905487211032 + -0.077934597969*_Complex_I, 1.003876696894 + -0.060334922974*_Complex_I, -0.739566795906 + -0.125966238551*_Complex_I, 0.638862295532 + 0.312440320520*_Complex_I, 0.812688518156 + -0.687832384174*_Complex_I, -0.247460071939 + 1.506637100983*_Complex_I, 1.119835012306 + 1.284530437377*_Complex_I, 0.514075655596 + 0.315432575412*_Complex_I, -0.556581507109 + -2.240098527759*_Complex_I, 0.249592136667 + 0.505876736625*_Complex_I, 0.138808728752 + -0.362938299441*_Complex_I, -1.295018476090 + -0.498162870507*_Complex_I, 0.633165144610 + -1.395172629954*_Complex_I, 0.932960550573 + -0.237180627122*_Complex_I, 1.661895463725 + 0.690503082347*_Complex_I, 0.333824445072 + -1.788741666587*_Complex_I, 0.489887999458 + -0.706548054495*_Complex_I, -0.548551848905 + 0.898884888429*_Complex_I, -0.608101416118 + -0.201679435156*_Complex_I, 0.890886957534 + -0.480205878554*_Complex_I, -0.000052987921 + 0.753051843488*_Complex_I, -2.008688335321 + -0.531405355010*_Complex_I, 0.178224821311 + 0.093166214057*_Complex_I, -1.028365245165 + -0.852475963885*_Complex_I, 0.686303677542 + 1.543109809415*_Complex_I, 1.711982713732 + -0.058899888612*_Complex_I, 1.120881384941 + 0.023773370634*_Complex_I, 0.452547007139 + -0.345550830853*_Complex_I, 0.851642145828 + 0.918449585078*_Complex_I, 1.354411836149 + 0.053840956523*_Complex_I, 0.186505302140 + 0.455350659118*_Complex_I, 1.178867803924 + 0.561242592990*_Complex_I, -0.867274007830 + 0.778369347385*_Complex_I, -0.763210306046 + -0.056553236256*_Complex_I, -0.925493602469 + 1.802123360882*_Complex_I, -0.381880717193 + 0.836790955039*_Complex_I, 0.740584915503 + 0.410451383495*_Complex_I, -1.739773756173 + -0.008392421431*_Complex_I, -0.927812449353 + 0.225621894111*_Complex_I, 0.291685537968 + -0.631710150727*_Complex_I, 1.044752342554 + -0.921336822198*_Complex_I, 0.379926674636 + 0.104269280376*_Complex_I, -0.747794397492 + -1.586409810217*_Complex_I, -0.707471806222 + -3.451349626151*_Complex_I, -0.610242217287 + -0.050520690817*_Complex_I, -1.141609802996 + -0.450890109498*_Complex_I, -0.110600652376 + 0.711135784835*_Complex_I, -2.154140310955 + -0.464833145767*_Complex_I, 2.215673027150 + 0.378163057373*_Complex_I, -0.654346983910 + -0.446467309237*_Complex_I, 0.054883600089 + -0.699447750344*_Complex_I, 0.806739839269 + 0.085857123252*_Complex_I, -1.606523541279 + 0.816575059374*_Complex_I, 0.592874861350 + -0.160053556472*_Complex_I, -0.487687814535 + 2.062004006591*_Complex_I, -0.494854876646 + 1.222171460716*_Complex_I, 1.143598578272 + -0.256116050124*_Complex_I, 2.400451006261 + -0.615247709498*_Complex_I, 1.794972603823 + 0.061326347413*_Complex_I, -1.785033202582 + 1.285030637182*_Complex_I, 0.952408789671 + -0.061111017884*_Complex_I, 0.045375503932 + -0.337506966204*_Complex_I, 0.098933506757 + 1.552870310423*_Complex_I, -0.114562876521 + 0.289943289341*_Complex_I, -0.283731751338 + -0.946113439136*_Complex_I, 0.461130821204 + 0.048895395259*_Complex_I, -1.174095369155 + 0.023986190137*_Complex_I, -0.098711272023 + 0.155133236840*_Complex_I, 1.644296831488 + -0.763890180558*_Complex_I, -0.598417564337 + -0.286264760137*_Complex_I, 0.526726895394 + 1.073518895905*_Complex_I, -0.853228628205 + -1.282488324989*_Complex_I, -1.020706122357 + 0.248901790873*_Complex_I, 1.313386656293 + 1.883626375861*_Complex_I, -0.596968080006 + 1.198886796626*_Complex_I, -1.090527229732 + 1.322486318068*_Complex_I, 0.055643681240 + -1.476648993263*_Complex_I, -0.134166277120 + 0.538780165850*_Complex_I, -0.394194728658 + 0.287017836253*_Complex_I, 0.451499019863 + 0.196444291722*_Complex_I, -1.227900659262 + 0.066951464777*_Complex_I, 0.281655958102 + 0.477082252845*_Complex_I, 1.584578121348 + 2.263167026855*_Complex_I, -0.337702889133 + -1.675522983729*_Complex_I, -1.262293072370 + 0.295093464675*_Complex_I, -1.466903736895 + 0.492057686013*_Complex_I, -1.485463891249 + 1.082857775981*_Complex_I, -0.275569696975 + -0.635382067043*_Complex_I, 1.705596337300 + 2.104558859516*_Complex_I, 0.704228406430 + 1.560694307633*_Complex_I, 0.940747890984 + 0.080075753674*_Complex_I, -0.671195049979 + -0.305225546505*_Complex_I, 1.351213152915 + -0.159424965469*_Complex_I, -0.168781019368 + 0.642571757925*_Complex_I, -0.431378015911 + -0.017150397606*_Complex_I, 0.084141441624 + 0.021065037620*_Complex_I, -0.464340239256 + -0.192995496761*_Complex_I, -1.333718595841 + -0.017151207176*_Complex_I, 1.699781888517 + 1.611185583580*_Complex_I, -0.413570253776 + -0.044257707528*_Complex_I, 2.258631378215 + -0.166004542094*_Complex_I, -0.465389665786 + 0.871749883624*_Complex_I, 1.029189363291 + 0.713498194652*_Complex_I, -0.094915760832 + -1.625030317385*_Complex_I, -1.232066038521 + -0.607872994844*_Complex_I, 1.502005331699 + -0.020525271340*_Complex_I, -0.683321223012 + -0.293225147764*_Complex_I, -0.907670613167 + -0.107969897144*_Complex_I, 0.462429724200 + -0.775625444256*_Complex_I, -1.205101490966 + -0.132384994859*_Complex_I, -1.179628062446 + 2.189754291494*_Complex_I, -0.631509862810 + 1.222985676196*_Complex_I, 0.789563515020 + 0.698677701769*_Complex_I, 1.687609752565 + 0.400827580780*_Complex_I, -0.645610608306 + -0.014606261491*_Complex_I, -1.361740989948 + -0.117827247124*_Complex_I, 1.314229682964 + -0.603800894199*_Complex_I, -1.956380418062 + 1.043229034913*_Complex_I, -0.801537986631 + 2.532651178906*_Complex_I, -2.386565797106 + -1.098115563132*_Complex_I, 0.220407348326 + -1.279188578233*_Complex_I, -0.692180379497 + 0.560515689944*_Complex_I, -0.356604504521 + 0.793303202093*_Complex_I, -0.159496968171 + -1.294766371488*_Complex_I, 1.198119217621 + -1.994862046372*_Complex_I, -0.568527073111 + 0.401071277388*_Complex_I, 2.987226058138 + -0.073884662975*_Complex_I, 1.799586418676 + -0.574490253290*_Complex_I, 0.011347684988 + -0.745307885407*_Complex_I, 0.729683796427 + -1.060721735894*_Complex_I, -1.966760785708 + -0.605669511192*_Complex_I, 1.142741187156 + 0.019297308388*_Complex_I, -1.561621247893 + -0.095007722087*_Complex_I, 0.336572557763 + -0.651058510390*_Complex_I, 0.040766936719 + 1.217219328749*_Complex_I, 0.200903662048 + 0.393373958513*_Complex_I, -1.236464108144 + 0.541280738924*_Complex_I, 0.117909377974 + -0.607773139351*_Complex_I, 0.379616825601 + -0.643186918605*_Complex_I, 0.643537081891 + 0.275436892658*_Complex_I, 0.225873382688 + -0.158194256053*_Complex_I, 0.053176096756 + 1.458472268368*_Complex_I, 1.414145044178 + -0.733638770750*_Complex_I, 1.347289531912 + 0.169321860659*_Complex_I, -0.840384203303 + 0.763005504852*_Complex_I, 1.214072735988 + 1.485891717688*_Complex_I, -0.348223438412 + 1.020459174171*_Complex_I, 0.073882541886 + -0.905791314139*_Complex_I, -0.705446913782 + 0.056186574618*_Complex_I, -0.960863041873 + -0.196833332985*_Complex_I, 1.006218030516 + -0.467774405167*_Complex_I, 0.602372049969 + -2.674593305127*_Complex_I, -0.934722056514 + -0.016922494007*_Complex_I, 0.257679561629 + -0.885684235693*_Complex_I, 0.044866947149 + 0.936359293985*_Complex_I, 0.950842198317 + 1.868559062575*_Complex_I, 1.498943799171 + -0.019107821973*_Complex_I, -1.868507034816 + 0.197524971623*_Complex_I, 0.970832401725 + -0.074109462719*_Complex_I, -2.886469419266 + 0.142475981345*_Complex_I, 1.240964551237 + 0.153090872958*_Complex_I, -0.000396756859 + -1.046593294557*_Complex_I, 1.117655103664 + 1.647657701398*_Complex_I, 1.162930856009 + -0.975104959968*_Complex_I, -0.934535360620 + 0.307953402722*_Complex_I, -0.573780565126 + -0.375508524005*_Complex_I, -0.103208834185 + 2.105768262189*_Complex_I, -1.379507684252 + -0.280894989725*_Complex_I, 0.859242654654 + 0.201801911064*_Complex_I, 0.214128192305 + -0.427748749718*_Complex_I, 1.559388133754 + -2.233121573297*_Complex_I, 0.019639327733 + 0.360300645061*_Complex_I, -0.133932495128 + -0.722680847651*_Complex_I, 0.863036773382 + -2.922284619456*_Complex_I, 0.334598761557 + -0.983050027547*_Complex_I, -1.077563482460 + 0.417379502415*_Complex_I, -0.198656810153 + 0.569701104618*_Complex_I, 0.913145816840 + 2.052526155977*_Complex_I, 0.854066622796 + -0.413714533361*_Complex_I, -0.414380668765 + -1.405489197548*_Complex_I, -1.110627741502 + -1.820107908459*_Complex_I, -0.613940194705 + 1.779435308312*_Complex_I, -2.105251634607 + 0.525272681631*_Complex_I, 0.609098015750 + -0.895402748194*_Complex_I, 1.934336563550 + 0.543860167180*_Complex_I, -0.782446497605 + 0.641226314552*_Complex_I, -0.955134630524 + -0.077175268361*_Complex_I, -0.210873574493 + -1.715168716896*_Complex_I, 1.628059930554 + -1.533301168339*_Complex_I, -1.421933758706 + -0.241187651806*_Complex_I, 2.187891215143 + -0.023407875710*_Complex_I, 0.548885995861 + 0.285435244871*_Complex_I, 0.674430997216 + -0.481078429799*_Complex_I, 0.397489182610 + -0.446320110483*_Complex_I, -0.865204055951 + -0.020571209344*_Complex_I, -0.155857632710 + -1.473838050536*_Complex_I, -0.825650581473 + 0.501060420785*_Complex_I, 0.506220809313 + 1.124359364738*_Complex_I, 0.199383983129 + 0.552775919340*_Complex_I, -0.675785644869 + -0.015515289402*_Complex_I, 0.347119071389 + -0.046308125867*_Complex_I, -0.580411900444 + 0.473043358519*_Complex_I, -1.073929642005 + -1.146130174539*_Complex_I, -1.137495899690 + -1.309784871827*_Complex_I, 1.171486989096 + 1.823857109273*_Complex_I, -0.742946853968 + 0.049703242746*_Complex_I, -0.160432289828 + 1.724103887278*_Complex_I, -0.546035353551 + 0.386968779514*_Complex_I, -1.213047883956 + -0.537389928129*_Complex_I, -1.339236442910 + -1.248701576327*_Complex_I, -0.815367922604 + 0.085728302177*_Complex_I, -2.349193819868 + 0.427831727302*_Complex_I, -0.276194199790 + 1.234485714534*_Complex_I, -0.355231570763 + -0.995816467388*_Complex_I, 1.137208262430 + 0.216271557004*_Complex_I, 0.962040804090 + -1.065610794498*_Complex_I, -0.668324382362 + 0.822590130460*_Complex_I, -1.202015945307 + -1.480043875470*_Complex_I, 1.179225549720 + 1.767048172045*_Complex_I, -0.684123959923 + -0.862865878982*_Complex_I, -0.174319873616 + 0.167752215701*_Complex_I, -1.446536704664 + 1.172516467428*_Complex_I, 0.858114162859 + 2.295181364008*_Complex_I, 0.124270375245 + 0.997986406329*_Complex_I, 0.394906672949 + 1.154862665198*_Complex_I, 1.053903228740 + 1.779817113028*_Complex_I, -0.230950556520 + -0.175979989611*_Complex_I, -1.265383803223 + -0.026310311336*_Complex_I, 0.762972265227 + 1.429231386216*_Complex_I, 1.162409662447 + -1.112322698285*_Complex_I, 0.775539802471 + -1.323064642721*_Complex_I, 0.666613966503 + -0.129946108336*_Complex_I, 1.930414467502 + 0.436695033239*_Complex_I, 0.885068429064 + 0.115321831962*_Complex_I, 1.551024374006 + 0.416463074882*_Complex_I, 0.247974255137 + 0.627306468118*_Complex_I, 0.781609286510 + 0.378212834621*_Complex_I, 0.332343800329 + 0.539122959506*_Complex_I, 0.519709930109 + -1.064947224271*_Complex_I, -0.635850608190 + 1.257862397877*_Complex_I, 1.628515077193 + -1.103666746889*_Complex_I, -0.849325965524 + -1.767990899186*_Complex_I, 0.743956616560 + -2.505409755963*_Complex_I, 0.830498883146 + 0.057323145873*_Complex_I, -1.470980958211 + -1.558079958147*_Complex_I, -0.088063460329 + 0.426467567974*_Complex_I, -0.219298752127 + -0.711676070690*_Complex_I, -0.283866135348 + 1.254036523517*_Complex_I, -0.254391988290 + 0.215410095075*_Complex_I, -0.590092311740 + -1.507631350024*_Complex_I, -1.535360519901 + -0.437319427483*_Complex_I, 1.026878345705 + -0.182042614613*_Complex_I}; float complex fft_test_y317[] = { 19.891894947904 + 5.655090929781*_Complex_I, 18.838569316919 + -27.216365987549*_Complex_I, -11.140787864820 + -1.700693291107*_Complex_I, 9.248191980131 + -11.880625755527*_Complex_I, 0.877433246927 + 5.210710512463*_Complex_I, 12.613756002695 + -22.914829471885*_Complex_I, -7.522954808149 + 2.580642036625*_Complex_I, -24.806396396859 + 14.114587974426*_Complex_I, 9.875249841730 + -22.004495722041*_Complex_I, -18.222931551932 + 2.572927350772*_Complex_I, 20.867583356509 + -1.458843546852*_Complex_I, 38.916192529134 + -7.826129128685*_Complex_I, -19.618271263978 + -21.217111192894*_Complex_I, 0.549362128526 + 18.584275483073*_Complex_I, -5.258299327834 + -0.446452119776*_Complex_I, -6.830532675831 + -35.800356213084*_Complex_I, 16.124101912097 + -2.387751210287*_Complex_I, 19.602770799308 + -18.449258115561*_Complex_I, -4.933124103618 + 8.281766183665*_Complex_I, -13.560383009984 + 0.970618524872*_Complex_I, 41.610229013366 + 5.152249379736*_Complex_I, 1.415309104711 + 11.210809107531*_Complex_I, -40.441003535705 + -12.405906077032*_Complex_I, -12.530216678354 + 22.864679881966*_Complex_I, -29.573667819723 + -22.154070735316*_Complex_I, -8.933348019353 + -25.720405793092*_Complex_I, -3.072833505067 + 16.874820762270*_Complex_I, -8.751051523099 + -9.544252802963*_Complex_I, 19.619902222112 + -22.765558912475*_Complex_I, 3.204939906092 + -25.426020065167*_Complex_I, -18.600493227238 + 2.762236432333*_Complex_I, 10.833867918922 + -38.070397977737*_Complex_I, 25.869914191964 + -19.192002503531*_Complex_I, 12.052348942398 + -1.338816803484*_Complex_I, -38.656067918699 + -24.135381967263*_Complex_I, 5.700781235700 + 11.219859126000*_Complex_I, -23.338619501120 + 32.607593688928*_Complex_I, -10.686035441793 + 16.337999228208*_Complex_I, -9.517260831300 + 17.469953582495*_Complex_I, 11.452433021422 + -2.244848000851*_Complex_I, 3.355159985201 + -0.950021809091*_Complex_I, 11.960645612996 + 6.893274528846*_Complex_I, 9.585251410761 + 10.141135223678*_Complex_I, -7.050051336892 + 27.613088292755*_Complex_I, 7.367552651770 + -6.006047409882*_Complex_I, 19.902478672101 + -16.730550563777*_Complex_I, 32.759288191850 + 1.162079163303*_Complex_I, -10.679222098466 + -0.414496389670*_Complex_I, -17.167648316558 + 13.231819142930*_Complex_I, -15.270670234876 + 12.750590771914*_Complex_I, 7.808635317834 + -1.976327148026*_Complex_I, 3.659364354893 + 12.967348190608*_Complex_I, 8.516191035487 + -3.814776057042*_Complex_I, -2.967686164798 + -2.759276437723*_Complex_I, -10.217022770046 + 22.446524490020*_Complex_I, -13.759629399132 + 0.428077429397*_Complex_I, 12.108694472460 + 17.906136235301*_Complex_I, 0.500310973628 + 10.379459504754*_Complex_I, 22.170113416067 + -17.601071337137*_Complex_I, -4.547207763897 + 13.535378900333*_Complex_I, 35.073898289289 + -3.750408416097*_Complex_I, 12.960162045071 + -10.329236328497*_Complex_I, 5.155047938611 + 11.233862622741*_Complex_I, -19.366076595616 + 3.290152177759*_Complex_I, -2.547983907745 + -4.318523679571*_Complex_I, 13.079902614417 + -31.788319997011*_Complex_I, -0.294946700028 + 20.014494355305*_Complex_I, 18.602791112148 + -1.875890460773*_Complex_I, -13.396328282272 + 9.288327370031*_Complex_I, -3.117158916891 + 2.544747297232*_Complex_I, 14.226131115223 + 17.462152594662*_Complex_I, -19.578473387664 + 34.411911283259*_Complex_I, -6.579019542175 + 1.022001674347*_Complex_I, 30.972194959263 + -8.350211186911*_Complex_I, -23.959086942588 + -4.745490152344*_Complex_I, 18.433629972547 + 33.672506545950*_Complex_I, -3.583025093477 + 29.006005065761*_Complex_I, -3.421689832344 + -6.516619591564*_Complex_I, 17.468290088683 + 14.351378688148*_Complex_I, -20.170011170114 + -44.394817543067*_Complex_I, -13.150516148634 + 45.749703126153*_Complex_I, -6.345962437499 + 5.896690541701*_Complex_I, -3.508737698320 + 25.459472943049*_Complex_I, -9.590464636095 + -37.162638669309*_Complex_I, -7.707872774343 + -4.065042502767*_Complex_I, 4.310656075828 + 55.425516805330*_Complex_I, -8.841697395726 + 7.827822742296*_Complex_I, 6.538079696486 + 18.790190957680*_Complex_I, 3.052383346750 + -35.409567370640*_Complex_I, 6.790218518127 + 6.485107042363*_Complex_I, -1.939520400173 + 9.749487460014*_Complex_I, 27.335153513982 + -28.544990200718*_Complex_I, 1.310416901033 + -3.384377012660*_Complex_I, 39.882940481275 + -2.284359214074*_Complex_I, 10.547528262920 + -12.560415251324*_Complex_I, -39.735255177309 + 13.592975359455*_Complex_I, -15.339971072116 + -16.475578099072*_Complex_I, 17.033232877918 + 3.802866771597*_Complex_I, 28.013870016133 + 2.419611488016*_Complex_I, -2.265805112454 + 0.312114751003*_Complex_I, -33.149667339304 + -13.689695655857*_Complex_I, 17.388116065076 + 0.542000357078*_Complex_I, 24.899620116312 + -12.668755714836*_Complex_I, 4.917415611451 + -9.932194848538*_Complex_I, -11.738607295144 + -8.914945728892*_Complex_I, -19.712014537454 + 22.399807137247*_Complex_I, 5.053485084584 + 17.298193889941*_Complex_I, -7.079518754159 + 17.581889100321*_Complex_I, -10.281582568059 + 8.089169898931*_Complex_I, 1.422571832929 + 3.080323599470*_Complex_I, 8.605408612244 + -3.487094722779*_Complex_I, -11.890704936363 + 9.663054150701*_Complex_I, 9.768366151498 + 15.851583190991*_Complex_I, 15.643908708786 + -4.022026320351*_Complex_I, -23.153672099048 + 27.718041721476*_Complex_I, -10.673968698682 + -2.656942822276*_Complex_I, -3.084198946373 + 5.011470019270*_Complex_I, 30.294417286976 + -0.649680240512*_Complex_I, 9.336689517258 + -15.513350621571*_Complex_I, -0.332156127181 + 9.028518696767*_Complex_I, -18.028373273009 + 0.865624445339*_Complex_I, 18.478442253114 + -4.603304072176*_Complex_I, -23.690660760663 + 23.776870282847*_Complex_I, 15.985913856353 + -2.839961425057*_Complex_I, 1.572606311668 + -19.612416936799*_Complex_I, 16.810087235424 + 0.199177019879*_Complex_I, -15.975160985564 + 6.532163069799*_Complex_I, -32.272173936218 + -31.217876380070*_Complex_I, 15.826696571154 + 18.609590632164*_Complex_I, 47.902645387609 + 17.126787301492*_Complex_I, -2.541073313860 + 14.418504375704*_Complex_I, 14.540095561207 + 20.121389424019*_Complex_I, 26.277876001597 + -3.644634538637*_Complex_I, -2.512888880479 + -30.538233732588*_Complex_I, 16.529338657188 + 22.345368961768*_Complex_I, -1.812032422371 + -34.161479691113*_Complex_I, -0.453702679159 + -6.380888555304*_Complex_I, -3.152766309700 + -11.666085457234*_Complex_I, -11.122245781125 + -11.927016012323*_Complex_I, 36.608207324428 + 15.883213693451*_Complex_I, -7.991006509076 + 50.985368963626*_Complex_I, 4.226949261924 + 1.424207754420*_Complex_I, 17.463446429822 + 6.779880329142*_Complex_I, -3.489655564559 + 0.384578586369*_Complex_I, -5.888919363255 + -5.109974862115*_Complex_I, -7.227459554733 + 29.423681452522*_Complex_I, -5.599219759541 + -23.600754528481*_Complex_I, -1.449537808914 + -5.756622299277*_Complex_I, -19.475712102355 + -23.900197536654*_Complex_I, -21.448274996924 + 26.188122613033*_Complex_I, -29.449414779539 + 4.514251604734*_Complex_I, 0.711130838156 + 9.386706325613*_Complex_I, -4.964574769823 + 3.355702966205*_Complex_I, -69.341381991121 + -15.186662242307*_Complex_I, -9.570125543135 + -19.565859787554*_Complex_I, -10.294086283004 + 8.398169381304*_Complex_I, -1.885058572468 + -6.759464252726*_Complex_I, 27.070270898380 + -0.178665040288*_Complex_I, 47.866947417745 + -31.409630574884*_Complex_I, -8.921385543048 + 26.098382682234*_Complex_I, -2.790785416910 + 9.787980555385*_Complex_I, -11.714395450184 + 2.331009478742*_Complex_I, -15.110851454222 + -16.495034888485*_Complex_I, 4.191147002221 + 12.009574674807*_Complex_I, 13.441299656087 + -6.566453769009*_Complex_I, 37.589069138284 + -3.493855465671*_Complex_I, 12.583644012597 + 15.635478070296*_Complex_I, -10.233844300260 + -2.537026190645*_Complex_I, 32.544552127969 + -9.371296682693*_Complex_I, 5.840669998388 + -0.465346273045*_Complex_I, -32.889192462170 + -18.684446717050*_Complex_I, -15.105348929262 + 9.854947012189*_Complex_I, 2.561152455963 + -17.413141080242*_Complex_I, 13.746092833724 + -1.220057764138*_Complex_I, -23.803933926504 + 19.459415272545*_Complex_I, 13.809596770429 + -10.104944386386*_Complex_I, -8.303454415515 + 8.117739395766*_Complex_I, 6.133097727305 + -1.569418595484*_Complex_I, -8.760751262525 + -27.389777662710*_Complex_I, 10.131599125171 + 6.687127259801*_Complex_I, -25.519018101480 + 18.199522992831*_Complex_I, -13.233035001671 + -6.395819934405*_Complex_I, 11.700095411690 + -15.584918347062*_Complex_I, 18.906883235021 + -7.460982609320*_Complex_I, -17.459921203210 + 1.804228941706*_Complex_I, 12.317579017635 + 10.356522098016*_Complex_I, 26.023982632040 + -7.991255808237*_Complex_I, -37.779207166301 + -2.527619516503*_Complex_I, -16.084376241401 + -20.612256188135*_Complex_I, -6.114349663136 + -23.064645190863*_Complex_I, -2.116498608238 + 50.021918384600*_Complex_I, -7.117672685723 + -8.176883387504*_Complex_I, -5.412565357343 + 22.014215119309*_Complex_I, 6.088100003823 + -14.490088332571*_Complex_I, -23.952484213391 + -6.311185058243*_Complex_I, -41.692266879065 + -16.754070143984*_Complex_I, 15.044401210058 + 3.664913601471*_Complex_I, -33.750320820834 + 36.019579795022*_Complex_I, 13.347039200739 + -32.112552097269*_Complex_I, -15.461626675606 + 23.718105709185*_Complex_I, -12.296412987482 + 11.603712083795*_Complex_I, -5.811459938628 + -7.925008172416*_Complex_I, -1.192572683531 + -17.231195267270*_Complex_I, -20.865176875222 + -31.216074954599*_Complex_I, -28.168417257904 + -6.162171521961*_Complex_I, 14.071723863194 + -13.359093220787*_Complex_I, -10.855751735127 + -2.119685075188*_Complex_I, 10.100698435956 + -0.047663624125*_Complex_I, -16.742422653794 + -24.530696829578*_Complex_I, 4.000721417241 + -9.851748070066*_Complex_I, 13.784754826511 + 11.502447326859*_Complex_I, 24.102575046761 + 1.552286673184*_Complex_I, 6.070752306643 + -4.812888456253*_Complex_I, -5.300318786685 + -5.773884122203*_Complex_I, 4.177402715108 + 4.644324663894*_Complex_I, -34.005084599492 + 24.853411330269*_Complex_I, -4.077672998994 + 2.001774715846*_Complex_I, -21.978658258889 + -16.888801388499*_Complex_I, 16.217687213434 + 24.308462530919*_Complex_I, 9.698665151728 + -11.152518442318*_Complex_I, -0.713578550754 + -0.408153703877*_Complex_I, -13.404489453311 + -13.338812872852*_Complex_I, 12.438700016349 + 34.570234225070*_Complex_I, -9.926721954129 + 6.906926926113*_Complex_I, 34.152883393921 + 32.217622455379*_Complex_I, 18.232286791872 + 37.874687752978*_Complex_I, 12.000459208850 + -4.948870303603*_Complex_I, -32.687697613521 + -14.030824660001*_Complex_I, 9.549264725873 + -11.955689902942*_Complex_I, 14.839058751293 + -31.933475859189*_Complex_I, -14.754140603346 + -24.878350781691*_Complex_I, 10.712939318393 + -5.996862342613*_Complex_I, -17.907934788390 + 6.090055602127*_Complex_I, 36.124946787489 + -5.830186488894*_Complex_I, 8.800236613602 + -2.072057513781*_Complex_I, 3.437540103841 + 0.664749616099*_Complex_I, 31.950715457487 + -0.220151294656*_Complex_I, -0.045173525280 + 19.196581987850*_Complex_I, 1.870859081457 + -31.599244764015*_Complex_I, 0.209529336033 + 0.187035118051*_Complex_I, -20.188770724804 + -1.836423923991*_Complex_I, -0.878467583840 + 20.234622217282*_Complex_I, -2.102494717199 + -2.913862105328*_Complex_I, -12.424351209312 + 16.006770035694*_Complex_I, 4.029466210003 + -4.407643696893*_Complex_I, 5.945482525641 + 6.202857230453*_Complex_I, -10.003725089675 + 12.495974119472*_Complex_I, -30.517926092302 + -12.650897630264*_Complex_I, 4.362955303417 + -12.091129699738*_Complex_I, 16.312617526910 + 33.224889607577*_Complex_I, -7.191052604298 + 20.407651857657*_Complex_I, 20.796924916343 + -6.364968926767*_Complex_I, -12.625716653882 + 13.205109334295*_Complex_I, 8.088234917787 + 7.824060551408*_Complex_I, 1.922368898588 + 47.121922176668*_Complex_I, -22.856735196688 + 24.367218386007*_Complex_I, -7.383851526948 + 16.988073661561*_Complex_I, 44.161092935665 + -5.907735807977*_Complex_I, 21.472541358807 + -13.144261767738*_Complex_I, -11.542368964090 + 15.544417175199*_Complex_I, 27.503706468722 + -11.522885641815*_Complex_I, 47.558932357808 + 7.448305631246*_Complex_I, 11.766347399663 + 19.611745304561*_Complex_I, 9.190381176578 + 15.613955528574*_Complex_I, 4.579716108010 + -19.097122607568*_Complex_I, 8.259625237826 + 5.225672702106*_Complex_I, -29.407167921996 + 2.730538989362*_Complex_I, 28.823600196176 + 29.176827923246*_Complex_I, 7.192706095305 + -13.060381105412*_Complex_I, 25.710478454828 + 0.151963358956*_Complex_I, 2.912008664120 + -30.634293042262*_Complex_I, -18.887195071024 + 24.458778149068*_Complex_I, -11.270981360031 + 36.740254138082*_Complex_I, -27.910677769149 + -46.983604943585*_Complex_I, 28.541376587410 + -11.613642790751*_Complex_I, 4.477974452509 + 19.232597353019*_Complex_I, -4.293520064043 + 21.064976071666*_Complex_I, -35.598030786598 + 22.993609231670*_Complex_I, 15.465979612020 + -7.083850274044*_Complex_I, -20.864435551224 + -11.252291347107*_Complex_I, -8.098484900823 + 15.454651546399*_Complex_I, 7.922777952587 + -23.004986313444*_Complex_I, 5.362453523073 + -0.810615362821*_Complex_I, 23.691538716715 + 5.018112888735*_Complex_I, -0.840977210667 + 5.291230447587*_Complex_I, -14.732575553595 + 5.007945078325*_Complex_I, 11.153523811020 + 9.041741420055*_Complex_I, 10.332014628129 + -19.924730861837*_Complex_I, -14.993931961657 + 31.489106362903*_Complex_I, 18.595068458053 + -35.418285443670*_Complex_I, 39.450078173463 + 1.995244884889*_Complex_I, -1.199515997336 + -39.429463141214*_Complex_I, 32.594746366756 + 11.337568560792*_Complex_I, 12.403678050012 + -21.176744666160*_Complex_I, 3.346525369966 + -1.001631596928*_Complex_I, -19.825849167391 + 26.742894636469*_Complex_I, 4.915352470909 + 3.753914873323*_Complex_I, 8.679746038045 + -3.972380637551*_Complex_I, -3.287311421377 + 20.200996274143*_Complex_I, 22.907843859952 + 3.994757951688*_Complex_I, 2.844877291610 + -4.339174940613*_Complex_I, 4.103872158917 + -8.872001060599*_Complex_I, 28.989825837444 + -23.300936570044*_Complex_I, -7.955654262813 + 31.438036806524*_Complex_I, -6.389510821525 + -2.868211291181*_Complex_I, 2.583272449361 + -13.352995160958*_Complex_I, -38.239266883463 + 23.653429024344*_Complex_I, 8.079210774309 + 23.697861354779*_Complex_I, -37.713434701568 + 2.799035443775*_Complex_I, -26.751551315717 + 8.673836408974*_Complex_I, -33.613333707208 + -0.367929968698*_Complex_I, -14.541161127911 + -5.708211292132*_Complex_I, -3.393160511476 + -24.278587890684*_Complex_I, 26.111359371252 + -28.934022170518*_Complex_I, 14.009362482345 + -20.358022264859*_Complex_I, 7.316431660011 + 26.887415857021*_Complex_I, 8.199534997352 + -2.435205163079*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_32.c000066400000000000000000000105671317124540100214370ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 32-point transform // #include float complex fft_test_x32[] = { 0.010014623512 + 0.557635892111*_Complex_I, -0.206536736342 + -0.166543150147*_Complex_I, 0.538145349965 + -1.725439447290*_Complex_I, 0.302742823470 + -1.371600938217*_Complex_I, 1.002711341702 + 0.326114543577*_Complex_I, 0.141075699526 + 0.155158151624*_Complex_I, -0.607068327122 + 1.319516119806*_Complex_I, 0.368752062157 + -0.923715410356*_Complex_I, 2.103742061281 + -0.015112313666*_Complex_I, 0.161141569742 + 0.602136525051*_Complex_I, -0.450622712484 + 1.781653187693*_Complex_I, -0.135385448029 + 0.118136375039*_Complex_I, -0.881476360789 + 0.743248990846*_Complex_I, -0.470865375669 + 0.297577338949*_Complex_I, 1.578293870903 + 0.150586285410*_Complex_I, -0.582548890310 + -0.090131349592*_Complex_I, -0.728216825909 + -0.280660553441*_Complex_I, -0.405960077281 + -0.823236356122*_Complex_I, -0.689782453002 + -0.111721138015*_Complex_I, -0.483036608523 + -2.255409787531*_Complex_I, -1.773638052539 + 0.276871847058*_Complex_I, 1.768143481866 + 0.929411559777*_Complex_I, 1.598162436054 + 0.336924712326*_Complex_I, 0.025313208364 + 0.101634388542*_Complex_I, 1.295932058649 + -0.792267243573*_Complex_I, 0.197302929571 + -1.198246830820*_Complex_I, -0.674567746661 + 0.782836390216*_Complex_I, -1.155843266715 + -2.060346979162*_Complex_I, -1.174296668808 + -1.018450093532*_Complex_I, -2.374237969002 + 0.374087797223*_Complex_I, 0.773269391236 + -0.854101525457*_Complex_I, -0.320046719055 + -0.112754382318*_Complex_I}; float complex fft_test_y32[] = { -1.249387330241 + -4.946207393990*_Complex_I, 6.246388763884 + -6.773507691880*_Complex_I, -8.084921469264 + -10.845914953315*_Complex_I, 4.357263742580 + -0.359518611967*_Complex_I, 0.869129033150 + 4.810140005791*_Complex_I, -4.320755060606 + -2.990777115902*_Complex_I, -6.040916675986 + 11.391912365593*_Complex_I, 1.334419178501 + 8.684519829396*_Complex_I, 4.553475487339 + -2.672989876360*_Complex_I, 5.980003650433 + 0.810448601904*_Complex_I, -6.393705093395 + 4.226375095002*_Complex_I, -2.975901497257 + 6.587514214591*_Complex_I, -1.005810190439 + -6.128898292417*_Complex_I, 0.016624592858 + -1.973370861210*_Complex_I, 0.024605667140 + -7.634608092684*_Complex_I, 2.682037461215 + -1.379684965569*_Complex_I, 5.090591302217 + 7.901478702130*_Complex_I, 4.974928932755 + -2.673377557945*_Complex_I, 2.018958625049 + 1.429758433848*_Complex_I, -3.215930811783 + -5.513827987988*_Complex_I, 9.696021083826 + 2.712450847683*_Complex_I, -6.175824724853 + 6.515234684364*_Complex_I, -10.139408716624 + 3.456026873018*_Complex_I, 3.811736373367 + 3.481961808174*_Complex_I, -8.975590750922 + -1.092757154258*_Complex_I, 1.006822057237 + -4.766098514087*_Complex_I, -0.499087378413 + 4.387815733060*_Complex_I, -0.223489533627 + 2.032893439147*_Complex_I, 12.473346705334 + -4.826450587127*_Complex_I, 4.394902822920 + 12.095339998118*_Complex_I, -3.828535537115 + 2.263473712749*_Complex_I, -6.081522756885 + -0.365006140312*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_35.c000066400000000000000000000112431317124540100214320ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 35-point transform // #include float complex fft_test_x35[] = { 0.621203985274 + -1.170486588571*_Complex_I, 0.001346936460 + 0.911992162865*_Complex_I, 0.852266167932 + -0.485602417107*_Complex_I, -1.440614617555 + -0.143907395580*_Complex_I, -0.886824740774 + -0.735649970983*_Complex_I, 0.822316647558 + -2.190416870881*_Complex_I, -0.848542045588 + 0.265512380995*_Complex_I, 0.224076450439 + -2.302360677412*_Complex_I, -0.510056035858 + -1.331941821231*_Complex_I, 1.682894720322 + 1.515017086970*_Complex_I, -0.293255187957 + 0.559255597549*_Complex_I, 1.692889886331 + -1.640844999342*_Complex_I, -1.032973350809 + 0.405524091118*_Complex_I, 0.177413388869 + -1.166118195604*_Complex_I, -0.077664879368 + -1.471655833896*_Complex_I, -0.713927870525 + 1.118966977478*_Complex_I, 3.112942596938 + 0.183067680138*_Complex_I, -2.132342418783 + 0.888305824658*_Complex_I, 0.570015793758 + -1.075297345387*_Complex_I, 0.029232277101 + -0.052772048068*_Complex_I, 0.021810229730 + 1.026136624357*_Complex_I, 0.183820954153 + 0.359011138378*_Complex_I, -0.646415125847 + 0.878859460005*_Complex_I, 0.379503797426 + 0.690555809274*_Complex_I, -1.205501520591 + -1.281704908973*_Complex_I, -0.671296057445 + -1.202380495393*_Complex_I, 1.000730854392 + 1.337218974137*_Complex_I, -0.507823699969 + 0.667041823900*_Complex_I, 0.786493220706 + 0.711624105805*_Complex_I, -0.147343975279 + -0.421666316903*_Complex_I, 1.000992786069 + 0.072055493934*_Complex_I, -0.638324259500 + 0.503386775311*_Complex_I, 1.518863022405 + -0.447779056699*_Complex_I, -0.690987494413 + 0.744128091375*_Complex_I, 0.074647158829 + -1.048901976585*_Complex_I}; float complex fft_test_y35[] = { 2.309567594431 + -5.331826820366*_Complex_I, -7.442846930878 + -4.725553620071*_Complex_I, -2.183297818919 + 6.404493143269*_Complex_I, -2.751014847029 + 2.658941664250*_Complex_I, 8.330534466967 + 0.919074147759*_Complex_I, 6.588325473188 + -2.237962814214*_Complex_I, -7.983324045653 + -4.751388462518*_Complex_I, 9.842334426677 + -4.886656356639*_Complex_I, 2.723677138226 + -1.864201873505*_Complex_I, 3.314550864796 + -2.486087207928*_Complex_I, -9.968089532702 + -11.225031015883*_Complex_I, 3.348282695100 + 3.685146610266*_Complex_I, 3.650591794608 + 7.864477419325*_Complex_I, 12.324040428213 + -2.521426915911*_Complex_I, -1.118920460046 + -5.025187742730*_Complex_I, 14.513400880941 + 11.251977643133*_Complex_I, -2.482556277234 + -3.095357211645*_Complex_I, -7.549326283090 + 3.844289159351*_Complex_I, -6.554611159279 + -1.426517057076*_Complex_I, 6.564157092619 + 4.071022052298*_Complex_I, 5.022588868136 + -15.817689097768*_Complex_I, -5.251727726400 + 2.789037545358*_Complex_I, -2.128113345135 + -15.921584799030*_Complex_I, -6.717549051974 + 1.209151038219*_Complex_I, 3.222807461576 + 5.205190352829*_Complex_I, -2.420694516532 + -6.628232249491*_Complex_I, -0.210938110900 + 1.317502940068*_Complex_I, -4.284810675111 + 4.379050426632*_Complex_I, -1.842031171135 + 3.520287066742*_Complex_I, 5.259391106033 + -9.692983760094*_Complex_I, -3.879590649031 + 2.871689364722*_Complex_I, -1.641216184114 + 4.267406466810*_Complex_I, 1.294145378923 + -2.702480168973*_Complex_I, 1.886124883788 + -3.741139781213*_Complex_I, 7.958277715545 + -3.144460685955*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_36.c000066400000000000000000000114071317124540100214350ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 36-point transform // #include float complex fft_test_x36[] = { -0.515260084522 + 1.287529717076*_Complex_I, 0.587117158481 + -0.148572876243*_Complex_I, -0.782947562463 + 1.641852621518*_Complex_I, -0.526927266439 + 0.584647073200*_Complex_I, -1.531349139822 + -1.069623628897*_Complex_I, 1.018192400002 + -0.793147230271*_Complex_I, -1.074504882712 + -0.091149144200*_Complex_I, -0.401657438434 + 0.004317962559*_Complex_I, 1.259620132258 + -0.104377362194*_Complex_I, -0.102194404981 + -0.973411762169*_Complex_I, -0.895434561911 + -1.050093649832*_Complex_I, 1.026577410282 + 1.080478300358*_Complex_I, 0.691470386469 + -0.436083438367*_Complex_I, -0.230801075525 + 1.635643257519*_Complex_I, -0.121589188789 + 0.070584124184*_Complex_I, 0.332245123083 + 0.603463018191*_Complex_I, 0.098342650657 + 0.713292188052*_Complex_I, -0.653525164870 + 0.226711651388*_Complex_I, -0.486468735347 + 0.247902880597*_Complex_I, -0.092383856045 + 0.443156295025*_Complex_I, -1.207432550343 + -0.503252568552*_Complex_I, 0.680629730441 + 0.210743200774*_Complex_I, -1.655855919610 + 0.985314552623*_Complex_I, -0.635578415199 + 1.126805769525*_Complex_I, 0.429626094959 + -0.591166406548*_Complex_I, 0.843172830682 + -0.010918445865*_Complex_I, -0.130407009132 + 0.920489918178*_Complex_I, 0.879595565427 + 0.076478701355*_Complex_I, 0.407356105015 + 0.244802856694*_Complex_I, -0.247029167369 + 1.416537545584*_Complex_I, 0.001447109646 + -0.855321598060*_Complex_I, -1.005160244372 + 0.880697474487*_Complex_I, -1.506889600501 + -0.376866773437*_Complex_I, 0.595335431863 + 0.874899791600*_Complex_I, -1.720946712489 + -0.251050064927*_Complex_I, -0.304668621370 + -0.437688673914*_Complex_I}; float complex fft_test_y36[] = { -6.978283472983 + 7.583625277009*_Complex_I, -6.674217696450 + -3.304059977181*_Complex_I, -9.133615960691 + 4.553754806959*_Complex_I, 7.138280833022 + -0.461421293427*_Complex_I, 6.376807409683 + -0.306551799085*_Complex_I, 2.594166782732 + 4.623935739453*_Complex_I, 2.991096252215 + -1.709441742997*_Complex_I, 7.042547687256 + -5.210100129931*_Complex_I, -3.291195373643 + -2.837550873581*_Complex_I, 3.068320668506 + -5.673130538045*_Complex_I, 1.959771299385 + -2.235257672510*_Complex_I, -10.609066858652 + 0.928096828820*_Complex_I, 3.208839022246 + 0.484194748895*_Complex_I, 2.548602732505 + 9.743720342785*_Complex_I, 6.240917395617 + 6.571681544646*_Complex_I, -4.101181674885 + 4.039956075121*_Complex_I, -9.685452992487 + 0.380605286598*_Complex_I, -3.555255829985 + 3.488301753752*_Complex_I, -10.504163464296 + -6.018056829194*_Complex_I, -2.111740241301 + 1.705549685664*_Complex_I, 2.140088966360 + 7.541207884663*_Complex_I, 0.985036473018 + -0.558056384811*_Complex_I, -1.305685512500 + 8.210384283174*_Complex_I, 4.783233947768 + -2.666144508286*_Complex_I, 6.484426654393 + -5.252223925558*_Complex_I, -2.313461997972 + 5.743487698749*_Complex_I, -1.086778704978 + 8.029162089587*_Complex_I, 6.916062245443 + 0.764580425536*_Complex_I, -2.415195588075 + -0.073706064002*_Complex_I, -5.346986333451 + -3.512605491284*_Complex_I, -0.924055660625 + 2.282174534826*_Complex_I, -0.470350054245 + 2.031728408857*_Complex_I, 2.141016439694 + -1.773104703203*_Complex_I, -1.014341113192 + 7.641158118573*_Complex_I, -4.249655466965 + 2.206889911886*_Complex_I, 0.602106144731 + -0.611713697716*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_4.c000066400000000000000000000032041317124540100213440ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 4-point transform // #include float complex fft_test_x4[] = { -2.218920151449 + -1.079004048069*_Complex_I, 0.045264423484 + 0.426155393025*_Complex_I, 0.218614474268 + -0.334711618319*_Complex_I, 2.182538230032 + 1.706944462070*_Complex_I}; float complex fft_test_y4[] = { 0.227496976335 + 0.719384188708*_Complex_I, -3.718323694762 + 1.392981376798*_Complex_I, -4.228108330697 + -3.546815521483*_Complex_I, -1.156745556672 + -2.881566236299*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_43.c000066400000000000000000000127031317124540100214330ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 43-point transform // #include float complex fft_test_x43[] = { 0.086214736594 + -0.374055466225*_Complex_I, -0.398326405553 + 0.064437628903*_Complex_I, -0.086828498048 + -1.377541893939*_Complex_I, -0.014057206023 + -1.721581520365*_Complex_I, -1.130661886812 + -0.823144321334*_Complex_I, 0.265330564080 + -2.139333421737*_Complex_I, 0.987278886883 + 0.510016610694*_Complex_I, 1.388439583820 + -0.312226254937*_Complex_I, 1.314187441787 + 2.179164255828*_Complex_I, -0.134438842798 + -2.204082595282*_Complex_I, 0.245609009336 + 0.112479617279*_Complex_I, -1.038607185161 + 0.772906423002*_Complex_I, 0.816938259734 + -2.090685529624*_Complex_I, 0.975237183551 + -0.563625353818*_Complex_I, -0.941942184460 + 1.392834491457*_Complex_I, 1.369305972621 + 0.035788913101*_Complex_I, 0.274358812513 + 0.334025802789*_Complex_I, -0.187955769606 + 0.806622195637*_Complex_I, -0.435359111927 + 0.395863170294*_Complex_I, -1.059982565487 + -1.108626336147*_Complex_I, -0.085915350568 + -0.294840267490*_Complex_I, -0.202754288995 + -0.413065083074*_Complex_I, -0.607968226502 + 1.253761902790*_Complex_I, 2.921829936105 + 1.400641655759*_Complex_I, 0.493898754300 + 2.597915340403*_Complex_I, -0.939016287203 + 0.999025234458*_Complex_I, -1.213828533796 + -0.093371812474*_Complex_I, 0.049357784794 + -1.117710210403*_Complex_I, 0.291427701377 + 0.619473850471*_Complex_I, -0.297284045241 + 1.471963630624*_Complex_I, -1.204828141785 + 0.357668469775*_Complex_I, 1.214147177406 + -1.053652949447*_Complex_I, -0.669099873019 + 0.645208133613*_Complex_I, -0.669325749409 + 1.526826939113*_Complex_I, 1.388489801757 + -0.663313867864*_Complex_I, 1.528893702905 + -0.300643090523*_Complex_I, 0.969651597440 + 0.887262607328*_Complex_I, 0.961949407503 + -1.302265834141*_Complex_I, 0.025366344758 + 1.938755581562*_Complex_I, 0.012954685257 + -0.117840651513*_Complex_I, 0.422317736906 + 0.454593332125*_Complex_I, -1.225108444904 + -0.762684444639*_Complex_I, 0.510768457794 + 0.200474501150*_Complex_I}; float complex fft_test_y43[] = { 5.970664941924 + 2.123419383178*_Complex_I, -4.826258373494 + -10.530035821412*_Complex_I, -6.840438649504 + 2.195697396144*_Complex_I, -15.037444321130 + -0.498694877295*_Complex_I, -2.324178679783 + -5.588631770237*_Complex_I, -9.817989632278 + 8.215797271526*_Complex_I, 19.440508234356 + 0.725796090385*_Complex_I, -0.273833848905 + 4.924507895251*_Complex_I, 5.898110303453 + -7.584923619025*_Complex_I, -1.491058783404 + 7.983518326557*_Complex_I, -7.459786425320 + -5.471409031844*_Complex_I, 9.458054840383 + -1.411338639410*_Complex_I, -7.652963176561 + 16.470882260110*_Complex_I, 4.933008347551 + 1.752692467372*_Complex_I, 3.158349989133 + -10.520004874496*_Complex_I, 3.461440707146 + -1.053485004255*_Complex_I, 0.403169282390 + 15.216737475743*_Complex_I, 11.005277294499 + 0.924950795722*_Complex_I, -2.459303339406 + -4.952009870945*_Complex_I, -11.998504221115 + -4.269332241730*_Complex_I, -10.575401537817 + 0.521491539120*_Complex_I, -8.612771844559 + -4.765648940500*_Complex_I, 7.802134874811 + 3.882271887067*_Complex_I, 2.664085789892 + -5.430064274009*_Complex_I, 7.012256247961 + -6.119235310609*_Complex_I, -0.520208603756 + -0.845655711277*_Complex_I, 0.308220700989 + 3.533138362895*_Complex_I, -10.811305738786 + -4.238039944052*_Complex_I, 6.001274292511 + -2.592573440494*_Complex_I, 5.544361033380 + -11.920579663414*_Complex_I, -2.095258565391 + 0.336151200781*_Complex_I, -5.596706630782 + 7.291207810674*_Complex_I, 9.325757124002 + -3.598787999557*_Complex_I, 1.133897756930 + -1.612056679027*_Complex_I, -2.012305507947 + 5.032886593926*_Complex_I, -10.072407904704 + 5.354603355501*_Complex_I, 2.641399130952 + -1.713592877295*_Complex_I, 1.128116547129 + 7.394974387525*_Complex_I, 12.210114373933 + -3.041200993402*_Complex_I, -0.850951175674 + 3.946134783722*_Complex_I, -1.686631417770 + -4.776809881210*_Complex_I, -2.550902604765 + -2.082230855079*_Complex_I, 9.773642843061 + -9.294902010297*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_48.c000066400000000000000000000136671317124540100214520ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 48-point transform // #include float complex fft_test_x48[] = { -1.408383409504 + 0.661990153106*_Complex_I, -0.257850483647 + -2.392863066952*_Complex_I, -0.321563284081 + 1.408168751420*_Complex_I, -1.963488918325 + -0.315363008755*_Complex_I, 0.872572043811 + -1.774358495756*_Complex_I, -1.036243090405 + 0.085162186806*_Complex_I, -0.810463329242 + 0.370726012575*_Complex_I, 0.814727688017 + -0.148930236445*_Complex_I, -0.482188504339 + -0.888806074906*_Complex_I, 0.751010250272 + 0.610241893778*_Complex_I, 1.562853718365 + 0.338170177897*_Complex_I, 0.836367957185 + -1.685869538958*_Complex_I, -0.678836393610 + -1.105381292997*_Complex_I, 1.313536222418 + -1.604103598331*_Complex_I, 0.652309130012 + -1.915192986159*_Complex_I, -0.398123599463 + 1.372136473305*_Complex_I, 2.555137160099 + 0.715094591241*_Complex_I, 1.803926723963 + -0.470162240275*_Complex_I, -1.033969686967 + -1.754083599107*_Complex_I, 0.345505105620 + 1.869665415226*_Complex_I, 0.917886037796 + 1.488788889124*_Complex_I, -0.149819207787 + 0.641387132093*_Complex_I, 0.239135545455 + 0.491166352445*_Complex_I, 0.571741246274 + 0.056534896965*_Complex_I, -0.131630105163 + -1.508920032468*_Complex_I, 1.209119501276 + -0.078706912158*_Complex_I, -0.955610498388 + 1.044137820022*_Complex_I, 0.106457806412 + -0.585542024212*_Complex_I, -1.229933443664 + -0.322249167809*_Complex_I, 0.278186189361 + 1.807684972303*_Complex_I, -1.729784506112 + -0.939519586014*_Complex_I, 0.927483189137 + 0.431322133098*_Complex_I, 0.141968377392 + -0.120521833531*_Complex_I, 0.747436107175 + -1.117297332586*_Complex_I, 0.321427506892 + 0.604553538042*_Complex_I, -1.310259971951 + 0.301350874871*_Complex_I, 0.000616127451 + 1.395956853708*_Complex_I, 0.789283665376 + -0.378417239374*_Complex_I, 1.626071060809 + -0.838198796474*_Complex_I, -0.502170615893 + -0.371786828507*_Complex_I, 0.941560993676 + 0.083132997096*_Complex_I, 0.217335920952 + -0.775367298569*_Complex_I, -1.386726382455 + 1.228033537755*_Complex_I, 0.135305964480 + 1.010214926902*_Complex_I, -0.769134001940 + -1.642182708631*_Complex_I, 0.451443995268 + -1.443277308466*_Complex_I, 0.315403114502 + 0.409584212993*_Complex_I, 0.777007938735 + 0.033642728423*_Complex_I}; float complex fft_test_y48[] = { 5.666636855245 + -5.718253686246*_Complex_I, -9.318440723038 + -11.045628239935*_Complex_I, -10.484391800934 + 10.258547835119*_Complex_I, 5.692975013010 + -0.079178697546*_Complex_I, -0.031494239726 + -3.429117974659*_Complex_I, -1.633492827483 + 6.955978741593*_Complex_I, 9.741303637543 + 2.061588265899*_Complex_I, 1.051018454307 + 11.180284489721*_Complex_I, -8.006452512021 + 0.459314562290*_Complex_I, -7.397134103296 + 6.198088361763*_Complex_I, 4.688329496623 + 1.626283668222*_Complex_I, -8.380975402709 + -3.715659857481*_Complex_I, -4.832542130429 + -9.241813561210*_Complex_I, -5.444148048877 + -5.774968307876*_Complex_I, -2.557281197147 + -8.013068178874*_Complex_I, -2.508606838763 + 3.393130955025*_Complex_I, -13.856615792482 + -8.279988253172*_Complex_I, -0.275213201833 + 9.234040467214*_Complex_I, -10.548623142987 + 1.461152259705*_Complex_I, -5.454201445127 + 5.015988800202*_Complex_I, 3.151148175752 + 16.404964892896*_Complex_I, -2.628471739476 + 12.549705973202*_Complex_I, -5.309278338161 + -1.496205611507*_Complex_I, 8.327510797620 + 9.076602173656*_Complex_I, -7.249202313653 + 0.578432313391*_Complex_I, 0.278119672993 + 6.335493150399*_Complex_I, -4.400202487177 + 4.358641062270*_Complex_I, 1.825561215029 + -10.742991731336*_Complex_I, 2.059618967411 + 5.230483842207*_Complex_I, -0.589368957248 + -0.568413649725*_Complex_I, 5.846114680415 + 3.953722464016*_Complex_I, -4.790203069855 + 5.357335572595*_Complex_I, -16.219316666593 + 5.416145069047*_Complex_I, 4.053779640014 + 14.490156426037*_Complex_I, 10.343285976607 + -19.941466772140*_Complex_I, -0.179745539698 + -6.776924924303*_Complex_I, 9.333647116859 + 2.311810446775*_Complex_I, -0.778589953827 + -7.796695480692*_Complex_I, -5.728518422011 + -0.187241621271*_Complex_I, 15.554791252022 + 3.837751365144*_Complex_I, -3.410115684107 + -2.362837725953*_Complex_I, -14.699080682437 + 4.704009521181*_Complex_I, 4.974381394298 + -3.870880098021*_Complex_I, 4.347015481178 + 1.639590273798*_Complex_I, 6.775882853829 + -8.045391749167*_Complex_I, -6.905056488040 + -1.077414483536*_Complex_I, -6.906638779165 + -3.861138554296*_Complex_I, -0.790121808651 + -0.288436445313*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_5.c000066400000000000000000000033501317124540100213470ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 5-point transform // #include float complex fft_test_x5[] = { 1.043452789296 + -0.216675780077*_Complex_I, -0.039259154719 + -0.756503590362*_Complex_I, -1.378329383804 + -1.629692578129*_Complex_I, 0.695728357044 + -2.639675956000*_Complex_I, -0.019932891052 + 0.123958045411*_Complex_I}; float complex fft_test_y5[] = { 0.301659716765 + -5.118589859158*_Complex_I, 1.333681830770 + 4.279329517647*_Complex_I, -0.597668794979 + -2.985429553632*_Complex_I, 2.358478480201 + 0.936943320049*_Complex_I, 1.821112713724 + 1.804367674708*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_509.c000066400000000000000000001457161317124540100215350ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 509-point transform // #include float complex fft_test_x509[] = { 0.359331995889 + -1.085301108776*_Complex_I, -1.932383412518 + 0.116856180907*_Complex_I, 0.496271262268 + 0.731796541816*_Complex_I, 0.431573865944 + 0.591703481184*_Complex_I, 0.589253369531 + -0.795072338555*_Complex_I, -0.870697944847 + -0.497562617185*_Complex_I, 1.247223411086 + 0.771429589056*_Complex_I, 0.924873577618 + -1.184353621638*_Complex_I, 0.659579079487 + 0.126294704315*_Complex_I, 1.647221437368 + -2.249906156787*_Complex_I, -1.334652205984 + -0.024425874102*_Complex_I, 0.095148747858 + -0.284583137620*_Complex_I, -2.534039905928 + 1.936731699042*_Complex_I, 0.370565605548 + -0.671454121821*_Complex_I, 0.382886168067 + 0.318205203845*_Complex_I, -1.314163630052 + 0.381239207410*_Complex_I, -0.258334295223 + 0.599344826242*_Complex_I, 1.542372805791 + -0.381018806439*_Complex_I, -0.015408662897 + 1.208686378191*_Complex_I, -3.023761214358 + -0.135651280290*_Complex_I, -0.916610967637 + 0.884088889046*_Complex_I, -2.081046862959 + 2.001230452826*_Complex_I, 1.031862595677 + 1.366475262140*_Complex_I, -0.259564882667 + 0.315307538802*_Complex_I, 0.161129496712 + -1.667686892086*_Complex_I, -1.241250123646 + 1.380715267035*_Complex_I, 0.027019787139 + 2.068943431414*_Complex_I, 0.164488255181 + -0.688316587237*_Complex_I, 1.114819509678 + -3.008077068837*_Complex_I, -1.374358189256 + 0.000217799371*_Complex_I, 1.783814617294 + -0.127391483103*_Complex_I, 1.648034611975 + -0.251680996856*_Complex_I, 1.678583258653 + 1.974165102901*_Complex_I, -0.857815837356 + -3.739419503346*_Complex_I, 1.227762010986 + -0.496092919671*_Complex_I, 0.275130781058 + 1.160971226357*_Complex_I, 0.333840127696 + 1.388036870908*_Complex_I, -0.805343489373 + 0.006883877363*_Complex_I, 0.113234013309 + 0.031253576243*_Complex_I, -0.610537915176 + 0.630710349348*_Complex_I, 1.397240850777 + -2.014373420814*_Complex_I, -0.255790837573 + 0.916792397001*_Complex_I, 0.129924388336 + -0.537587690895*_Complex_I, -0.926838068677 + 0.308336177664*_Complex_I, 3.010372178544 + -2.369144950446*_Complex_I, 1.263300917549 + -1.660219437257*_Complex_I, 0.841656993731 + 1.927041610736*_Complex_I, -0.904792064104 + -1.173048767457*_Complex_I, 0.989814388062 + 1.253071554414*_Complex_I, -0.257249205993 + -0.959941785447*_Complex_I, -1.205852496010 + 0.196179577313*_Complex_I, 1.940909824834 + -2.078512378665*_Complex_I, 0.300600588979 + 0.572506173199*_Complex_I, -0.375271364555 + -0.773019164981*_Complex_I, -0.858303843109 + -0.674765891031*_Complex_I, -1.189090659992 + 0.543093004900*_Complex_I, 2.165334883903 + 0.001082499227*_Complex_I, 2.057289953335 + -0.916206975165*_Complex_I, -0.161982761480 + -0.815858087637*_Complex_I, -1.390044285564 + -0.714076838951*_Complex_I, 0.766348194222 + 0.076251375781*_Complex_I, -0.630967707884 + 0.854026208416*_Complex_I, -1.309424118846 + 0.470225939681*_Complex_I, 0.664797780343 + -1.109803637533*_Complex_I, 3.563726896705 + 1.370311380835*_Complex_I, 0.850424444505 + -0.770251870088*_Complex_I, 0.316880772888 + -0.509312503865*_Complex_I, -1.439495581618 + -1.741765587801*_Complex_I, -1.095540513740 + 0.552478238644*_Complex_I, -0.879540480746 + -1.782154665595*_Complex_I, 1.394922475961 + 0.407153930461*_Complex_I, -1.583206834198 + 0.548532742373*_Complex_I, -0.330266310339 + 0.821466818961*_Complex_I, -1.157454328378 + 0.386301239269*_Complex_I, 0.823214183923 + 0.993600792956*_Complex_I, -0.665523708393 + -0.143306700746*_Complex_I, -2.274210663640 + -0.526858961140*_Complex_I, 0.675171584769 + 1.608754308056*_Complex_I, 0.067605428754 + 0.840683747814*_Complex_I, 0.927563962378 + 0.563153155030*_Complex_I, -0.129920407968 + 0.614536449089*_Complex_I, -0.633778727653 + 0.174141369494*_Complex_I, -0.579622089160 + -1.179631499150*_Complex_I, 3.157266013709 + 0.841577893721*_Complex_I, -1.564968432235 + 0.237536721331*_Complex_I, 0.832675154129 + 2.752538330003*_Complex_I, -1.003618718524 + -0.803502222719*_Complex_I, 1.033045390907 + -0.887091010037*_Complex_I, 0.406299848093 + -0.231522470982*_Complex_I, -1.224877731528 + 0.962620343882*_Complex_I, -0.287856500251 + -0.684348325534*_Complex_I, 0.769551121775 + 1.052171601110*_Complex_I, 1.211938362349 + -0.397315302619*_Complex_I, -1.801171069328 + 0.782481239455*_Complex_I, -0.428774166115 + 0.205654171857*_Complex_I, 0.742768169350 + 1.078779525233*_Complex_I, -0.760778783880 + -0.392123510805*_Complex_I, 0.530474251890 + 0.355891481054*_Complex_I, 1.455692020840 + 0.275438176816*_Complex_I, -0.256274791959 + -1.055463927568*_Complex_I, 1.397683977888 + -1.672842861191*_Complex_I, 1.059395488056 + -1.195826863369*_Complex_I, 0.535641711388 + -0.139593755691*_Complex_I, 0.767194249054 + 1.159606442946*_Complex_I, 0.730248752053 + 0.874096637495*_Complex_I, 0.374817248354 + 0.381042720649*_Complex_I, -1.290660859871 + -1.052408951473*_Complex_I, -0.698710060780 + -0.404862720632*_Complex_I, 0.260762012984 + -0.586144943477*_Complex_I, 0.471825306906 + 0.216309496806*_Complex_I, 0.902145392649 + 0.734793058179*_Complex_I, 0.970712066057 + 1.203301629983*_Complex_I, 0.697414298916 + -0.091399436653*_Complex_I, -0.763151612464 + -0.155822503488*_Complex_I, 0.571013025643 + -0.991520969075*_Complex_I, 0.488145846303 + 0.518072470835*_Complex_I, 0.382903596789 + -0.570642408749*_Complex_I, -0.068409602398 + -0.457729632233*_Complex_I, 0.328633596900 + -0.485642431490*_Complex_I, 1.463236532852 + -0.689222532447*_Complex_I, 0.843726237994 + 1.027737725483*_Complex_I, 0.411174457800 + 1.072703354585*_Complex_I, -0.553638496687 + 0.592560929746*_Complex_I, -0.519820674211 + 0.395335990219*_Complex_I, 0.816739721990 + 1.296561601952*_Complex_I, 0.839055358910 + 0.038232944058*_Complex_I, -1.321845319423 + 2.461463566622*_Complex_I, -1.244535108317 + -0.855331739033*_Complex_I, 0.174834515541 + -0.236103345803*_Complex_I, -0.817712897113 + 0.503960726952*_Complex_I, -0.723518973851 + 0.751673530926*_Complex_I, -0.189283180062 + 0.644019002779*_Complex_I, 0.237729751553 + 0.335607912526*_Complex_I, -0.969216001025 + -0.603266829416*_Complex_I, -0.207478679057 + -0.730339402811*_Complex_I, -0.024191569913 + -1.259252874185*_Complex_I, 1.472785074216 + -0.491418040669*_Complex_I, 0.143580527900 + -1.186038294726*_Complex_I, 0.835958076660 + 1.651209544972*_Complex_I, -1.330070431715 + 0.745655269480*_Complex_I, -2.351132556248 + 1.414206325062*_Complex_I, -0.647960722564 + 0.019824747070*_Complex_I, 0.054504089094 + -0.434505484307*_Complex_I, -1.069009000323 + 0.930859192631*_Complex_I, 2.256466805965 + 0.677754214770*_Complex_I, -1.017788464214 + 0.299270915482*_Complex_I, -1.350006249149 + 0.860365863370*_Complex_I, 0.554243078961 + 1.630321512911*_Complex_I, -1.709590344454 + -0.169567705711*_Complex_I, 0.650774374311 + 0.064592934208*_Complex_I, 1.989755256430 + 0.536482018456*_Complex_I, -0.373249333538 + -0.106134582591*_Complex_I, 0.095351627343 + -0.279297038594*_Complex_I, 0.230789928160 + 0.532796285505*_Complex_I, 0.247854968690 + -2.153358768182*_Complex_I, 0.136098798048 + 1.135668579132*_Complex_I, -0.208329927938 + 0.789350627066*_Complex_I, 0.039858273209 + -0.599940553834*_Complex_I, -0.117101531764 + 0.201275502180*_Complex_I, 0.817971264476 + -1.329760648517*_Complex_I, 0.035980481979 + -0.922818951948*_Complex_I, -1.888935382734 + -1.797450884362*_Complex_I, -0.097016985104 + -1.168628933267*_Complex_I, 0.452048304507 + -0.675116763083*_Complex_I, -1.209707805549 + 0.172148052410*_Complex_I, 1.432472352322 + 0.632406226221*_Complex_I, 2.933280640140 + 0.949590441066*_Complex_I, -0.309024453832 + 1.192611727581*_Complex_I, -0.255306372880 + 0.007559617013*_Complex_I, 0.081653931435 + -0.672920464273*_Complex_I, 0.405276164696 + -0.077841212841*_Complex_I, -0.338396874520 + 0.355225122224*_Complex_I, 0.109601214660 + 1.392547443330*_Complex_I, -1.871393476572 + 0.310989021924*_Complex_I, 0.332233956611 + 1.730122993833*_Complex_I, 1.439926026777 + -1.611064773734*_Complex_I, -1.860778448552 + 0.425384165779*_Complex_I, 0.274648666779 + 1.286600320037*_Complex_I, 0.762615580678 + -0.222402755827*_Complex_I, 0.426513801822 + 1.965805792967*_Complex_I, -0.103171697634 + -0.569960476279*_Complex_I, 1.562067509000 + -2.347766792543*_Complex_I, 0.467044769684 + 0.321342630659*_Complex_I, -1.416578640685 + -0.831113210732*_Complex_I, -0.733167805614 + 1.176375168746*_Complex_I, -1.282613845051 + -0.979773114694*_Complex_I, 0.506103347478 + -1.085270279646*_Complex_I, 2.539137831319 + 2.232625718408*_Complex_I, -1.637899545016 + 0.265528606195*_Complex_I, -1.931767882639 + 0.329066225098*_Complex_I, 0.127023806083 + 0.504962043815*_Complex_I, 0.588353928765 + -1.463911658760*_Complex_I, 0.907010785485 + -0.108879037057*_Complex_I, -0.951802902717 + -0.685757383062*_Complex_I, 1.723143501154 + -0.419300229480*_Complex_I, -0.943119843417 + 0.652144368853*_Complex_I, -0.851586780301 + -1.516257192307*_Complex_I, 0.472227887604 + 1.052236419944*_Complex_I, 0.113888251161 + -1.124587148028*_Complex_I, 0.051529667469 + -0.136410527640*_Complex_I, -0.647857223628 + 0.431204980149*_Complex_I, 1.349209612218 + -0.768179692308*_Complex_I, -0.026826971021 + -0.545234111539*_Complex_I, -0.514071604921 + -0.664124619949*_Complex_I, 0.320778745077 + 1.111997835236*_Complex_I, -0.232562962611 + -0.669159856913*_Complex_I, -0.896014800467 + 0.082046851667*_Complex_I, -0.167690950519 + -1.119443226265*_Complex_I, -0.433053084055 + -0.204133858571*_Complex_I, -1.567141147453 + -0.972571871430*_Complex_I, -1.040971048402 + 0.473975308345*_Complex_I, -1.551423307502 + -0.934406696693*_Complex_I, 1.267729903934 + 2.062089282704*_Complex_I, -0.814068862944 + -0.268491284145*_Complex_I, 0.721715833176 + -0.368317000932*_Complex_I, -0.236677967201 + -1.031498627296*_Complex_I, -0.027596539058 + -0.526943246450*_Complex_I, 0.607765602666 + 0.747238787304*_Complex_I, 0.442222664332 + -0.844428479402*_Complex_I, -0.584746227099 + 0.008876873310*_Complex_I, 0.249251666407 + 1.120945916837*_Complex_I, 0.406090989317 + -0.832304494623*_Complex_I, -1.420792340638 + 0.417700569682*_Complex_I, 0.469433523536 + -0.703036988315*_Complex_I, 0.799192929845 + 0.584252218542*_Complex_I, -0.846345284557 + -0.125059394154*_Complex_I, 0.187771816466 + 0.373470766869*_Complex_I, -2.668531322148 + 0.189825888614*_Complex_I, 0.684689436275 + 1.519032618934*_Complex_I, -0.452797714368 + 1.843053037274*_Complex_I, -0.614449241246 + -0.006236652039*_Complex_I, 0.929289964606 + 0.965819481866*_Complex_I, 0.800433661968 + 0.829558429420*_Complex_I, -1.088281420026 + -0.801332579437*_Complex_I, -0.080346758942 + 0.412114096369*_Complex_I, 1.491530334351 + -0.037720112002*_Complex_I, -1.419313834957 + 1.309423611663*_Complex_I, 0.626194884901 + 0.448698878768*_Complex_I, 1.062456184701 + -1.574268630848*_Complex_I, -0.284112227827 + 0.550018601059*_Complex_I, -0.080443635589 + -1.362211376503*_Complex_I, 0.383016098417 + 1.081967093575*_Complex_I, 0.484156075687 + -0.162493291081*_Complex_I, -0.632696839217 + -1.499586717062*_Complex_I, 1.771132365818 + -0.691460076219*_Complex_I, 1.177429509865 + -0.486631740300*_Complex_I, 0.452912528112 + 1.368403825897*_Complex_I, 0.007493867542 + -0.269397882793*_Complex_I, -1.107355722972 + 0.037650076863*_Complex_I, -0.524329801696 + 1.542074025962*_Complex_I, 0.448469395501 + 0.620253813644*_Complex_I, 0.937797278085 + 0.094893367525*_Complex_I, 0.244627220423 + -0.865982595984*_Complex_I, -0.620857271928 + 1.618502476045*_Complex_I, -0.727959747987 + -1.748132622853*_Complex_I, -1.814748553219 + 0.357659723379*_Complex_I, -1.190951476209 + -0.302683547331*_Complex_I, -0.642926196548 + -0.441431483518*_Complex_I, 0.906018063143 + -0.456267895782*_Complex_I, 1.658412527962 + 0.602929674812*_Complex_I, -1.372573150919 + -0.165247494352*_Complex_I, 0.701050669178 + 0.784117117798*_Complex_I, -1.093947418964 + -2.169417895648*_Complex_I, -0.619306010978 + 0.346306836794*_Complex_I, -1.153602396000 + 0.310559458662*_Complex_I, 1.857961002742 + 1.662749378565*_Complex_I, 0.726892056406 + 0.559412940831*_Complex_I, 0.618501787181 + 0.753344508665*_Complex_I, 0.060088823625 + -1.132388678000*_Complex_I, -0.790715886898 + 1.256189591885*_Complex_I, -1.346611550340 + -1.002213804884*_Complex_I, -0.153748736848 + -1.273877582585*_Complex_I, -1.102237529635 + -1.113178017398*_Complex_I, -0.526084982723 + 1.255781208343*_Complex_I, -0.738929991536 + 1.454321302002*_Complex_I, -1.015352909554 + 0.057528759460*_Complex_I, 0.675998598897 + -0.143860246243*_Complex_I, 0.189558927003 + 0.513691656677*_Complex_I, 0.009183574378 + 0.963901374647*_Complex_I, -0.163787067951 + -1.522554558143*_Complex_I, 0.302708128196 + 0.904573259262*_Complex_I, 0.975710589669 + -1.011907000330*_Complex_I, -0.117268931532 + 0.858171829955*_Complex_I, -1.306428434179 + 0.113727230388*_Complex_I, -0.959251067394 + 0.253171642011*_Complex_I, 0.898435910380 + 0.293195734212*_Complex_I, -0.621680975624 + -0.582564866291*_Complex_I, 0.179461744683 + 0.209868112155*_Complex_I, -0.203784114877 + -0.011115684099*_Complex_I, 1.795424157294 + -0.117231500488*_Complex_I, 0.015989098360 + -0.642768987364*_Complex_I, -1.375016631330 + -2.085463142461*_Complex_I, -0.655990108553 + 0.722884678316*_Complex_I, 1.172312994480 + -0.355468862899*_Complex_I, -0.564442301948 + 0.323979441156*_Complex_I, 0.899045729865 + -1.148993122117*_Complex_I, 1.045854100254 + 1.711078921366*_Complex_I, 0.592020255938 + 0.219085296351*_Complex_I, 0.118211086528 + -1.123504917557*_Complex_I, 0.233426106939 + -1.883587119594*_Complex_I, -0.301438222142 + -0.697732158432*_Complex_I, 0.312117398590 + -0.010728436711*_Complex_I, -0.956339212238 + 0.275577083186*_Complex_I, 1.086666854829 + -1.181802410378*_Complex_I, 1.074818739604 + -0.636045956563*_Complex_I, 0.644130821770 + -0.481626402565*_Complex_I, 0.055564592606 + -0.355383569012*_Complex_I, -1.710794754131 + -0.311499134725*_Complex_I, -1.357530095316 + 1.586038700811*_Complex_I, 0.643883320289 + -1.661496495893*_Complex_I, 0.916591063253 + 0.463263213793*_Complex_I, 0.795060678890 + 0.253692839397*_Complex_I, -0.353293483561 + -0.793786778605*_Complex_I, 1.523091692648 + 1.009541299320*_Complex_I, -0.351467193764 + -0.233882680674*_Complex_I, -1.006204919749 + -1.722099827433*_Complex_I, -0.425646600377 + -0.067539377037*_Complex_I, -2.152456912795 + 0.355174573898*_Complex_I, -1.397998826498 + 0.043192513073*_Complex_I, 0.463250457123 + 0.785418638026*_Complex_I, 0.551007796000 + -0.600950335023*_Complex_I, 1.336913064335 + 0.299718316993*_Complex_I, 0.576007704981 + -0.703000454871*_Complex_I, 0.501091983740 + 0.079592846760*_Complex_I, 0.178571647134 + -0.055720934489*_Complex_I, 0.843544810635 + 0.526236292547*_Complex_I, 1.354311088400 + -0.480046041766*_Complex_I, -1.121411263124 + -0.220337368903*_Complex_I, 0.018969956960 + -0.526588981826*_Complex_I, -0.874090913826 + 1.731623994129*_Complex_I, -1.108295529258 + 1.163520621835*_Complex_I, -0.656720377715 + 0.245096653391*_Complex_I, 0.625251262223 + 1.662769471886*_Complex_I, 0.503819391123 + -1.441549149924*_Complex_I, -0.164837089741 + -0.715463798642*_Complex_I, 0.355362378583 + 2.159694721953*_Complex_I, -0.008848280750 + -0.018260892822*_Complex_I, -0.136686667816 + 1.182755498355*_Complex_I, -0.136433742988 + 0.851417981048*_Complex_I, -0.395460120756 + 0.812014412771*_Complex_I, 0.025308338705 + 0.630907052235*_Complex_I, 1.006681294297 + 1.783315896794*_Complex_I, -0.402626477026 + 0.776761257059*_Complex_I, -1.317690399125 + 0.130484673594*_Complex_I, -0.868791706762 + -0.642771615764*_Complex_I, 0.137146795180 + -0.102157755198*_Complex_I, 1.633710393863 + -0.768782548860*_Complex_I, -0.867759427420 + 1.601477458878*_Complex_I, -1.157703488657 + -0.206031874994*_Complex_I, 0.041016911327 + -1.180389310249*_Complex_I, -0.189738035969 + -0.713067619743*_Complex_I, 0.933408353482 + 1.194576784859*_Complex_I, 0.514861178855 + 0.368016550894*_Complex_I, 0.881690626307 + 2.753761417447*_Complex_I, -0.133670635264 + 1.543292970173*_Complex_I, 2.091596895159 + -0.093690078394*_Complex_I, -1.188956830982 + -0.114523278237*_Complex_I, -0.053197690454 + 0.907571243350*_Complex_I, 0.401291232622 + -0.415340086801*_Complex_I, -0.681924799342 + 0.669543900292*_Complex_I, 0.530696047517 + -0.997585317896*_Complex_I, -0.533192039121 + -1.431729688530*_Complex_I, 0.536364895113 + 1.169805471895*_Complex_I, -1.016375434615 + -1.450239121127*_Complex_I, -1.561071693564 + -0.170486342837*_Complex_I, -0.183747193975 + -0.977837337154*_Complex_I, -0.181940033627 + -0.248171826564*_Complex_I, -0.328526087010 + -0.030637600322*_Complex_I, -1.002704137273 + -0.085997551664*_Complex_I, 1.368038996286 + -0.141325193319*_Complex_I, 0.403836121556 + 2.008528522943*_Complex_I, -0.810518568790 + -0.149400127852*_Complex_I, -0.693120904958 + -1.117715197785*_Complex_I, 1.558993909095 + -2.012078672111*_Complex_I, 0.029046234836 + -1.049286048426*_Complex_I, 0.790327688876 + 0.101616687460*_Complex_I, -0.401919211737 + -0.430529168165*_Complex_I, 0.287473232440 + -0.564999246068*_Complex_I, 1.716421030546 + -0.404965480273*_Complex_I, 0.050376052116 + 0.795529162825*_Complex_I, -1.281143070062 + 0.808984215487*_Complex_I, -2.314127686421 + -0.020801982220*_Complex_I, 1.606737133361 + 0.283817403079*_Complex_I, 0.355463854549 + 0.044155238023*_Complex_I, -1.076907023070 + 0.442916691766*_Complex_I, 0.087222702651 + 1.349524189157*_Complex_I, -1.625272715780 + 0.294000847904*_Complex_I, 2.355923230363 + 0.786258163154*_Complex_I, 0.590797134194 + -1.524824299804*_Complex_I, -0.247232063439 + 0.027525184425*_Complex_I, 0.422150431137 + 0.191460073698*_Complex_I, 0.333205469444 + 0.566695459783*_Complex_I, 2.040179995474 + -0.033523279638*_Complex_I, 1.708801210517 + -0.514673828477*_Complex_I, -1.148367840353 + 0.175705040636*_Complex_I, -0.208810451052 + 1.955963982995*_Complex_I, 0.277462389542 + 0.341691402206*_Complex_I, 1.115415958264 + 0.268951601110*_Complex_I, 0.039043618322 + 1.093842223424*_Complex_I, 0.154656090432 + -2.528281845522*_Complex_I, -0.169580739559 + 1.232275509700*_Complex_I, -0.117411131677 + -1.002389093350*_Complex_I, 0.035928732692 + 2.439878625945*_Complex_I, -0.332442060919 + 0.086411580288*_Complex_I, 1.801599291824 + -0.728371893507*_Complex_I, 2.510167669033 + 0.293277743476*_Complex_I, 1.336012143828 + 0.553373968985*_Complex_I, 0.179581375233 + 0.219695624924*_Complex_I, 0.593263517685 + 0.407445722133*_Complex_I, 0.684624183099 + 0.589697664907*_Complex_I, -2.496382874468 + 0.024438752127*_Complex_I, -2.222694698779 + 1.701453939912*_Complex_I, 0.154420002119 + -1.338536134506*_Complex_I, 0.256365846642 + -0.981555435302*_Complex_I, 0.646498405245 + 1.015323083702*_Complex_I, 1.816099125502 + -0.873689502536*_Complex_I, 0.973113786206 + 0.638143551822*_Complex_I, 1.082802452802 + 0.054273301693*_Complex_I, -1.477958702052 + -1.876253882821*_Complex_I, -1.509174430498 + -1.366946689175*_Complex_I, 0.770200379893 + -0.037358369644*_Complex_I, 0.020528472364 + 0.071112924686*_Complex_I, 1.163573145482 + 0.270667445496*_Complex_I, -0.685276141620 + 1.042179563446*_Complex_I, -1.450457525407 + -0.619572993396*_Complex_I, -1.087848848412 + 0.747504403403*_Complex_I, 0.182987452127 + 0.130972663746*_Complex_I, -0.146555893049 + 0.691910395951*_Complex_I, -1.735762675547 + -0.761410376033*_Complex_I, 0.130810608875 + -1.132633564866*_Complex_I, 0.393865724887 + -0.821588251430*_Complex_I, 1.287503514649 + -0.355212207325*_Complex_I, 0.319345692829 + -1.117466320715*_Complex_I, 0.418623558075 + -1.759140288875*_Complex_I, 1.041852719916 + 0.176006788980*_Complex_I, -0.297227854618 + 0.227296263697*_Complex_I, -0.164089543129 + -1.043612906074*_Complex_I, 0.008690483342 + 1.110377157604*_Complex_I, -0.219664588199 + 0.427614664824*_Complex_I, 1.343587074840 + 0.375898274813*_Complex_I, 1.490739162431 + 0.021350208856*_Complex_I, 0.945367199263 + 0.180821025970*_Complex_I, 0.522231273825 + -0.497986782057*_Complex_I, 0.523336519862 + -0.933508311700*_Complex_I, 0.496982629732 + 1.473461947118*_Complex_I, -0.003062144935 + -0.162840951249*_Complex_I, 0.984875642474 + -0.848717378538*_Complex_I, -0.461516263319 + -0.685745084807*_Complex_I, -1.175877458107 + -0.177846365813*_Complex_I, -0.932200203193 + 1.107705439242*_Complex_I, 1.406397814811 + 0.054681766136*_Complex_I, 1.109360316168 + -1.679067648707*_Complex_I, 0.924696326741 + 0.067692426194*_Complex_I, -0.000830800316 + -0.473092403298*_Complex_I, -0.731674917791 + -0.551769981624*_Complex_I, -0.569303781517 + -0.006801228336*_Complex_I, 0.110391386502 + -1.899793883492*_Complex_I, 0.814109796724 + -0.160466492041*_Complex_I, 1.138698851351 + -0.625131274654*_Complex_I, -1.963957708898 + 0.775152493271*_Complex_I, -1.659897790238 + 1.056053755857*_Complex_I, -0.649474775762 + 1.460655545851*_Complex_I, -0.741388571452 + -1.820826399375*_Complex_I, -1.572911393570 + 1.569354704216*_Complex_I, 0.744026763162 + 0.835499539241*_Complex_I, 0.095754291390 + 0.796930944242*_Complex_I, 0.507814608179 + 0.818154740321*_Complex_I, -0.383708274783 + -0.068423423510*_Complex_I, -0.888346025964 + 0.571095503271*_Complex_I, 0.925179546159 + -1.052147910287*_Complex_I, -0.438552116998 + -0.225556401800*_Complex_I, 1.164226743249 + 0.148695281475*_Complex_I, 0.964606990498 + 0.259930491349*_Complex_I, -0.343680793432 + 0.578310893020*_Complex_I, 0.093080205932 + 1.723388863831*_Complex_I, -0.756655985085 + 0.681598873690*_Complex_I, 0.939758986711 + 0.011205851149*_Complex_I, -0.141899272761 + 0.521507574016*_Complex_I, -0.716208197806 + 1.303295936061*_Complex_I, -0.813031307398 + 1.372568923775*_Complex_I, 1.023111911832 + -0.701776162450*_Complex_I, -0.059513464951 + -0.562779118569*_Complex_I, -1.783877678017 + 1.123340885741*_Complex_I, -0.129189002044 + 0.152272891142*_Complex_I, 0.594929872664 + 0.920537744435*_Complex_I, 0.958591761922 + 1.041651647113*_Complex_I, 0.496121593665 + -0.038971974072*_Complex_I, 0.184620294659 + -2.865914521972*_Complex_I, -0.173289102032 + 1.628057214738*_Complex_I, -1.450876580978 + -1.542121010661*_Complex_I, -0.585624617416 + -0.000140441111*_Complex_I, -0.165171139738 + -0.792078084035*_Complex_I, 1.008588335837 + 2.483679153708*_Complex_I, -1.101668002181 + -0.867864575222*_Complex_I, 1.778741775885 + 1.238012027547*_Complex_I, 0.418624110589 + -0.516903858622*_Complex_I, -0.623664358679 + 0.685852774278*_Complex_I, 1.473049190104 + -0.824653187025*_Complex_I, -1.125651402746 + -0.051861075402*_Complex_I, 0.942173492837 + 0.284253723912*_Complex_I, 1.468609011081 + 0.872878783090*_Complex_I, -0.523118553730 + 0.065885163104*_Complex_I, -1.209516269354 + 1.712795511905*_Complex_I, -0.164914664862 + -1.060198690347*_Complex_I, 0.081083509872 + 0.514122164431*_Complex_I, 0.014993899314 + -0.421407997613*_Complex_I, 0.921737261188 + -0.891135385409*_Complex_I, -0.186548224004 + 0.410695725270*_Complex_I, -0.138866088362 + -0.530179759052*_Complex_I}; float complex fft_test_y509[] = { 15.695701816574 + 18.430646076972*_Complex_I, 17.496535538521 + 6.323908273548*_Complex_I, -15.330535795607 + -16.826373817993*_Complex_I, -22.995137994536 + 5.848541065489*_Complex_I, -29.715938835044 + 12.754412174777*_Complex_I, 10.901257286656 + -8.716929489684*_Complex_I, -19.628646037487 + 19.226286624799*_Complex_I, -20.480875354016 + -31.897908691975*_Complex_I, 35.124732513036 + 16.324491517218*_Complex_I, 46.193539420959 + 25.851763792302*_Complex_I, 5.792757151559 + -12.926180930790*_Complex_I, -22.013847261245 + -5.613610031493*_Complex_I, 9.404166069447 + -0.019908771755*_Complex_I, 8.201675624257 + -8.967673070400*_Complex_I, 15.181089874097 + -6.297364574465*_Complex_I, 14.570696506052 + -1.051310941558*_Complex_I, -1.882106797398 + -5.240669196133*_Complex_I, -14.868309562238 + 6.106637681928*_Complex_I, -15.129890494726 + -2.984311531498*_Complex_I, 4.030179316698 + -51.075734845707*_Complex_I, -34.365285768090 + 9.975973436808*_Complex_I, -10.705381975285 + -9.109285126921*_Complex_I, -9.128619721470 + -32.793223942182*_Complex_I, -3.884615181749 + 5.589810405219*_Complex_I, -53.818876953386 + 9.826695061389*_Complex_I, 7.391928508119 + -6.174427305668*_Complex_I, -9.942167986468 + -39.833241210704*_Complex_I, -1.462704472474 + -2.725068915079*_Complex_I, -8.330269618062 + -2.806674135719*_Complex_I, 25.194669213199 + 30.149530622780*_Complex_I, 24.265507703667 + 35.899758345115*_Complex_I, 8.921289067584 + 4.788182047802*_Complex_I, -43.846571049868 + -11.381289894906*_Complex_I, 30.751599932238 + 20.081621692604*_Complex_I, 12.282504139594 + -23.757854873259*_Complex_I, 29.365318997990 + -23.868021174550*_Complex_I, -18.191992659645 + 23.039066554514*_Complex_I, -26.138981350472 + -27.807762467872*_Complex_I, 4.906806518050 + -64.830853635320*_Complex_I, 17.645400306096 + 6.438919813853*_Complex_I, -8.877478921993 + 22.121925579022*_Complex_I, -8.857083278794 + 2.248345191669*_Complex_I, -10.165898578719 + 14.029663983838*_Complex_I, -4.760350989354 + 14.471217793420*_Complex_I, 10.088121839257 + 10.378681492497*_Complex_I, 8.818549764286 + 28.002638865768*_Complex_I, 15.815201542566 + -8.171918556057*_Complex_I, 11.043628161039 + -4.557146048106*_Complex_I, -15.424873625059 + -1.742974782342*_Complex_I, 5.374423440509 + 15.897637103576*_Complex_I, 10.405830658480 + 5.110319843375*_Complex_I, -26.501807327618 + -12.862253830222*_Complex_I, 8.361320271594 + -12.127500776378*_Complex_I, -7.065209772913 + -13.109659416735*_Complex_I, 6.150458328525 + 21.558378724678*_Complex_I, 19.192390552195 + 57.078335145777*_Complex_I, 16.247539210043 + -5.178795721988*_Complex_I, -2.182213653083 + -31.382522380551*_Complex_I, -3.317969463714 + -1.385753951871*_Complex_I, 24.974480529165 + 22.521516957567*_Complex_I, 29.614215910955 + 22.614533535316*_Complex_I, 6.616213388437 + -6.945021315685*_Complex_I, -21.081077266042 + 27.911030510024*_Complex_I, -16.921827301441 + 18.479208860530*_Complex_I, 8.043988870051 + -36.113906522591*_Complex_I, 41.917272128407 + 26.843086076462*_Complex_I, -13.727079990761 + 5.205402325839*_Complex_I, -4.984705459021 + -6.291381865515*_Complex_I, -2.300982364859 + -21.708353496884*_Complex_I, 32.721343545850 + -16.032669392585*_Complex_I, 0.519352193540 + 45.753678340865*_Complex_I, 31.562265581157 + -4.268866755468*_Complex_I, -40.236062083037 + -2.384241501530*_Complex_I, -30.936637211857 + 3.338370340206*_Complex_I, -21.959385231675 + 0.895928669913*_Complex_I, 7.483781797051 + -52.076927900468*_Complex_I, -64.519015760392 + 10.979148490947*_Complex_I, -28.029903074937 + 7.946066875195*_Complex_I, -0.807954143368 + 10.641591910611*_Complex_I, 34.165604774109 + -19.071113266579*_Complex_I, 10.309282793998 + -14.648195920539*_Complex_I, 26.307206562160 + 3.878504634615*_Complex_I, -21.207352431217 + 12.063691363252*_Complex_I, -54.243540120475 + -0.287217034895*_Complex_I, -32.080496755198 + 30.540317997631*_Complex_I, 9.760803073410 + 16.055868478901*_Complex_I, -16.078558738770 + -5.356833086497*_Complex_I, 36.213555936943 + -24.363868386505*_Complex_I, -10.697416407844 + 24.319983619540*_Complex_I, 17.684302893605 + -12.378065186883*_Complex_I, 41.844539573965 + -46.705571091504*_Complex_I, -24.945971628906 + -10.079221453585*_Complex_I, -10.513894508491 + -4.599940107164*_Complex_I, 26.189867010892 + -17.124071629849*_Complex_I, -34.363585674086 + -4.077385676473*_Complex_I, -32.102375469900 + 18.736917526908*_Complex_I, -20.887619654518 + -54.461316084166*_Complex_I, 0.064775230615 + 24.195856216286*_Complex_I, 32.270028792805 + 48.132373628158*_Complex_I, -1.916807810798 + -12.903225028783*_Complex_I, -1.669256173251 + 16.652308679485*_Complex_I, -3.071210123118 + 18.164002571879*_Complex_I, 17.931710499892 + -13.922708426108*_Complex_I, 19.373112705930 + 8.858054642852*_Complex_I, 1.712477146172 + -34.349666851373*_Complex_I, 3.720328613972 + -37.016904392694*_Complex_I, 5.546925594994 + -0.892192373145*_Complex_I, -22.124438618468 + -41.843458261756*_Complex_I, -19.235688566387 + -2.162824631740*_Complex_I, 21.783941115220 + -6.695594391248*_Complex_I, 33.493805068723 + 62.763842873419*_Complex_I, -10.896810929881 + -8.404131804641*_Complex_I, 18.216817415924 + -33.590802005326*_Complex_I, -25.763824584844 + -6.302405967415*_Complex_I, -15.929448259002 + 49.656053432255*_Complex_I, -2.645182567345 + 3.823015231654*_Complex_I, 33.565352588744 + -14.801476451303*_Complex_I, 34.780028538088 + 14.782512818128*_Complex_I, 22.270348337592 + 17.396233784708*_Complex_I, -23.998646351712 + -2.572970386926*_Complex_I, -5.212660897164 + -38.032125746868*_Complex_I, -5.937127593805 + -21.823373120555*_Complex_I, 12.376774565444 + 33.920254294747*_Complex_I, 19.629474738185 + -7.562284518099*_Complex_I, -25.524838793958 + -25.917842984307*_Complex_I, 7.908690793819 + 53.160190581823*_Complex_I, -22.547459647000 + -31.810110557445*_Complex_I, 14.825411801114 + -2.623765490622*_Complex_I, 21.016615330301 + 22.000151402955*_Complex_I, -3.127363744257 + -13.350072969695*_Complex_I, -57.702154359177 + -15.154831462388*_Complex_I, -13.446876000722 + -13.069388640893*_Complex_I, -2.176317185084 + 17.496721580831*_Complex_I, -54.132263906341 + 16.018239354033*_Complex_I, -3.699736432956 + 27.741980074527*_Complex_I, -7.311559889274 + -20.665154049268*_Complex_I, 6.161991265193 + -5.267960280914*_Complex_I, -0.083765300728 + -15.394352140009*_Complex_I, -10.209228018076 + -6.471795099909*_Complex_I, -0.812704485184 + -3.943529308850*_Complex_I, -3.174962269778 + -37.702639197964*_Complex_I, 14.138710546364 + 11.048967022727*_Complex_I, 6.870463853253 + 10.314002260772*_Complex_I, 3.221828051661 + 51.234801230509*_Complex_I, -2.186983936437 + 38.473329840101*_Complex_I, 13.533239595473 + 16.037592135971*_Complex_I, 39.103943522729 + 7.078614835194*_Complex_I, 30.565445217772 + 12.659846713522*_Complex_I, 30.303359360199 + -34.312315640466*_Complex_I, -20.057347170511 + 50.200448109342*_Complex_I, 15.117190448180 + 7.835893578929*_Complex_I, -15.209082571565 + 10.364865373220*_Complex_I, 9.144422828705 + -66.027702727533*_Complex_I, -18.356336362499 + -27.596404803404*_Complex_I, -21.642296590182 + -23.328234101983*_Complex_I, -38.679552975441 + -27.294969526274*_Complex_I, -17.537683264549 + 11.145767113244*_Complex_I, -28.415217286677 + 2.450538508370*_Complex_I, -7.839159290091 + 9.590153493395*_Complex_I, -4.077913680565 + 3.514849319651*_Complex_I, 36.547874214296 + -13.621221107484*_Complex_I, 14.644978554755 + -21.980389507971*_Complex_I, -3.073299724899 + -8.758687284937*_Complex_I, 35.118241555864 + -42.903789231571*_Complex_I, -22.783245832308 + -9.082081737025*_Complex_I, -25.929291660507 + 18.758508598154*_Complex_I, 33.025142390877 + 5.904152955421*_Complex_I, 11.948227318252 + 2.161590454494*_Complex_I, -1.006102550557 + -28.161894386541*_Complex_I, 45.136250419544 + 3.976787326589*_Complex_I, -33.291978336755 + 0.798986604330*_Complex_I, 11.265970488150 + -1.327315667000*_Complex_I, 3.519436365736 + 16.927952719295*_Complex_I, -33.602300462457 + 32.163188907263*_Complex_I, -8.361310619248 + -8.809090782568*_Complex_I, 11.294901581957 + -4.245164072484*_Complex_I, 14.566011481616 + 26.519668998172*_Complex_I, 14.769898592012 + 56.527707423485*_Complex_I, 33.116957851259 + -1.090132926951*_Complex_I, 20.848136410578 + 10.345884350214*_Complex_I, 18.958342797158 + 6.566708563840*_Complex_I, 15.396069027712 + -31.284159225464*_Complex_I, 2.886181696729 + 18.205515439993*_Complex_I, 2.258601161648 + -12.548779081296*_Complex_I, 18.639723094734 + -13.486140556024*_Complex_I, -11.071519074610 + -19.339094005264*_Complex_I, 16.895170033002 + -9.987185658559*_Complex_I, -3.870068718996 + 22.233540496971*_Complex_I, 8.964139966565 + -27.313941129646*_Complex_I, -17.059785268381 + -4.400625859198*_Complex_I, -6.175147302779 + 30.096445776903*_Complex_I, 18.669084089316 + 6.968259188573*_Complex_I, 7.657184873046 + -41.697203143381*_Complex_I, -33.549050077833 + 24.392895555181*_Complex_I, 13.852529446346 + -24.121363551436*_Complex_I, -8.184532144280 + -21.955892305419*_Complex_I, -19.335525950576 + 31.604135153122*_Complex_I, 30.219851790692 + 9.312089638267*_Complex_I, -9.099736227858 + 10.891340718152*_Complex_I, 8.000001281397 + -11.689007297193*_Complex_I, 15.301942508385 + -30.427794390813*_Complex_I, -7.727208416300 + 13.998979881879*_Complex_I, -6.394185171364 + 3.146108002402*_Complex_I, 9.252474513141 + -16.461589767495*_Complex_I, 26.863242542498 + 24.608331497751*_Complex_I, 46.975091007265 + -22.976780803246*_Complex_I, -46.543917156055 + 15.869672486948*_Complex_I, -4.728161553855 + 29.037018944500*_Complex_I, 4.070927662548 + -36.042387888924*_Complex_I, 14.921971168495 + 30.690814385233*_Complex_I, 35.791446149577 + 4.619796889845*_Complex_I, 2.303273709336 + 11.205822209351*_Complex_I, 8.168201691579 + -10.908743400107*_Complex_I, -0.043567851626 + 24.059334278527*_Complex_I, 7.466916906592 + 18.610504314019*_Complex_I, 7.031977571019 + -9.358602921852*_Complex_I, 5.391773391774 + -0.966245883858*_Complex_I, 3.392189608224 + -10.986430122434*_Complex_I, 34.562609814015 + 40.520419348321*_Complex_I, -9.427806154592 + 14.449317738714*_Complex_I, -28.980935248249 + 35.723542184020*_Complex_I, -25.087680212574 + -12.353756547678*_Complex_I, -10.456225394292 + 26.299032407868*_Complex_I, -3.551781425808 + 36.487758403775*_Complex_I, -13.555856836256 + 11.377498259126*_Complex_I, -5.711875186735 + 63.014002174535*_Complex_I, 8.802482546452 + -9.877617002550*_Complex_I, 12.398023754693 + -17.252746153510*_Complex_I, 48.590307765142 + -39.869959281353*_Complex_I, -4.228834590895 + -16.849706340702*_Complex_I, 1.157565934241 + 10.439891849608*_Complex_I, 6.162905961542 + -42.121455332219*_Complex_I, 18.623319771899 + 6.782479204326*_Complex_I, 40.359667537403 + -5.227038429096*_Complex_I, 3.960846512784 + -2.184979700635*_Complex_I, -11.294281203268 + 1.462688924503*_Complex_I, 4.235940899795 + -5.069039031037*_Complex_I, -19.757480291431 + -19.995127344309*_Complex_I, 9.293994179429 + 30.574726633130*_Complex_I, -11.912765926945 + 1.982525086253*_Complex_I, 32.506223545239 + -17.228481622244*_Complex_I, 23.261121675341 + -41.619757453530*_Complex_I, -16.699711374017 + 17.184396509178*_Complex_I, -30.981944222728 + 18.381540125799*_Complex_I, -28.134836328395 + -9.882313867372*_Complex_I, -40.216518853122 + 7.954899537374*_Complex_I, -17.952578865387 + 27.478809719211*_Complex_I, -28.849862783745 + 0.512912610070*_Complex_I, 21.721522411732 + -6.115881482201*_Complex_I, -82.815498795687 + -8.942733727142*_Complex_I, 3.740277816696 + -14.522905567941*_Complex_I, -35.229732095265 + 26.709488731346*_Complex_I, 11.290125122898 + 24.224877496545*_Complex_I, -16.635941007754 + 8.630637395391*_Complex_I, 22.134876007936 + 2.574582351782*_Complex_I, 33.251774617807 + 5.457413908840*_Complex_I, -3.124095302802 + -30.945315750230*_Complex_I, 25.380261145256 + -12.895408190578*_Complex_I, 29.590560891351 + -35.336175817647*_Complex_I, 23.190389336153 + -51.584432366600*_Complex_I, 23.182126536797 + -30.991661680296*_Complex_I, -37.142295822241 + 7.721940476748*_Complex_I, 26.833304952389 + 15.281809854672*_Complex_I, 3.795011817607 + 47.705908075813*_Complex_I, 44.822699796166 + 4.630736159645*_Complex_I, 20.899042041270 + 2.487657439412*_Complex_I, 8.742060078106 + 9.864203556590*_Complex_I, 16.980059178338 + 35.222546217902*_Complex_I, -19.255543627730 + 9.410996006466*_Complex_I, 21.517616907420 + 26.338377945165*_Complex_I, 48.642251867035 + 6.924884525443*_Complex_I, 23.548326097336 + 10.784367397399*_Complex_I, -11.550545599595 + -22.108959248798*_Complex_I, 16.733078720638 + -6.587000041071*_Complex_I, -24.552765736255 + 20.310652954928*_Complex_I, 17.292953612417 + 29.643678070378*_Complex_I, 9.373109698654 + 24.904713123755*_Complex_I, 25.238503675115 + -15.183892795659*_Complex_I, -1.508310287534 + -32.049583340956*_Complex_I, -1.442670825788 + -39.824563428950*_Complex_I, 3.230145000210 + -25.420530195927*_Complex_I, 13.229685977004 + -14.075607613923*_Complex_I, -19.526361502130 + -29.370000953029*_Complex_I, -21.782631521002 + -37.617721671791*_Complex_I, 27.816003478663 + 24.303079202481*_Complex_I, -43.381077867759 + 24.837480951743*_Complex_I, -9.560217395595 + 2.382563375055*_Complex_I, -1.168465306817 + 1.589115227489*_Complex_I, 52.542490127417 + 1.424383301004*_Complex_I, -10.794625364629 + -19.749473263855*_Complex_I, 26.168847841768 + -26.658825280073*_Complex_I, 4.233092270819 + -48.303662607018*_Complex_I, -5.014341149907 + -33.130134324155*_Complex_I, 9.190470374905 + -26.953795736734*_Complex_I, -2.846241405053 + -0.651859597413*_Complex_I, -20.225979212962 + -24.560140693339*_Complex_I, -10.802336686843 + 51.446188240204*_Complex_I, -9.492345818087 + -27.286465734423*_Complex_I, -24.394227434292 + 36.495286678206*_Complex_I, -4.610288224660 + 13.785902137795*_Complex_I, 25.266817655154 + 8.853318181494*_Complex_I, -1.108114899344 + -8.902780819762*_Complex_I, -34.949213732955 + 16.304692482063*_Complex_I, 12.401176411050 + -49.617470306114*_Complex_I, 13.450715987122 + 23.780568951393*_Complex_I, 0.327891662517 + 20.945521301723*_Complex_I, -24.347872941432 + -20.261920769569*_Complex_I, -3.742508301325 + 15.297035114593*_Complex_I, 20.157765205649 + -2.771550168366*_Complex_I, -26.861338262008 + 10.330263597466*_Complex_I, -19.103391377917 + 29.070399414699*_Complex_I, 33.355739256457 + 0.786653290415*_Complex_I, -15.811410357704 + 12.334342632002*_Complex_I, -31.067213179934 + 4.812703947794*_Complex_I, -38.464666136613 + -9.734460624273*_Complex_I, -27.018641211199 + -10.676307399360*_Complex_I, 10.601332462223 + 12.602266185181*_Complex_I, -14.863945203402 + 18.405001560411*_Complex_I, 6.151006234331 + -1.325265142280*_Complex_I, 10.654450023041 + 24.877489064003*_Complex_I, 7.753711320427 + -24.877496668386*_Complex_I, 14.215523169674 + 15.750750989795*_Complex_I, 10.063422021746 + 49.306566727230*_Complex_I, -83.835199786581 + -35.146747496108*_Complex_I, -0.218459362048 + -0.770721115796*_Complex_I, 22.431242892732 + -36.430877828612*_Complex_I, 17.435164403992 + -17.764746880777*_Complex_I, -18.336005961075 + -40.785661916947*_Complex_I, -9.708667273758 + -6.212236081880*_Complex_I, 15.661415503945 + -23.058769144173*_Complex_I, 6.754601945166 + -19.307935713609*_Complex_I, 21.850846235150 + 8.741417315883*_Complex_I, 25.652896421543 + 2.796534004126*_Complex_I, -1.843079544502 + 1.784869908972*_Complex_I, -2.568058272174 + -31.336348759351*_Complex_I, -23.530597236048 + 17.793870333201*_Complex_I, 41.700575857144 + 9.089193485713*_Complex_I, 44.662282998158 + -3.699022752392*_Complex_I, 29.042445473764 + -11.349519417295*_Complex_I, -7.073983554684 + 29.402856163434*_Complex_I, 19.939374137561 + -20.731019858441*_Complex_I, -27.044678373347 + -39.264065270489*_Complex_I, 20.211317017215 + 41.386816030545*_Complex_I, 1.043164784676 + -2.519947587522*_Complex_I, -6.375700266136 + -29.785712929923*_Complex_I, -27.700591743931 + 16.461560631605*_Complex_I, 10.095278660268 + 2.666042949098*_Complex_I, 6.614197587453 + -36.267409940122*_Complex_I, 3.024977063712 + 22.518622158190*_Complex_I, 22.730131517026 + 14.937191189086*_Complex_I, 0.061498915482 + -33.204005635365*_Complex_I, 3.246333795519 + 12.298349815877*_Complex_I, 5.921582958906 + 20.790686987339*_Complex_I, 22.777331137604 + 6.555360530677*_Complex_I, 21.199065974566 + 30.692801789200*_Complex_I, -1.064699299018 + -30.735783458333*_Complex_I, 1.711968922160 + 2.764830482799*_Complex_I, 57.479865205031 + 14.741051010187*_Complex_I, -5.222691142638 + -12.945556728288*_Complex_I, 24.618941208703 + -8.335156868108*_Complex_I, 5.362345191955 + -29.659123854849*_Complex_I, -13.759594910763 + -2.839225605024*_Complex_I, -0.744944069183 + 9.536259763486*_Complex_I, -7.266281313994 + -9.788530410618*_Complex_I, -16.072026028887 + 16.172115574565*_Complex_I, -6.901619139003 + -7.747255335591*_Complex_I, -16.302588968059 + -9.014933207001*_Complex_I, -9.878306363842 + -19.984075902846*_Complex_I, 2.088664771255 + -8.999802528190*_Complex_I, -21.345209871678 + -33.541210734395*_Complex_I, 12.617534995502 + -12.378687252061*_Complex_I, 10.047409736042 + -6.607933917427*_Complex_I, 9.334831941537 + 10.948924308348*_Complex_I, 25.695968260034 + 7.063988558158*_Complex_I, -9.625298547784 + 16.677076422518*_Complex_I, -3.108963319630 + 3.376941849928*_Complex_I, -47.044223301845 + -22.447723404064*_Complex_I, 6.172396063478 + 3.130567372603*_Complex_I, -12.391233504725 + -18.965209575430*_Complex_I, 7.816421386094 + -18.829210484343*_Complex_I, 2.299165958987 + 21.664313726413*_Complex_I, 23.073574880632 + -40.647794133271*_Complex_I, 11.788478207223 + 10.388520650659*_Complex_I, 2.495494346482 + -40.903748493834*_Complex_I, 9.204196215081 + 3.731305183829*_Complex_I, -11.705334181886 + -5.698373301119*_Complex_I, -10.576847226819 + -24.400174262686*_Complex_I, 1.125349170571 + -42.931316430041*_Complex_I, -34.927593970119 + 15.363588886694*_Complex_I, -5.051369474478 + 57.553472286872*_Complex_I, -17.737882109182 + 20.993190450070*_Complex_I, 37.177637689060 + 16.991173325998*_Complex_I, 44.283601354742 + 17.412222591528*_Complex_I, 36.495623940354 + -20.061033291263*_Complex_I, -0.821113211121 + -3.092318774340*_Complex_I, -22.377701901316 + -16.198210370561*_Complex_I, 12.319993479497 + -21.923811281565*_Complex_I, 15.511676349072 + -9.483307137734*_Complex_I, 20.189875802738 + -17.301968082172*_Complex_I, -5.805824615680 + -36.079316378374*_Complex_I, 30.255637146078 + -44.362762846218*_Complex_I, -20.832965183425 + -7.304495538217*_Complex_I, -13.022907320332 + -57.530437725034*_Complex_I, -10.564105798288 + -34.560059804429*_Complex_I, 21.361954258419 + -36.855969871716*_Complex_I, 4.506530938557 + 32.048954769246*_Complex_I, -33.027950438924 + 28.211482991964*_Complex_I, -29.352439177975 + 26.783042078482*_Complex_I, -28.424459734912 + -8.558362358430*_Complex_I, -19.967959416569 + 10.959195107292*_Complex_I, -23.791686165010 + 32.501306546259*_Complex_I, -33.216256571387 + 2.738726266389*_Complex_I, 8.569384712402 + 1.130870024297*_Complex_I, 28.525451062286 + 17.073062203997*_Complex_I, -1.502286920189 + -10.160446478808*_Complex_I, -6.861394365693 + 36.910381121986*_Complex_I, -6.268440765630 + -17.493038905156*_Complex_I, 11.322039030102 + -23.206689618074*_Complex_I, -8.701154518730 + 34.222038681525*_Complex_I, -24.669027160846 + -36.326555770368*_Complex_I, 20.943711343327 + -24.033336369879*_Complex_I, 29.209555657259 + -20.413413259064*_Complex_I, -2.572238542979 + -20.816303598934*_Complex_I, -1.994249544729 + 23.007487924841*_Complex_I, -44.905945955860 + 29.216643846282*_Complex_I, -24.062162530228 + 12.109221679204*_Complex_I, -12.180111153692 + 17.875695962678*_Complex_I, 20.435116656247 + 5.797199859832*_Complex_I, 3.493004564937 + -5.812772133417*_Complex_I, -27.034394973848 + 24.948810080561*_Complex_I, 21.936211599800 + -5.553436322258*_Complex_I, -4.478679537619 + -2.641131963451*_Complex_I, 5.120700840097 + 6.186528528634*_Complex_I, -47.624247374659 + -34.895963725954*_Complex_I, -43.479965560285 + 10.001886840601*_Complex_I, -20.718614873021 + 24.908643623897*_Complex_I, 9.472646766463 + -4.586461637219*_Complex_I, 9.294883958873 + 5.219642918744*_Complex_I, 24.547287109336 + 15.988189397184*_Complex_I, 12.811611969328 + -60.146862637486*_Complex_I, 33.520279815394 + 29.907221430910*_Complex_I, -14.152533165001 + -16.446995449346*_Complex_I, 23.465425390528 + -4.669981744595*_Complex_I, -29.290184394031 + -6.824899055323*_Complex_I, 36.044925366731 + 39.699979702815*_Complex_I, 45.609805078654 + -0.363597033482*_Complex_I, 12.247988815457 + -6.993931713410*_Complex_I, 14.744368729437 + 4.566968366531*_Complex_I, -3.612287261480 + -31.882623904258*_Complex_I, -4.625837065570 + -49.204985934025*_Complex_I, 10.369874666738 + 23.286668162235*_Complex_I, -29.995409795889 + 22.748837275811*_Complex_I, 7.693482749378 + 12.894738140873*_Complex_I, -74.632562519909 + -20.685236968252*_Complex_I, 24.465299052921 + -16.879295578319*_Complex_I, -17.287451187811 + -5.253265233981*_Complex_I, -12.792544818057 + -22.347701435426*_Complex_I, -30.500042038025 + -6.625643844530*_Complex_I, -25.032206738905 + -11.617648580783*_Complex_I, -33.767830120583 + -19.967382042671*_Complex_I, 8.352625196160 + -0.210944382477*_Complex_I, -2.824794695557 + 7.815259159406*_Complex_I, -30.449907818874 + -38.156235692042*_Complex_I, 34.223672868260 + 5.423974272822*_Complex_I, -3.473532089262 + -45.188663541294*_Complex_I, 1.929635364775 + -17.899772348612*_Complex_I, -17.366629103993 + 63.817371804672*_Complex_I, -23.515133356267 + -0.250964260288*_Complex_I, -26.558406280873 + 5.464454223022*_Complex_I, 7.459074663716 + -5.360173061781*_Complex_I, -2.740551125358 + -28.954513936397*_Complex_I, 26.831634155936 + 7.298762429258*_Complex_I, 26.189721830795 + 13.528176613886*_Complex_I, 0.552527132215 + 12.528332436204*_Complex_I, -18.980402436415 + 14.388413407600*_Complex_I, -2.948074258737 + -26.092284933664*_Complex_I, 11.237345817375 + 40.862341094348*_Complex_I, -31.224869298160 + 17.176727608508*_Complex_I, 2.721793055983 + -9.744545888653*_Complex_I, -0.776323448517 + -40.995023347911*_Complex_I, -49.192082010750 + 11.872769267713*_Complex_I, -43.807462185673 + -6.259081354893*_Complex_I, -2.175065114292 + 6.493046453358*_Complex_I, 23.334296943174 + 19.135612282249*_Complex_I, -6.817794711121 + 3.642740073112*_Complex_I, 11.873498813840 + 37.496197060973*_Complex_I, 14.779256218032 + -13.159994239230*_Complex_I, -19.232512636676 + 5.916208467040*_Complex_I, -0.581631693027 + 22.531394609402*_Complex_I, 1.544210909483 + 14.296122579802*_Complex_I, 7.044576628257 + -10.190237629704*_Complex_I, -4.813365711741 + 7.129670574765*_Complex_I, 41.167970529260 + -12.916981484001*_Complex_I, 26.669078124418 + -15.501207232456*_Complex_I, 12.492422072442 + -9.037015700661*_Complex_I, 17.418311261915 + 11.203344744823*_Complex_I, 18.500273199469 + 19.568644933327*_Complex_I, -23.216101473541 + -2.306087143311*_Complex_I, -1.651207984446 + 1.920560461483*_Complex_I, 22.032664625569 + -67.269204021659*_Complex_I, 2.687054355440 + -6.150483980195*_Complex_I, -42.445780624117 + -52.847480030760*_Complex_I, -18.575368994624 + -11.378786258777*_Complex_I, 12.874123481209 + 11.199236114650*_Complex_I, 6.553360933113 + -7.014357063713*_Complex_I, 24.351668075370 + 32.239707779122*_Complex_I, -3.293543380713 + 15.964518188392*_Complex_I, -15.175792848341 + -2.924538577813*_Complex_I, 17.561582795484 + -3.560828531875*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_6.c000066400000000000000000000035141317124540100213520ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 6-point transform // #include float complex fft_test_x6[] = { -0.946868805918 + 0.048419613876*_Complex_I, -1.426556442325 + 1.356194807524*_Complex_I, 0.262357323076 + 1.594616904796*_Complex_I, -1.032912520662 + 0.046391595464*_Complex_I, -0.271359734201 + -2.390517158747*_Complex_I, -0.288151144041 + 0.071324517238*_Complex_I}; float complex fft_test_y6[] = { -3.703491324072 + 0.726430280150*_Complex_I, 3.797148775593 + 1.637413185851*_Complex_I, -3.456423352393 + 1.227102112087*_Complex_I, 1.791748889984 + -2.221391560299*_Complex_I, 1.220570696725 + -1.669098764217*_Complex_I, -5.330766521347 + 0.590062429687*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_63.c000066400000000000000000000166231317124540100214420ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 63-point transform // #include float complex fft_test_x63[] = { -0.165065089334 + 1.102101871091*_Complex_I, -0.981973148546 + 0.541468656777*_Complex_I, -0.253554650102 + -0.121332795252*_Complex_I, 0.944969891304 + -0.207365910694*_Complex_I, 0.435801732783 + 1.116850636842*_Complex_I, -2.058668461583 + 1.768420128659*_Complex_I, 0.404062083774 + -1.055764673267*_Complex_I, -1.173590903686 + 0.058528368777*_Complex_I, -0.598414155862 + -0.497560622574*_Complex_I, -1.861198860149 + 0.229658791022*_Complex_I, -2.562456370500 + 0.495624931472*_Complex_I, 0.673656989316 + 2.905410000205*_Complex_I, 0.867056802014 + 1.798292948964*_Complex_I, -2.078980954663 + 0.098338397564*_Complex_I, -0.330038784071 + 0.481340360434*_Complex_I, 1.276384585521 + 1.297002232435*_Complex_I, 0.261810533047 + -1.797403878425*_Complex_I, -2.153713373163 + -0.426579749412*_Complex_I, 0.065709110586 + -0.887295333513*_Complex_I, -0.504714672950 + -0.491403278968*_Complex_I, 0.314910052074 + -0.711703174875*_Complex_I, 0.817545815846 + 2.684246900528*_Complex_I, 0.899097356674 + 2.316804935463*_Complex_I, 1.234132120370 + -0.619880076717*_Complex_I, 0.791329122849 + -1.491623691612*_Complex_I, -1.543373050418 + -0.676542277175*_Complex_I, 0.671442701409 + 0.216191301849*_Complex_I, 0.131373689049 + 0.579119405459*_Complex_I, -0.372079387235 + -0.810986260520*_Complex_I, 0.509295824480 + 2.533724020332*_Complex_I, 1.724705779066 + 0.166621824873*_Complex_I, 1.578021811166 + 0.495673960042*_Complex_I, -0.388517506381 + 0.654051926694*_Complex_I, 0.780148148992 + -1.186745985806*_Complex_I, -0.998699640841 + -2.290498316764*_Complex_I, 1.225655499248 + 0.539258663300*_Complex_I, 0.647174747272 + -1.701050133294*_Complex_I, -1.961810462975 + -0.885111538141*_Complex_I, 0.708722105215 + 2.298722273781*_Complex_I, 0.003407269436 + -0.160897403251*_Complex_I, -1.461677661847 + 0.035003203295*_Complex_I, -0.003031847788 + 0.263418857310*_Complex_I, -0.921189208563 + -0.548149166993*_Complex_I, 1.607243811931 + 1.460044138769*_Complex_I, 1.474955000858 + -0.319625335378*_Complex_I, -1.479420038984 + 0.442261731228*_Complex_I, -0.501705519202 + -0.107677110586*_Complex_I, -0.555052849202 + -2.288466181238*_Complex_I, 0.115695886330 + 0.958546419969*_Complex_I, -0.272372848704 + -0.160652497732*_Complex_I, 0.329785731274 + -0.424936229335*_Complex_I, 0.480745655276 + 1.205406168541*_Complex_I, 0.070825951395 + 2.104542991271*_Complex_I, -0.006185321246 + 0.587388482318*_Complex_I, -0.694069041213 + 0.770735193308*_Complex_I, 0.908386043892 + -1.602236263851*_Complex_I, -0.699555084329 + 0.976937982289*_Complex_I, -0.954674992562 + -0.016401236894*_Complex_I, -0.309302754137 + 0.958214618988*_Complex_I, -0.127271579222 + 1.856678631720*_Complex_I, -0.871347344939 + -2.036988579664*_Complex_I, 0.135839855058 + -0.627341937358*_Complex_I, -0.335848209970 + -2.547865701465*_Complex_I}; float complex fft_test_y63[] = { -7.089662066859 + 9.296545614813*_Complex_I, -8.501752827269 + 5.888942352564*_Complex_I, 3.278359396134 + 3.509899786067*_Complex_I, 5.034502581381 + -10.325422246173*_Complex_I, 0.779395837363 + -11.641131257781*_Complex_I, 6.583373182868 + -0.765170650399*_Complex_I, 7.673022911242 + 5.376349934527*_Complex_I, 6.901124231347 + -11.572359190453*_Complex_I, -12.551588348101 + -5.650836104556*_Complex_I, 13.135291423808 + -9.005088743334*_Complex_I, 6.256581548275 + 7.656394164588*_Complex_I, -9.007597317001 + 6.540328187752*_Complex_I, 5.970311877450 + 11.718061229294*_Complex_I, 3.567004157825 + 0.672928597121*_Complex_I, -14.427943038803 + 8.900678790697*_Complex_I, 1.056847529506 + 3.528462625077*_Complex_I, 13.620920754920 + 14.305922963856*_Complex_I, 8.760078200432 + 11.222488908434*_Complex_I, 5.722531558556 + 7.234622735459*_Complex_I, -5.247983376866 + -11.345081644681*_Complex_I, 1.314257740811 + 1.904662960921*_Complex_I, 0.730895747988 + 5.589496067590*_Complex_I, 6.527229987789 + -10.176960210420*_Complex_I, -4.341510788445 + -8.731233871509*_Complex_I, 7.581071089827 + -9.540336644811*_Complex_I, 4.648868334483 + -7.155035929172*_Complex_I, -2.205072254220 + 17.534621681153*_Complex_I, 6.858512702532 + 3.813829755562*_Complex_I, 0.193418696750 + 11.693363675036*_Complex_I, 5.619907773283 + 4.653892039135*_Complex_I, -1.855582230893 + 10.861851324746*_Complex_I, 14.627670681377 + -2.489204973764*_Complex_I, 0.605824410285 + -7.016190132363*_Complex_I, 2.624656390216 + 3.561441210498*_Complex_I, 0.709206425704 + 12.728091932012*_Complex_I, -3.982794699993 + 6.878915353589*_Complex_I, -13.376734767433 + 1.691306437014*_Complex_I, -2.349794152830 + -0.330132617385*_Complex_I, -3.726616620789 + 15.817788395019*_Complex_I, -16.729175354871 + -8.409111133317*_Complex_I, 17.882515293846 + -3.208404044366*_Complex_I, -7.470918853421 + 18.877686110403*_Complex_I, 12.668798353590 + -9.060907565117*_Complex_I, -6.220564671186 + -5.153664668923*_Complex_I, -1.712331740792 + -15.816196915449*_Complex_I, -11.816550492910 + 12.590312098504*_Complex_I, 5.948638061621 + 10.638444837386*_Complex_I, 13.008103746204 + -15.557670122101*_Complex_I, -13.266957624044 + 3.898836567164*_Complex_I, -1.862920665209 + -4.724933699937*_Complex_I, -4.695828593392 + 9.661188336137*_Complex_I, -7.542434926702 + 17.373541879534*_Complex_I, 1.008284652559 + 2.011360297386*_Complex_I, -6.854631802630 + -4.014486905376*_Complex_I, -6.668218293484 + 4.636855650199*_Complex_I, 3.172812378583 + -20.418734887614*_Complex_I, -23.330375903759 + -12.181015318516*_Complex_I, 6.267118807644 + 17.748053544942*_Complex_I, -8.369069881119 + 5.704956182541*_Complex_I, 9.266781179990 + -5.431082220535*_Complex_I, -2.621123339590 + -4.576508645033*_Complex_I, 3.116382580437 + -13.991211520556*_Complex_I, -15.293666222030 + 1.998407515632*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_64.c000066400000000000000000000167671317124540100214540ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 64-point transform // #include float complex fft_test_x64[] = { -0.021754290353 + -0.612017802190*_Complex_I, 0.484276408753 + 0.753944723650*_Complex_I, -1.051031916820 + 0.166448506301*_Complex_I, 0.185316597591 + -0.053758419799*_Complex_I, -0.775208247301 + -1.344741618220*_Complex_I, 1.008977328193 + 0.309312932614*_Complex_I, 0.225467083836 + -1.771870588253*_Complex_I, 0.469982216778 + -1.560265270836*_Complex_I, 0.015796870295 + 0.514270976406*_Complex_I, 0.021523250463 + -1.531865633331*_Complex_I, 0.374810770914 + -1.819295376215*_Complex_I, -0.271362317574 + 1.223581370818*_Complex_I, 1.095264083148 + 0.119410767188*_Complex_I, 0.176833870554 + -0.357067009123*_Complex_I, -0.844150660609 + -0.402483548788*_Complex_I, 0.121027264669 + -1.289015413302*_Complex_I, 0.263581726117 + -1.020960568111*_Complex_I, -1.850367234488 + 0.252491065243*_Complex_I, 0.180744535235 + 0.799594483178*_Complex_I, -0.844109705065 + -0.510108698929*_Complex_I, -0.036218762055 + 1.294869055398*_Complex_I, 0.258512790360 + 0.568441072457*_Complex_I, 1.626275624183 + 0.634319322667*_Complex_I, 0.322617919951 + 0.212628458295*_Complex_I, 0.160934986434 + -0.163540330171*_Complex_I, 1.047849823612 + -0.095800483192*_Complex_I, 0.481794672802 + -0.457172404256*_Complex_I, 0.129133928192 + 0.091760813424*_Complex_I, -0.060049809575 + 0.184851257642*_Complex_I, -1.806557059379 + -0.712577972074*_Complex_I, -1.514896468556 + -0.698585251055*_Complex_I, 1.839754692918 + 0.489376426678*_Complex_I, -1.243735376399 + 1.952793219096*_Complex_I, 0.254245070501 + 1.389680075711*_Complex_I, 0.692307414060 + 1.566188401796*_Complex_I, -0.194903488026 + -0.439000848041*_Complex_I, 1.668407720772 + -0.910104238535*_Complex_I, -0.575848786837 + 0.375593796515*_Complex_I, 0.429092097669 + -0.640962925803*_Complex_I, -1.534318288920 + -1.204243660541*_Complex_I, 1.340275852733 + -1.091482736862*_Complex_I, -0.683541799234 + 1.328028176092*_Complex_I, 0.346674268228 + -1.556024203629*_Complex_I, 0.808325600843 + 0.879310154017*_Complex_I, -1.083115089529 + 0.217436971911*_Complex_I, 0.208798197538 + 1.065533831174*_Complex_I, -0.075819341427 + -1.489702533787*_Complex_I, -0.768117108951 + -0.395669850882*_Complex_I, -0.171257456484 + -1.684427171232*_Complex_I, 0.008638877159 + 0.828227749071*_Complex_I, -0.907835739258 + 1.661585546412*_Complex_I, -0.842311802407 + 0.128045074908*_Complex_I, -0.480781325156 + -0.060205164274*_Complex_I, -0.332968153644 + -0.725579827560*_Complex_I, 0.385831273126 + -0.734953099969*_Complex_I, 0.078244895870 + 0.187320802435*_Complex_I, 0.822725278030 + 1.761602936253*_Complex_I, 0.854139534803 + -0.447804374730*_Complex_I, 1.139585202373 + 0.594363516587*_Complex_I, -0.327644569515 + -1.601512234292*_Complex_I, 0.066470112247 + 0.272352995689*_Complex_I, -0.233514955808 + 0.151832081236*_Complex_I, 0.804170356884 + 0.191021429001*_Complex_I, -0.141790367715 + 0.873289762818*_Complex_I}; float complex fft_test_y64[] = { 1.725198076750 + -4.343291505303*_Complex_I, -1.306135600819 + -7.829723137959*_Complex_I, -5.438260077023 + 4.634490918041*_Complex_I, -1.955793027433 + 4.362156087676*_Complex_I, -8.012216700915 + 8.400026452278*_Complex_I, -4.952000692368 + 3.096434501516*_Complex_I, 5.298208914176 + 4.534862681807*_Complex_I, -0.880561110671 + -1.467056178833*_Complex_I, 11.861836819015 + -0.544519325409*_Complex_I, -1.503603146027 + 8.809918042520*_Complex_I, -5.363184446773 + 9.548803374715*_Complex_I, -6.505800504816 + -7.798968990377*_Complex_I, 14.636787307656 + -0.228256068710*_Complex_I, 0.052560363405 + -12.014345616554*_Complex_I, -1.959253467557 + 8.402198459668*_Complex_I, -6.980453925187 + -6.436081969205*_Complex_I, 5.388968837267 + 3.576485581891*_Complex_I, 1.433883925658 + -1.990690693711*_Complex_I, 0.745585452676 + -3.797939482423*_Complex_I, 2.695240683264 + -0.969955745711*_Complex_I, -6.338874171853 + -7.732858525855*_Complex_I, 11.298952810793 + -13.037152643099*_Complex_I, -15.351176639589 + 9.947482416391*_Complex_I, -5.345010122884 + 0.498205314186*_Complex_I, -4.369620686268 + 0.751093800562*_Complex_I, 7.632293961493 + 0.946244674824*_Complex_I, -2.209404645076 + -8.887676077977*_Complex_I, 9.546753476599 + -11.691028922291*_Complex_I, -10.473480711255 + 0.645167184977*_Complex_I, 9.912509001236 + -22.116979184633*_Complex_I, 7.805895621936 + 2.010265856692*_Complex_I, -7.638461665175 + 0.687493859037*_Complex_I, 5.983512814381 + -4.711548846349*_Complex_I, 1.432584757253 + 2.618196841573*_Complex_I, -16.409812005381 + 2.126260364995*_Complex_I, -4.891966320361 + 4.829626903245*_Complex_I, -3.218785198666 + -4.443535570591*_Complex_I, 2.772033282272 + -1.143468987354*_Complex_I, -8.913495498818 + 3.327029248182*_Complex_I, 8.015679354394 + -3.131930356460*_Complex_I, 1.419572328954 + -0.132902166668*_Complex_I, 3.850100186885 + 9.527061186961*_Complex_I, 0.681611518886 + 4.259777024769*_Complex_I, 12.246604521898 + -0.790289131992*_Complex_I, 3.241695686006 + -15.727090004602*_Complex_I, -9.932323330295 + -0.102559333310*_Complex_I, -2.411503210251 + -0.408856287097*_Complex_I, 1.884210002432 + 7.477017352531*_Complex_I, -6.852334636700 + 3.198788969708*_Complex_I, 1.141049818230 + 1.542427926488*_Complex_I, 0.732333269451 + -1.802063276954*_Complex_I, -6.450414970103 + -2.758985609350*_Complex_I, -3.738653299253 + -7.196005387959*_Complex_I, 7.300969515165 + -7.844893935009*_Complex_I, 8.053617788503 + 5.389482632745*_Complex_I, 9.227999871537 + -2.302018386805*_Complex_I, -5.824592830409 + -0.544198322926*_Complex_I, -3.152065877231 + -6.410831104251*_Complex_I, -1.003575490144 + 23.308352736314*_Complex_I, 1.725485190234 + -10.960063101324*_Complex_I, -14.199659988605 + 7.198846575963*_Complex_I, 4.186354051025 + -2.044041800204*_Complex_I, 14.017389932813 + 2.146139910120*_Complex_I, 4.242720273094 + -3.627670543295*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_7.c000066400000000000000000000036601317124540100213550ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 7-point transform // #include float complex fft_test_x7[] = { 0.325737557343 + 0.347762560645*_Complex_I, -0.464568614672 + 1.344201995758*_Complex_I, -1.458140194879 + 0.983317270098*_Complex_I, 1.679041515327 + 1.025013762005*_Complex_I, -0.178483024495 + -0.711524629930*_Complex_I, 0.986194459374 + -1.709315563086*_Complex_I, 0.387998802736 + -1.150726066104*_Complex_I}; float complex fft_test_y7[] = { 1.277780500734 + 0.128729329387*_Complex_I, 4.360250363806 + 2.591163135631*_Complex_I, 1.609972293897 + 2.377175130550*_Complex_I, 0.436888889637 + -3.701058823864*_Complex_I, -0.903757801309 + 3.003131513942*_Complex_I, 1.797162255231 + -0.068636624441*_Complex_I, -6.298133600593 + -1.896165736688*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_79.c000066400000000000000000000217231317124540100214460ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 79-point transform // #include float complex fft_test_x79[] = { -0.831644933479 + -1.369566252119*_Complex_I, 1.382261515245 + 0.344632239578*_Complex_I, 1.522173067917 + -0.879128649493*_Complex_I, 0.412263305825 + -2.214373495146*_Complex_I, 0.167471424272 + 2.442885876862*_Complex_I, -0.995700286447 + -0.269798312873*_Complex_I, -0.495500240228 + -1.483255164915*_Complex_I, -1.294110579031 + 0.198434791977*_Complex_I, -0.725558739350 + 0.113152102484*_Complex_I, 0.245130536761 + -1.776484046331*_Complex_I, -0.902695579029 + -0.321701515101*_Complex_I, 0.612573133829 + 0.706900606440*_Complex_I, -1.446805571584 + 0.549130825767*_Complex_I, 0.779487733787 + 1.006717179605*_Complex_I, 0.482652400616 + -0.602577004101*_Complex_I, -0.075416135474 + 0.994234640494*_Complex_I, 1.169794509155 + 0.142737162623*_Complex_I, -0.552532601786 + -0.192607542361*_Complex_I, 0.410837027020 + -0.565889656334*_Complex_I, 0.141957082162 + -0.801461876260*_Complex_I, -0.593199921160 + 0.901175943982*_Complex_I, -1.360958657407 + -0.483045804780*_Complex_I, -1.919982203277 + 0.057049812902*_Complex_I, 0.597068489025 + 1.216028879537*_Complex_I, 0.553702635589 + 1.236264938570*_Complex_I, -0.600595429992 + 0.147163421599*_Complex_I, 0.311936436694 + -0.216250614525*_Complex_I, -1.091501993588 + 0.833497783365*_Complex_I, 1.744199597330 + 0.588786957660*_Complex_I, 2.530575868723 + 1.039372684186*_Complex_I, 1.028391846884 + -0.023635041523*_Complex_I, 1.289280692909 + -1.032658504022*_Complex_I, -0.717633308140 + -0.744729509226*_Complex_I, 0.305920738055 + 0.657498377749*_Complex_I, -1.129964121827 + -0.435663177627*_Complex_I, 1.648005569065 + 1.195099617541*_Complex_I, -2.115562921407 + -1.910525019001*_Complex_I, -0.596385890353 + 0.887009643025*_Complex_I, -0.230825994339 + -0.188182502664*_Complex_I, 0.263886383603 + -0.439257543266*_Complex_I, -0.523070205646 + 0.777409974948*_Complex_I, -0.219529035132 + 1.383569408478*_Complex_I, -0.718591132998 + 0.789138773979*_Complex_I, -0.584598456206 + 0.201764886974*_Complex_I, -0.569756495022 + -0.592160140902*_Complex_I, 0.187040275696 + 1.071817729923*_Complex_I, -0.157385303066 + -0.207843225364*_Complex_I, 1.277595054999 + -0.235819967829*_Complex_I, -0.096458535032 + 0.092010581965*_Complex_I, 0.359513513761 + 0.945023449614*_Complex_I, -0.907097860111 + 0.645605162871*_Complex_I, -0.651303141773 + 2.145291744091*_Complex_I, 0.114198590617 + 1.903139164821*_Complex_I, -0.079111313379 + 0.022610329502*_Complex_I, -1.170099271217 + -0.560852156056*_Complex_I, -0.857261592064 + 0.764585655287*_Complex_I, -0.308274947188 + 0.793759490894*_Complex_I, 1.075701520371 + 0.665603485423*_Complex_I, 0.121769228873 + 1.080351294531*_Complex_I, 1.775909597196 + -0.152691005919*_Complex_I, 1.592857837122 + 1.642268527260*_Complex_I, 0.206041280093 + 0.680507676427*_Complex_I, -0.447718650910 + -1.049968522775*_Complex_I, -1.571476809016 + 0.131194680122*_Complex_I, 1.668956017050 + -0.788549453555*_Complex_I, -1.464619492806 + -0.514115875797*_Complex_I, 2.085001980617 + 0.514847563050*_Complex_I, 0.928930120111 + -0.581073787447*_Complex_I, 0.446239202479 + -0.653366428964*_Complex_I, 1.064861444804 + -0.041135862801*_Complex_I, 0.072500637635 + 1.082811081123*_Complex_I, -1.400912797632 + -0.318643643314*_Complex_I, -0.475876438927 + 0.416837808588*_Complex_I, -0.066362697792 + 0.020225742927*_Complex_I, -0.153794040015 + -0.251785474065*_Complex_I, -1.237542116335 + 0.809600386690*_Complex_I, 0.871326964554 + 0.924351961256*_Complex_I, -2.389508044422 + -0.601457844861*_Complex_I, 0.080578131708 + 0.388813172800*_Complex_I}; float complex fft_test_y79[] = { -2.198332092440 + 12.650658598176*_Complex_I, -6.456670989242 + -7.479301674890*_Complex_I, -2.895336385229 + 1.221846928494*_Complex_I, -4.636342294176 + -0.801909581371*_Complex_I, -9.731802903280 + -5.232001275010*_Complex_I, 6.761030360809 + -1.721885218978*_Complex_I, 1.867893673405 + -10.436764472711*_Complex_I, 7.129857916226 + -15.261303660272*_Complex_I, 16.581711031970 + 5.179082607705*_Complex_I, -16.126836936739 + -5.300370279404*_Complex_I, -4.576577504775 + -12.699766318030*_Complex_I, -7.579093623452 + -12.405022376124*_Complex_I, -1.692330593182 + -8.516631597504*_Complex_I, -6.195245930268 + 0.070273567822*_Complex_I, 1.551185200774 + -5.151973196311*_Complex_I, -7.892299216869 + -6.606437030189*_Complex_I, 11.038003489600 + 4.657211823028*_Complex_I, 7.075974564323 + 0.545694748078*_Complex_I, -6.869510368707 + -0.939533375646*_Complex_I, -12.801782277417 + 4.703619318878*_Complex_I, 4.730103334639 + 3.588402018073*_Complex_I, 4.302722751897 + 5.818086352910*_Complex_I, 2.141745733069 + -1.961941960610*_Complex_I, 5.318048536295 + -0.010643144676*_Complex_I, 10.574791653730 + -2.110839910741*_Complex_I, 18.403982142892 + -4.968829844315*_Complex_I, -4.861819678415 + 0.167673326078*_Complex_I, -2.630720570170 + 1.594403564449*_Complex_I, 0.363441779769 + -10.436412333140*_Complex_I, -8.279198460723 + -3.380426807459*_Complex_I, -0.740797623754 + -2.814734090095*_Complex_I, -9.827753678018 + -12.010129525106*_Complex_I, 0.873038175248 + -1.031218712521*_Complex_I, -8.699339400800 + 12.933077680277*_Complex_I, -5.053719376427 + 3.839008815587*_Complex_I, -17.469957324379 + -0.249103089343*_Complex_I, 3.184401964192 + 3.862169536519*_Complex_I, 0.438203015374 + -2.050441604463*_Complex_I, -14.617902230891 + 13.404027008609*_Complex_I, -3.326663756629 + -9.464457202630*_Complex_I, -16.780077393079 + 4.427043334783*_Complex_I, 2.414049361911 + -12.349549334690*_Complex_I, -2.071827347449 + 0.131158553257*_Complex_I, 12.619462722043 + 3.785353059626*_Complex_I, 0.681152626465 + -5.767839231705*_Complex_I, -2.536944134501 + -4.990736350292*_Complex_I, -9.887559098728 + -30.445442814418*_Complex_I, -8.158210630371 + -2.609637272072*_Complex_I, 14.923059038703 + 2.059503206139*_Complex_I, 4.682549931928 + -0.864654149312*_Complex_I, 3.308241623127 + -8.932248210446*_Complex_I, -7.447372005399 + -15.848177608870*_Complex_I, 11.470445857602 + -17.244634800179*_Complex_I, -0.352198189530 + -5.465835457604*_Complex_I, 0.595131131258 + 1.784167835328*_Complex_I, -4.958773866897 + 1.052005175981*_Complex_I, -8.549314756256 + 10.245571680581*_Complex_I, -13.074676867355 + -9.163782974489*_Complex_I, -2.244945835090 + 13.220346166155*_Complex_I, -4.198374817495 + 10.065229182925*_Complex_I, -0.700355709960 + 6.827087899627*_Complex_I, 2.412030908809 + -6.042014368503*_Complex_I, -1.467215162979 + 16.669129234939*_Complex_I, 1.755798753328 + -6.540065639162*_Complex_I, -6.456991908144 + -7.304947059496*_Complex_I, -2.375547326101 + 18.123374474356*_Complex_I, 6.311057482521 + -9.358027340793*_Complex_I, 2.466570091641 + 5.305925828815*_Complex_I, 0.001957161866 + 18.960020221647*_Complex_I, -3.859854792754 + -4.745420470903*_Complex_I, 2.984060727978 + -4.759922601530*_Complex_I, 4.314065539668 + -4.099188676984*_Complex_I, -4.122177040779 + 6.664910801689*_Complex_I, 4.892466468902 + 19.707013122151*_Complex_I, 21.618605295806 + -12.301445853986*_Complex_I, -0.720795540227 + 3.447422417270*_Complex_I, 6.265639354108 + 13.611595323686*_Complex_I, -11.081101178789 + -14.511845349920*_Complex_I, 4.451917671114 + -12.130333484146*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_8.c000066400000000000000000000040241317124540100213510ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 8-point transform // #include float complex fft_test_x8[] = { 1.143832659273 + 0.058730029889*_Complex_I, -0.094390429919 + 0.229144161540*_Complex_I, -0.231936945111 + 0.250418514706*_Complex_I, 0.180568135767 + -0.869698396678*_Complex_I, -0.345282052584 + 1.176003338020*_Complex_I, 0.544428216952 + -0.610473584454*_Complex_I, 0.928035714223 + 0.647778401795*_Complex_I, 0.441211141066 + -1.176622015089*_Complex_I}; float complex fft_test_y8[] = { 2.566466439667 + -0.294719550271*_Complex_I, 1.635071437815 + 1.055386414782*_Complex_I, 1.767442826430 + 0.508277941207*_Complex_I, 2.964612333261 + -2.017902163711*_Complex_I, 0.422832311935 + 4.560580119089*_Complex_I, 0.548438211721 + -0.969987712376*_Complex_I, -1.562539151277 + 0.164794961607*_Complex_I, 0.808336864628 + -2.536589771219*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_9.c000066400000000000000000000041701317124540100213540ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 9-point transform // #include float complex fft_test_x9[] = { 0.318149471742 + -0.872622265472*_Complex_I, 0.380460329361 + 0.204662364547*_Complex_I, -0.569767779072 + -0.271995206036*_Complex_I, 1.334787120105 + -0.238015105170*_Complex_I, -0.644864052383 + 0.948536285238*_Complex_I, -0.489784794370 + 0.158143326416*_Complex_I, 1.783096398872 + -2.166235062454*_Complex_I, -0.138901921376 + -0.646377338691*_Complex_I, -0.257444231274 + 0.857372365765*_Complex_I}; float complex fft_test_y9[] = { 1.715730541604 + -2.026530635857*_Complex_I, 1.685963762512 + 0.399226582084*_Complex_I, -4.115380429157 + 1.255898079784*_Complex_I, 4.091196716626 + -4.693323087763*_Complex_I, -1.668677608930 + -1.439432143007*_Complex_I, -2.523905986916 + -0.920217192051*_Complex_I, 4.501171713926 + -3.110763575667*_Complex_I, 1.269999384456 + 3.193455688437*_Complex_I, -2.092752848444 + -0.511914105207*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_92.c000066400000000000000000000243471317124540100214460ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 92-point transform // #include float complex fft_test_x92[] = { -1.533248238739 + -0.465630703218*_Complex_I, -0.249958865116 + 0.582751340535*_Complex_I, -0.052014206281 + 0.945510877668*_Complex_I, 0.566817251755 + 0.873302572342*_Complex_I, -1.076106091336 + -0.264177557543*_Complex_I, 0.170852437277 + -0.619571758149*_Complex_I, 0.440747636244 + -0.170212602153*_Complex_I, 0.354775561873 + -0.272786796202*_Complex_I, 1.853177639448 + -1.188389922347*_Complex_I, 0.410907829911 + -0.451660724815*_Complex_I, -0.650435006722 + 1.672142963707*_Complex_I, -0.488214214181 + -0.805655420589*_Complex_I, -0.731929006826 + 1.054082992594*_Complex_I, -0.288141810907 + 0.209057566980*_Complex_I, -0.611240793053 + 1.293902538452*_Complex_I, -1.776441085660 + 0.958157296522*_Complex_I, -0.692307740144 + 0.075952098739*_Complex_I, 0.179804764868 + 1.730521926975*_Complex_I, -0.314045230459 + 1.905941797877*_Complex_I, 1.110105359337 + 1.465687036226*_Complex_I, -1.650241785564 + -2.376992111936*_Complex_I, 1.355816874526 + -2.252579556526*_Complex_I, 1.314750282984 + 0.595272183468*_Complex_I, 0.387080055146 + 0.205073570108*_Complex_I, -1.088814882881 + 1.793386020599*_Complex_I, -0.720166712307 + 0.890262821808*_Complex_I, -0.062602073879 + -0.031786415520*_Complex_I, -0.888507446134 + -0.536607709525*_Complex_I, -0.510561833378 + -0.675309226502*_Complex_I, 0.453615728261 + -0.387399412056*_Complex_I, 2.033274332370 + 1.120734915608*_Complex_I, 0.361177016452 + 0.840380849208*_Complex_I, 0.907153428882 + 0.117975673876*_Complex_I, 0.959754000635 + -0.182686914078*_Complex_I, -1.880157998612 + 1.024007596710*_Complex_I, -0.355239481254 + -1.157943305297*_Complex_I, 0.732180611349 + 0.476767076883*_Complex_I, 0.217871850693 + 0.378282281897*_Complex_I, 0.708348214996 + 1.015785074730*_Complex_I, 1.376611167796 + 0.025670694927*_Complex_I, 0.795489734327 + 2.447726960093*_Complex_I, -0.401589815356 + -1.887124361666*_Complex_I, -0.332674038856 + 0.654292754224*_Complex_I, 0.050773204061 + 1.851727945919*_Complex_I, 1.040820725747 + 0.163264568160*_Complex_I, -0.473870168659 + -0.135085060425*_Complex_I, -0.405218690036 + -0.210036331236*_Complex_I, -1.048228113315 + 1.224144846525*_Complex_I, -1.039363245830 + 0.571242521536*_Complex_I, 0.434387333441 + -0.667088930502*_Complex_I, 1.323498894566 + 0.321341399415*_Complex_I, -0.111430629981 + -0.911660421532*_Complex_I, -2.119793066060 + -0.604468380769*_Complex_I, -0.759768309222 + -1.196195111817*_Complex_I, -0.117965675009 + -0.853563152009*_Complex_I, 0.776854555180 + -1.044436698117*_Complex_I, -0.208543038837 + -0.719688047768*_Complex_I, 0.329085055714 + -0.731568530556*_Complex_I, 0.948200526516 + 0.778615477506*_Complex_I, -1.004787748593 + -1.447117819386*_Complex_I, -0.370036778975 + -1.041283005778*_Complex_I, 0.278647623179 + 0.132465770957*_Complex_I, -0.241472714303 + -0.804153723576*_Complex_I, -2.065839345003 + -0.285350361634*_Complex_I, 0.709097179382 + 1.197671609730*_Complex_I, -0.276234692523 + -0.085308137997*_Complex_I, -0.892034005938 + 1.470177172557*_Complex_I, 2.111093179577 + 0.214091335543*_Complex_I, 0.348125157569 + 0.660499475216*_Complex_I, -0.440004517499 + -0.381421105771*_Complex_I, -0.121445816759 + -0.900682972998*_Complex_I, 0.219762835492 + 0.024815977673*_Complex_I, -0.179837662261 + 0.545204347104*_Complex_I, 0.575266794792 + -0.857820948237*_Complex_I, -0.665258207110 + -0.142008087173*_Complex_I, 0.926210675302 + 0.676996743235*_Complex_I, -0.358453435398 + 0.218721578288*_Complex_I, 0.465198395168 + 0.321437159886*_Complex_I, -0.700888464307 + 0.026867992734*_Complex_I, 0.077912840097 + -0.700256177377*_Complex_I, 0.814218687572 + -0.237318115696*_Complex_I, 0.735605726247 + -0.843989440195*_Complex_I, 0.326456107919 + 1.621890601713*_Complex_I, 0.279920713907 + 1.255568802945*_Complex_I, -0.587220611906 + 0.854502071021*_Complex_I, 0.287904397154 + 1.370012449616*_Complex_I, 0.262419514043 + 0.783285944590*_Complex_I, -0.960094532334 + -1.295021304935*_Complex_I, 1.282525406387 + -0.543459424061*_Complex_I, -0.533518221919 + -0.066344323134*_Complex_I, -1.343771938200 + -0.320382155842*_Complex_I, -0.432681592095 + 0.159701208438*_Complex_I}; float complex fft_test_y92[] = { -2.518102271573 + 10.044654216417*_Complex_I, 6.643542265073 + 4.256887583025*_Complex_I, -11.918532524663 + 7.755442009935*_Complex_I, 7.568118092597 + -13.006486128008*_Complex_I, -18.363301435074 + -1.152166283835*_Complex_I, -5.786681211618 + -13.408541093492*_Complex_I, -8.010496951983 + 2.213039809355*_Complex_I, -1.411436744972 + 0.130962118237*_Complex_I, 7.222128824656 + 8.763744480410*_Complex_I, 13.775439027085 + 2.076241093317*_Complex_I, 6.773877664536 + -6.756550626162*_Complex_I, -7.137502543426 + 22.613697101003*_Complex_I, 9.970236986411 + 8.723751585267*_Complex_I, 3.388712243523 + -19.707507460853*_Complex_I, -22.698345626199 + -8.699233708477*_Complex_I, 2.966129501632 + -5.083169407361*_Complex_I, 0.748694115570 + 1.246761748677*_Complex_I, 7.286176947585 + -17.177394603147*_Complex_I, -4.640184708188 + -4.742141169474*_Complex_I, -15.653012036283 + 3.723708191064*_Complex_I, -0.304540600637 + 8.131182330682*_Complex_I, 6.514836424576 + -3.631934956688*_Complex_I, 14.631671446075 + -12.918654725994*_Complex_I, -9.079675359871 + -12.980498823161*_Complex_I, -2.396312070783 + -0.555311616694*_Complex_I, -5.516481227937 + 5.537031351170*_Complex_I, 16.946789253652 + -11.802977753669*_Complex_I, -9.863602251151 + 17.961504389879*_Complex_I, -1.089641984420 + 8.797684899764*_Complex_I, -3.199834226297 + -5.263692533431*_Complex_I, 3.613039090453 + 21.668260647267*_Complex_I, 4.356502756142 + 3.769573390222*_Complex_I, -11.010076007411 + -0.606073476312*_Complex_I, 1.249394309031 + 10.604580497016*_Complex_I, 0.432971670642 + -8.028445673142*_Complex_I, 1.772492721651 + -3.463373418618*_Complex_I, -12.314467825833 + -13.413674383092*_Complex_I, -4.796108671665 + -1.279659252444*_Complex_I, -4.135554898661 + 6.501150787072*_Complex_I, 4.235361817536 + 7.284416823675*_Complex_I, 4.645716809901 + -20.010236546155*_Complex_I, -11.820881373135 + -3.121702955852*_Complex_I, -1.176033491231 + -12.716343647780*_Complex_I, 0.309217041323 + 1.171408626241*_Complex_I, 7.362816400606 + 0.244428623814*_Complex_I, -5.010068913978 + -5.765683583933*_Complex_I, -6.876294123140 + 17.669794480924*_Complex_I, -3.948263111315 + -6.648206550629*_Complex_I, 2.175533159130 + -1.121668038664*_Complex_I, 10.506942679678 + 0.132441506635*_Complex_I, -6.051550803688 + -3.522998291999*_Complex_I, -12.716395512066 + -1.993147768949*_Complex_I, 0.716905419911 + -2.118308817826*_Complex_I, -6.214220320215 + 9.890190258116*_Complex_I, -3.496757347797 + 0.760118583470*_Complex_I, -0.165689780061 + 9.326952571297*_Complex_I, 3.608065605999 + 1.223288778006*_Complex_I, -15.368180054772 + 4.696419623807*_Complex_I, 6.532262844351 + -15.337625047848*_Complex_I, 11.463488167992 + -13.033909534322*_Complex_I, -3.089385178638 + 2.386958780173*_Complex_I, -8.764516788755 + -15.458094712422*_Complex_I, 5.161844954690 + 3.690438400691*_Complex_I, 7.483979541054 + 5.496267849787*_Complex_I, -3.191656352209 + -2.378455932485*_Complex_I, 3.346071918545 + -5.947101296914*_Complex_I, -7.911752024929 + 15.534843484634*_Complex_I, 4.990245834162 + -8.000769949862*_Complex_I, 3.430754206047 + -6.541036958204*_Complex_I, 3.819396364706 + -6.492827881304*_Complex_I, -5.791806578535 + -3.103857093968*_Complex_I, -0.378045544744 + 7.208602763143*_Complex_I, -6.569094552634 + -15.273087240577*_Complex_I, 2.045385676585 + 5.705039211157*_Complex_I, -3.551170334917 + -9.324062375092*_Complex_I, -3.762304723821 + 6.431485809437*_Complex_I, -13.592727599777 + -3.762490773764*_Complex_I, 14.293467882786 + 15.519778083180*_Complex_I, 7.838444610094 + -5.394721016744*_Complex_I, -6.164859647536 + 2.323160141970*_Complex_I, -6.775035839038 + 3.176555591565*_Complex_I, 3.450970697637 + 5.952471575141*_Complex_I, -9.694440566030 + 17.192480020342*_Complex_I, -4.389843029510 + -14.424868721698*_Complex_I, -13.182552822942 + -10.208834890358*_Complex_I, -15.936588561479 + 10.544520991017*_Complex_I, -14.982276290696 + 9.596052705212*_Complex_I, 2.219118227020 + -0.954468671057*_Complex_I, 8.714041016800 + 4.805998810501*_Complex_I, -6.362077161917 + -2.563077169544*_Complex_I, 5.636818008460 + -11.718358270750*_Complex_I, -12.128080581717 + 5.291433812970*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_data_96.c000066400000000000000000000251671317124540100214530ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data for 96-point transform // #include float complex fft_test_x96[] = { 0.231855789328 + 0.392790591230*_Complex_I, 0.454049797380 + 0.679061446432*_Complex_I, 0.528744029877 + -0.002005026486*_Complex_I, 0.585153010445 + -0.548050212091*_Complex_I, -0.688324957589 + -1.837254802682*_Complex_I, -1.210661843723 + -0.571711786295*_Complex_I, 1.276297465652 + -1.918840937281*_Complex_I, 0.903361922100 + -1.011460232753*_Complex_I, 0.477567600087 + 1.205903424233*_Complex_I, -0.786388960666 + 1.649160493258*_Complex_I, -0.690114487232 + 0.189150053367*_Complex_I, -0.123298428085 + 1.440273117047*_Complex_I, -1.824871622703 + -0.028412622663*_Complex_I, -0.005824551846 + -1.985955234017*_Complex_I, 0.441673373932 + 2.184282527711*_Complex_I, -0.302888535198 + 0.442593100570*_Complex_I, -1.138671997435 + 0.800927463670*_Complex_I, -0.113113592732 + 0.764107269897*_Complex_I, -1.301467098151 + 1.879202303512*_Complex_I, 1.216552799598 + 1.187277605073*_Complex_I, -0.414624947172 + -0.192700931033*_Complex_I, 0.157426358097 + -0.883438491265*_Complex_I, 1.314432283757 + -2.209536410386*_Complex_I, 0.115962402453 + 0.100570503666*_Complex_I, -0.184110258490 + -0.274585396498*_Complex_I, 1.182232744060 + -0.525435229715*_Complex_I, 1.369228680727 + -1.296270108729*_Complex_I, 0.679139800457 + 0.521729684119*_Complex_I, 1.466742696053 + -1.109181731398*_Complex_I, 0.423928449957 + 0.893374724805*_Complex_I, 0.097387993047 + -1.166367457697*_Complex_I, -0.319951780834 + 0.333472678246*_Complex_I, -0.851035928014 + 1.174430249645*_Complex_I, -0.741367318352 + 0.683540921651*_Complex_I, 0.063169486746 + 0.571172676088*_Complex_I, -1.973683326170 + -1.139982408570*_Complex_I, -0.176533972367 + 2.303718667820*_Complex_I, 1.427168284563 + 0.147925345978*_Complex_I, 0.168590812490 + 1.242460845878*_Complex_I, -0.463999677511 + -0.037151173794*_Complex_I, -2.536137467463 + -1.681395390537*_Complex_I, -0.968155862697 + 1.560777014683*_Complex_I, 0.679881050576 + 1.356938443072*_Complex_I, 0.882676978778 + -0.850244916120*_Complex_I, 0.356671274755 + -0.673629272452*_Complex_I, 0.770786696014 + 1.394669751828*_Complex_I, 1.879418388790 + -1.423104148622*_Complex_I, -1.625009605282 + 1.071684804070*_Complex_I, 0.523881317301 + -1.877721023134*_Complex_I, -0.810889778170 + 0.977110976206*_Complex_I, 1.184940081921 + 1.172520365453*_Complex_I, 0.614349326074 + 0.102072818821*_Complex_I, -0.022137672632 + -1.083247965012*_Complex_I, -0.608327216411 + -0.797618802167*_Complex_I, 1.718428073949 + -1.056519198093*_Complex_I, 0.060567885123 + 1.676707157575*_Complex_I, -0.495113579030 + 0.653357680357*_Complex_I, -0.854188871032 + 0.411288746049*_Complex_I, -0.410417801407 + 0.607919306211*_Complex_I, -1.442853726865 + -1.517927421271*_Complex_I, 0.274363566701 + 0.446776625735*_Complex_I, -0.625143151100 + 1.305210751509*_Complex_I, 1.212571305417 + 0.002561202196*_Complex_I, 0.964380743057 + -0.130831945021*_Complex_I, -1.467000571347 + -0.173752863470*_Complex_I, -0.361064943808 + -0.453821406270*_Complex_I, -0.435558558438 + -0.349465935625*_Complex_I, 1.160653554933 + 0.097609577607*_Complex_I, 0.824326827067 + -0.141377219902*_Complex_I, 0.151294380041 + 0.722300985052*_Complex_I, -0.160268192079 + 2.322410769696*_Complex_I, 1.756726727738 + -0.285586369209*_Complex_I, -1.614230674187 + -0.241407720255*_Complex_I, -0.035193854160 + -0.456767111405*_Complex_I, 1.997549686826 + 0.610571776676*_Complex_I, -1.013290679060 + 1.072224366678*_Complex_I, 0.966131190541 + 1.156926252511*_Complex_I, -0.085548688965 + -1.173983462045*_Complex_I, -1.258925646165 + 0.570319789600*_Complex_I, -0.009163839577 + -0.458346841578*_Complex_I, 0.328942919560 + -0.410428744477*_Complex_I, 1.359093898482 + -0.077096836434*_Complex_I, 0.269427793307 + 1.756132969724*_Complex_I, -1.612257645892 + 1.531514720616*_Complex_I, 1.344264226102 + 0.027502937744*_Complex_I, 1.369576658531 + 0.382536868127*_Complex_I, 0.172747665849 + 0.388258199964*_Complex_I, -0.226008514710 + -0.315160242926*_Complex_I, 0.150075935489 + 0.260574914740*_Complex_I, -0.170611752947 + -1.382717411879*_Complex_I, -1.216483547464 + -0.767792980333*_Complex_I, -1.976466005823 + 0.458969099499*_Complex_I, -0.645507778235 + 2.051797937683*_Complex_I, 0.981465939529 + 2.517091270417*_Complex_I, 1.174746235178 + -1.612669537430*_Complex_I, 0.896264508571 + 0.843449048976*_Complex_I}; float complex fft_test_y96[] = { 4.609981707790 + 14.165957863955*_Complex_I, -2.663372690989 + 3.381865489792*_Complex_I, -6.250889898983 + 0.856018997500*_Complex_I, 4.388447703102 + 0.709127580060*_Complex_I, 10.524498612708 + -15.765075233017*_Complex_I, -21.883023288862 + -5.754013136199*_Complex_I, -3.032497734395 + 3.435059152768*_Complex_I, 10.141510735231 + 6.569590619684*_Complex_I, -3.943788049939 + 4.985622407622*_Complex_I, -8.471948591549 + 3.436253039913*_Complex_I, -8.880296739352 + 18.329925169953*_Complex_I, 8.081550419966 + 4.959140273664*_Complex_I, 1.902048356207 + 12.753862442288*_Complex_I, 23.710137236631 + -5.734748416060*_Complex_I, 18.967547060099 + 2.261420011861*_Complex_I, -13.117649377758 + 5.255774731680*_Complex_I, 2.565218803705 + -25.049831530536*_Complex_I, 0.395850231743 + -4.532129398987*_Complex_I, 6.995600852169 + -7.386596256854*_Complex_I, -2.132719003770 + 6.698594558144*_Complex_I, -9.929306991332 + 6.869396317874*_Complex_I, 11.346428057260 + 15.752032502527*_Complex_I, -10.078874711603 + -6.207899239799*_Complex_I, -4.061971394211 + 1.001130636914*_Complex_I, -13.995272885614 + -4.455343352338*_Complex_I, 4.451519347892 + 7.926049461659*_Complex_I, 16.857007165977 + 8.029468101958*_Complex_I, 6.827258648561 + 14.930217154284*_Complex_I, -0.559549304382 + 8.208567303238*_Complex_I, -3.551940117450 + -7.211758268580*_Complex_I, 1.734999071287 + -3.632491293309*_Complex_I, -7.304392369767 + -14.527214303395*_Complex_I, -11.262783549629 + -1.605589170344*_Complex_I, -11.512374272203 + 16.561245028560*_Complex_I, 7.482726055364 + -2.727439658405*_Complex_I, 15.246746816163 + 17.569026228008*_Complex_I, -15.136445648942 + -1.722052787143*_Complex_I, -0.596784032900 + 1.036483442957*_Complex_I, -8.295090222700 + -14.787777542426*_Complex_I, -10.388667668932 + -3.677948124346*_Complex_I, 1.442374069335 + 2.369895137413*_Complex_I, -11.286677919418 + -0.442216831320*_Complex_I, -4.258359681535 + -5.877299409944*_Complex_I, 8.474879358850 + 11.133599053803*_Complex_I, 4.521324398684 + -5.575361516985*_Complex_I, -10.852733452716 + -8.187793263992*_Complex_I, 10.282241432010 + -14.787653906149*_Complex_I, -0.967326508687 + 1.045774363086*_Complex_I, 5.315060279059 + -6.564076763307*_Complex_I, -14.103481813190 + 7.024414693592*_Complex_I, 7.672189491846 + -8.914876516755*_Complex_I, 5.234244256475 + 3.602992887989*_Complex_I, -0.039164279610 + -30.448360387467*_Complex_I, -16.064792699661 + 6.718770045507*_Complex_I, 4.235111030143 + 2.478115209729*_Complex_I, -9.198909959126 + -8.290580416319*_Complex_I, 10.578975231033 + 2.559822357827*_Complex_I, 9.243136171627 + -9.377891910936*_Complex_I, 5.862895817529 + 0.431692246149*_Complex_I, -11.618990491528 + 17.539850472094*_Complex_I, -1.161363450862 + -2.941910938932*_Complex_I, -1.268260133904 + 1.005441709892*_Complex_I, 31.421272506426 + -0.240397785028*_Complex_I, -10.921843261114 + 10.855028296636*_Complex_I, 6.680208942916 + 7.902869278527*_Complex_I, 9.744767683416 + -15.653561656933*_Complex_I, 11.963236965081 + 2.757863055376*_Complex_I, -0.657516528727 + -1.513346377612*_Complex_I, -5.778133404808 + 0.380938385839*_Complex_I, 3.001034357249 + -0.472690292826*_Complex_I, 4.361975174738 + -0.082813022517*_Complex_I, 7.393956533023 + 3.595190860536*_Complex_I, -16.383681435953 + -0.148093500883*_Complex_I, 15.448535613211 + 13.699034854832*_Complex_I, -26.046188537886 + 4.672758210947*_Complex_I, -25.431394530510 + 19.149176229623*_Complex_I, 0.452366402127 + -9.284164787222*_Complex_I, -8.853642184491 + 7.831408406510*_Complex_I, -6.688478485009 + -3.439251128678*_Complex_I, -6.810859551138 + -8.440912926245*_Complex_I, -19.102617555696 + 6.927486844509*_Complex_I, 8.934833377990 + -11.564936252737*_Complex_I, -7.393024014592 + -0.714887967192*_Complex_I, -0.719859551514 + -13.605720898747*_Complex_I, -17.742142235287 + -12.458797479604*_Complex_I, 15.978186136167 + 5.980922906846*_Complex_I, 10.780516210769 + -5.413148370626*_Complex_I, 18.156965553233 + -2.629625388886*_Complex_I, 16.391744903218 + 7.895225147305*_Complex_I, 6.290790245017 + 6.997124329976*_Complex_I, 3.689747766167 + 11.534985962311*_Complex_I, 9.391595767018 + 17.298374496500*_Complex_I, 25.027955260120 + -7.023151206389*_Complex_I, -5.241064162059 + -8.249917715987*_Complex_I, -0.085493630186 + -3.829269584478*_Complex_I, 3.782595963629 + -0.412071285666*_Complex_I}; liquid-dsp-1.3.1/src/fft/tests/data/fft_r2rdata_27.c000066400000000000000000000142051317124540100220620ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft r2r (real-to-real) data // // 27-point real even/odd dft data float fftdata_r2r_x27[] = { 1.00000000e+00, 9.67720449e-01, 8.74232948e-01, 7.29134023e-01, 5.46968460e-01, 3.45309585e-01, 1.42522618e-01, -4.44371328e-02, -2.01871306e-01, -3.20590228e-01, -3.96443307e-01, -4.30132151e-01, -4.26421911e-01, -3.92946303e-01, -3.38838935e-01, -2.73413390e-01, -2.05070078e-01, -1.40540510e-01, -8.45066383e-02, -3.95672210e-02, -6.47628168e-03, 1.54448878e-02, 2.78246514e-02, 3.27720679e-02, 3.24839540e-02, 2.89606918e-02, 2.38370150e-02 }; // REDFT00 float fftdata_r2r_REDFT00_y27[] = { 1.90807498e+00, 6.92315578e+00, 1.18128624e+01, 5.63927364e+00, 6.24250948e-01, 6.22979142e-02, -2.71553919e-02, 1.96029730e-02, -1.47504276e-02, 1.15671754e-02, -9.38177109e-03, 7.82203674e-03, -6.67411089e-03, 5.80593944e-03, -5.13643026e-03, 4.61196899e-03, -4.19497490e-03, 3.86145711e-03, -3.59269325e-03, 3.37751862e-03, -3.20415385e-03, 3.06731090e-03, -2.96133757e-03, 2.88200378e-03, -2.82669067e-03, 2.79450417e-03, -2.78437138e-03 }; // REDFT10 float fftdata_r2r_REDFT10_y27[] = { 2.93191195e+00, 7.81435204e+00, 1.25262451e+01, 5.87700558e+00, 3.13943624e-01, -2.23003000e-01, -1.98579907e-01, -9.58713368e-02, -9.68946069e-02, -5.19125164e-02, -5.74545190e-02, -3.24527398e-02, -3.75072435e-02, -2.18437612e-02, -2.58425809e-02, -1.53105119e-02, -1.83160957e-02, -1.09222922e-02, -1.30745629e-02, -7.76020437e-03, -9.17540491e-03, -5.33153862e-03, -6.08742610e-03, -3.34636122e-03, -3.48186493e-03, -1.61480904e-03, -1.13347173e-03 }; // REDFT01 float fftdata_r2r_REDFT01_y27[] = { 3.24506021e+00, 1.02413387e+01, 1.02888603e+01, 2.94090056e+00, 3.01434755e-01, -3.94552648e-02, 4.12662849e-02, -3.65541428e-02, 3.23217735e-02, -2.86298655e-02, 2.54328623e-02, -2.26499923e-02, 2.02035718e-02, -1.80307329e-02, 1.60805881e-02, -1.43106822e-02, 1.26882717e-02, -1.11882668e-02, 9.78851132e-03, -8.47033411e-03, 7.21932389e-03, -6.02424145e-03, 4.87267971e-03, -3.75625165e-03, 2.66467361e-03, -1.59203156e-03, 5.29353623e-04 }; // REDFT11 float fftdata_r2r_REDFT11_y27[] = { 4.32605982e+00, 1.13771296e+01, 1.02061100e+01, 2.13518620e+00, -1.33218557e-01, -2.76073009e-01, -8.56223330e-02, -1.44742057e-01, -2.83730812e-02, -9.47302654e-02, -7.39809964e-03, -6.90608099e-02, 2.49255938e-03, -5.37654683e-02, 7.92805944e-03, -4.37831581e-02, 1.13052810e-02, -3.68458964e-02, 1.36666447e-02, -3.17945704e-02, 1.55290905e-02, -2.79758442e-02, 1.71851665e-02, -2.49931645e-02, 1.88217703e-02, -2.25886870e-02, 2.05794629e-02 }; // RODFT00 float fftdata_r2r_RODFT00_y27[] = { -3.07457280e+00, 4.34810066e+00, 1.09639254e+01, 7.64511538e+00, 4.62730789e+00, 3.26789522e+00, 2.68699503e+00, 2.17084169e+00, 1.91607285e+00, 1.60684299e+00, 1.45886230e+00, 1.24392998e+00, 1.14396501e+00, 9.81968999e-01, 9.06752288e-01, 7.78145194e-01, 7.16473997e-01, 6.10574782e-01, 5.56297779e-01, 4.66658950e-01, 4.16026711e-01, 3.38447809e-01, 2.88945198e-01, 2.20500469e-01, 1.70261383e-01, 1.08778238e-01, 5.62527180e-02 }; // RODFT10 float fftdata_r2r_RODFT10_y27[] = { -3.45587444e+00, 3.69455957e+00, 1.00895662e+01, 7.11557245e+00, 4.58258820e+00, 3.34214282e+00, 2.84152031e+00, 2.34757495e+00, 2.14987850e+00, 1.85646343e+00, 1.76226008e+00, 1.56126976e+00, 1.51575768e+00, 1.36674178e+00, 1.34836006e+00, 1.23211598e+00, 1.23075652e+00, 1.13685036e+00, 1.14728224e+00, 1.06952679e+00, 1.08892000e+00, 1.02343559e+00, 1.05029333e+00, 9.94573593e-01, 1.02823102e+00, 9.80662346e-01, 1.02105260e+00 }; // RODFT01 float fftdata_r2r_RODFT01_y27[] = { -2.61891890e+00, -4.18362617e-02, 9.58289337e+00, 9.41432190e+00, 5.27894020e+00, 3.62661290e+00, 2.76587272e+00, 2.31010056e+00, 1.92357457e+00, 1.67965138e+00, 1.44504440e+00, 1.28557563e+00, 1.12212110e+00, 1.00580621e+00, 8.81629765e-01, 7.90346980e-01, 6.89975739e-01, 6.14315927e-01, 5.29168069e-01, 4.63644713e-01, 3.88459831e-01, 3.29564214e-01, 2.60825515e-01, 2.06111193e-01, 1.41254663e-01, 8.88549462e-02, 2.58288011e-02 }; // RODFT11 float fftdata_r2r_RODFT11_y27[] = { -2.72205544e+00, -1.06129467e+00, 8.21426964e+00, 9.14769840e+00, 5.52553558e+00, 3.88690162e+00, 3.03581023e+00, 2.59010696e+00, 2.22776008e+00, 2.00389194e+00, 1.79835343e+00, 1.66311359e+00, 1.53181064e+00, 1.44247937e+00, 1.35311365e+00, 1.29120958e+00, 1.22834873e+00, 1.18450797e+00, 1.13985527e+00, 1.10885823e+00, 1.07762277e+00, 1.05639505e+00, 1.03571594e+00, 1.02242053e+00, 1.01060724e+00, 1.00419796e+00, 1.00035369e+00 }; liquid-dsp-1.3.1/src/fft/tests/data/fft_r2rdata_32.c000066400000000000000000000157211317124540100220620ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft r2r (real-to-real) data // // 32-point real even/odd dft data float fftdata_r2r_x32[] = { 1.00000000e+00, 9.76961553e-01, 9.09556091e-01, 8.02746117e-01, 6.64265335e-01, 5.03880322e-01, 3.32481116e-01, 1.61105037e-01, -3.40424648e-08, -1.42174676e-01, -2.58936524e-01, -3.46311510e-01, -4.02897298e-01, -4.29679066e-01, -4.29643869e-01, -4.07258183e-01, -3.67879450e-01, -3.17172974e-01, -2.60592192e-01, -2.02966005e-01, -1.48217648e-01, -9.92199481e-02, -5.77765778e-02, -2.47062612e-02, 1.25687316e-09, 1.69803519e-02, 2.72917245e-02, 3.22119817e-02, 3.30718160e-02, 3.11258435e-02, 2.74662171e-02, 2.29759347e-02 }; // REDFT00 float fftdata_r2r_REDFT00_y32[] = { 2.27039862e+00, 8.13895798e+00, 1.40223389e+01, 6.84894085e+00, 7.96620846e-01, 7.64858574e-02, -3.17813009e-02, 2.30059568e-02, -1.72815435e-02, 1.35012688e-02, -1.08927619e-02, 9.02237184e-03, -7.63727259e-03, 6.58483105e-03, -5.76706184e-03, 5.12006786e-03, -4.60112654e-03, 4.17934125e-03, -3.83267412e-03, 3.54650151e-03, -3.30836512e-03, 3.10952030e-03, -2.94351298e-03, 2.80511752e-03, -2.69039162e-03, 2.59574503e-03, -2.51914933e-03, 2.45943666e-03, -2.41351128e-03, 2.37989426e-03, -2.36272812e-03, 2.35617161e-03 }; // REDFT10 float fftdata_r2r_REDFT10_y32[] = { 3.29337406e+00, 9.03484726e+00, 1.47411804e+01, 7.09897327e+00, 4.95285779e-01, -2.08808795e-01, -2.04274148e-01, -9.34088752e-02, -1.00554205e-01, -5.08193560e-02, -6.01783060e-02, -3.20817754e-02, -3.97967622e-02, -2.19255462e-02, -2.79445965e-02, -1.57238189e-02, -2.03754716e-02, -1.16170188e-02, -1.51962955e-02, -8.72472394e-03, -1.14511019e-02, -6.57916535e-03, -8.60831141e-03, -4.91373613e-03, -6.35385327e-03, -3.56272981e-03, -4.48495522e-03, -2.41775438e-03, -2.86681950e-03, -1.40333176e-03, -1.39808655e-03, -4.60088253e-04 }; // REDFT01 float fftdata_r2r_REDFT01_y32[] = { 3.84605742e+00, 1.21377001e+01, 1.21945066e+01, 3.48508573e+00, 3.57804537e-01, -4.74350490e-02, 4.97081988e-02, -4.42513935e-02, 3.93650271e-02, -3.51234674e-02, 3.14703509e-02, -2.83105075e-02, 2.55550444e-02, -2.31280141e-02, 2.09678225e-02, -1.90287828e-02, 1.72705650e-02, -1.56631656e-02, 1.41822286e-02, -1.28069818e-02, 1.15218461e-02, -1.03116995e-02, 9.16616712e-03, -8.07419885e-03, 7.02799764e-03, -6.01985678e-03, 5.04441932e-03, -4.09346819e-03, 3.16351652e-03, -2.24826857e-03, 1.34513900e-03, -4.47750092e-04 }; // REDFT11 float fftdata_r2r_REDFT11_y32[] = { 4.92722511e+00, 1.32802725e+01, 1.21282454e+01, 2.68794346e+00, -7.75258020e-02, -2.84586310e-01, -7.88819566e-02, -1.52703851e-01, -2.31686458e-02, -1.01293720e-01, -3.44139524e-03, -7.46235624e-02, 5.45739289e-03, -5.86049184e-02, 1.00630848e-02, -4.80872169e-02, 1.27020460e-02, -4.07497510e-02, 1.43614262e-02, -3.54013182e-02, 1.55183356e-02, -3.13723050e-02, 1.64255053e-02, -2.82586850e-02, 1.72268860e-02, -2.58033480e-02, 1.80160627e-02, -2.38352567e-02, 1.88578963e-02, -2.22345591e-02, 1.98070407e-02, -2.09140405e-02 }; // RODFT00 float fftdata_r2r_RODFT00_y32[] = { -3.80376291e+00, 4.75984573e+00, 1.26453495e+01, 8.96690750e+00, 5.51104832e+00, 3.91941833e+00, 3.23827934e+00, 2.63059449e+00, 2.33582568e+00, 1.97329426e+00, 1.80615771e+00, 1.55536008e+00, 1.44624805e+00, 1.25815463e+00, 1.17955160e+00, 1.03102541e+00, 9.69759405e-01, 8.48199964e-01, 7.97134459e-01, 6.94987476e-01, 6.49889886e-01, 5.62294245e-01, 5.20456970e-01, 4.44106996e-01, 4.03675139e-01, 3.36212277e-01, 2.95823514e-01, 2.35492110e-01, 1.94067836e-01, 1.39503479e-01, 9.61183906e-02, 4.62093353e-02 }; // RODFT10 float fftdata_r2r_RODFT10_y32[] = { -4.18236399e+00, 4.10336685e+00, 1.17561054e+01, 8.40457535e+00, 5.42492485e+00, 3.95339370e+00, 3.35005546e+00, 2.76342392e+00, 2.52070665e+00, 2.17183208e+00, 2.05204034e+00, 1.81259131e+00, 1.75025475e+00, 1.57222724e+00, 1.54146743e+00, 1.40205300e+00, 1.39061260e+00, 1.27737224e+00, 1.27877247e+00, 1.18427241e+00, 1.19484186e+00, 1.11434531e+00, 1.13192439e+00, 1.06226850e+00, 1.08557940e+00, 1.02458429e+00, 1.05290902e+00, 9.99043226e-01, 1.03204751e+00, 9.84234095e-01, 1.02187860e+00, 9.79380608e-01 }; // RODFT01 float fftdata_r2r_RODFT01_y32[] = { -3.14800310e+00, -4.45067883e-01, 1.08461933e+01, 1.10677624e+01, 6.34346628e+00, 4.38031149e+00, 3.35651875e+00, 2.81504726e+00, 2.36018848e+00, 2.07406235e+00, 1.80141354e+00, 1.61707830e+00, 1.43000770e+00, 1.29786718e+00, 1.15834939e+00, 1.05674410e+00, 9.46406841e-01, 8.64174008e-01, 7.72926450e-01, 7.03647554e-01, 6.25416100e-01, 5.65090656e-01, 4.95949268e-01, 4.41907734e-01, 3.79158407e-01, 3.29515547e-01, 2.71191031e-01, 2.24530101e-01, 1.69109464e-01, 1.24305725e-01, 7.05337524e-02, 2.66184807e-02 }; // RODFT11 float fftdata_r2r_RODFT11_y32[] = { -3.24692512e+00, -1.44892704e+00, 9.45565414e+00, 1.07434196e+01, 6.54239464e+00, 4.59986401e+00, 3.58518982e+00, 3.05150127e+00, 2.61707282e+00, 2.34726048e+00, 2.09873915e+00, 1.93409348e+00, 1.77332234e+00, 1.66290724e+00, 1.55142403e+00, 1.47315228e+00, 1.39249706e+00, 1.33510482e+00, 1.27525985e+00, 1.23238277e+00, 1.18744755e+00, 1.15523088e+00, 1.12153363e+00, 1.09753525e+00, 1.07270765e+00, 1.05533838e+00, 1.03783357e+00, 1.02606010e+00, 1.01488125e+00, 1.00805402e+00, 1.00260448e+00, 1.00036693e+00 }; liquid-dsp-1.3.1/src/fft/tests/data/fft_r2rdata_8.c000066400000000000000000000057661317124540100220150ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft r2r (real-to-real) data // // 8-point real even/odd dft data float fftdata_r2r_x8[] = { 0.0000000000, 1.0000000000, 2.0000000000, 3.0000000000, 4.0000000000, 5.0000000000, 6.0000000000, 7.0000000000}; // REDFT00 float fftdata_r2r_REDFT00_y8[] = { 49.0000000000, -20.1956693581, -0.0000000000, -2.5724165284, -0.0000000000, -1.2319141135, -0.0000000000, -1.0000000000}; // REDFT10 float fftdata_r2r_REDFT10_y8[] = { 56.0000000000, -25.7692920908, 0.0000000000, -2.6938192036, 0.0000000000, -0.8036116149, 0.0000000000, -0.2028092910}; // REDFT01 float fftdata_r2r_REDFT01_y8[] = { 29.1819286410, -32.3061136840, 12.7168729872, -10.9904036256, 5.7286734878, -4.9189401648, 1.8807638636, -1.2927815051}; // REDFT11 float fftdata_r2r_REDFT11_y8[] = { 24.7243981823, -31.5148535947, 13.9257769120, -12.7826885392, 9.1714938314, -8.8071984223, 7.6789810021, -7.5857732734}; // RODFT00 float fftdata_r2r_RODFT00_y8[] = { 39.6989727373, -24.7272967751, 12.1243556530, -10.7257823333, 5.8736974182, -5.1961524227, 2.5477916399, -1.5869428264}; // RODFT10 float fftdata_r2r_RODFT10_y8[] = { 35.8808162684, -20.9050074380, 12.5996671239, -11.3137084990, 8.4188284171, -8.6591376023, 7.1371381075, -8.0000000000}; // RODFT01 float fftdata_r2r_RODFT01_y8[] = { 41.8902640723, -9.2302062214, 0.3792058953, -2.4608789465, 0.0160780480, -1.1773622132, 0.2426629216, -0.6033416816}; // RODFT11 float fftdata_r2r_RODFT11_y8[] = { 46.6916824794, -7.4005942194, 0.9237106918, -1.7485238108, -0.1159888643, -0.8699819349, -0.3640003929, -0.5519032668}; liquid-dsp-1.3.1/src/fft/tests/fft_composite_autotest.c000066400000000000000000000047211317124540100232360ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fft_composite_autotest.c : test FFTs of 'composite' length (not // prime, not of form 2^m) // #include "autotest/autotest.h" #include "liquid.h" // autotest data definitions #include "src/fft/tests/fft_runtest.h" // // AUTOTESTS: n-point ffts // void autotest_fft_10() { fft_test( fft_test_x10, fft_test_y10, 10); } void autotest_fft_21() { fft_test( fft_test_x21, fft_test_y21, 21); } void autotest_fft_22() { fft_test( fft_test_x22, fft_test_y22, 22); } void autotest_fft_24() { fft_test( fft_test_x24, fft_test_y24, 24); } void autotest_fft_26() { fft_test( fft_test_x26, fft_test_y26, 26); } void autotest_fft_30() { fft_test( fft_test_x30, fft_test_y30, 30); } void autotest_fft_35() { fft_test( fft_test_x35, fft_test_y35, 35); } void autotest_fft_36() { fft_test( fft_test_x36, fft_test_y36, 36); } void autotest_fft_48() { fft_test( fft_test_x48, fft_test_y48, 48); } void autotest_fft_63() { fft_test( fft_test_x63, fft_test_y63, 63); } void autotest_fft_92() { fft_test( fft_test_x92, fft_test_y92, 92); } void autotest_fft_96() { fft_test( fft_test_x96, fft_test_y96, 96); } void autotest_fft_120() { fft_test( fft_test_x120, fft_test_y120, 120); } void autotest_fft_130() { fft_test( fft_test_x130, fft_test_y130, 130); } void autotest_fft_192() { fft_test( fft_test_x192, fft_test_y192, 192); } liquid-dsp-1.3.1/src/fft/tests/fft_prime_autotest.c000066400000000000000000000034001317124540100223410ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fft_prime_autotest.c : test FFTs of prime length // #include "autotest/autotest.h" #include "liquid.h" // autotest data definitions #include "src/fft/tests/fft_runtest.h" // // AUTOTESTS: n-point ffts // void autotest_fft_17() { fft_test( fft_test_x17, fft_test_y17, 17); } void autotest_fft_43() { fft_test( fft_test_x43, fft_test_y43, 43); } void autotest_fft_79() { fft_test( fft_test_x79, fft_test_y79, 79); } void autotest_fft_157() { fft_test( fft_test_x157, fft_test_y157, 157); } void autotest_fft_317() { fft_test( fft_test_x317, fft_test_y317, 317); } void autotest_fft_509() { fft_test( fft_test_x509, fft_test_y509, 509); } liquid-dsp-1.3.1/src/fft/tests/fft_r2r_autotest.c000066400000000000000000000115571317124540100217460ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.h" // include data sets #include "fft_runtest.h" // autotest helper function void fft_r2r_test(float * _x, float * _test, unsigned int _n, unsigned int _kind) { int _flags = 0; float tol=1e-4f; unsigned int i; float y[_n]; // compute real even/odd FFT fftplan q = fft_create_plan_r2r_1d(_n, _x, y, _kind, _flags); fft_execute(q); // print results if (liquid_autotest_verbose) { printf("%12s %12s\n", "expected", "actual"); for (i=0; i<_n; i++) printf("%12.8f %12.8f\n", _test[i], y[i]); } // validate results for (i=0; i<_n; i++) CONTEND_DELTA( y[i], _test[i], tol); // destroy plans fft_destroy_plan(q); } // // AUTOTESTS: 8-point real-to-real ffts // void autotest_fft_r2r_REDFT00_n8() { fft_r2r_test(fftdata_r2r_x8, fftdata_r2r_REDFT00_y8, 8, LIQUID_FFT_REDFT00); } void autotest_fft_r2r_REDFT10_n8() { fft_r2r_test(fftdata_r2r_x8, fftdata_r2r_REDFT10_y8, 8, LIQUID_FFT_REDFT10); } void autotest_fft_r2r_REDFT01_n8() { fft_r2r_test(fftdata_r2r_x8, fftdata_r2r_REDFT01_y8, 8, LIQUID_FFT_REDFT01); } void autotest_fft_r2r_REDFT11_n8() { fft_r2r_test(fftdata_r2r_x8, fftdata_r2r_REDFT11_y8, 8, LIQUID_FFT_REDFT11); } void autotest_fft_r2r_RODFT00_n8() { fft_r2r_test(fftdata_r2r_x8, fftdata_r2r_RODFT00_y8, 8, LIQUID_FFT_RODFT00); } void autotest_fft_r2r_RODFT10_n8() { fft_r2r_test(fftdata_r2r_x8, fftdata_r2r_RODFT10_y8, 8, LIQUID_FFT_RODFT10); } void autotest_fft_r2r_RODFT01_n8() { fft_r2r_test(fftdata_r2r_x8, fftdata_r2r_RODFT01_y8, 8, LIQUID_FFT_RODFT01); } void autotest_fft_r2r_RODFT11_n8() { fft_r2r_test(fftdata_r2r_x8, fftdata_r2r_RODFT11_y8, 8, LIQUID_FFT_RODFT11); } // // AUTOTESTS: 32-point real-to-real ffts // void autotest_fft_r2r_REDFT00_n32() { fft_r2r_test(fftdata_r2r_x32, fftdata_r2r_REDFT00_y32, 32, LIQUID_FFT_REDFT00); } void autotest_fft_r2r_REDFT10_n32() { fft_r2r_test(fftdata_r2r_x32, fftdata_r2r_REDFT10_y32, 32, LIQUID_FFT_REDFT10); } void autotest_fft_r2r_REDFT01_n32() { fft_r2r_test(fftdata_r2r_x32, fftdata_r2r_REDFT01_y32, 32, LIQUID_FFT_REDFT01); } void autotest_fft_r2r_REDFT11_n32() { fft_r2r_test(fftdata_r2r_x32, fftdata_r2r_REDFT11_y32, 32, LIQUID_FFT_REDFT11); } void autotest_fft_r2r_RODFT00_n32() { fft_r2r_test(fftdata_r2r_x32, fftdata_r2r_RODFT00_y32, 32, LIQUID_FFT_RODFT00); } void autotest_fft_r2r_RODFT10_n32() { fft_r2r_test(fftdata_r2r_x32, fftdata_r2r_RODFT10_y32, 32, LIQUID_FFT_RODFT10); } void autotest_fft_r2r_RODFT01_n32() { fft_r2r_test(fftdata_r2r_x32, fftdata_r2r_RODFT01_y32, 32, LIQUID_FFT_RODFT01); } void autotest_fft_r2r_RODFT11_n32() { fft_r2r_test(fftdata_r2r_x32, fftdata_r2r_RODFT11_y32, 32, LIQUID_FFT_RODFT11); } // // AUTOTESTS: 27-point real-to-real ffts // void autotest_fft_r2r_REDFT00_n27() { fft_r2r_test(fftdata_r2r_x27, fftdata_r2r_REDFT00_y27, 27, LIQUID_FFT_REDFT00); } void autotest_fft_r2r_REDFT10_n27() { fft_r2r_test(fftdata_r2r_x27, fftdata_r2r_REDFT10_y27, 27, LIQUID_FFT_REDFT10); } void autotest_fft_r2r_REDFT01_n27() { fft_r2r_test(fftdata_r2r_x27, fftdata_r2r_REDFT01_y27, 27, LIQUID_FFT_REDFT01); } void autotest_fft_r2r_REDFT11_n27() { fft_r2r_test(fftdata_r2r_x27, fftdata_r2r_REDFT11_y27, 27, LIQUID_FFT_REDFT11); } void autotest_fft_r2r_RODFT00_n27() { fft_r2r_test(fftdata_r2r_x27, fftdata_r2r_RODFT00_y27, 27, LIQUID_FFT_RODFT00); } void autotest_fft_r2r_RODFT10_n27() { fft_r2r_test(fftdata_r2r_x27, fftdata_r2r_RODFT10_y27, 27, LIQUID_FFT_RODFT10); } void autotest_fft_r2r_RODFT01_n27() { fft_r2r_test(fftdata_r2r_x27, fftdata_r2r_RODFT01_y27, 27, LIQUID_FFT_RODFT01); } void autotest_fft_r2r_RODFT11_n27() { fft_r2r_test(fftdata_r2r_x27, fftdata_r2r_RODFT11_y27, 27, LIQUID_FFT_RODFT11); } liquid-dsp-1.3.1/src/fft/tests/fft_radix2_autotest.c000066400000000000000000000035001317124540100224170ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fft_radix2_autotest.c : test power-of-two transforms // #include "autotest/autotest.h" #include "liquid.h" // autotest data definitions #include "src/fft/tests/fft_runtest.h" // // AUTOTESTS: power-of-two transforms // void autotest_fft_2() { fft_test( fft_test_x2, fft_test_y2, 2); } void autotest_fft_4() { fft_test( fft_test_x4, fft_test_y4, 4); } void autotest_fft_8() { fft_test( fft_test_x8, fft_test_y8, 8); } void autotest_fft_16() { fft_test( fft_test_x16, fft_test_y16, 16); } void autotest_fft_32() { fft_test( fft_test_x32, fft_test_y32, 32); } void autotest_fft_64() { fft_test( fft_test_x64, fft_test_y64, 64); } liquid-dsp-1.3.1/src/fft/tests/fft_runtest.c000066400000000000000000000041571317124540100210130ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.h" // autotest helper function // _x : fft input array // _test : expected fft output // _n : fft size void fft_test(float complex * _x, float complex * _test, unsigned int _n) { int _method = 0; float tol=2e-4f; unsigned int i; float complex y[_n], z[_n]; // compute FFT fftplan pf = fft_create_plan(_n, _x, y, LIQUID_FFT_FORWARD, _method); fft_execute(pf); // compute IFFT fftplan pr = fft_create_plan(_n, y, z, LIQUID_FFT_BACKWARD, _method); fft_execute(pr); // normalize inverse for (i=0; i<_n; i++) z[i] /= (float) _n; // validate results float fft_error, ifft_error; for (i=0; i<_n; i++) { fft_error = cabsf( y[i] - _test[i] ); ifft_error = cabsf( _x[i] - z[i] ); CONTEND_DELTA( fft_error, 0, tol); CONTEND_DELTA( ifft_error, 0, tol); } // destroy plans fft_destroy_plan(pf); fft_destroy_plan(pr); } liquid-dsp-1.3.1/src/fft/tests/fft_runtest.h000066400000000000000000000120401317124540100210060ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fft data definitions // #ifndef __LIQUID_FFT_DATA_H__ #define __LIQUID_FFT_DATA_H__ // autotest helper function // _x : fft input array // _test : expected fft output // _n : fft size void fft_test(float complex * _x, float complex * _test, unsigned int _n); // // autotest datasets // // extern float complex fft_test_x2[]; extern float complex fft_test_y2[]; extern float complex fft_test_x3[]; extern float complex fft_test_y3[]; extern float complex fft_test_x4[]; extern float complex fft_test_y4[]; extern float complex fft_test_x5[]; extern float complex fft_test_y5[]; extern float complex fft_test_x6[]; extern float complex fft_test_y6[]; extern float complex fft_test_x7[]; extern float complex fft_test_y7[]; extern float complex fft_test_x8[]; extern float complex fft_test_y8[]; extern float complex fft_test_x9[]; extern float complex fft_test_y9[]; // extern float complex fft_test_x10[]; extern float complex fft_test_y10[]; extern float complex fft_test_x16[]; extern float complex fft_test_y16[]; extern float complex fft_test_x17[]; extern float complex fft_test_y17[]; extern float complex fft_test_x20[]; extern float complex fft_test_y20[]; extern float complex fft_test_x21[]; extern float complex fft_test_y21[]; extern float complex fft_test_x22[]; extern float complex fft_test_y22[]; extern float complex fft_test_x24[]; extern float complex fft_test_y24[]; extern float complex fft_test_x26[]; extern float complex fft_test_y26[]; extern float complex fft_test_x30[]; extern float complex fft_test_y30[]; extern float complex fft_test_x32[]; extern float complex fft_test_y32[]; extern float complex fft_test_x35[]; extern float complex fft_test_y35[]; extern float complex fft_test_x36[]; extern float complex fft_test_y36[]; extern float complex fft_test_x43[]; extern float complex fft_test_y43[]; extern float complex fft_test_x48[]; extern float complex fft_test_y48[]; extern float complex fft_test_x63[]; extern float complex fft_test_y63[]; extern float complex fft_test_x64[]; extern float complex fft_test_y64[]; extern float complex fft_test_x79[]; extern float complex fft_test_y79[]; extern float complex fft_test_x92[]; extern float complex fft_test_y92[]; extern float complex fft_test_x96[]; extern float complex fft_test_y96[]; // extern float complex fft_test_x120[]; extern float complex fft_test_y120[]; extern float complex fft_test_x130[]; extern float complex fft_test_y130[]; extern float complex fft_test_x157[]; extern float complex fft_test_y157[]; extern float complex fft_test_x192[]; extern float complex fft_test_y192[]; extern float complex fft_test_x317[]; extern float complex fft_test_y317[]; extern float complex fft_test_x509[]; extern float complex fft_test_y509[]; // 8-point real even/odd dft data extern float fftdata_r2r_x8[]; extern float fftdata_r2r_REDFT00_y8[]; extern float fftdata_r2r_REDFT10_y8[]; extern float fftdata_r2r_REDFT01_y8[]; extern float fftdata_r2r_REDFT11_y8[]; extern float fftdata_r2r_RODFT00_y8[]; extern float fftdata_r2r_RODFT10_y8[]; extern float fftdata_r2r_RODFT01_y8[]; extern float fftdata_r2r_RODFT11_y8[]; // 27-point real even/odd dft data extern float fftdata_r2r_x27[]; extern float fftdata_r2r_REDFT00_y27[]; extern float fftdata_r2r_REDFT10_y27[]; extern float fftdata_r2r_REDFT01_y27[]; extern float fftdata_r2r_REDFT11_y27[]; extern float fftdata_r2r_RODFT00_y27[]; extern float fftdata_r2r_RODFT10_y27[]; extern float fftdata_r2r_RODFT01_y27[]; extern float fftdata_r2r_RODFT11_y27[]; // 32-point real even/odd dft data extern float fftdata_r2r_x32[]; extern float fftdata_r2r_REDFT00_y32[]; extern float fftdata_r2r_REDFT10_y32[]; extern float fftdata_r2r_REDFT01_y32[]; extern float fftdata_r2r_REDFT11_y32[]; extern float fftdata_r2r_RODFT00_y32[]; extern float fftdata_r2r_RODFT10_y32[]; extern float fftdata_r2r_RODFT01_y32[]; extern float fftdata_r2r_RODFT11_y32[]; #endif // __LIQUID_FFT_DATA_H__ liquid-dsp-1.3.1/src/fft/tests/fft_shift_autotest.c000066400000000000000000000041601317124540100223460ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.h" void autotest_fft_shift_4() { float complex x[] = { 0 + 0*_Complex_I, 1 + 1*_Complex_I, 2 + 2*_Complex_I, 3 + 3*_Complex_I }; float complex test[] = { 2 + 2*_Complex_I, 3 + 3*_Complex_I, 0 + 0*_Complex_I, 1 + 1*_Complex_I }; fft_shift(x,4); CONTEND_SAME_DATA(x,test,4*sizeof(float complex)); } void autotest_fft_shift_8() { float complex x[] = { 0 + 0*_Complex_I, 1 + 1*_Complex_I, 2 + 2*_Complex_I, 3 + 3*_Complex_I, 4 + 4*_Complex_I, 5 + 5*_Complex_I, 6 + 6*_Complex_I, 7 + 7*_Complex_I }; float complex test[] = { 4 + 4*_Complex_I, 5 + 5*_Complex_I, 6 + 6*_Complex_I, 7 + 7*_Complex_I, 0 + 0*_Complex_I, 1 + 1*_Complex_I, 2 + 2*_Complex_I, 3 + 3*_Complex_I }; fft_shift(x,8); CONTEND_SAME_DATA(x,test,8*sizeof(float complex)); } liquid-dsp-1.3.1/src/fft/tests/fft_small_autotest.c000066400000000000000000000033301317124540100223370ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fft_small_autotest.c : test small transforms // #include "autotest/autotest.h" #include "liquid.h" // autotest data definitions #include "src/fft/tests/fft_runtest.h" // // AUTOTESTS: small FFTs // void autotest_fft_3() { fft_test( fft_test_x4, fft_test_y4, 4); } void autotest_fft_5() { fft_test( fft_test_x5, fft_test_y5, 5); } void autotest_fft_6() { fft_test( fft_test_x6, fft_test_y6, 6); } void autotest_fft_7() { fft_test( fft_test_x7, fft_test_y7, 7); } void autotest_fft_9() { fft_test( fft_test_x9, fft_test_y9, 9); } liquid-dsp-1.3.1/src/fft/tests/gen_fft_data.m000066400000000000000000000046371317124540100210660ustar00rootroot00000000000000% generate fft data for autotests function gen_fft_data(n); n = round(n); x = randn(1,n) + j*randn(1,n); y = fft(x); % print results filename = ['fft_data_' num2str(n) '.c']; fid = fopen(filename,'w'); fprintf(fid,'/* Copyright (c) 2007 - 2015 Joseph Gaeddert\n'); fprintf(fid,' *\n'); fprintf(fid,' * Permission is hereby granted, free of charge, to any person obtaining a copy\n'); fprintf(fid,' * of this software and associated documentation files (the "Software"), to deal\n'); fprintf(fid,' * in the Software without restriction, including without limitation the rights\n'); fprintf(fid,' * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n'); fprintf(fid,' * copies of the Software, and to permit persons to whom the Software is\n'); fprintf(fid,' * furnished to do so, subject to the following conditions:\n'); fprintf(fid,' * \n'); fprintf(fid,' * The above copyright notice and this permission notice shall be included in\n'); fprintf(fid,' * all copies or substantial portions of the Software.\n'); fprintf(fid,' *\n'); fprintf(fid,' * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n'); fprintf(fid,' * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n'); fprintf(fid,' * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n'); fprintf(fid,' * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n'); fprintf(fid,' * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n'); fprintf(fid,' * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n'); fprintf(fid,' * THE SOFTWARE.\n'); fprintf(fid,' */\n'); fprintf(fid,'\n'); fprintf(fid,'//\n'); fprintf(fid,'// autotest fft data for %u-point transform\n', n); fprintf(fid,'//\n'); fprintf(fid,'\n'); fprintf(fid,'#include \n'); fprintf(fid,'\n'); fprintf(fid,'float complex fft_test_x%d[] = {\n',n); for i=1:n, fprintf(fid,' %16.12f + %16.12f*_Complex_I', real(x(i)), imag(x(i))); if i==n, fprintf(fid,'};\n'); else, fprintf(fid,',\n'); end; end; fprintf(fid,'\n'); fprintf(fid,'float complex fft_test_y%d[] = {\n',n); for i=1:n, fprintf(fid,' %16.12f + %16.12f*_Complex_I', real(y(i)), imag(y(i))); if i==n, fprintf(fid,'};\n'); else, fprintf(fid,',\n'); end; end; fprintf(fid,'\n'); fclose(fid); printf('results written to %s\n', filename); liquid-dsp-1.3.1/src/fft/tests/gen_fft_files.m000066400000000000000000000003641317124540100212500ustar00rootroot00000000000000% generate fft data for autotests n = [2, 3, 4, 5, 6, 7, 8, 9,... 10, 16, 17, 20, 21, 22, 24, 26,... 30, 32, 35, 36, 43, 48, 63, 64, 79, 92, 96,... 120, 130, 157, 192, 317, 509] for i=1:length(n), gen_fft_data(n(i)); end; liquid-dsp-1.3.1/src/filter/000077500000000000000000000000001317124540100156415ustar00rootroot00000000000000liquid-dsp-1.3.1/src/filter/bench/000077500000000000000000000000001317124540100167205ustar00rootroot00000000000000liquid-dsp-1.3.1/src/filter/bench/fftfilt_crcf_benchmark.c000066400000000000000000000060311317124540100235310ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // Helper function to keep code base small void fftfilt_crcf_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _n) { // adjust number of iterations: *_num_iterations *= 100; if (_n < 6) *_num_iterations /= 120; else if (_n < 12) *_num_iterations /= 40; else *_num_iterations /= 5*_n; // generate coefficients unsigned int h_len = _n+1; float h[h_len]; unsigned long int i; for (i=0; i #include "liquid.h" // Helper function to keep code base small void firdecim_crcf_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _M, unsigned int _h_len) { // normalize number of iterations *_num_iterations /= _h_len; if (*_num_iterations < 1) *_num_iterations = 1; float h[_h_len]; unsigned int i; for (i=0; i<_h_len; i++) h[i] = 1.0f; firdecim_crcf q = firdecim_crcf_create(_M,h,_h_len); // initialize input float complex x[_M]; for (i=0; i<_M; i++) x[i] = (i%2) ? 1.0f : -1.0f; float complex y; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { firdecim_crcf_execute(q, x, &y); firdecim_crcf_execute(q, x, &y); firdecim_crcf_execute(q, x, &y); firdecim_crcf_execute(q, x, &y); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; firdecim_crcf_destroy(q); } #define FIRDECIM_CRCF_BENCHMARK_API(M,H_LEN) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { firdecim_crcf_bench(_start, _finish, _num_iterations, M, H_LEN); } void benchmark_firdecim_crcf_m2_h8 FIRDECIM_CRCF_BENCHMARK_API(2, 8) void benchmark_firdecim_crcf_m4_h16 FIRDECIM_CRCF_BENCHMARK_API(4, 16) void benchmark_firdecim_crcf_m8_h32 FIRDECIM_CRCF_BENCHMARK_API(8, 32) void benchmark_firdecim_crcf_m16_h64 FIRDECIM_CRCF_BENCHMARK_API(16,64) void benchmark_firdecim_cccf_m32_h128 FIRDECIM_CRCF_BENCHMARK_API(32,128) liquid-dsp-1.3.1/src/filter/bench/firfilt_crcf_benchmark.c000066400000000000000000000056231317124540100235400ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // Helper function to keep code base small void firfilt_crcf_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _n) { // adjust number of iterations: // cycles/trial ~ 107 + 4.3*_n *_num_iterations *= 1000; *_num_iterations /= (unsigned int)(107+4.3*_n); // generate coefficients float h[_n]; unsigned long int i; for (i=0; i<_n; i++) h[i] = randnf(); // create filter object firfilt_crcf f = firfilt_crcf_create(h,_n); // generate input vector float complex x[4]; for (i=0; i<4; i++) x[i] = randnf() + _Complex_I*randnf(); // output vector float complex y[4]; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { firfilt_crcf_push(f, x[0]); firfilt_crcf_execute(f, &y[0]); firfilt_crcf_push(f, x[1]); firfilt_crcf_execute(f, &y[1]); firfilt_crcf_push(f, x[2]); firfilt_crcf_execute(f, &y[2]); firfilt_crcf_push(f, x[3]); firfilt_crcf_execute(f, &y[3]); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; firfilt_crcf_destroy(f); } #define FIRFILT_CRCF_BENCHMARK_API(N) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { firfilt_crcf_bench(_start, _finish, _num_iterations, N); } void benchmark_firfilt_crcf_4 FIRFILT_CRCF_BENCHMARK_API(4) void benchmark_firfilt_crcf_8 FIRFILT_CRCF_BENCHMARK_API(8) void benchmark_firfilt_crcf_16 FIRFILT_CRCF_BENCHMARK_API(16) void benchmark_firfilt_crcf_32 FIRFILT_CRCF_BENCHMARK_API(32) void benchmark_firfilt_crcf_64 FIRFILT_CRCF_BENCHMARK_API(64) liquid-dsp-1.3.1/src/filter/bench/firhilb_benchmark.c000066400000000000000000000047361317124540100225270ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // Helper function to keep code base small void firhilbf_decim_bench( struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _m) { // normalize number of trials *_num_iterations *= 20; *_num_iterations /= liquid_nextpow2(_m+1); // create hilber transform object firhilbf q = firhilbf_create(_m,60.0f); float x[] = {1.0f, -1.0f}; float complex y; unsigned long int i; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { firhilbf_decim_execute(q,x,&y); firhilbf_decim_execute(q,x,&y); firhilbf_decim_execute(q,x,&y); firhilbf_decim_execute(q,x,&y); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; firhilbf_destroy(q); } #define FIRHILB_DECIM_BENCHMARK_API(M) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { firhilbf_decim_bench(_start, _finish, _num_iterations, M); } void benchmark_firhilbf_decim_m3 FIRHILB_DECIM_BENCHMARK_API(3) // m=3 void benchmark_firhilbf_decim_m5 FIRHILB_DECIM_BENCHMARK_API(5) // m=5 void benchmark_firhilbf_decim_m9 FIRHILB_DECIM_BENCHMARK_API(9) // m=9 void benchmark_firhilbf_decim_m13 FIRHILB_DECIM_BENCHMARK_API(13) // m=13 liquid-dsp-1.3.1/src/filter/bench/firinterp_crcf_benchmark.c000066400000000000000000000053651317124540100241060ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // Helper function to keep code base small void firinterp_crcf_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _M, unsigned int _h_len) { // normalize number of iterations *_num_iterations *= 80; *_num_iterations /= _h_len; if (*_num_iterations < 1) *_num_iterations = 1; float h[_h_len]; unsigned int i; for (i=0; i<_h_len; i++) h[i] = 1.0f; firinterp_crcf q = firinterp_crcf_create(_M,h,_h_len); float complex y[_M]; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { firinterp_crcf_execute(q,1.0f,y); firinterp_crcf_execute(q,1.0f,y); firinterp_crcf_execute(q,1.0f,y); firinterp_crcf_execute(q,1.0f,y); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; firinterp_crcf_destroy(q); } #define FIRINTERP_CRCF_BENCHMARK_API(M,H_LEN) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { firinterp_crcf_bench(_start, _finish, _num_iterations, M, H_LEN); } void benchmark_firinterp_crcf_m2_h8 FIRINTERP_CRCF_BENCHMARK_API(2, 8) void benchmark_firinterp_crcf_m4_h16 FIRINTERP_CRCF_BENCHMARK_API(4, 16) void benchmark_firinterp_crcf_m8_h32 FIRINTERP_CRCF_BENCHMARK_API(8, 32) void benchmark_firinterp_crcf_m16_h64 FIRINTERP_CRCF_BENCHMARK_API(16,64) void benchmark_firinterp_crcf_m32_h128 FIRINTERP_CRCF_BENCHMARK_API(32,128) liquid-dsp-1.3.1/src/filter/bench/iirdecim_crcf_benchmark.c000066400000000000000000000061421317124540100236630ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // Helper function to keep code base small void iirdecim_crcf_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _M, unsigned int _order) { // normalize number of iterations *_num_iterations /= _order; if (*_num_iterations < 1) *_num_iterations = 1; // create decimator from prototype liquid_iirdes_filtertype ftype = LIQUID_IIRDES_BUTTER; liquid_iirdes_bandtype btype = LIQUID_IIRDES_LOWPASS; liquid_iirdes_format format = LIQUID_IIRDES_SOS; float fc = 0.5f / (float)_M; float f0 = 0.0f; float Ap = 0.1f; float As = 60.0f; iirdecim_crcf q = iirdecim_crcf_create_prototype(_M,ftype,btype,format,_order,fc,f0,Ap,As); // initialize input float complex x[_M]; unsigned int i; for (i=0; i<_M; i++) x[i] = (i%2) ? 1.0f : -1.0f; float complex y; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { iirdecim_crcf_execute(q, x, &y); iirdecim_crcf_execute(q, x, &y); iirdecim_crcf_execute(q, x, &y); iirdecim_crcf_execute(q, x, &y); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; iirdecim_crcf_destroy(q); } #define IIRDECIM_CRCF_BENCHMARK_API(M,ORDER) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { iirdecim_crcf_bench(_start, _finish, _num_iterations, M, ORDER); } void benchmark_iirdecim_crcf_M2 IIRDECIM_CRCF_BENCHMARK_API(2, 5) void benchmark_iirdecim_crcf_M4 IIRDECIM_CRCF_BENCHMARK_API(4, 5) void benchmark_iirdecim_crcf_M8 IIRDECIM_CRCF_BENCHMARK_API(8, 5) void benchmark_iirdecim_crcf_M16 IIRDECIM_CRCF_BENCHMARK_API(16,5) void benchmark_iirdecim_cccf_M32 IIRDECIM_CRCF_BENCHMARK_API(32,5) liquid-dsp-1.3.1/src/filter/bench/iirfilt_crcf_benchmark.c000066400000000000000000000121141317124540100235340ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // Helper function to keep code base small void iirfilt_crcf_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _order, unsigned int _format) { unsigned int i; // scale number of iterations (trials) if (_format == LIQUID_IIRDES_TF) { // cycles/trial ~ 128 + 15.3*_order; *_num_iterations *= 1000; *_num_iterations /= (unsigned int)(128 + 15.3*_order); } else { // cycles/trial ~ 93 + 53.3*_order *_num_iterations *= 800; *_num_iterations /= (unsigned int)(93 + 53.3*_order); } // create filter object from prototype float fc = 0.2f; // filter cut-off frequency float f0 = 0.0f; // filter center frequency (band-pass, band-stop) float Ap = 0.1f; // filter pass-band ripple float As = 60.0f; // filter stop-band attenuation iirfilt_crcf q = iirfilt_crcf_create_prototype(LIQUID_IIRDES_BUTTER, LIQUID_IIRDES_LOWPASS, _format, _order, fc, f0, Ap, As); // initialize input/output float complex x[4]; float complex y[4]; for (i=0; i<4; i++) x[i] = randnf() + _Complex_I*randnf(); // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { iirfilt_crcf_execute(q, x[0], &y[0]); iirfilt_crcf_execute(q, x[1], &y[1]); iirfilt_crcf_execute(q, x[2], &y[2]); iirfilt_crcf_execute(q, x[3], &y[3]); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; // destroy filter object iirfilt_crcf_destroy(q); } #define IIRFILT_CRCF_BENCHMARK_API(N,T) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { iirfilt_crcf_bench(_start, _finish, _num_iterations, N, T); } // benchmark regular transfer function form void benchmark_iirfilt_crcf_4 IIRFILT_CRCF_BENCHMARK_API(4, LIQUID_IIRDES_TF) void benchmark_iirfilt_crcf_8 IIRFILT_CRCF_BENCHMARK_API(8, LIQUID_IIRDES_TF) void benchmark_iirfilt_crcf_16 IIRFILT_CRCF_BENCHMARK_API(16, LIQUID_IIRDES_TF) void benchmark_iirfilt_crcf_32 IIRFILT_CRCF_BENCHMARK_API(32, LIQUID_IIRDES_TF) void benchmark_iirfilt_crcf_64 IIRFILT_CRCF_BENCHMARK_API(64, LIQUID_IIRDES_TF) // benchmark second-order sections form void benchmark_iirfilt_crcf_sos_4 IIRFILT_CRCF_BENCHMARK_API(4, LIQUID_IIRDES_SOS) void benchmark_iirfilt_crcf_sos_8 IIRFILT_CRCF_BENCHMARK_API(8, LIQUID_IIRDES_SOS) void benchmark_iirfilt_crcf_sos_16 IIRFILT_CRCF_BENCHMARK_API(16, LIQUID_IIRDES_SOS) void benchmark_iirfilt_crcf_sos_32 IIRFILT_CRCF_BENCHMARK_API(32, LIQUID_IIRDES_SOS) void benchmark_iirfilt_crcf_sos_64 IIRFILT_CRCF_BENCHMARK_API(64, LIQUID_IIRDES_SOS) // benchmark DC-blocking filter void benchmark_irfilt_crcf_dcblock(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations) { unsigned long int i; // create filter object iirfilt_crcf q = iirfilt_crcf_create_dc_blocker(0.1f); // initialize input/output float complex x[4]; for (i=0; i<4; i++) x[i] = randnf() + _Complex_I*randnf(); // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { iirfilt_crcf_execute(q, x[0], &x[0]); iirfilt_crcf_execute(q, x[1], &x[1]); iirfilt_crcf_execute(q, x[2], &x[2]); iirfilt_crcf_execute(q, x[3], &x[3]); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; // destroy filter object iirfilt_crcf_destroy(q); } liquid-dsp-1.3.1/src/filter/bench/iirinterp_crcf_benchmark.c000066400000000000000000000060661317124540100241100ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // Helper function to keep code base small void iirinterp_crcf_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _M, unsigned int _order) { // normalize number of iterations *_num_iterations *= 80; *_num_iterations /= _M*_order; if (*_num_iterations < 1) *_num_iterations = 1; // create interpolator from prototype liquid_iirdes_filtertype ftype = LIQUID_IIRDES_BUTTER; liquid_iirdes_bandtype btype = LIQUID_IIRDES_LOWPASS; liquid_iirdes_format format = LIQUID_IIRDES_SOS; float fc = 0.5f / (float)_M; // filter cut-off frequency float f0 = 0.0f; float Ap = 0.1f; float As = 60.0f; iirinterp_crcf q = iirinterp_crcf_create_prototype(_M,ftype,btype,format,_order,fc,f0,Ap,As); float complex y[_M]; // start trials getrusage(RUSAGE_SELF, _start); unsigned int i; for (i=0; i<(*_num_iterations); i++) { iirinterp_crcf_execute(q, 1.0f, y); iirinterp_crcf_execute(q, 1.0f, y); iirinterp_crcf_execute(q, 1.0f, y); iirinterp_crcf_execute(q, 1.0f, y); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; iirinterp_crcf_destroy(q); } #define IIRINTERP_CRCF_BENCHMARK_API(M,ORDER) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { iirinterp_crcf_bench(_start, _finish, _num_iterations, M, ORDER); } void benchmark_iirinterp_crcf_M2 IIRINTERP_CRCF_BENCHMARK_API(2, 5) void benchmark_iirinterp_crcf_M4 IIRINTERP_CRCF_BENCHMARK_API(4, 5) void benchmark_iirinterp_crcf_M8 IIRINTERP_CRCF_BENCHMARK_API(8, 5) void benchmark_iirinterp_crcf_M16 IIRINTERP_CRCF_BENCHMARK_API(16,5) void benchmark_iirinterp_crcf_M32 IIRINTERP_CRCF_BENCHMARK_API(32,5) liquid-dsp-1.3.1/src/filter/bench/resamp2_crcf_benchmark.c000066400000000000000000000071271317124540100234530ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" typedef enum { RESAMP2_DECIM, RESAMP2_INTERP } resamp2_type; // Helper function to keep code base small void resamp2_crcf_bench(struct rusage *_start, struct rusage *_finish, unsigned long int * _num_iterations, unsigned int _m, resamp2_type _type) { // scale number of iterations by filter length // NOTE: n = 4*m+1 // cycles/trial ~ 70.5 + 7.74*_m *_num_iterations *= 200; *_num_iterations /= 70.5 + 7.74*_m; unsigned long int i; resamp2_crcf q = resamp2_crcf_create(_m,0.0f,60.0f); float complex x[] = {1.0f, -1.0f}; float complex y[] = {1.0f, -1.0f}; // start trials getrusage(RUSAGE_SELF, _start); if (_type == RESAMP2_DECIM) { // run decimator for (i=0; i<(*_num_iterations); i++) { resamp2_crcf_decim_execute(q,x,y); resamp2_crcf_decim_execute(q,x,y); resamp2_crcf_decim_execute(q,x,y); resamp2_crcf_decim_execute(q,x,y); } } else { // run interpolator for (i=0; i<(*_num_iterations); i++) { resamp2_crcf_interp_execute(q,x[0],y); resamp2_crcf_interp_execute(q,x[0],y); resamp2_crcf_interp_execute(q,x[0],y); resamp2_crcf_interp_execute(q,x[0],y); } } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; resamp2_crcf_destroy(q); } #define RESAMP2_CRCF_BENCHMARK_API(M,T) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { resamp2_crcf_bench(_start, _finish, _num_iterations, M, T); } // // Decimators // void benchmark_resamp2_crcf_decim_m2 RESAMP2_CRCF_BENCHMARK_API( 2,RESAMP2_DECIM) // n=9 void benchmark_resamp2_crcf_decim_m4 RESAMP2_CRCF_BENCHMARK_API( 4,RESAMP2_DECIM) // n=17 void benchmark_resamp2_crcf_decim_m8 RESAMP2_CRCF_BENCHMARK_API( 8,RESAMP2_DECIM) // n=33 void benchmark_resamp2_crcf_decim_m16 RESAMP2_CRCF_BENCHMARK_API(16,RESAMP2_DECIM) // n=65 // // Interpolators // void benchmark_resamp2_crcf_interp_m2 RESAMP2_CRCF_BENCHMARK_API( 2,RESAMP2_INTERP) // n=9 void benchmark_resamp2_crcf_interp_m4 RESAMP2_CRCF_BENCHMARK_API( 4,RESAMP2_INTERP) // n=17 void benchmark_resamp2_crcf_interp_m8 RESAMP2_CRCF_BENCHMARK_API( 8,RESAMP2_INTERP) // n=33 void benchmark_resamp2_crcf_interp_m16 RESAMP2_CRCF_BENCHMARK_API(16,RESAMP2_INTERP) // n=65 liquid-dsp-1.3.1/src/filter/bench/resamp_crcf_benchmark.c000066400000000000000000000055231317124540100233670ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // Helper function to keep code base small void resamp_crcf_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _m) { unsigned long int i; float r = 1.03f; // resampling rate float bw = 0.35f; // filter bandwidth float As = 60.0f; // stop-band attenuation [dB] unsigned int npfb = 32; // number of polyphase filters unsigned int m = _m; // filter semi-length resamp_crcf q = resamp_crcf_create(r,m,bw,As,npfb); float complex y[4]; unsigned int num_written; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { resamp_crcf_execute(q, 1.0f, y, &num_written); resamp_crcf_execute(q, 1.1f, y, &num_written); resamp_crcf_execute(q, 0.9f, y, &num_written); resamp_crcf_execute(q, 1.0f, y, &num_written); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; resamp_crcf_destroy(q); } #define RESAMP_CRCF_BENCHMARK_API(M) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { resamp_crcf_bench(_start, _finish, _num_iterations, M); } // // Resampler benchmark prototypes // void benchmark_resamp_crcf_m4 RESAMP_CRCF_BENCHMARK_API(4) void benchmark_resamp_crcf_m8 RESAMP_CRCF_BENCHMARK_API(8) void benchmark_resamp_crcf_m16 RESAMP_CRCF_BENCHMARK_API(16) void benchmark_resamp_crcf_m32 RESAMP_CRCF_BENCHMARK_API(32) void benchmark_resamp_crcf_m64 RESAMP_CRCF_BENCHMARK_API(64) void benchmark_resamp_crcf_m128 RESAMP_CRCF_BENCHMARK_API(128) liquid-dsp-1.3.1/src/filter/bench/symsync_crcf_benchmark.c000066400000000000000000000064161317124540100236070ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // Helper function to keep code base small void symsync_crcf_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _k, unsigned int _m) { unsigned long int i; unsigned int npfb = 16; // number of filters in bank unsigned int k = _k; // samples/symbol unsigned int m = _m; // filter delay [symbols] float beta = 0.3f; // filter excess bandwidth factor // create symbol synchronizer symsync_crcf q = symsync_crcf_create_rnyquist(LIQUID_FIRFILT_RRC, k, m, beta, npfb); // unsigned int num_samples = 64; *_num_iterations /= num_samples; unsigned int num_written; float complex x[num_samples]; float complex y[num_samples]; // generate pseudo-random data msequence ms = msequence_create_default(6); for (i=0; i #include #include #include // defined: // AUTOCORR() name-mangling macro // TI type (input) // TC type (coefficients) // TO type (output) // WINDOW() window macro // DOTPROD() dotprod macro // PRINTVAL() print macro struct AUTOCORR(_s) { unsigned int window_size; unsigned int delay; WINDOW() w; // input buffer WINDOW() wdelay; // input buffer with delay float * we2; // energy buffer float e2_sum; // running sum of energy unsigned int ie2; // read index }; // create auto-correlator object // _window_size : size of the correlator window // _delay : correlator delay [samples] AUTOCORR() AUTOCORR(_create)(unsigned int _window_size, unsigned int _delay) { // create main object AUTOCORR() q = (AUTOCORR()) malloc(sizeof(struct AUTOCORR(_s))); // set user-based parameters q->window_size = _window_size; q->delay = _delay; // create window objects q->w = WINDOW(_create)(q->window_size); q->wdelay = WINDOW(_create)(q->window_size + q->delay); // allocate array for squared energy buffer q->we2 = (float*) malloc( (q->window_size)*sizeof(float) ); // clear object AUTOCORR(_reset)(q); // return main object return q; } // destroy auto-correlator object, freeing internal memory void AUTOCORR(_destroy)(AUTOCORR() _q) { // destroy internal window objects WINDOW(_destroy)(_q->w); WINDOW(_destroy)(_q->wdelay); // free array for squared energy buffer free(_q->we2); // free main object memory free(_q); } // reset auto-correlator object's internals void AUTOCORR(_reset)(AUTOCORR() _q) { // clear/reset internal window buffers WINDOW(_reset)(_q->w); WINDOW(_reset)(_q->wdelay); // reset internal squared energy buffer _q->e2_sum = 0.0; unsigned int i; for (i=0; i<_q->window_size; i++) _q->we2[i] = 0.0; _q->ie2 = 0; // reset read index to zero } // print auto-correlator parameters to stdout void AUTOCORR(_print)(AUTOCORR() _q) { printf("autocorr [%u window, %u delay]\n", _q->window_size, _q->delay); } // push sample into auto-correlator object void AUTOCORR(_push)(AUTOCORR() _q, TI _x) { // push input sample into buffers WINDOW(_push)(_q->w, _x); // non-delayed buffer WINDOW(_push)(_q->wdelay, conj(_x)); // delayed buffer // push |_x|^2 into buffer at appropriate location float e2 = creal( _x*conj(_x) ); _q->e2_sum -= _q->we2[ _q->ie2 ]; _q->e2_sum += e2; _q->we2[ _q->ie2 ] = e2; _q->ie2 = (_q->ie2+1) % _q->window_size; } // compute auto-correlation output void AUTOCORR(_execute)(AUTOCORR() _q, TO *_rxx) { // provide pointers for reading buffer TI * rw; // input buffer read pointer TC * rwdelay; // input buffer read pointer (with delay) // read buffers; set internal pointers appropriately WINDOW(_read)(_q->w, &rw ); WINDOW(_read)(_q->wdelay, &rwdelay); // execute vector dot product on arrays, saving result to // user-supplied output pointer DOTPROD(_run4)(rw, rwdelay, _q->window_size, _rxx); } // compute auto-correlation on block of samples; the input // and output arrays may have the same pointer // _q : auto-correlation object // _x : input array [size: _n x 1] // _n : number of input, output samples // _rxx : input array [size: _n x 1] void AUTOCORR(_execute_block)(AUTOCORR() _q, TI * _x, unsigned int _n, TO * _rxx) { unsigned int i; for (i=0; i<_n; i++) { // push input sample into auto-correlator AUTOCORR(_push)(_q, _x[i]); // compute output AUTOCORR(_execute)(_q, &_rxx[i]); } } // return sum of squares of buffered samples float AUTOCORR(_get_energy)(AUTOCORR() _q) { // value is already computed; simply return value return _q->e2_sum; } liquid-dsp-1.3.1/src/filter/src/bessel.c000066400000000000000000000206771317124540100200650ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Bessel filter design // // References: // [Bianchi:2007] G. Bianchi and R. Sorrentino, "Electronic Filter Simulation // and Design." New York: McGraw-Hill, 2007. // [Orchard:1965] H. J. Orchard, "The Roots of the Maximally Flat-Delay // Polynomials." IEEE Transactions on Circuit Theory, September, 1965. // #include #include #include #include #include #include "liquid.internal.h" #define LIQUID_DEBUG_BESSEL_PRINT 0 // forward declarations void fpoly_bessel(unsigned int _n, float * _p); void fpoly_bessel_roots(unsigned int _n, float complex * _roots); void fpoly_bessel_roots_orchard(unsigned int _n, float complex * _roots); void fpoly_bessel_roots_orchard_recursion(unsigned int _n, float _x, float _y, float * _x_hat, float * _y_hat); // **************************************** // Compute analog zeros, poles, gain of low-pass Bessel // filter, grouping complex conjugates together. If // the filter order is odd, the single real pole is at // the end of the array. There are no zeros for the // analog Bessel filter. The gain is unity. // _n : filter order // _z : output analog zeros [length: 0] // _p : output analog poles [length: _n] // _k : output analog gain void bessel_azpkf(unsigned int _n, float complex * _za, float complex * _pa, float complex * _ka) { // compute poles (roots to Bessel polynomial) fpoly_bessel_roots(_n+1,_pa); // analog Bessel filter prototype has no zeros // The analog Bessel filter's 3-dB cut-off frequency is a // non-linear function of its order. This frequency can // be approximated from [Bianchi:2007] (1.67), pp. 33. // Re-normalize poles by (approximated) 3-dB frequency. float w3dB = sqrtf((2*_n-1)*logf(2.0f)); unsigned int i; for (i=0; i<_n; i++) _pa[i] /= w3dB; // set gain *_ka = 1.0f; for (i=0; i<_n; i++) *_ka *= _pa[i]; } void fpoly_bessel(unsigned int _n, float * _p) { unsigned int k; unsigned int N = _n-1; for (k=0; k<_n; k++) { #if 0 // use internal log(gamma(z)) float t0 = liquid_lngammaf((float)(2*N-k)+1); float t1 = liquid_lngammaf((float)(N-k) +1); float t2 = liquid_lngammaf((float)(k) +1); #else // use standard math log(gamma(z)) float t0 = lgammaf((float)(2*N-k)+1); float t1 = lgammaf((float)(N-k) +1); float t2 = lgammaf((float)(k) +1); #endif // M_LN2 = log(2) = 0.693147180559945 float t3 = M_LN2 * (float)(N-k); // log(2^(N-k)) = log(2)*log(N-k) _p[k] = roundf(expf(t0 - t1 - t2 - t3)); #if 0 printf(" p[%3u,%3u] = %12.4e\n", k, _n, _p[k]); printf(" t0 : %12.4e\n", t0); printf(" t1 : %12.4e\n", t1); printf(" t2 : %12.4e\n", t2); printf(" t3 : %12.4e\n", t3); #endif } } void fpoly_bessel_roots(unsigned int _n, float complex * _roots) { fpoly_bessel_roots_orchard(_n, _roots); } // Estimate the roots of the _n^th-order Bessel polynomial using // Orchard's recursion. The initial estimates for the roots of // L_{k} are extrapolated from those in L_{k-2} and L_{k-1}. // The resulting root is near enough the true root such that // Orchard's recursion will find it. void fpoly_bessel_roots_orchard(unsigned int _n, float complex * _roots) { // initialize arrays float complex r0[_n]; // roots of L_{k-2} float complex r1[_n]; // roots of L_{k-1} float complex r_hat[_n]; // roots of L_{k} unsigned int i, j; unsigned int p, L; for (i=1; i<_n; i++) { p = i % 2; // order is odd? L = (i+p)/2; //printf("\n***** order %3u, p=%3u, L=%3u\n", i, p, L); if (i == 1) { r1[0] = -1; r_hat[0] = -1; } else if (i == 2) { r1[0] = -1; r_hat[0] = -1.5f + _Complex_I*0.5f*sqrtf(3.0f); } else { // use previous 2 sets of roots to estimate this set if (p) { // odd order : one real root on negative imaginary axis r_hat[0] = 2*crealf(r1[0]) - crealf(r0[0]); } else { // even order r_hat[0] = 2*r1[0] - conjf(r0[0]); } // linear extrapolation of roots of L_{k-2} and L_{k-1} for // new root estimate in L_{k} for (j=1; j roots(L_{k+2)) // roots(L_{k}) -> roots(L_{k+1)) memmove(r0, r1, (L-p)*sizeof(float complex)); memmove(r1, r_hat, L*sizeof(float complex)); } // copy results to output p = _n % 2; L = (_n-p)/2; for (i=0; i #include #include #include "liquid.internal.h" #define LIQUID_DEBUG_BILINEAR_PRINT 0 // bilinear z-transform using zeros, poles, gain // // (s-z[0])*(s-z[1])*...*(s-z[nz-1]) // H(s) = k * --------------------------------- // (s-p[0])*(s-p[1])*...*(s-z[np-1]) // // inputs // _z : array of polynomial zeros (length _nz) // _nz : number of zeros // _p : array of polynomial poles (length _np) // _np : number of poles // _k : scaling factor // _m : bilateral warping factor // // outputs // _b : digital numerator (length _nz+1) // _a : digital denominator (length _np+1) void bilinear_zpk(float complex * _z, unsigned int _nz, float complex * _p, unsigned int _np, float complex _k, float _m, float complex * _b, float complex * _a) { unsigned int i; // expand numerator unsigned int nb = _nz+1; float complex pb[nb]; cfpoly_expandroots(_z,_nz,pb); if (_nz == 0) pb[0] = 1.; // expand denominator unsigned int na = _np+1; float complex pa[na]; cfpoly_expandroots(_p,_np,pa); if (_np == 0) pa[0] = 1.; // scale numerator by _k for (i=0; i _m*(z-1)/(z+1) ) and expands as // // bd[0] + bd[1]*z^-1 + ... + bd[nb]*z^-n // H(z) = -------------------------------------- // ad[0] + ad[1]*z^-1 + ... + ad[nb]*z^-m // // inputs // _b : numerator array (length _b_order+1) // _b_order : polynomial order of _b // _a : denominator array (length _a_order+1) // _a_order : polynomial order of _a // _m : bilateral warping factor // // outputs // _bd : digital filter numerator (length _b_order+1) // _ad : digital filter numerator (length _a_order+1) void bilinear_nd(float complex * _b, unsigned int _b_order, float complex * _a, unsigned int _a_order, float _m, float complex * _bd, float complex * _ad) { if (_b_order > _a_order) { fprintf(stderr,"error: bilinear_nd(), numerator order cannot be higher than denominator\n"); exit(1); } #if LIQUID_DEBUG_BILINEAR_PRINT printf("***********************************\n"); printf("bilinear(nd), numerator order : %u\n", _b_order); printf("bilinear(nd), denominator order : %u\n", _a_order); #endif // ... unsigned int nb = _b_order+1; // input numerator polynomial array length unsigned int na = _a_order+1; // input denominator polynomial array length unsigned int i, j; // clear output arrays (both are length na = _a_order+1) for (i=0; i #include #include #include #include "liquid.internal.h" #define LIQUID_DEBUG_BUTTER_PRINT 0 // Compute analog zeros, poles, gain of low-pass Butterworth // filter, grouping complex conjugates together. If filter // order is odd, the single real pole (-1) is at the end of // the array. There are no zeros for the analog Butterworth // filter. The gain is unity. // _n : filter order // _za : output analog zeros [length: 0] // _pa : output analog poles [length: _n] // _ka : output analog gain void butter_azpkf(unsigned int _n, liquid_float_complex * _za, liquid_float_complex * _pa, liquid_float_complex * _ka) { unsigned int r = _n%2; unsigned int L = (_n - r)/2; unsigned int i; unsigned int k=0; for (i=0; i #include #include #include #include #include "liquid.internal.h" #define LIQUID_DEBUG_CHEBY1_PRINT 0 // Compute analog zeros, poles, gain of low-pass Chebyshev // Type I filter, grouping complex conjugates together. If // the filter order is odd, the single real pole is at the // end of the array. There are no zeros for the analog // Chebyshev Type I filter. // _n : filter order // _ep : epsilon, related to pass-band ripple // _za : output analog zeros [length: 0] // _pa : output analog poles [length: _n] // _ka : output analog gain void cheby1_azpkf(unsigned int _n, float _ep, liquid_float_complex * _za, liquid_float_complex * _pa, liquid_float_complex * _ka) { // temporary values float t0 = sqrt(1.0 + 1.0/(_ep*_ep)); float tp = powf( t0 + 1.0/_ep, 1.0/(float)(_n) ); float tm = powf( t0 - 1.0/_ep, 1.0/(float)(_n) ); float b = 0.5*(tp + tm); // ellipse major axis float a = 0.5*(tp - tm); // ellipse minor axis #if LIQUID_DEBUG_CHEBY1_PRINT printf(" ep : %12.8f\n", _ep); printf(" b : %12.8f\n", b); printf(" a : %12.8f\n", a); #endif // filter order variables unsigned int r = _n%2; // odd order? unsigned int L = (_n - r)/2; // half order // compute poles unsigned int i; unsigned int k=0; for (i=0; i #include #include #include #include #include "liquid.internal.h" #define LIQUID_DEBUG_CHEBY2_PRINT 0 // Compute analog zeros, poles, gain of low-pass Chebyshev // Type II filter, grouping complex conjugates together. If // the filter order is odd, the single real pole is at the // end of the array. // _n : filter order // _ep : epsilon, related to stop-band ripple // _za : output analog zeros [length: floor(_n/2)] // _pa : output analog poles [length: _n] // _ka : output analog gain void cheby2_azpkf(unsigned int _n, float _es, liquid_float_complex * _za, liquid_float_complex * _pa, liquid_float_complex * _ka) { // temporary values float t0 = sqrt(1.0 + 1.0/(_es*_es)); float tp = powf( t0 + 1.0/_es, 1.0/(float)(_n) ); float tm = powf( t0 - 1.0/_es, 1.0/(float)(_n) ); float b = 0.5*(tp + tm); // ellipse major axis float a = 0.5*(tp - tm); // ellipse minor axis #if LIQUID_DEBUG_CHEBY2_PRINT printf("ep : %12.8f\n", _es); printf("b : %12.8f\n", b); printf("a : %12.8f\n", a); #endif // filter order variables unsigned int r = _n % 2; // odd order? unsigned int L = (_n - r)/2; // half order // compute poles unsigned int i; unsigned int k=0; for (i=0; i #include #include #include #include "liquid.internal.h" #define LIQUID_DEBUG_ELLIP_PRINT 0 // landenf() // // Compute the Landen transformation of _k over _n iterations, // k[n] = (k[n-1] / (1+k'[n-1]))^2 // where // k'[n-1] = sqrt(1-k[n-1]^2) // // _k : elliptic modulus // _n : number of iterations // _v : sequence of decreasing moduli [size: _n] void landenf(float _k, unsigned int _n, float * _v) { unsigned int i; float k = _k; // k[n] float kp; // k'[n] for (i=0; i<_n; i++) { kp = sqrtf(1 - k*k); k = (1 - kp)/(1 + kp); _v[i] = k; } } // ellipkf() // // compute elliptic integral K(k) for _n recursions // // _k : elliptic modulus // _n : number of iterations // _K : complete elliptic integral (modulus k) // _Kp : complete elliptic integral (modulus k') void ellipkf(float _k, unsigned int _n, float * _K, float * _Kp) { // define range for k due to machine precision float kmin = 4e-4f; float kmax = sqrtf(1-kmin*kmin); float K; float Kp; float kp = sqrtf(1-_k*_k); //printf("ellipkf: k = %16.8e, kp = %16.8e\n", _k, kp); // Floating point resolution limits the range of the // computation of K on input _k [Orfanidis:2005] if (_k > kmax) { // input exceeds maximum extreme for this precision; use // approximation float L = -logf(0.25f*kp); K = L + 0.25f*(L-1)*kp*kp; } else { float v[_n]; landenf(_k,_n,v); K = M_PI * 0.5f; unsigned int i; for (i=0; i<_n; i++) K *= (1 + v[i]); } if (_k < kmin) { // input exceeds minimum extreme for this precision; use // approximation float L = -logf(_k*0.25f); Kp = L + 0.25f*(L-1)*_k*_k; } else { float vp[_n]; landenf(kp,_n,vp); Kp = M_PI * 0.5f; unsigned int i; for (i=0; i<_n; i++) Kp *= (1 + vp[i]); } // set return values *_K = K; *_Kp = Kp; } // ellipdegf() // // Compute elliptic degree using _n iterations // // _N : analog filter order // _k1 : elliptic modulus for stop-band, ep/ep1 // _n : number of Landen iterations float ellipdegf(float _N, float _k1, unsigned int _n) { // compute K1, K1p from _k1 float K1, K1p; ellipkf(_k1,_n,&K1,&K1p); // compute q1 from K1, K1p float q1 = expf(-M_PI*K1p/K1); // compute q from q1 float q = powf(q1,1.0f/_N); // expand numerator, denominator unsigned int m; float b = 0.0f; for (m=0; m<_n; m++) b += powf(q,(float)(m*(m+1))); float a = 0.0f; for (m=1; m<_n; m++) a += powf(q,(float)(m*m)); float g = b / (1.0f + 2.0f*a); float k = 4.0f*sqrtf(q)*g*g; #if LIQUID_DEBUG_ELLIP_PRINT printf("ellipdegf(N=%f, k1=%f, n=%u):\n", _N, _k1, _n); printf(" K1 : %12.4e;\n", K1); printf(" K1p : %12.4e;\n", K1p); printf(" q1 : %12.4e;\n", q1); printf(" q : %12.4e;\n", q); #endif return k; } // ellip_cdf() // // complex elliptic cd() function (Jacobian elliptic cosine) // // _u : vector in the complex u-plane // _k : elliptic modulus (0 <= _k < 1) // _n : number of Landen iterations (typically 5-6) float complex ellip_cdf(float complex _u, float _k, unsigned int _n) { float complex wn = ccosf(_u*M_PI*0.5f); float v[_n]; landenf(_k,_n,v); unsigned int i; for (i=_n; i>0; i--) { wn = (1 + v[i-1])*wn / (1 + v[i-1]*wn*wn); } return wn; } // ellip_snf() // // complex elliptic sn() function (Jacobian elliptic sine) // // _u : vector in the complex u-plane // _k : elliptic modulus (0 <= _k < 1) // _n : number of Landen iterations (typically 5-6) float complex ellip_snf(float complex _u, float _k, unsigned int _n) { float complex wn = csinf(_u*M_PI*0.5f); float v[_n]; landenf(_k,_n,v); unsigned int i; for (i=_n; i>0; i--) { wn = (1 + v[i-1])*wn / (1 + v[i-1]*wn*wn); } return wn; } // ellip_acdf() // // complex elliptic inverse cd() function (Jacobian elliptic // arc cosine) // // _w : vector in the complex u-plane // _k : elliptic modulus (0 <= _k < 1) // _n : number of Landen iterations (typically 5-6) float complex ellip_acdf(float complex _w, float _k, unsigned int _n) { float v[_n]; landenf(_k,_n,v); float v1; float complex w = _w; unsigned int i; for (i=0; i<_n; i++) { v1 = (i==0) ? _k : v[i-1]; w = w / (1 + liquid_csqrtf(1 - w*w*v1*v1)) * 2.0 / (1+v[i]); //printf(" w[%3u] = %12.8f + j*%12.8f\n", i, crealf(w), cimagf(w)); } float complex u = liquid_cacosf(w) * 2.0 / M_PI; //printf(" u = %12.8f + j*%12.8f\n", crealf(u), cimagf(u)); #if 0 float K, Kp; ellipkf(_k, _n, &K, &Kp); float R = Kp / K; #endif return u; } // ellip_asnf() // // complex elliptic inverse sn() function (Jacobian elliptic // arc sine) // // _w : vector in the complex u-plane // _k : elliptic modulus (0 <= _k < 1) // _n : number of Landen iterations (typically 5-6) float complex ellip_asnf(float complex _w, float _k, unsigned int _n) { return 1.0 - ellip_acdf(_w,_k,_n); } // ellip_azpkf() // // Compute analog zeros, poles, gain of low-pass elliptic // filter, grouping complex conjugates together. If // the filter order is odd, the single real pole is at the // end of the array. // _n : filter order // _ep : epsilon_p, related to pass-band ripple // _es : epsilon_s, related to stop-band ripple // _za : output analog zeros [length: floor(_n/2)] // _pa : output analog poles [length: _n] // _ka : output analog gain void ellip_azpkf(unsigned int _n, float _ep, float _es, float complex * _za, float complex * _pa, float complex * _ka) { // filter specifications float fp = 1.0f / (2.0f * M_PI); // pass-band cutoff float fs = 1.1*fp; // stop-band cutoff //float Gp = 1/sqrtf(1 + _ep*_ep); // pass-band gain //float Gs = 1/sqrtf(1 + _es*_es); // stop-band gain // number of iterations for elliptic integral // approximations unsigned int n=7; float Wp = 2*M_PI*fp; float Ws = 2*M_PI*fs; // ripples passband, stopband float ep = _ep; float es = _es; #if LIQUID_DEBUG_ELLIP_PRINT printf("ep, es : %12.8f, %12.8f\n", _ep, _es); #endif float k = Wp/Ws; // 0.8889f; float k1 = ep/es; // 0.0165f; #if LIQUID_DEBUG_ELLIP_PRINT printf("k : %12.4e\n", k); printf("k1 : %12.4e\n", k1); #endif float K, Kp; float K1, K1p; ellipkf(k, n, &K, &Kp); // K = 2.23533416, Kp = 1.66463780 ellipkf(k1,n, &K1, &K1p); // K1 = 1.57090271, K1p = 5.49361753 #if LIQUID_DEBUG_ELLIP_PRINT printf("K, Kp : %12.8f, %12.8f\n", K, Kp); printf("K1, K1p : %12.8f, %12.8f\n", K1, K1p); #endif float N = (float)_n; // ceilf(Nexact) = 5 #if LIQUID_DEBUG_ELLIP_PRINT float Nexact = (K1p/K1)/(Kp/K); // 4.69604063 printf("N (exact) : %12.8f\n", Nexact); printf("N : %12.8f\n", N); #endif k = ellipdegf(N,k1,n); // 0.91427171 #if LIQUID_DEBUG_ELLIP_PRINT printf("k : %12.4e\n", k); #endif #if LIQUID_DEBUG_ELLIP_PRINT float fs_new = fp/k; // 4.37506723 printf("fs_new : %12.8f\n", fs_new); #endif unsigned int L = (unsigned int)(floorf(N/2.0f)); // 2 unsigned int r = ((unsigned int)N) % 2; float u[L]; unsigned int i; for (i=0; i #include #include // defined: // FFTFILT() name-mangling macro // T coefficients type // WINDOW() window macro // DOTPROD() dotprod macro // PRINTVAL() print macro // fftfilt object structure struct FFTFILT(_s) { TC * h; // filter coefficients array [size; h_len x 1] unsigned int h_len; // filter length unsigned int n; // input/output block size // internal memory arrays // TODO: make TI/TO type, but ensuring complex // TODO: use special format for fftfilt_rrrf type float complex * time_buf; // time buffer [size: 2*n x 1] float complex * freq_buf; // freq buffer [size: 2*n x 1] float complex * H; // FFT of filter coefficients [size: 2*n x 1] float complex * w; // overlap array [size: n x 1] // FFT objects #ifdef LIQUID_FFTOVERRIDE fftplan fft; // FFT object (forward) fftplan ifft; // FFT object (inverse) #else FFT_PLAN fft; // FFT object (forward) FFT_PLAN ifft; // FFT object (inverse) #endif TC scale; // output scaling factor }; // create FFT-based FIR filter using external coefficients // _h : filter coefficients [size: _h_len x 1] // _h_len : filter length, _h_len > 0 // _n : block size = nfft/2, at least _h_len-1 FFTFILT() FFTFILT(_create)(TC * _h, unsigned int _h_len, unsigned int _n) { // validate input if (_h_len == 0) { fprintf(stderr,"error: fftfilt_%s_create(), filter length must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_n < _h_len-1) { fprintf(stderr,"error: fftfilt_%s_create(), block length must be greater than _h_len-1 (%u)\n", EXTENSION_FULL, _h_len-1); exit(1); } // create filter object and initialize FFTFILT() q = (FFTFILT()) malloc(sizeof(struct FFTFILT(_s))); q->h_len = _h_len; q->n = _n; // copy filter coefficients q->h = (TC *) malloc((q->h_len)*sizeof(TC)); memmove(q->h, _h, _h_len*sizeof(TC)); // allocate internal memory arrays q->time_buf = (float complex *) malloc((2*q->n)* sizeof(float complex)); // time buffer q->freq_buf = (float complex *) malloc((2*q->n)* sizeof(float complex)); // frequency buffer q->H = (float complex *) malloc((2*q->n)* sizeof(float complex)); // FFT{ h } q->w = (float complex *) malloc(( q->n)* sizeof(float complex)); // delay buffer // create internal FFT objects #ifdef LIQUID_FFTOVERRIDE q->fft = fft_create_plan(2*q->n, q->time_buf, q->freq_buf, LIQUID_FFT_FORWARD, 0); q->ifft = fft_create_plan(2*q->n, q->freq_buf, q->time_buf, LIQUID_FFT_BACKWARD, 0); #else q->fft = FFT_CREATE_PLAN(2*q->n, q->time_buf, q->freq_buf, FFT_DIR_FORWARD, FFT_METHOD); q->ifft = FFT_CREATE_PLAN(2*q->n, q->freq_buf, q->time_buf, FFT_DIR_BACKWARD, FFT_METHOD); #endif // compute FFT of filter coefficients and copy to internal H array unsigned int i; for (i=0; i<2*q->n; i++) q->time_buf[i] = (i < q->h_len) ? q->h[i] : 0; // time_buf > {FFT} > freq_buf #ifdef LIQUID_FFTOVERRIDE fft_execute(q->fft); #else FFT_EXECUTE(q->fft); #endif memmove(q->H, q->freq_buf, 2*q->n*sizeof(float complex)); // set default scaling FFTFILT(_set_scale)(q, 1); // reset filter state (clear buffer) FFTFILT(_reset)(q); // return object return q; } // destroy object, freeing all internally-allocated memory void FFTFILT(_destroy)(FFTFILT() _q) { // free internal arrays free(_q->h); // filter coefficients free(_q->time_buf); // buffer (time domain) free(_q->freq_buf); // buffer (frequency domain) free(_q->H); // frequency response of filter coefficients free(_q->w); // output window buffer // destroy FFT objects #ifdef LIQUID_FFTOVERRIDE fft_destroy_plan(_q->fft); // forward transform fft_destroy_plan(_q->ifft); // reverse transform #else FFT_DESTROY_PLAN(_q->fft); // forward transform FFT_DESTROY_PLAN(_q->ifft); // reverse transform #endif // free main object free(_q); } // reset internal state of filter object void FFTFILT(_reset)(FFTFILT() _q) { // reset overlap window unsigned int i; for (i=0; i<_q->n; i++) _q->w[i] = 0; } // print filter object internals (taps, buffer) void FFTFILT(_print)(FFTFILT() _q) { printf("fftfilt_%s: [h_len=%u, n=%u]\n", EXTENSION_FULL, _q->h_len, _q->n); unsigned int i; unsigned int n = _q->h_len; for (i=0; iscale = _scale / (float)(2*_q->n); } // execute the filter on internal buffer and coefficients // _q : filter object // _x : pointer to input data array [size: _n x 1] // _y : pointer to output data array [size: _n x 1] void FFTFILT(_execute)(FFTFILT() _q, TI * _x, TO * _y) { unsigned int i; // copy input #if 0 //TI_COMPLEX memmove(_q->time_buf, _x, _q->n*sizeof(TI)); #else // manual copy for type conversion // TODO: use DCT or equivalent for (i=0; i<_q->n; i++) _q->time_buf[i] = _x[i]; #endif // pad end of time-domain buffer with zeros // TODO: not necessary to do this every time #if 0 memset(&_q->time_buf[_q->n], 0, _q->n*sizeof(TI)); #else for (i=0; i<_q->n; i++) _q->time_buf[_q->n + i] = 0; #endif // run forward transform #ifdef LIQUID_FFTOVERRIDE fft_execute(_q->fft); #else FFT_EXECUTE(_q->fft); #endif // compute inner product between FFT{ _x } and FFT{ H } #if 1 for (i=0; i<2*_q->n; i++) _q->freq_buf[i] *= _q->H[i]; #else // use SIMD vector extensions # if TI_COMPLEX // complex floating-point inner product liquid_vectorcf_mul(_q->freq_buf, _q->H, 2*_q->n, _q->freq_buf); # else // real floating-point inner product liquid_vectorf_mul(_q->freq_buf, _q->H, 2*_q->n, _q->freq_buf); # endif #endif // compute inverse transform #ifdef LIQUID_FFTOVERRIDE fft_execute(_q->ifft); #else FFT_EXECUTE(_q->ifft); #endif // copy output summed with buffer and scaled #if TI_COMPLEX for (i=0; i<_q->n; i++) _y[i] = (_q->time_buf[i] + _q->w[i]) * _q->scale; #else // manual copy for type conversion // TODO: use DCT or equivalent for (i=0; i<_q->n; i++) _y[i] = (T) crealf(_q->time_buf[i] + _q->w[i]) * _q->scale; #endif // copy buffer memmove(_q->w, &_q->time_buf[_q->n], _q->n*sizeof(float complex)); } // return length of filter object's internal coefficients unsigned int FFTFILT(_get_length)(FFTFILT() _q) { return _q->h_len; } liquid-dsp-1.3.1/src/filter/src/filter_cccf.c000066400000000000000000000063561317124540100210510ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Filter API: complex floating-point // #include "liquid.internal.h" // naming extensions (useful for print statements) #define EXTENSION_SHORT "f" #define EXTENSION_FULL "cccf" // #define AUTOCORR(name) LIQUID_CONCAT(autocorr_cccf,name) #define FFTFILT(name) LIQUID_CONCAT(fftfilt_cccf,name) #define FIRDECIM(name) LIQUID_CONCAT(firdecim_cccf,name) #define FIRFILT(name) LIQUID_CONCAT(firfilt_cccf,name) #define FIRINTERP(name) LIQUID_CONCAT(firinterp_cccf,name) #define FIRPFB(name) LIQUID_CONCAT(firpfb_cccf,name) #define IIRDECIM(name) LIQUID_CONCAT(iirdecim_cccf,name) #define IIRFILT(name) LIQUID_CONCAT(iirfilt_cccf,name) #define IIRFILTSOS(name) LIQUID_CONCAT(iirfiltsos_cccf,name) #define IIRINTERP(name) LIQUID_CONCAT(iirinterp_cccf,name) #define NCO(name) LIQUID_CONCAT(nco_crcf,name) #define MSRESAMP(name) LIQUID_CONCAT(msresamp_cccf,name) #define MSRESAMP2(name) LIQUID_CONCAT(msresamp2_cccf,name) #define RESAMP(name) LIQUID_CONCAT(resamp_cccf,name) #define RESAMP2(name) LIQUID_CONCAT(resamp2_cccf,name) //#define SYMSYNC(name) LIQUID_CONCAT(symsync_cccf,name) #define T float complex // general #define TO float complex // output #define TC float complex // coefficients #define TI float complex // input #define WINDOW(name) LIQUID_CONCAT(windowcf,name) #define DOTPROD(name) LIQUID_CONCAT(dotprod_cccf,name) #define POLY(name) LIQUID_CONCAT(polyf,name) #define TO_COMPLEX 1 #define TC_COMPLEX 1 #define TI_COMPLEX 1 #define PRINTVAL_TO(X,F) PRINTVAL_CFLOAT(X,F) #define PRINTVAL_TC(X,F) PRINTVAL_CFLOAT(X,F) #define PRINTVAL_TI(X,F) PRINTVAL_CFLOAT(X,F) // source files #include "autocorr.c" #include "fftfilt.c" #include "firdecim.c" #include "firfilt.c" #include "firinterp.c" #include "firpfb.c" #include "iirdecim.c" #include "iirfilt.c" #include "iirfiltsos.c" #include "iirinterp.c" //#include "qmfb.c" #include "msresamp.c" #include "msresamp2.c" #include "resamp.c" #include "resamp2.c" //#include "symsync.c" liquid-dsp-1.3.1/src/filter/src/filter_crcf.c000066400000000000000000000065251317124540100210660ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Filter API: complex floating-point // #include "liquid.internal.h" // naming extensions (useful for print statements) #define EXTENSION_SHORT "f" #define EXTENSION_FULL "crcf" // #define AUTOCORR(name) LIQUID_CONCAT(autocorr_crcf,name) #define FFTFILT(name) LIQUID_CONCAT(fftfilt_crcf,name) #define FIRDECIM(name) LIQUID_CONCAT(firdecim_crcf,name) #define FIRFARROW(name) LIQUID_CONCAT(firfarrow_crcf,name) #define FIRFILT(name) LIQUID_CONCAT(firfilt_crcf,name) #define FIRINTERP(name) LIQUID_CONCAT(firinterp_crcf,name) #define FIRPFB(name) LIQUID_CONCAT(firpfb_crcf,name) #define IIRDECIM(name) LIQUID_CONCAT(iirdecim_crcf,name) #define IIRFILT(name) LIQUID_CONCAT(iirfilt_crcf,name) #define IIRFILTSOS(name) LIQUID_CONCAT(iirfiltsos_crcf,name) #define IIRINTERP(name) LIQUID_CONCAT(iirinterp_crcf,name) #define MSRESAMP(name) LIQUID_CONCAT(msresamp_crcf,name) #define MSRESAMP2(name) LIQUID_CONCAT(msresamp2_crcf,name) #define RESAMP(name) LIQUID_CONCAT(resamp_crcf,name) #define RESAMP2(name) LIQUID_CONCAT(resamp2_crcf,name) #define SYMSYNC(name) LIQUID_CONCAT(symsync_crcf,name) #define T float complex // general #define TO float complex // output #define TC float // coefficients #define TI float complex // input #define WINDOW(name) LIQUID_CONCAT(windowcf,name) #define DOTPROD(name) LIQUID_CONCAT(dotprod_crcf,name) #define POLY(name) LIQUID_CONCAT(polyf,name) #define TO_COMPLEX 1 #define TC_COMPLEX 0 #define TI_COMPLEX 1 #define PRINTVAL_TO(X,F) PRINTVAL_CFLOAT(X,F) #define PRINTVAL_TC(X,F) PRINTVAL_FLOAT(X,F) #define PRINTVAL_TI(X,F) PRINTVAL_CFLOAT(X,F) // source files //#include "autocorr.c" #include "fftfilt.c" #include "firdecim.c" #include "firfarrow.c" #include "firfilt.c" #include "firinterp.c" #include "firpfb.c" #include "iirdecim.c" #include "iirfilt.c" #include "iirfiltsos.c" #include "iirinterp.c" #include "msresamp.c" #include "msresamp2.c" #include "resamp.c" // floating-point phase version //#include "resamp.fixed.c" // fixed-point phase version #include "resamp2.c" #include "symsync.c" liquid-dsp-1.3.1/src/filter/src/filter_rrrf.c000066400000000000000000000064251317124540100211230ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Filter API: floating-point // #include "liquid.internal.h" // naming extensions (useful for print statements) #define EXTENSION_SHORT "f" #define EXTENSION_FULL "rrrf" // #define AUTOCORR(name) LIQUID_CONCAT(autocorr_rrrf,name) #define FFTFILT(name) LIQUID_CONCAT(fftfilt_rrrf,name) #define FIRDECIM(name) LIQUID_CONCAT(firdecim_rrrf,name) #define FIRFARROW(name) LIQUID_CONCAT(firfarrow_rrrf,name) #define FIRFILT(name) LIQUID_CONCAT(firfilt_rrrf,name) #define FIRINTERP(name) LIQUID_CONCAT(firinterp_rrrf,name) #define FIRHILB(name) LIQUID_CONCAT(firhilbf,name) #define FIRPFB(name) LIQUID_CONCAT(firpfb_rrrf,name) #define IIRDECIM(name) LIQUID_CONCAT(iirdecim_rrrf,name) #define IIRFILT(name) LIQUID_CONCAT(iirfilt_rrrf,name) #define IIRFILTSOS(name) LIQUID_CONCAT(iirfiltsos_rrrf,name) #define IIRINTERP(name) LIQUID_CONCAT(iirinterp_rrrf,name) #define MSRESAMP(name) LIQUID_CONCAT(msresamp_rrrf,name) #define MSRESAMP2(name) LIQUID_CONCAT(msresamp2_rrrf,name) #define RESAMP(name) LIQUID_CONCAT(resamp_rrrf,name) #define RESAMP2(name) LIQUID_CONCAT(resamp2_rrrf,name) #define SYMSYNC(name) LIQUID_CONCAT(symsync_rrrf,name) #define T float // general #define TO float // output #define TC float // coefficients #define TI float // input #define WINDOW(name) LIQUID_CONCAT(windowf,name) #define DOTPROD(name) LIQUID_CONCAT(dotprod_rrrf,name) #define POLY(name) LIQUID_CONCAT(polyf,name) #define TO_COMPLEX 0 #define TC_COMPLEX 0 #define TI_COMPLEX 0 #define PRINTVAL_TO(X,F) PRINTVAL_FLOAT(X,F) #define PRINTVAL_TC(X,F) PRINTVAL_FLOAT(X,F) #define PRINTVAL_TI(X,F) PRINTVAL_FLOAT(X,F) // source files #include "autocorr.c" #include "fftfilt.c" #include "firdecim.c" #include "firfarrow.c" #include "firfilt.c" #include "firinterp.c" #include "firhilb.c" #include "firpfb.c" #include "iirdecim.c" #include "iirfilt.c" #include "iirfiltsos.c" #include "iirinterp.c" #include "msresamp.c" #include "msresamp2.c" #include "resamp.c" #include "resamp2.c" #include "symsync.c" liquid-dsp-1.3.1/src/filter/src/firdecim.c000066400000000000000000000162441317124540100203650ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firdecim.c // // finite impulse response decimator object definitions // #include #include #include // decimator structure struct FIRDECIM(_s) { TC * h; // coefficients array unsigned int h_len; // number of coefficients unsigned int M; // decimation factor WINDOW() w; // buffer DOTPROD() dp; // vector dot product }; // create decimator object // _M : decimation factor // _h : filter coefficients [size: _h_len x 1] // _h_len : filter coefficients length FIRDECIM() FIRDECIM(_create)(unsigned int _M, TC * _h, unsigned int _h_len) { // validate input if (_h_len == 0) { fprintf(stderr,"error: decim_%s_create(), filter length must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_M == 0) { fprintf(stderr,"error: decim_%s_create(), decimation factor must be greater than zero\n", EXTENSION_FULL); exit(1); } FIRDECIM() q = (FIRDECIM()) malloc(sizeof(struct FIRDECIM(_s))); q->h_len = _h_len; q->M = _M; // allocate memory for coefficients q->h = (TC*) malloc((q->h_len)*sizeof(TC)); // load filter in reverse order unsigned int i; for (i=0; ih_len; i++) q->h[i] = _h[_h_len-i-1]; // create window (internal buffer) q->w = WINDOW(_create)(q->h_len); // create dot product object q->dp = DOTPROD(_create)(q->h, q->h_len); // reset filter state (clear buffer) FIRDECIM(_reset)(q); return q; } // create decimator from Kaiser prototype // _M : decimolation factor // _m : symbol delay // _As : stop-band attenuation [dB] FIRDECIM() FIRDECIM(_create_kaiser)(unsigned int _M, unsigned int _m, float _As) { // validate input if (_M < 2) { fprintf(stderr,"error: decim_%s_create_kaiser(), decim factor must be greater than 1\n", EXTENSION_FULL); exit(1); } else if (_m == 0) { fprintf(stderr,"error: decim_%s_create_kaiser(), filter delay must be greater than 0\n", EXTENSION_FULL); exit(1); } else if (_As < 0.0f) { fprintf(stderr,"error: decim_%s_create_kaiser(), stop-band attenuation must be positive\n", EXTENSION_FULL); exit(1); } // compute filter coefficients (floating point precision) unsigned int h_len = 2*_M*_m + 1; float hf[h_len]; float fc = 0.5f / (float) (_M); liquid_firdes_kaiser(h_len, fc, _As, 0.0f, hf); // copy coefficients to type-specific array (e.g. float complex) TC hc[h_len]; unsigned int i; for (i=0; i 1 // _m : filter delay (symbols), _m > 0 // _beta : excess bandwidth factor, 0 < _beta < 1 // _dt : fractional sample delay, 0 <= _dt < 1 FIRDECIM() FIRDECIM(_create_prototype)(int _type, unsigned int _M, unsigned int _m, float _beta, float _dt) { // validate input if (_M < 2) { fprintf(stderr,"error: decim_%s_create_prototype(), decimation factor must be greater than 1\n", EXTENSION_FULL); exit(1); } else if (_m == 0) { fprintf(stderr,"error: decim_%s_create_prototype(), filter delay must be greater than 0\n", EXTENSION_FULL); exit(1); } else if (_beta < 0.0f || _beta > 1.0f) { fprintf(stderr,"error: decim_%s_create_prototype(), filter excess bandwidth factor must be in [0,1]\n", EXTENSION_FULL); exit(1); } else if (_dt < -1.0f || _dt > 1.0f) { fprintf(stderr,"error: decim_%s_create_prototype(), filter fractional sample delay must be in [-1,1]\n", EXTENSION_FULL); exit(1); } // generate square-root Nyquist filter unsigned int h_len = 2*_M*_m + 1; float h[h_len]; liquid_firdes_prototype(_type,_M,_m,_beta,_dt,h); // copy coefficients to type-specific array (e.g. float complex) unsigned int i; TC hc[h_len]; for (i=0; iw); DOTPROD(_destroy)(_q->dp); free(_q->h); free(_q); } // print decimator object internals void FIRDECIM(_print)(FIRDECIM() _q) { printf("FIRDECIM() [%u] :\n", _q->M); printf(" window:\n"); WINDOW(_print)(_q->w); } // clear decimator object void FIRDECIM(_reset)(FIRDECIM() _q) { WINDOW(_reset)(_q->w); } // execute decimator // _q : decimator object // _x : input sample array [size: _M x 1] // _y : output sample pointer void FIRDECIM(_execute)(FIRDECIM() _q, TI * _x, TO * _y) { TI * r; // read pointer unsigned int i; for (i=0; i<_q->M; i++) { WINDOW(_push)(_q->w, _x[i]); if (i==0) { // read buffer (retrieve pointer to aligned memory array) WINDOW(_read)(_q->w, &r); // execute dot product DOTPROD(_execute)(_q->dp, r, _y); } } } // execute decimator on block of _n*_M input samples // _q : decimator object // _x : input array [size: _n*_M x 1] // _n : number of _output_ samples // _y : output array [_size: _n x 1] void FIRDECIM(_execute_block)(FIRDECIM() _q, TI * _x, unsigned int _n, TO * _y) { unsigned int i; for (i=0; i<_n; i++) { // execute _M input samples computing just one output each time FIRDECIM(_execute)(_q, &_x[i*_q->M], &_y[i]); } } liquid-dsp-1.3.1/src/filter/src/firdes.c000066400000000000000000000500531317124540100200530ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Finite impulse response filter design // // References: // [Herrmann:1973] O. Herrmann, L. R. Rabiner, and D. S. K. Chan, // "Practical design rules for optimum finite impulse response // lowpass digital filters," Bell Syst. Tech. Journal, vol. 52, // pp. 769--99, July-Aug. 1973 // [Vaidyanathan:1993] Vaidyanathan, P. P., "Multirate Systems and // Filter Banks," 1993, Prentice Hall, Section 3.2.1 #include #include #include #include #include "liquid.internal.h" // method to estimate required filter length #define ESTIMATE_REQ_FILTER_LEN_METHOD_KAISER (0) #define ESTIMATE_REQ_FILTER_LEN_METHOD_HERRMANN (1) // select filter estimate method #define ESTIMATE_REQ_FILTER_LEN_METHOD (0) // esimate required filter length given transition bandwidth and // stop-band attenuation // _df : transition bandwidth (0 < _df < 0.5) // _As : stopband suppression level [dB] (_As > 0) unsigned int estimate_req_filter_len(float _df, float _As) { if (_df > 0.5f || _df <= 0.0f) { fprintf(stderr,"error: estimate_req_filter_len(), invalid bandwidth : %f\n", _df); exit(1); } else if (_As <= 0.0f) { fprintf(stderr,"error: estimate_req_filter_len(), invalid stopband level : %f\n", _As); exit(1); } // compute filter length estimate #if ESTIMATE_REQ_FILTER_LEN_METHOD == ESTIMATE_REQ_FILTER_LEN_METHOD_KAISER // use Kaiser's estimate unsigned int h_len = (unsigned int) estimate_req_filter_len_Kaiser(_df,_As); #elif ESTIMATE_REQ_FILTER_LEN_METHOD == ESTIMATE_REQ_FILTER_LEN_METHOD_HERRMANN // use Herrmann's estimate unsigned int h_len = (unsigned int) estimate_req_filter_len_Herrmann(_df,_As); #else # error "invalid required filter length estimation method" #endif return h_len; } // estimate filter stop-band attenuation given // _df : transition bandwidth (0 < _b < 0.5) // _N : filter length float estimate_req_filter_As(float _df, unsigned int _N) { // run search for stop-band attenuation which gives these results float As0 = 0.01f; // lower bound float As1 = 200.0f; // upper bound float As_hat = 0.0f; // stop-band attenuation estimate float N_hat = 0.0f; // filter length estimate // perform simple bisection search unsigned int num_iterations = 20; unsigned int i; for (i=0; i 0 // _N : filter length float estimate_req_filter_df(float _As, unsigned int _N) { // run search for stop-band attenuation which gives these results float df0 = 1e-3f; // lower bound float df1 = 0.499f; // upper bound float df_hat = 0.0f; // stop-band attenuation estimate float N_hat = 0.0f; // filter length estimate // perform simple bisection search unsigned int num_iterations = 20; unsigned int i; for (i=0; i 0) float estimate_req_filter_len_Kaiser(float _df, float _As) { if (_df > 0.5f || _df <= 0.0f) { fprintf(stderr,"error: estimate_req_filter_len_Kaiser(), invalid bandwidth : %f\n", _df); exit(1); } else if (_As <= 0.0f) { fprintf(stderr,"error: estimate_req_filter_len(), invalid stopband level : %f\n", _As); exit(1); } // compute filter length estimate return (_As - 7.95f)/(14.26f*_df); } // esimate required filter length given transition bandwidth and // stop-band attenuation (algorithm from [Herrmann:1973]) // _df : transition bandwidth (0 < _df < 0.5) // _As : stop-band attenuation [dB] (As > 0) float estimate_req_filter_len_Herrmann(float _df, float _As) { if (_df > 0.5f || _df <= 0.0f) { fprintf(stderr,"error: estimate_req_filter_len_Herrmann(), invalid bandwidth : %f\n", _df); exit(1); } else if (_As <= 0.0f) { fprintf(stderr,"error: estimate_req_filter_len(), invalid stopband level : %f\n", _As); exit(1); } // Gaeddert's revisions: if (_As > 105.0f) return estimate_req_filter_len_Kaiser(_df,_As); _As += 7.4f; // compute delta_1, delta_2 float d1, d2; d1 = d2 = powf(10.0, -_As/20.0); // compute log of delta_1, delta_2 float t1 = log10f(d1); float t2 = log10f(d2); // compute D_infinity(delta_1, delta_2) float Dinf = (0.005309f*t1*t1 + 0.07114f*t1 - 0.4761f)*t2 - (0.002660f*t1*t1 + 0.59410f*t1 + 0.4278f); // compute f(delta_1, delta_2) float f = 11.012f + 0.51244f*(t1-t2); // compute filter length estimate float h_len = (Dinf - f*_df*_df) / _df + 1.0f; return h_len; } // returns the Kaiser window beta factor give the filter's target // stop-band attenuation (As) [Vaidyanathan:1993] // _As : target filter's stop-band attenuation [dB], _As > 0 float kaiser_beta_As(float _As) { _As = fabsf(_As); float beta; if (_As > 50.0f) beta = 0.1102f*(_As - 8.7f); else if (_As > 21.0f) beta = 0.5842*powf(_As - 21, 0.4f) + 0.07886f*(_As - 21); else beta = 0.0f; return beta; } // Design FIR using kaiser window // _n : filter length, _n > 0 // _fc : cutoff frequency, 0 < _fc < 0.5 // _As : stop-band attenuation [dB], _As > 0 // _mu : fractional sample offset, -0.5 < _mu < 0.5 // _h : output coefficient buffer, [size: _n x 1] void liquid_firdes_kaiser(unsigned int _n, float _fc, float _As, float _mu, float *_h) { // validate inputs if (_mu < -0.5f || _mu > 0.5f) { fprintf(stderr,"error: liquid_firdes_kaiser(), _mu (%12.4e) out of range [-0.5,0.5]\n", _mu); exit(1); } else if (_fc < 0.0f || _fc > 0.5f) { fprintf(stderr,"error: liquid_firdes_kaiser(), cutoff frequency (%12.4e) out of range (0, 0.5)\n", _fc); exit(1); } else if (_n == 0) { fprintf(stderr,"error: liquid_firdes_kaiser(), filter length must be greater than zero\n"); exit(1); } // choose kaiser beta parameter (approximate) float beta = kaiser_beta_As(_As); float t, h1, h2; unsigned int i; for (i=0; i<_n; i++) { t = (float)i - (float)(_n-1)/2 + _mu; // sinc prototype h1 = sincf(2.0f*_fc*t); // kaiser window h2 = kaiser(i,_n,beta,_mu); //printf("t = %f, h1 = %f, h2 = %f\n", t, h1, h2); // composite _h[i] = h1*h2; } } // Design (root-)Nyquist filter from prototype // _type : filter type (e.g. LIQUID_FIRFILT_RRRC) // _k : samples/symbol // _m : symbol delay // _beta : excess bandwidth factor, _beta in [0,1] // _dt : fractional sample delay // _h : output coefficient buffer (length: 2*k*m+1) void liquid_firdes_prototype(liquid_firfilt_type _type, unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h) { // compute filter parameters unsigned int h_len = 2*_k*_m + 1; // length float fc = 0.5f / (float)_k; // cut-off frequency float df = _beta / (float)_k; // transition bandwidth float As = estimate_req_filter_As(df,h_len); // stop-band attenuation // Parks-McClellan algorithm parameters float bands[6] = { 0.0f, fc-0.5f*df, fc, fc, fc+0.5f*df, 0.5f}; float des[3] = { (float)_k, 0.5f*_k, 0.0f }; float weights[3] = {1.0f, 1.0f, 1.0f}; liquid_firdespm_wtype wtype[3] = { LIQUID_FIRDESPM_FLATWEIGHT, LIQUID_FIRDESPM_FLATWEIGHT, LIQUID_FIRDESPM_FLATWEIGHT}; switch (_type) { // Nyquist filter prototypes case LIQUID_FIRFILT_KAISER: liquid_firdes_kaiser(h_len, fc, As, _dt, _h); break; case LIQUID_FIRFILT_PM: // WARNING: input timing offset is ignored here firdespm_run(h_len, 3, bands, des, weights, wtype, LIQUID_FIRDESPM_BANDPASS, _h); break; case LIQUID_FIRFILT_RCOS: liquid_firdes_rcos(_k, _m, _beta, _dt, _h); break; case LIQUID_FIRFILT_FEXP: liquid_firdes_fexp(_k, _m, _beta, _dt, _h); break; case LIQUID_FIRFILT_FSECH: liquid_firdes_fsech(_k, _m, _beta, _dt, _h); break; case LIQUID_FIRFILT_FARCSECH: liquid_firdes_farcsech(_k, _m, _beta, _dt, _h); break; // root-Nyquist filter prototypes case LIQUID_FIRFILT_ARKAISER: liquid_firdes_arkaiser(_k, _m, _beta, _dt, _h); break; case LIQUID_FIRFILT_RKAISER: liquid_firdes_rkaiser(_k, _m, _beta, _dt, _h); break; case LIQUID_FIRFILT_RRC: liquid_firdes_rrcos(_k, _m, _beta, _dt, _h); break; case LIQUID_FIRFILT_hM3: liquid_firdes_hM3(_k, _m, _beta, _dt, _h); break; case LIQUID_FIRFILT_GMSKTX: liquid_firdes_gmsktx(_k, _m, _beta, _dt, _h); break; case LIQUID_FIRFILT_GMSKRX: liquid_firdes_gmskrx(_k, _m, _beta, _dt, _h); break; case LIQUID_FIRFILT_RFEXP: liquid_firdes_rfexp(_k, _m, _beta, _dt, _h); break; case LIQUID_FIRFILT_RFSECH: liquid_firdes_rfsech(_k, _m, _beta, _dt, _h); break; case LIQUID_FIRFILT_RFARCSECH: liquid_firdes_rfarcsech(_k, _m, _beta, _dt, _h); break; default: fprintf(stderr,"error: liquid_firdes_prototype(), invalid root-Nyquist filter type '%d'\n", _type); exit(1); } } // Design FIR doppler filter // _n : filter length // _fd : normalized doppler frequency (0 < _fd < 0.5) // _K : Rice fading factor (K >= 0) // _theta : LoS component angle of arrival // _h : output coefficient buffer void liquid_firdes_doppler(unsigned int _n, float _fd, float _K, float _theta, float * _h) { float t, J, r, w; float beta = 4; // kaiser window parameter unsigned int i; for (i=0; i<_n; i++) { // time sample t = (float)i - (float)(_n-1)/2; // Bessel J = 1.5*liquid_besselj0f(fabsf((float)(2*M_PI*_fd*t))); // Rice-K component r = 1.5*_K/(_K+1)*cosf(2*M_PI*_fd*t*cosf(_theta)); // Window w = kaiser(i, _n, beta, 0); // composite _h[i] = (J+r)*w; //printf("t=%f, J=%f, r=%f, w=%f\n", t, J, r, w); } } // // filter analysis // // liquid_filter_autocorr() // // Compute auto-correlation of filter at a specific lag. // // _h : filter coefficients [size: _h_len x 1] // _h_len : filter length // _lag : auto-correlation lag (samples) float liquid_filter_autocorr(float * _h, unsigned int _h_len, int _lag) { // auto-correlation is even symmetric _lag = abs(_lag); // lag outside of filter length is zero if (_lag >= _h_len) return 0.0f; // compute auto-correlation float rxx=0.0f; // initialize auto-correlation to zero unsigned int i; for (i=_lag; i<_h_len; i++) rxx += _h[i] * _h[i-_lag]; return rxx; } // liquid_filter_crosscorr() // // Compute cross-correlation of two filters at a specific lag. // // _h : filter coefficients [size: _h_len] // _h_len : filter length // _g : filter coefficients [size: _g_len] // _g_len : filter length // _lag : cross-correlation lag (samples) float liquid_filter_crosscorr(float * _h, unsigned int _h_len, float * _g, unsigned int _g_len, int _lag) { // cross-correlation is odd symmetric if (_h_len < _g_len) { return liquid_filter_crosscorr(_g, _g_len, _h, _h_len, -_lag); } // at this point _h_len > _g_len // assert(_h_len > _g_len); if (_lag <= -(int)_g_len) return 0.0f; if (_lag >= (int)_h_len) return 0.0f; int ig = _lag < 0 ? -_lag : 0; // starting index for _g int ih = _lag > 0 ? _lag : 0; // starting index for _h // compute length of overlap // condition 1: condition 2: condition 3: // [------ h ------] [------ h ------] [------ h ------] // [-- g --] [-- g --] [-- g --] // >| n |< >| n |< >| n |< // int n; if (_lag < 0) n = (int)_g_len + _lag; else if (_lag < (_h_len-_g_len)) n = _g_len; else n = _h_len - _lag; // compute cross-correlation float rxy=0.0f; // initialize auto-correlation to zero int i; for (i=0; i< n; i++) rxy += _h[ih+i] * _g[ig+i]; return rxy; } // liquid_filter_isi() // // Compute inter-symbol interference (ISI)--both RMS and // maximum--for the filter _h. // // _h : filter coefficients [size: 2*_k*_m+1 x 1] // _k : filter over-sampling rate (samples/symbol) // _m : filter delay (symbols) // _rms : output root mean-squared ISI // _max : maximum ISI void liquid_filter_isi(float * _h, unsigned int _k, unsigned int _m, float * _rms, float * _max) { unsigned int h_len = 2*_k*_m+1; // compute zero-lag auto-correlation float rxx0 = liquid_filter_autocorr(_h,h_len,0); //printf("rxx0 = %12.8f\n", rxx0); //exit(1); unsigned int i; float isi_rms = 0.0f; float isi_max = 0.0f; float e; for (i=1; i<=2*_m; i++) { e = liquid_filter_autocorr(_h,h_len,i*_k) / rxx0; e = fabsf(e); isi_rms += e*e; if (i==1 || e > isi_max) isi_max = e; } *_rms = sqrtf( isi_rms / (float)(2*_m) ); *_max = isi_max; } // Compute relative out-of-band energy // // _h : filter coefficients [size: _h_len x 1] // _h_len : filter length // _fc : analysis cut-off frequency // _nfft : fft size float liquid_filter_energy(float * _h, unsigned int _h_len, float _fc, unsigned int _nfft) { // validate input if (_fc < 0.0f || _fc > 0.5f) { fprintf(stderr,"error: liquid_filter_energy(), cut-off frequency must be in [0,0.5]\n"); exit(1); } else if (_h_len == 0) { fprintf(stderr,"error: liquid_filter_energy(), filter length must be greater than zero\n"); exit(1); } else if (_nfft == 0) { fprintf(stderr,"error: liquid_filter_energy(), fft size must be greater than zero\n"); exit(1); } // allocate memory for complex phasor float complex expjwt[_h_len]; // initialize accumulators float e_total = 0.0f; // total energy float e_stopband = 0.0f; // stop-band energy // create dotprod object dotprod_crcf dp = dotprod_crcf_create(_h,_h_len); unsigned int i; unsigned int k; for (i=0; i<_nfft; i++) { float f = 0.5f * (float)i / (float)(_nfft); // initialize complex phasor for (k=0; k<_h_len; k++) expjwt[k] = cexpf(_Complex_I*2*M_PI*f*k); // compute vector dot product float complex v; dotprod_crcf_execute(dp, expjwt, &v); // accumulate output float e2 = crealf( v*conjf(v) ); e_total += e2; e_stopband += (f >= _fc) ? e2 : 0.0f; } // destroy dotprod object dotprod_crcf_destroy(dp); // return energy ratio return e_stopband / e_total; } // returns filter type based on input string int liquid_getopt_str2firfilt(const char * _str) { // Generic filter designs if (strcmp(_str,"kaiser") ==0) return LIQUID_FIRFILT_KAISER; else if (strcmp(_str,"pm") ==0) return LIQUID_FIRFILT_PM; // Nyquist filter designs else if (strcmp(_str,"rcos") ==0) return LIQUID_FIRFILT_RCOS; else if (strcmp(_str,"fexp") ==0) return LIQUID_FIRFILT_FEXP; else if (strcmp(_str,"fsech") ==0) return LIQUID_FIRFILT_FSECH; else if (strcmp(_str,"farcsech") ==0) return LIQUID_FIRFILT_FARCSECH; // root-Nyquist filter designs else if (strcmp(_str,"arkaiser") ==0) return LIQUID_FIRFILT_ARKAISER; else if (strcmp(_str,"rkaiser") ==0) return LIQUID_FIRFILT_RKAISER; else if (strcmp(_str,"rrcos") ==0) return LIQUID_FIRFILT_RRC; else if (strcmp(_str,"hM3") ==0) return LIQUID_FIRFILT_hM3; else if (strcmp(_str,"gmsktx") ==0) return LIQUID_FIRFILT_GMSKTX; else if (strcmp(_str,"gmskrx") ==0) return LIQUID_FIRFILT_GMSKRX; else if (strcmp(_str,"rfexp") ==0) return LIQUID_FIRFILT_RFEXP; else if (strcmp(_str,"rfsech") ==0) return LIQUID_FIRFILT_RFSECH; else if (strcmp(_str,"rfarcsech")==0) return LIQUID_FIRFILT_RFARCSECH; // filter type unknown return LIQUID_FIRFILT_UNKNOWN; } liquid-dsp-1.3.1/src/filter/src/firdespm.c000066400000000000000000001015641317124540100204140ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2017 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fir (finite impulse response) filter design using Parks-McClellan // algorithm // // Much of this program has been borrowed heavily from [McClellan:1973] // and [Janovetz:1998] with the exception of the Lagrange polynomial // interpolation formulas and the structured 'firdespm' object. Several // improvements have been made in the search algorithm to help maintain // stability and convergence. // // References: // [Parks:1972] T. W. Parks and J. H. McClellan, "Chebyshev // Approximation for Nonrecursive Digital Filters with Linear // Phase," IEEE Transactions on Circuit Theory, vol. CT-19, // no. 2, March 1972. // [McClellan:1973] J. H. McClellan, T. W. Parks, L. R. Rabiner, "A // Computer Program for Designing Optimum FIR Linear Phase // Digital Filters," IEEE Transactions on Audio and // Electroacoustics, vol. AU-21, No. 6, December 1973. // [Rabiner:1975] L. R. Rabiner, J. H. McClellan, T. W. Parks, "FIR // Digital filter Design Techniques Using Weighted Chebyshev // Approximations," Proceedings of the IEEE, March 1975. // [Parks:1987] T. W. Parks and C. S. Burrus, "Digital Filter // Design," Upper Saddle River, NJ, John Wiley & Sons, Inc., 1987 // (Section 3.3.3) // [Janovetz:1998] J. Janovetz, online: http://www.janovetz.com/jake/ #include #include #include #include #include #include "liquid.internal.h" #define LIQUID_FIRDESPM_DEBUG 0 #define LIQUID_FIRDESPM_DEBUG_PRINT 0 #define LIQUID_FIRDESPM_DEBUG_FILENAME "firdespm_internal_debug.m" #if LIQUID_FIRDESPM_DEBUG void firdespm_output_debug_file(firdespm _q); #endif // initialize internal memory and arrays void firdespm_init_memory(firdespm _q, unsigned int _h_len, unsigned int _num_bands); // initialize the frequency grid on the disjoint bounded set void firdespm_init_grid(firdespm _q); // compute interpolating polynomial void firdespm_compute_interp(firdespm _q); // compute error signal from actual response (interpolator // output), desired response, and weights void firdespm_compute_error(firdespm _q); // search error curve for _r+1 extremal indices void firdespm_iext_search(firdespm _q); // evaluates result to determine if Remez exchange algorithm // has converged int firdespm_is_search_complete(firdespm _q); // compute filter taps (coefficients) from result void firdespm_compute_taps(firdespm _q, float * _h); // structured data type struct firdespm_s { // constants unsigned int h_len; // filter length unsigned int s; // odd/even filter length unsigned int n; // filter semi-length unsigned int r; // number of approximating functions unsigned int num_bands; // number of discrete bands unsigned int grid_size; // number of points on the grid unsigned int grid_density; // density of the grid // band type (e.g. LIQUID_FIRDESPM_BANDPASS) liquid_firdespm_btype btype; // filter description parameters double * bands; // bands array [size: 2*num_bands] double * des; // desired response [size: num_bands] double * weights; // weights [size: num_bands] liquid_firdespm_wtype * wtype; // dense grid elements double * F; // frequencies, [0, 0.5] double * D; // desired response double * W; // weight double * E; // error double * x; // Chebyshev points : cos(2*pi*f) double * alpha; // Lagrange interpolating polynomial double * c; // interpolants double rho; // extremal weighted error unsigned int * iext; // indices of extrema unsigned int num_exchanges; // number of changes in extrema firdespm_callback callback; // user-defined callback function void * userdata; // user-defined structure for callback function #if LIQUID_FIRDESPM_DEBUG FILE * fid; #endif }; // run filter design (full life cycle of object) // _h_len : length of filter (number of taps) // _num_bands : number of frequency bands // _bands : band edges, f in [0,0.5], [size: _num_bands x 2] // _des : desired response [size: _num_bands x 1] // _weights : response weighting [size: _num_bands x 1] // _wtype : weight types (e.g. LIQUID_FIRDESPM_FLATWEIGHT) [size: _num_bands x 1] // _btype : band type (e.g. LIQUID_FIRDESPM_BANDPASS) // _h : output coefficients array [size: _h_len x 1] void firdespm_run(unsigned int _h_len, unsigned int _num_bands, float * _bands, float * _des, float * _weights, liquid_firdespm_wtype * _wtype, liquid_firdespm_btype _btype, float * _h) { // create object firdespm q = firdespm_create(_h_len,_num_bands,_bands,_des,_weights,_wtype,_btype); // execute firdespm_execute(q,_h); // destroy firdespm_destroy(q); } // run filter design for basic low-pass filter // _n : filter length, _n > 0 // _fc : cutoff frequency, 0 < _fc < 0.5 // _As : stop-band attenuation [dB], _As > 0 // _mu : fractional sample offset, -0.5 < _mu < 0.5 [ignored] // _h : output coefficient buffer, [size: _n x 1] void firdespm_lowpass(unsigned int _n, float _fc, float _As, float _mu, float * _h) { // validate inputs if (_mu < -0.5f || _mu > 0.5f) { fprintf(stderr,"error: firdespm_lowpass(), _mu (%12.4e) out of range [-0.5,0.5]\n", _mu); exit(1); } else if (_fc < 0.0f || _fc > 0.5f) { fprintf(stderr,"error: firdespm_lowpass(), cutoff frequency (%12.4e) out of range (0, 0.5)\n", _fc); exit(1); } else if (_n == 0) { fprintf(stderr,"error: firdespm_lowpass(), filter length must be greater than zero\n"); exit(1); } // estimate transition band float ft = estimate_req_filter_df(_As, _n); // derived values float fp = _fc - 0.5*ft; // pass-band cutoff frequency float fs = _fc + 0.5*ft; // stop-band cutoff frequency liquid_firdespm_btype btype = LIQUID_FIRDESPM_BANDPASS; // derived values unsigned int num_bands = 2; float bands[4] = {0.0f, fp, fs, 0.5f}; float des[2] = {1.0f, 0.0f}; float weights[2] = {1.0f, 1.0f}; liquid_firdespm_wtype wtype[2] = {LIQUID_FIRDESPM_FLATWEIGHT, LIQUID_FIRDESPM_EXPWEIGHT}; // design filter firdespm_run(_n,num_bands,bands,des,weights,wtype,btype,_h); } // create firdespm object // _h_len : length of filter (number of taps) // _num_bands : number of frequency bands // _bands : band edges, f in [0,0.5], [size: _num_bands x 2] // _des : desired response [size: _num_bands x 1] // _weights : response weighting [size: _num_bands x 1] // _wtype : weight types (e.g. LIQUID_FIRDESPM_FLATWEIGHT) [size: _num_bands x 1] // _btype : band type (e.g. LIQUID_FIRDESPM_BANDPASS) firdespm firdespm_create(unsigned int _h_len, unsigned int _num_bands, float * _bands, float * _des, float * _weights, liquid_firdespm_wtype * _wtype, liquid_firdespm_btype _btype) { unsigned int i; // validate input int bands_valid = 1; int weights_valid = 1; // ensure bands are withing [0,0.5] for (i=0; i<2*_num_bands; i++) bands_valid &= _bands[i] >= 0.0 && _bands[i] <= 0.5; // ensure bands are non-decreasing for (i=1; i<2*_num_bands; i++) bands_valid &= _bands[i] >= _bands[i-1]; // ensure weights are greater than 0 // TODO: ignore weights if pointer is NULL for (i=0; i<_num_bands; i++) weights_valid &= _weights[i] > 0; if (!bands_valid) { fprintf(stderr,"error: firdespm_create(), invalid bands\n"); exit(1); } else if (!weights_valid) { fprintf(stderr,"error: firdespm_create(), invalid weights (must be positive)\n"); exit(1); } else if (_num_bands == 0) { fprintf(stderr,"error: firdespm_create(), number of bands must be > 0\n"); exit(1); } // create object firdespm q = (firdespm) malloc(sizeof(struct firdespm_s)); // compute number of extremal frequencies q->h_len = _h_len; // filter length q->s = q->h_len % 2; // odd/even length q->n = (q->h_len - q->s)/2; // filter semi-length q->r = q->n + q->s; // number of approximating functions q->btype = _btype; // set band type // allocate memory for extremal frequency set, interpolating polynomial q->iext = (unsigned int*) malloc((q->r+1)*sizeof(unsigned int)); q->x = (double*) malloc((q->r+1)*sizeof(double)); q->alpha = (double*) malloc((q->r+1)*sizeof(double)); q->c = (double*) malloc((q->r+1)*sizeof(double)); // allocate memory for arrays q->num_bands = _num_bands; q->bands = (double*) malloc(2*q->num_bands*sizeof(double)); q->des = (double*) malloc( q->num_bands*sizeof(double)); q->weights = (double*) malloc( q->num_bands*sizeof(double)); // allocate memory for weighting types q->wtype = (liquid_firdespm_wtype*) malloc(q->num_bands*sizeof(liquid_firdespm_wtype)); if (_wtype == NULL) { // set to default (LIQUID_FIRDESPM_FLATWEIGHT) for (i=0; inum_bands; i++) q->wtype[i] = LIQUID_FIRDESPM_FLATWEIGHT; } else { // copy from input for (i=0; inum_bands; i++) q->wtype[i] = _wtype[i]; } // copy input arrays for (i=0; inum_bands; i++) { q->bands[2*i+0] = _bands[2*i+0]; q->bands[2*i+1] = _bands[2*i+1]; q->des[i] = _des[i]; q->weights[i] = _weights == NULL ? 1.0f : _weights[i]; } // estimate grid size // TODO : adjust grid density based on expected value for rho q->grid_density = 20; q->grid_size = 0; double df = 0.5/(q->grid_density*q->r); // frequency step for (i=0; inum_bands; i++) { double f0 = q->bands[2*i+0]; // lower band edge double f1 = q->bands[2*i+1]; // upper band edge q->grid_size += (unsigned int)( (f1-f0)/df + 1.0 ); } // create the grid q->F = (double*) malloc(q->grid_size*sizeof(double)); q->D = (double*) malloc(q->grid_size*sizeof(double)); q->W = (double*) malloc(q->grid_size*sizeof(double)); q->E = (double*) malloc(q->grid_size*sizeof(double)); q->callback = NULL; q->userdata = NULL; firdespm_init_grid(q); // TODO : fix grid, weights according to filter type // return object return q; } // create firdespm object with user-defined callback // _h_len : length of filter (number of taps) // _num_bands : number of frequency bands // _bands : band edges, f in [0,0.5], [size: _num_bands x 2] // _btype : band type (e.g. LIQUID_FIRDESPM_BANDPASS) // _callback : user-defined callback for specifying desired response & weights // _userdata : user-defined data structure for callback function firdespm firdespm_create_callback(unsigned int _h_len, unsigned int _num_bands, float * _bands, liquid_firdespm_btype _btype, firdespm_callback _callback, void * _userdata) { unsigned int i; // validate input int bands_valid = 1; // ensure bands are withing [0,0.5] for (i=0; i<2*_num_bands; i++) bands_valid &= _bands[i] >= 0.0 && _bands[i] <= 0.5; // ensure bands are non-decreasing for (i=1; i<2*_num_bands; i++) bands_valid &= _bands[i] >= _bands[i-1]; if (!bands_valid) { fprintf(stderr,"error: firdespm_create(), invalid bands\n"); exit(1); } else if (_num_bands == 0) { fprintf(stderr,"error: firdespm_create(), number of bands must be > 0\n"); exit(1); } // create object firdespm q = (firdespm) malloc(sizeof(struct firdespm_s)); // compute number of extremal frequencies q->h_len = _h_len; // filter length q->s = q->h_len % 2; // odd/even length q->n = (q->h_len - q->s)/2; // filter semi-length q->r = q->n + q->s; // number of approximating functions q->btype = _btype; // set band type q->callback = _callback; q->userdata = _userdata; // allocate memory for extremal frequency set, interpolating polynomial q->iext = (unsigned int*) malloc((q->r+1)*sizeof(unsigned int)); q->x = (double*) malloc((q->r+1)*sizeof(double)); q->alpha = (double*) malloc((q->r+1)*sizeof(double)); q->c = (double*) malloc((q->r+1)*sizeof(double)); // allocate memory for arrays q->num_bands = _num_bands; q->bands = (double*) malloc(2*q->num_bands*sizeof(double)); q->des = (double*) malloc( q->num_bands*sizeof(double)); q->weights = (double*) malloc( q->num_bands*sizeof(double)); q->wtype = (liquid_firdespm_wtype*) malloc(q->num_bands*sizeof(liquid_firdespm_wtype)); // copy input arrays for (i=0; inum_bands; i++) { q->bands[2*i+0] = _bands[2*i+0]; q->bands[2*i+1] = _bands[2*i+1]; q->des[i] = 0.0f; q->weights[i] = 0.0f; } // estimate grid size // TODO : adjust grid density based on expected value for rho q->grid_density = 20; q->grid_size = 0; double df = 0.5/(q->grid_density*q->r); // frequency step for (i=0; inum_bands; i++) { double f0 = q->bands[2*i+0]; // lower band edge double f1 = q->bands[2*i+1]; // upper band edge q->grid_size += (unsigned int)( (f1-f0)/df + 1.0 ); } // create the grid q->F = (double*) malloc(q->grid_size*sizeof(double)); q->D = (double*) malloc(q->grid_size*sizeof(double)); q->W = (double*) malloc(q->grid_size*sizeof(double)); q->E = (double*) malloc(q->grid_size*sizeof(double)); firdespm_init_grid(q); // TODO : fix grid, weights according to filter type // return object return q; } // destroy firdespm object void firdespm_destroy(firdespm _q) { #if LIQUID_FIRDESPM_DEBUG firdespm_output_debug_file(_q); #endif // free memory for extremal frequency set, interpolating polynomial free(_q->iext); free(_q->x); free(_q->alpha); free(_q->c); // free dense grid elements free(_q->F); free(_q->D); free(_q->W); free(_q->E); // free band description elements free(_q->bands); free(_q->des); free(_q->weights); free(_q->wtype); // free object free(_q); } // print firdespm object internals void firdespm_print(firdespm _q) { unsigned int i; printf("firdespm: "); for (i=0; i<_q->num_bands; i++) printf(" band %-5u", i); printf("\n"); printf(" lower band edge "); for (i=0; i<_q->num_bands; i++) printf("%16.8f", _q->bands[2*i+0]); printf("\n"); printf(" upper band edge "); for (i=0; i<_q->num_bands; i++) printf("%16.8f", _q->bands[2*i+1]); printf("\n"); printf(" desired value "); for (i=0; i<_q->num_bands; i++) printf("%16.8f", _q->des[i]); printf("\n"); printf(" weighting "); for (i=0; i<_q->num_bands; i++) printf("%16.8f", _q->weights[i]); printf("\n"); } // execute filter design, storing result in _h void firdespm_execute(firdespm _q, float * _h) { unsigned int i; // initial guess of extremal frequencies evenly spaced on F // TODO : guarantee at least one extremal frequency lies in each band for (i=0; i<_q->r+1; i++) { _q->iext[i] = (i * (_q->grid_size-1)) / _q->r; #if LIQUID_FIRDESPM_DEBUG_PRINT printf("iext_guess[%3u] = %u\n", i, _q->iext[i]); #endif } // iterate over the Remez exchange algorithm unsigned int p; unsigned int max_iterations = 40; for (p=0; pgrid_density*_q->r); #if LIQUID_FIRDESPM_DEBUG_PRINT printf("df : %12.8f\n", df); #endif #if 0 firdespm_print(_q); // compute total bandwidth double b=0.0; for (i=0; i<_q->num_bands; i++) b += _q->bands[2*i+1] - _q->bands[2*i+0]; printf("b : %12.8f\n", b); // adjust frequency step size if it is too large double g = b / (df * _q->r); // approximate oversampling rate (points/extrema) double gmin = 4.0; if (g < gmin) df *= g / gmin; printf("df : %12.8f\n", df); //exit(1); #endif // number of grid points counter unsigned int n = 0; double f0, f1; double fw = 1.0f; // weighting function for (i=0; i<_q->num_bands; i++) { // extract band edges f0 = _q->bands[2*i+0]; f1 = _q->bands[2*i+1]; // ensure first point is not zero for differentiator // and Hilbert transforms due to transformation (below) if (i==0 && _q->btype != LIQUID_FIRDESPM_BANDPASS) f0 = f0 < df ? df : f0; // compute the number of gridpoints in this band unsigned int num_points = (unsigned int)( (f1-f0)/df + 0.5 ); // ensure at least one point per band if (num_points < 1) num_points = 1; //printf("band : [%12.8f %12.8f] %3u points\n",f0,f1,num_points); // add points to grid for (j=0; jF[n] = f0 + j*df; // compute desired response using function pointer if provided if (_q->callback != NULL) { _q->callback(_q->F[n], _q->userdata, &_q->D[n], &_q->W[n]); } else { _q->D[n] = _q->des[i]; // compute weight, applying weighting function switch (_q->wtype[i]) { case LIQUID_FIRDESPM_FLATWEIGHT: fw = 1.0f; break; case LIQUID_FIRDESPM_EXPWEIGHT: fw = expf(2.0f*j*df); break; case LIQUID_FIRDESPM_LINWEIGHT: fw = 1.0f + 2.7f*j*df; break; default: fprintf(stderr,"error: firdespm_init_grid(), invalid weighting specifyer: %d\n", _q->wtype[i]); exit(1); } _q->W[n] = _q->weights[i] * fw; } n++; } // force endpoint to be upper edge of frequency band _q->F[n-1] = f1; // according to Janovetz } _q->grid_size = n; // take care of special symmetry conditions here if (_q->btype == LIQUID_FIRDESPM_BANDPASS) { if (_q->s == 0) { // even length filter for (i=0; i<_q->grid_size; i++) { _q->D[i] /= cos(M_PI*_q->F[i]); _q->W[i] *= cos(M_PI*_q->F[i]); } // force weight at endpoint to be (nearly) zero //_q->W[_q->grid_size-1] = 6.12303177e-17f; } } else { // differentiator, Hilbert transform if (_q->s == 0) { // even length filter for (i=0; i<_q->grid_size; i++) { _q->D[i] /= sin(M_PI*_q->F[i]); _q->W[i] *= sin(M_PI*_q->F[i]); } } else { // odd length filter for (i=0; i<_q->grid_size; i++) { _q->D[i] /= sin(2*M_PI*_q->F[i]); _q->W[i] *= sin(2*M_PI*_q->F[i]); } } } } // compute interpolating polynomial void firdespm_compute_interp(firdespm _q) { unsigned int i; // compute Chebyshev points on F[iext[]] : cos(2*pi*f) for (i=0; i<_q->r+1; i++) { _q->x[i] = cos(2*M_PI*_q->F[_q->iext[i]]); #if LIQUID_FIRDESPM_DEBUG_PRINT printf("x[%3u] = %12.8f\n", i, _q->x[i]); #endif } //printf("\n"); // compute Lagrange interpolating polynomial poly_fit_lagrange_barycentric(_q->x,_q->r+1,_q->alpha); #if LIQUID_FIRDESPM_DEBUG_PRINT for (i=0; i<_q->r+1; i++) printf("a[%3u] = %12.8f\n", i, _q->alpha[i]); #endif // compute rho double t0 = 0.0; // numerator double t1 = 0.0; // denominator for (i=0; i<_q->r+1; i++) { //printf("D[%3u] = %16.8e, W[%3u] = %16.8e\n", i, _q->D[_q->iext[i]], i, _q->W[_q->iext[i]]); t0 += _q->alpha[i] * _q->D[_q->iext[i]]; t1 += _q->alpha[i] / _q->W[_q->iext[i]] * (i % 2 ? -1.0 : 1.0); } _q->rho = t0/t1; #if LIQUID_FIRDESPM_DEBUG_PRINT printf(" rho : %12.4e\n", _q->rho); printf("\n"); #endif // compute polynomial values (interpolants) for (i=0; i<_q->r+1; i++) { _q->c[i] = _q->D[_q->iext[i]] - (i % 2 ? -1 : 1) * _q->rho / _q->W[_q->iext[i]]; #if LIQUID_FIRDESPM_DEBUG_PRINT printf("c[%3u] = %16.8e\n", i, _q->c[i]); #endif } } void firdespm_compute_error(firdespm _q) { unsigned int i; double xf; double H; for (i=0; i<_q->grid_size; i++) { // compute actual response xf = cos(2*M_PI*_q->F[i]); H = poly_val_lagrange_barycentric(_q->x,_q->c,_q->alpha,xf,_q->r+1); // compute error _q->E[i] = _q->W[i] * (_q->D[i] - H); } } // search error curve for r+1 extremal indices // TODO : return number of values which have changed (exit criteria) void firdespm_iext_search(firdespm _q) { unsigned int i; // found extremal frequency indices unsigned int nmax = 2*_q->r + 2*_q->num_bands; // max number of extremals unsigned int found_iext[nmax]; unsigned int num_found=0; #if 0 // check for extremum at f=0 if ( fabs(_q->E[0]) > fabs(_q->E[1]) ) found_iext[num_found++] = 0; #else // force f=0 into candidate set found_iext[num_found++] = 0; #if LIQUID_FIRDESPM_DEBUG_PRINT printf("num_found : %4u [%4u / %4u]\n", num_found, 0, _q->grid_size); #endif #endif // search inside grid for (i=1; i<_q->grid_size-1; i++) { if ( ((_q->E[i]>=0.0) && (_q->E[i-1]<=_q->E[i]) && (_q->E[i+1]<=_q->E[i]) ) || ((_q->E[i]< 0.0) && (_q->E[i-1]>=_q->E[i]) && (_q->E[i+1]>=_q->E[i]) ) ) { assert(num_found < nmax); found_iext[num_found++] = i; #if LIQUID_FIRDESPM_DEBUG_PRINT printf("num_found : %4u [%4u / %4u]\n", num_found, i, _q->grid_size); #endif } } #if 0 // check for extremum at f=0.5 if ( fabs(_q->E[_q->grid_size-1]) > fabs(_q->E[_q->grid_size-2]) ) found_iext[num_found++] = _q->grid_size-1; #else // force f=0.5 into candidate set assert(num_found < nmax); found_iext[num_found++] = _q->grid_size-1; //printf("num_found : %4u [%4u / %4u]\n", num_found, _q->grid_size-1, _q->grid_size); #endif //printf("r+1 = %4u, num_found = %4u\n", _q->r+1, num_found); if (num_found < _q->r+1) { // too few extremal frequencies found. Theoretically, this // should never happen as the Chebyshev alternation theorem // guarantees at least r+1 extrema, however due to finite // machine precision, interpolation can be imprecise fprintf(stderr,"warning: firdespm_iext_search(), too few extrema found (expected %u, found %u); exiting prematurely\n", _q->r+1, num_found); _q->num_exchanges = 0; return; } assert(num_found <= nmax); // search extrema and eliminate smallest unsigned int imin=0; // index of found_iext where _E is a minimum extreme unsigned int sign=0; // sign of error unsigned int num_extra = num_found - _q->r - 1; // number of extra extremal frequencies unsigned int alternating_sign; #if LIQUID_FIRDESPM_DEBUG_PRINT for (i=0; i<_q->r+1; i++) printf("iext[%4u] = %4u : %16.8e\n", i, found_iext[i], _q->E[found_iext[i]]); #endif while (num_extra) { // evaluate sign of first extrema sign = _q->E[found_iext[0]] > 0.0; // imin = 0; alternating_sign = 1; for (i=1; iE[found_iext[i]]) < fabs(_q->E[found_iext[imin]]) ) imin = i; if ( sign && _q->E[found_iext[i]] < 0.0 ) { sign = 0; } else if ( !sign && _q->E[found_iext[i]] >= 0.0 ) { sign = 1; } else { // found two extrema with non-alternating sign; delete // the smaller of the two if ( fabs(_q->E[found_iext[i]]) < fabs(_q->E[found_iext[i-1]]) ) imin = i; else imin = i-1; alternating_sign = 0; break; } } //printf(" imin : %3u : %12.4e;\n", imin, _q->E[found_iext[imin]]); // if ( alternating_sign && num_extra==1) { //imin = (fabs(_q->E[found_iext[0]]) > fabs(_q->E[found_iext[num_extra-1]])) ? 0 : num_extra-1; if (fabs(_q->E[found_iext[0]]) < fabs(_q->E[found_iext[num_found-1]])) imin = 0; else imin = num_found-1; } // Delete value in 'found_iext' at 'index imin'. This // is equivalent to shifing all values left one position // starting at index imin+1 //printf("deleting found_iext[%3u] = %3u\n", imin, found_iext[imin]); #if 0 memmove( &found_iext[imin], &found_iext[imin+1], (num_found-imin)*sizeof(unsigned int)); #else // equivalent code: for (i=imin; inum_exchanges=0; for (i=0; i<_q->r+1; i++) _q->num_exchanges += _q->iext[i] == found_iext[i] ? 0 : 1; // copy new values memmove(_q->iext, found_iext, (_q->r+1)*sizeof(unsigned int)); #if LIQUID_FIRDESPM_DEBUG_PRINT for (i=0; i<_q->r+1; i++) printf("iext_new[%4u] = %4u : %16.8e\n", i, found_iext[i], _q->E[found_iext[i]]); #endif } // evaluates result to determine if Remez exchange algorithm // has converged int firdespm_is_search_complete(firdespm _q) { // if no extremal frequencies have been exchanged, Remez // algorithm has converged if (_q->num_exchanges == 0) return 1; unsigned int i; double tol = 1e-3f; double e=0.0; double emin=0.0; double emax=0.0; for (i=0; i<_q->r+1; i++) { e = fabs(_q->E[_q->iext[i]]); if (i==0 || e < emin) emin = e; if (i==0 || e > emax) emax = e; } #if LIQUID_FIRDESPM_DEBUG_PRINT printf("emin : %16.8e, emax : %16.8e, metric : %16.8e\n", emin, emax, (emax-emin)/emax); #endif return (emax-emin) / emax < tol ? 1 : 0; } // compute filter taps (coefficients) from result void firdespm_compute_taps(firdespm _q, float * _h) { unsigned int i; // re-generate interpolator and compute coefficients // for best cosine approximation firdespm_compute_interp(_q); // evaluate Lagrange polynomial on evenly spaced points unsigned int p = _q->r - _q->s + 1; double G[p]; for (i=0; ih_len); double xf = cos(2*M_PI*f); double cf = poly_val_lagrange_barycentric(_q->x,_q->c,_q->alpha,xf,_q->r+1); double g=1.0; if (_q->btype == LIQUID_FIRDESPM_BANDPASS && _q->s==1) { // odd filter length, even symmetry g = 1.0; } else if (_q->btype == LIQUID_FIRDESPM_BANDPASS && _q->s==0) { // even filter length, even symmetry g = cos(M_PI * i / _q->h_len); } else if (_q->btype != LIQUID_FIRDESPM_BANDPASS && _q->s==1) { // odd filter length, odd symmetry } else if (_q->btype != LIQUID_FIRDESPM_BANDPASS && _q->s==0) { // even filter length, odd symmetry } G[i] = cf * g; //printf("G(%3u) = %12.4e (cf = %12.8f, f=%12.8f, c = %12.8f);\n", i+1, G[i], cf, f, g); } // compute inverse DFT (slow method), performing // transformation here for different filter types // TODO : flesh out computation for other filter types unsigned int j; if (_q->btype == LIQUID_FIRDESPM_BANDPASS) { // odd filter length, even symmetry for (i=0; i<_q->h_len; i++) { double v = G[0]; double f = ((double)i - (double)(p-1) + 0.5*(1-_q->s)) / (double)(_q->h_len); for (j=1; j<_q->r; j++) v += 2.0 * G[j] * cos(2*M_PI*f*j); _h[i] = v / (double)(_q->h_len); } } else if (_q->btype != LIQUID_FIRDESPM_BANDPASS && _q->s==1) { // odd filter length, odd symmetry fprintf(stderr,"warning: firdespm_compute_taps(), filter configuration not yet supported\n"); } else if (_q->btype != LIQUID_FIRDESPM_BANDPASS && _q->s==0) { // even filter length, odd symmetry fprintf(stderr,"warning: firdespm_compute_taps(), filter configuration not yet supported\n"); } #if LIQUID_FIRDESPM_DEBUG_PRINT printf("\n"); for (i=0; i<_q->h_len; i++) printf("h(%3u) = %12.8f;\n", i+1, _h[i]); #endif } #if LIQUID_FIRDESPM_DEBUG void firdespm_output_debug_file(firdespm _q) { FILE * fid = fopen(LIQUID_FIRDESPM_DEBUG_FILENAME,"w"); fprintf(fid,"%% %s : auto-generated file\n", LIQUID_FIRDESPM_DEBUG_FILENAME); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); unsigned int i; for (i=0; i<_q->grid_size; i++) { fprintf(fid,"F(%4u) = %16.8e;\n", i+1, _q->F[i]); fprintf(fid,"D(%4u) = %16.8e;\n", i+1, _q->D[i]); fprintf(fid,"W(%4u) = %16.8e;\n", i+1, _q->W[i]); fprintf(fid,"E(%4u) = %16.8e;\n", i+1, _q->E[i]); } for (i=0; i<_q->r+1; i++) { fprintf(fid,"iext(%4u) = %u;\n", i+1, _q->iext[i]+1); } fprintf(fid,"figure;\n"); fprintf(fid,"plot(F,E,'-', F(iext),E(iext),'x');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"xlabel('frequency');\n"); fprintf(fid,"ylabel('error');\n"); // evaluate poly unsigned int n=1024; for (i=0; ix,_q->c,_q->alpha,x,_q->r+1); fprintf(fid,"f(%4u) = %20.12e; H(%4u) = %20.12e;\n", i+1, f, i+1, c); } fprintf(fid,"figure;\n"); fprintf(fid,"plot(f,H,'-', F(iext),D(iext)-E(iext),'x');\n"); //fprintf(fid,"plot(f,20*log10(abs(H)),'-', F(iext),20*log10(abs(D(iext)-E(iext))),'x');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"xlabel('frequency');\n"); fprintf(fid,"ylabel('filter response');\n"); fprintf(fid,"rho = %20.12e;\n", _q->rho); fclose(fid); printf("internal debugging results written to %s.\n", LIQUID_FIRDESPM_DEBUG_FILENAME); } #endif liquid-dsp-1.3.1/src/filter/src/firfarrow.c000066400000000000000000000241561317124540100206050ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firfarrow.c // // Finite impulse response Farrow filter // #include #include #include #include #define FIRFARROW_USE_DOTPROD 1 #define FIRFARROW_DEBUG 0 // defined: // FIRFARROW() name-mangling macro // T coefficients type // WINDOW() window macro // DOTPROD() dotprod macro // PRINTVAL() print macro struct FIRFARROW(_s) { TC * h; // filter coefficients unsigned int h_len; // filter length float fc; // filter cutoff float As; // stop-band attenuation [dB] unsigned int Q; // polynomial order float mu; // fractional sample delay float * P; // polynomail coefficients matrix [ h_len x Q+1 ] float gamma; // inverse of DC response (normalization factor) #if FIRFARROW_USE_DOTPROD WINDOW() w; #else TI * v; unsigned int v_index; #endif }; // create firfarrow object // _h_len : filter length // _p : polynomial order // _fc : filter cutoff frequency // _As : stopband attenuation [dB] FIRFARROW() FIRFARROW(_create)(unsigned int _h_len, unsigned int _p, float _fc, float _As) { // validate input if (_h_len < 2) { fprintf(stderr,"error: firfarrow_%s_create(), filter length must be > 2\n", EXTENSION_FULL); exit(1); } else if (_p < 1) { fprintf(stderr,"error: firfarrow_%s_create(), polynomial order must be at least 1\n", EXTENSION_FULL); exit(1); } else if (_fc < 0.0f || _fc > 0.5f) { fprintf(stderr,"error: firfarrow_%s_create(), filter cutoff must be in [0,0.5]\n", EXTENSION_FULL); exit(1); } // create main object FIRFARROW() q = (FIRFARROW()) malloc(sizeof(struct FIRFARROW(_s))); // set internal properties q->h_len = _h_len; // filter length q->Q = _p; // polynomial order q->As = _As; // filter stop-band attenuation q->fc = _fc; // filter cutoff frequency // allocate memory for filter coefficients q->h = (TC *) malloc((q->h_len)*sizeof(TC)); #if FIRFARROW_USE_DOTPROD q->w = WINDOW(_create)(q->h_len); #else q->v = malloc((q->h_len)*sizeof(TI)); #endif // allocate memory for polynomial matrix [ h_len x Q+1 ] q->P = (float*) malloc((q->h_len)*(q->Q+1)*sizeof(float)); // reset the filter object FIRFARROW(_reset)(q); // generate polynomials FIRFARROW(_genpoly)(q); // set nominal delay of 0 FIRFARROW(_set_delay)(q,0.0f); // return main object return q; } // destroy firfarrow object, freeing all internal memory void FIRFARROW(_destroy)(FIRFARROW() _q) { #if FIRFARROW_USE_DOTPROD WINDOW(_destroy)(_q->w); #else free(_q->v); #endif free(_q->h); // free the filter coefficients array free(_q->P); // free the polynomial matrix // free main object free(_q); } // print firfarrow object's internal properties void FIRFARROW(_print)(FIRFARROW() _q) { printf("firfarrow [len : %u, poly-order : %u]\n", _q->h_len, _q->Q); printf("polynomial coefficients:\n"); // print coefficients unsigned int i, j, n=0; for (i=0; i<_q->h_len; i++) { printf(" %3u : ", i); for (j=0; j<_q->Q+1; j++) printf("%12.4e ", _q->P[n++]); printf("\n"); } printf("filter coefficients (mu=%8.4f):\n", _q->mu); n = _q->h_len; for (i=0; iw); #else unsigned int i; for (i=0; i<_q->h_len; i++) _q->v[i] = 0; _q->v_index = 0; #endif } // push sample into firfarrow object // _q : firfarrow object // _x : input sample void FIRFARROW(_push)(FIRFARROW() _q, TI _x) { #if FIRFARROW_USE_DOTPROD WINDOW(_push)(_q->w, _x); #else _q->v[ _q->v_index ] = _x; (_q->v_index)++; _q->v_index = (_q->v_index) % (_q->h_len); #endif } // set fractional delay of firfarrow object // _q : firfarrow object // _mu : fractional sample delay void FIRFARROW(_set_delay)(FIRFARROW() _q, float _mu) { // validate input if (_mu < -1.0f || _mu > 1.0f) { fprintf(stderr,"warning: firfarrow_%s_set_delay(), delay out of range\n", EXTENSION_FULL); } unsigned int i, n=0; for (i=0; i<_q->h_len; i++) { // compute filter tap from polynomial using negative // value for _mu _q->h[i] = POLY(_val)(_q->P+n, _q->Q, -_mu); // normalize filter by inverse of DC response _q->h[i] *= _q->gamma; n += _q->Q+1; //printf(" h[%3u] = %12.8f\n", i, _q->h[i]); } } // execute firfarrow internal dot product // _q : firfarrow object // _y : output sample pointer void FIRFARROW(_execute)(FIRFARROW() _q, TO * _y) { #if FIRFARROW_USE_DOTPROD TI *r; WINDOW(_read)(_q->w, &r); DOTPROD(_run4)(_q->h, r, _q->h_len, _y); #else TO y = 0; unsigned int i; for (i=0; i<_q->h_len; i++) y += _q->v[ (i+_q->v_index)%(_q->h_len) ] * _q->h[i]; *_y = y; #endif } // compute firfarrow filter on block of samples; the input // and output arrays may have the same pointer // _q : firfarrow object // _x : input array [size: _n x 1] // _n : input, output array size // _y : output array [size: _n x 1] void FIRFARROW(_execute_block)(FIRFARROW() _q, TI * _x, unsigned int _n, TO * _y) { unsigned int i; for (i=0; i<_n; i++) { // push input sample FIRFARROW(_push)(_q, _x[i]); // compute output FIRFARROW(_execute)(_q, &_y[i]); } } // get length of firfarrow object (number of filter taps) unsigned int FIRFARROW(_get_length)(FIRFARROW() _q) { return _q->h_len; } // get coefficients of firfarrow object // _q : firfarrow object // _h : output coefficients pointer void FIRFARROW(_get_coefficients)(FIRFARROW() _q, TC * _h) { memmove(_h, _q->h, (_q->h_len)*sizeof(TC)); } // compute complex frequency response // _q : filter object // _fc : frequency // _H : output frequency response void FIRFARROW(_freqresponse)(FIRFARROW() _q, float _fc, float complex * _H) { unsigned int i; float complex H = 0.0f; for (i=0; i<_q->h_len; i++) H += _q->h[i] * cexpf(_Complex_I*2*M_PI*_fc*i); // set return value *_H = H; } // compute group delay [samples] // _q : filter object // _fc : frequency float FIRFARROW(_groupdelay)(FIRFARROW() _q, float _fc) { // copy coefficients to be in correct order float h[_q->h_len]; unsigned int i; unsigned int n = _q->h_len; for (i=0; ih[i]); return fir_group_delay(h, n, _fc); } // // internal // // generate polynomials to represent filter coefficients void FIRFARROW(_genpoly)(FIRFARROW() _q) { // TODO : shy away from 'float' and use 'TC' types unsigned int i, j, n=0; float x, mu, h0, h1; float mu_vect[_q->Q+1]; float hp_vect[_q->Q+1]; float p[_q->Q]; float beta = kaiser_beta_As(_q->As); for (i=0; i<_q->h_len; i++) { #if FIRFARROW_DEBUG printf("i : %3u / %3u\n", i, _q->h_len); #endif x = (float)(i) - (float)(_q->h_len-1)/2.0f; for (j=0; j<=_q->Q; j++) { mu = ((float)j - (float)_q->Q)/((float)_q->Q) + 0.5f; h0 = sincf(2.0f*(_q->fc)*(x + mu)); h1 = kaiser(i,_q->h_len,beta,mu); #if FIRFARROW_DEBUG printf(" %3u : x=%12.8f, mu=%12.8f, h0=%12.8f, h1=%12.8f, hp=%12.8f\n", j, x, mu, h0, h1, h0*h1); #endif mu_vect[j] = mu; hp_vect[j] = h0*h1; } POLY(_fit)(mu_vect,hp_vect,_q->Q+1,p,_q->Q+1); #if FIRFARROW_DEBUG printf(" polynomial : "); for (j=0; j<=_q->Q; j++) printf("%8.4f,", p[j]); printf("\n"); #endif // copy coefficients to internal matrix memmove(_q->P+n, p, (_q->Q+1)*sizeof(float)); n += _q->Q+1; } #if FIRFARROW_DEBUG // print coefficients n=0; for (i=0; i<_q->h_len; i++) { printf("%3u : ", i); for (j=0; j<_q->Q+1; j++) printf("%12.4e ", _q->P[n++]); printf("\n"); } #endif // normalize DC gain _q->gamma = 1.0f; // initialize gamma to 1 FIRFARROW(_set_delay)(_q,0.0f); // compute filter taps with zero delay _q->gamma = 0.0f; // clear gamma for (i=0; i<_q->h_len; i++) // compute DC response _q->gamma += _q->h[i]; _q->gamma = 1.0f / (_q->gamma); // invert result } liquid-dsp-1.3.1/src/filter/src/firfilt.c000066400000000000000000000264531317124540100202450ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firfilt : finite impulse response (FIR) filter // #include #include #include // defined: // FIRFILT() name-mangling macro // T coefficients type // WINDOW() window macro // DOTPROD() dotprod macro // PRINTVAL() print macro #define LIQUID_FIRFILT_USE_WINDOW (0) // firfilt object structure struct FIRFILT(_s) { TC * h; // filter coefficients array [size; h_len x 1] unsigned int h_len; // filter length #if LIQUID_FIRFILT_USE_WINDOW // use window object for internal buffer WINDOW() w; #else // use array as internal buffer (faster) TI * w; // internal buffer object unsigned int w_len; // window length unsigned int w_mask; // window index mask unsigned int w_index; // window read index #endif DOTPROD() dp; // dot product object TC scale; // output scaling factor }; // create firfilt object // _h : coefficients (filter taps) [size: _n x 1] // _n : filter length FIRFILT() FIRFILT(_create)(TC * _h, unsigned int _n) { // validate input if (_n == 0) { fprintf(stderr,"error: firfilt_%s_create(), filter length must be greater than zero\n", EXTENSION_FULL); exit(1); } // create filter object and initialize FIRFILT() q = (FIRFILT()) malloc(sizeof(struct FIRFILT(_s))); q->h_len = _n; q->h = (TC *) malloc((q->h_len)*sizeof(TC)); #if LIQUID_FIRFILT_USE_WINDOW // create window (internal buffer) q->w = WINDOW(_create)(q->h_len); #else // initialize array for buffering q->w_len = 1<h_len); // effectively 2^{floor(log2(len))+1} q->w_mask = q->w_len - 1; q->w = (TI *) malloc((q->w_len + q->h_len + 1)*sizeof(TI)); q->w_index = 0; #endif // load filter in reverse order unsigned int i; for (i=_n; i>0; i--) q->h[i-1] = _h[_n-i]; // create dot product object q->dp = DOTPROD(_create)(q->h, q->h_len); // set default scaling q->scale = 1; // reset filter state (clear buffer) FIRFILT(_reset)(q); return q; } // create filter using Kaiser-Bessel windowed sinc method // _n : filter length, _n > 0 // _fc : cutoff frequency, 0 < _fc < 0.5 // _As : stop-band attenuation [dB], _As > 0 // _mu : fractional sample offset, -0.5 < _mu < 0.5 FIRFILT() FIRFILT(_create_kaiser)(unsigned int _n, float _fc, float _As, float _mu) { // validate input if (_n == 0) { fprintf(stderr,"error: firfilt_%s_create_kaiser(), filter length must be greater than zero\n", EXTENSION_FULL); exit(1); } // compute temporary array for holding coefficients float hf[_n]; liquid_firdes_kaiser(_n, _fc, _As, _mu, hf); // copy coefficients to type-specific array TC h[_n]; unsigned int i; for (i=0; i<_n; i++) h[i] = (TC) hf[i]; // return FIRFILT(_create)(h, _n); } // create from square-root Nyquist prototype // _type : filter type (e.g. LIQUID_RNYQUIST_RRC) // _k : nominal samples/symbol, _k > 1 // _m : filter delay [symbols], _m > 0 // _beta : rolloff factor, 0 < beta <= 1 // _mu : fractional sample offset,-0.5 < _mu < 0.5 FIRFILT() FIRFILT(_create_rnyquist)(int _type, unsigned int _k, unsigned int _m, float _beta, float _mu) { // validate input if (_k < 2) { fprintf(stderr,"error: firfilt_%s_create_rnyquist(), filter samples/symbol must be greater than 1\n", EXTENSION_FULL); exit(1); } else if (_m == 0) { fprintf(stderr,"error: firfilt_%s_create_rnyquist(), filter delay must be greater than 0\n", EXTENSION_FULL); exit(1); } else if (_beta < 0.0f || _beta > 1.0f) { fprintf(stderr,"error: firfilt_%s_create_rnyquist(), filter excess bandwidth factor must be in [0,1]\n", EXTENSION_FULL); exit(1); } // generate square-root Nyquist filter unsigned int h_len = 2*_k*_m + 1; float hf[h_len]; liquid_firdes_prototype(_type,_k,_m,_beta,_mu,hf); // copy coefficients to type-specific array (e.g. float complex) unsigned int i; TC hc[h_len]; for (i=0; i 1024) { fprintf(stderr,"error: firfilt_%s_create_rect(), filter length must be in [1,1024]\n", EXTENSION_FULL); exit(1); } // create float array coefficients float hf[_n]; unsigned int i; for (i=0; i<_n; i++) hf[i] = 1.0f; // copy coefficients to type-specific array TC h[_n]; for (i=0; i<_n; i++) h[i] = (TC) hf[i]; // return filter object and return return FIRFILT(_create)(h, _n); } // re-create firfilt object // _q : original firfilt object // _h : new coefficients [size: _n x 1] // _n : new filter length FIRFILT() FIRFILT(_recreate)(FIRFILT() _q, TC * _h, unsigned int _n) { unsigned int i; // reallocate memory array if filter length has changed if (_n != _q->h_len) { // reallocate memory _q->h_len = _n; _q->h = (TC*) realloc(_q->h, (_q->h_len)*sizeof(TC)); #if LIQUID_FIRFILT_USE_WINDOW // recreate window object, preserving internal state _q->w = WINDOW(_recreate)(_q->w, _q->h_len); #else // free old array free(_q->w); // initialize array for buffering _q->w_len = 1<h_len); // effectively 2^{floor(log2(len))+1} _q->w_mask = _q->w_len - 1; _q->w = (TI *) malloc((_q->w_len + _q->h_len + 1)*sizeof(TI)); _q->w_index = 0; #endif } // load filter in reverse order for (i=_n; i>0; i--) _q->h[i-1] = _h[_n-i]; // re-create dot product object DOTPROD(_destroy)(_q->dp); _q->dp = DOTPROD(_create)(_q->h, _q->h_len); return _q; } // destroy firfilt object void FIRFILT(_destroy)(FIRFILT() _q) { #if LIQUID_FIRFILT_USE_WINDOW WINDOW(_destroy)(_q->w); #else free(_q->w); #endif DOTPROD(_destroy)(_q->dp); free(_q->h); free(_q); } // reset internal state of filter object void FIRFILT(_reset)(FIRFILT() _q) { #if LIQUID_FIRFILT_USE_WINDOW WINDOW(_reset)(_q->w); #else unsigned int i; for (i=0; i<_q->w_len; i++) _q->w[i] = 0.0; _q->w_index = 0; #endif } // print filter object internals (taps, buffer) void FIRFILT(_print)(FIRFILT() _q) { printf("firfilt_%s:\n", EXTENSION_FULL); unsigned int i; unsigned int n = _q->h_len; for (i=0; iw); #endif } // set output scaling for filter void FIRFILT(_set_scale)(FIRFILT() _q, TC _scale) { _q->scale = _scale; } // push sample into filter object's internal buffer // _q : filter object // _x : input sample void FIRFILT(_push)(FIRFILT() _q, TI _x) { #if LIQUID_FIRFILT_USE_WINDOW WINDOW(_push)(_q->w, _x); #else // increment index _q->w_index++; // wrap around pointer _q->w_index &= _q->w_mask; // if pointer wraps around, copy excess memory if (_q->w_index == 0) memmove(_q->w, _q->w + _q->w_len, (_q->h_len)*sizeof(TI)); // append value to end of buffer _q->w[_q->w_index + _q->h_len - 1] = _x; #endif } // compute output sample (dot product between internal // filter coefficients and internal buffer) // _q : filter object // _y : output sample pointer void FIRFILT(_execute)(FIRFILT() _q, TO * _y) { // read buffer (retrieve pointer to aligned memory array) #if LIQUID_FIRFILT_USE_WINDOW TI *r; WINDOW(_read)(_q->w, &r); #else TI *r = _q->w + _q->w_index; #endif // execute dot product DOTPROD(_execute)(_q->dp, r, _y); // apply scaling factor *_y *= _q->scale; } // execute the filter on a block of input samples; the // input and output buffers may be the same // _q : filter object // _x : pointer to input array [size: _n x 1] // _n : number of input, output samples // _y : pointer to output array [size: _n x 1] void FIRFILT(_execute_block)(FIRFILT() _q, TI * _x, unsigned int _n, TO * _y) { unsigned int i; for (i=0; i<_n; i++) { // push sample into filter FIRFILT(_push)(_q, _x[i]); // compute output sample FIRFILT(_execute)(_q, &_y[i]); } } // get filter length unsigned int FIRFILT(_get_length)(FIRFILT() _q) { return _q->h_len; } // compute complex frequency response // _q : filter object // _fc : frequency // _H : output frequency response void FIRFILT(_freqresponse)(FIRFILT() _q, float _fc, float complex * _H) { unsigned int i; float complex H = 0.0f; // compute dot product between coefficients and exp{ 2 pi fc {0..n-1} } for (i=0; i<_q->h_len; i++) H += _q->h[i] * cexpf(_Complex_I*2*M_PI*_fc*i); // apply scaling H *= _q->scale; // set return value *_H = H; } // compute group delay in samples // _q : filter object // _fc : frequency float FIRFILT(_groupdelay)(FIRFILT() _q, float _fc) { // copy coefficients to be in correct order float h[_q->h_len]; unsigned int i; unsigned int n = _q->h_len; for (i=0; ih[n-i-1]); return fir_group_delay(h, n, _fc); } liquid-dsp-1.3.1/src/filter/src/firhilb.c000066400000000000000000000216331317124540100202200ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firhilb.c // // finite impulse response (FIR) Hilbert transform // #include #include #include #include // defined: // FIRHILB() name-mangling macro // T coefficients type // WINDOW() window macro // DOTPROD() dotprod macro // PRINTVAL() print macro struct FIRHILB(_s) { T * h; // filter coefficients T complex * hc; // filter coefficients (complex) unsigned int h_len; // length of filter float As; // filter stop-band attenuation [dB] unsigned int m; // filter semi-length, h_len = 4*m+1 // quadrature filter component T * hq; // quadrature filter coefficients unsigned int hq_len; // quadrature filter length (2*m) // input buffers WINDOW() w0; // input buffer (even samples) WINDOW() w1; // input buffer (odd samples) // vector dot product DOTPROD() dpq; // regular real-to-complex/complex-to-real operation unsigned int toggle; }; // create firhilb object // _m : filter semi-length (delay: 2*m+1) // _As : stop-band attenuation [dB] FIRHILB() FIRHILB(_create)(unsigned int _m, float _As) { // validate firhilb inputs if (_m < 2) { fprintf(stderr,"error: firhilb_create(), filter semi-length (m) must be at least 2\n"); exit(1); } // allocate memory for main object FIRHILB() q = (FIRHILB()) malloc(sizeof(struct FIRHILB(_s))); q->m = _m; // filter semi-length q->As = fabsf(_As); // stop-band attenuation // set filter length and allocate memory for coefficients q->h_len = 4*(q->m) + 1; q->h = (T *) malloc((q->h_len)*sizeof(T)); q->hc = (T complex *) malloc((q->h_len)*sizeof(T complex)); // allocate memory for quadrature filter component q->hq_len = 2*(q->m); q->hq = (T *) malloc((q->hq_len)*sizeof(T)); // compute filter coefficients for half-band filter liquid_firdes_kaiser(q->h_len, 0.25f, q->As, 0.0f, q->h); // alternate sign of non-zero elements unsigned int i; for (i=0; ih_len; i++) { float t = (float)i - (float)(q->h_len-1)/2.0f; q->hc[i] = q->h[i] * cexpf(_Complex_I*0.5f*M_PI*t); q->h[i] = cimagf(q->hc[i]); } // resample, reverse direction unsigned int j=0; for (i=1; ih_len; i+=2) q->hq[j++] = q->h[q->h_len - i - 1]; // create windows for upper and lower polyphase filter branches q->w1 = WINDOW(_create)(2*(q->m)); q->w0 = WINDOW(_create)(2*(q->m)); // create internal dot product object q->dpq = DOTPROD(_create)(q->hq, q->hq_len); // reset internal state and return object FIRHILB(_reset)(q); return q; } // destroy firhilb object void FIRHILB(_destroy)(FIRHILB() _q) { // destroy window buffers WINDOW(_destroy)(_q->w0); WINDOW(_destroy)(_q->w1); // destroy internal dot product object DOTPROD(_destroy)(_q->dpq); // free coefficients arrays free(_q->h); free(_q->hc); free(_q->hq); // free main object memory free(_q); } // print firhilb object internals void FIRHILB(_print)(FIRHILB() _q) { printf("fir hilbert transform: [%u]\n", _q->h_len); unsigned int i; for (i=0; i<_q->h_len; i++) { printf(" hc(%4u) = %8.4f + j*%8.4f;\n", i+1, crealf(_q->hc[i]), cimagf(_q->hc[i])); } printf("---\n"); for (i=0; i<_q->h_len; i++) { printf(" h(%4u) = %8.4f;\n", i+1, _q->h[i]); } printf("---\n"); for (i=0; i<_q->hq_len; i++) { printf(" hq(%4u) = %8.4f;\n", i+1, _q->hq[i]); } } // reset firhilb object internal state void FIRHILB(_reset)(FIRHILB() _q) { // clear window buffers WINDOW(_reset)(_q->w0); WINDOW(_reset)(_q->w1); // reset toggle flag _q->toggle = 0; } // execute Hilbert transform (real to complex) // _q : firhilb object // _x : real-valued input sample // _y : complex-valued output sample void FIRHILB(_r2c_execute)(FIRHILB() _q, T _x, T complex * _y) { T * r; // buffer read pointer T yi; // in-phase component T yq; // quadrature component if ( _q->toggle == 0 ) { // push sample into upper branch WINDOW(_push)(_q->w0, _x); // upper branch (delay) WINDOW(_index)(_q->w0, _q->m-1, &yi); // lower branch (filter) WINDOW(_read)(_q->w1, &r); // execute dotprod DOTPROD(_execute)(_q->dpq, r, &yq); } else { // push sample into lower branch WINDOW(_push)(_q->w1, _x); // upper branch (delay) WINDOW(_index)(_q->w1, _q->m-1, &yi); // lower branch (filter) WINDOW(_read)(_q->w0, &r); // execute dotprod DOTPROD(_execute)(_q->dpq, r, &yq); } // toggle flag _q->toggle = 1 - _q->toggle; // set return value *_y = yi + _Complex_I * yq; } // execute Hilbert transform (complex to real) // _q : firhilb object // _y : complex-valued input sample // _x : real-valued output sample void FIRHILB(_c2r_execute)(FIRHILB() _q, T complex _x, T * _y) { *_y = crealf(_x); } // execute Hilbert transform decimator (real to complex) // _q : firhilb object // _x : real-valued input array [size: 2 x 1] // _y : complex-valued output sample void FIRHILB(_decim_execute)(FIRHILB() _q, T * _x, T complex * _y) { T * r; // buffer read pointer T yi; // in-phase component T yq; // quadrature component // compute quadrature component (filter branch) WINDOW(_push)(_q->w1, _x[0]); WINDOW(_read)(_q->w1, &r); DOTPROD(_execute)(_q->dpq, r, &yq); WINDOW(_push)(_q->w0, _x[1]); WINDOW(_index)(_q->w0, _q->m-1, &yi); // set return value *_y = yi + _Complex_I * yq; } // execute Hilbert transform decimator (real to complex) on // a block of samples // _q : Hilbert transform object // _x : real-valued input array [size: 2*_n x 1] // _n : number of *output* samples // _y : complex-valued output array [size: _n x 1] void FIRHILB(_decim_execute_block)(FIRHILB() _q, T * _x, unsigned int _n, T complex * _y) { unsigned int i; for (i=0; i<_n; i++) FIRHILB(_decim_execute)(_q, &_x[2*i], &_y[i]); } // execute Hilbert transform interpolator (complex to real) // _q : firhilb object // _y : complex-valued input sample // _x : real-valued output array [size: 2 x 1] void FIRHILB(_interp_execute)(FIRHILB() _q, T complex _x, T * _y) { T * r; // buffer read pointer // TODO macro for crealf, cimagf? WINDOW(_push)(_q->w0, cimagf(_x)); WINDOW(_index)(_q->w0, _q->m-1, &_y[0]); // compute second branch (filter) WINDOW(_push)(_q->w1, crealf(_x)); WINDOW(_read)(_q->w1, &r); DOTPROD(_execute)(_q->dpq, r, &_y[1]); } // execute Hilbert transform interpolator (complex to real) // on a block of samples // _q : Hilbert transform object // _x : complex-valued input array [size: _n x 1] // _n : number of *input* samples // _y : real-valued output array [size: 2*_n x 1] void FIRHILB(_interp_execute_block)(FIRHILB() _q, T complex * _x, unsigned int _n, T * _y) { unsigned int i; for (i=0; i<_n; i++) FIRHILB(_interp_execute)(_q, _x[i], &_y[2*i]); } liquid-dsp-1.3.1/src/filter/src/firinterp.c000066400000000000000000000164751317124540100206130ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Interpolator // #include #include #include struct FIRINTERP(_s) { TC * h; // prototype filter coefficients unsigned int h_len; // prototype filter length unsigned int h_sub_len; // sub-filter length unsigned int M; // interpolation factor FIRPFB() filterbank; // polyphase filterbank object }; // create interpolator // _M : interpolation factor // _h : filter coefficients array [size: _h_len x 1] // _h_len : filter length FIRINTERP() FIRINTERP(_create)(unsigned int _M, TC * _h, unsigned int _h_len) { // validate input if (_M < 2) { fprintf(stderr,"error: firinterp_%s_create(), interp factor must be greater than 1\n", EXTENSION_FULL); exit(1); } else if (_h_len < _M) { fprintf(stderr,"error: firinterp_%s_create(), filter length cannot be less than interp factor\n", EXTENSION_FULL); exit(1); } // allocate main object memory and set internal parameters FIRINTERP() q = (FIRINTERP()) malloc(sizeof(struct FIRINTERP(_s))); q->M = _M; q->h_len = _h_len; // compute sub-filter length q->h_sub_len=0; while (q->M * q->h_sub_len < _h_len) q->h_sub_len++; // compute effective filter length (pad end of prototype with zeros) q->h_len = q->M * q->h_sub_len; q->h = (TC*) malloc((q->h_len)*sizeof(TC)); // load filter coefficients in regular order, padding end with zeros unsigned int i; for (i=0; ih_len; i++) q->h[i] = i < _h_len ? _h[i] : 0.0f; // create polyphase filterbank q->filterbank = FIRPFB(_create)(q->M, q->h, q->h_len); // return interpolator object return q; } // create interpolator from Kaiser prototype // _M : interpolation factor // _m : symbol delay // _As : stop-band attenuation [dB] FIRINTERP() FIRINTERP(_create_kaiser)(unsigned int _M, unsigned int _m, float _As) { // validate input if (_M < 2) { fprintf(stderr,"error: firinterp_%s_create_kaiser(), interp factor must be greater than 1\n", EXTENSION_FULL); exit(1); } else if (_m == 0) { fprintf(stderr,"error: firinterp_%s_create_kaiser(), filter delay must be greater than 0\n", EXTENSION_FULL); exit(1); } else if (_As < 0.0f) { fprintf(stderr,"error: firinterp_%s_create_kaiser(), stop-band attenuation must be positive\n", EXTENSION_FULL); exit(1); } // compute filter coefficients (floating point precision) unsigned int h_len = 2*_M*_m + 1; float hf[h_len]; float fc = 0.5f / (float) (_M); liquid_firdes_kaiser(h_len, fc, _As, 0.0f, hf); // copy coefficients to type-specific array (e.g. float complex) TC hc[h_len]; unsigned int i; for (i=0; i 1 // _m : filter delay (symbols), _m > 0 // _beta : excess bandwidth factor, _beta < 1 // _dt : fractional sample delay, _dt in (-1, 1) FIRINTERP() FIRINTERP(_create_prototype)(int _type, unsigned int _k, unsigned int _m, float _beta, float _dt) { // validate input if (_k < 2) { fprintf(stderr,"error: firinterp_%s_create_prototype(), interp factor must be greater than 1\n", EXTENSION_FULL); exit(1); } else if (_m == 0) { fprintf(stderr,"error: firinterp_%s_create_prototype(), filter delay must be greater than 0\n", EXTENSION_FULL); exit(1); } else if (_beta < 0.0f || _beta > 1.0f) { fprintf(stderr,"error: firinterp_%s_create_prototype(), filter excess bandwidth factor must be in [0,1]\n", EXTENSION_FULL); exit(1); } else if (_dt < -1.0f || _dt > 1.0f) { fprintf(stderr,"error: firinterp_%s_create_prototype(), filter fractional sample delay must be in [-1,1]\n", EXTENSION_FULL); exit(1); } // generate Nyquist filter unsigned int h_len = 2*_k*_m + 1; float h[h_len]; liquid_firdes_prototype(_type,_k,_m,_beta,_dt,h); // copy coefficients to type-specific array (e.g. float complex) unsigned int i; TC hc[h_len]; for (i=0; ifilterbank); free(_q->h); free(_q); } // print interpolator state void FIRINTERP(_print)(FIRINTERP() _q) { printf("interp():\n"); printf(" M : %u\n", _q->M); printf(" h_len : %u\n", _q->h_len); FIRPFB(_print)(_q->filterbank); } // clear internal state void FIRINTERP(_reset)(FIRINTERP() _q) { FIRPFB(_reset)(_q->filterbank); } // execute interpolator // _q : interpolator object // _x : input sample // _y : output array [size: 1 x _M] void FIRINTERP(_execute)(FIRINTERP() _q, TI _x, TO * _y) { // push sample into filterbank FIRPFB(_push)(_q->filterbank, _x); // compute output for each filter in the bank unsigned int i; for (i=0; i<_q->M; i++) FIRPFB(_execute)(_q->filterbank, i, &_y[i]); } // execute interpolation on block of input samples // _q : firinterp object // _x : input array [size: _n x 1] // _n : size of input array // _y : output sample array [size: _M*_n x 1] void FIRINTERP(_execute_block)(FIRINTERP() _q, TI * _x, unsigned int _n, TO * _y) { unsigned int i; for (i=0; i<_n; i++) { // execute one input at a time with an output stride _M FIRINTERP(_execute)(_q, _x[i], &_y[i*_q->M]); } } liquid-dsp-1.3.1/src/filter/src/firpfb.c000066400000000000000000000300211317124540100200400ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2016 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // FIR Polyphase filter bank // #include #include #include struct FIRPFB(_s) { TC * h; // filter coefficients array unsigned int h_len; // total number of filter coefficients unsigned int h_sub_len; // sub-sampled filter length unsigned int num_filters; // number of filters WINDOW() w; // window buffer DOTPROD() * dp; // array of vector dot product objects TC scale; // output scaling factor }; // create firpfb from external coefficients // _M : number of filters in the bank // _h : coefficients [size: _M*_h_len x 1] // _h_len : filter delay (symbols) FIRPFB() FIRPFB(_create)(unsigned int _M, TC * _h, unsigned int _h_len) { // validate input if (_M == 0) { fprintf(stderr,"error: firpfb_%s_create(), number of filters must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_h_len == 0) { fprintf(stderr,"error: firpfb_%s_create(), filter length must be greater than zero\n", EXTENSION_FULL); exit(1); } // create main filter object FIRPFB() q = (FIRPFB()) malloc(sizeof(struct FIRPFB(_s))); // set user-defined parameters q->num_filters = _M; q->h_len = _h_len; // each filter is realized as a dotprod object q->dp = (DOTPROD()*) malloc((q->num_filters)*sizeof(DOTPROD())); // generate bank of sub-samped filters // length of each sub-sampled filter unsigned int h_sub_len = _h_len / q->num_filters; TC h_sub[h_sub_len]; unsigned int i, n; for (i=0; inum_filters; i++) { for (n=0; nnum_filters)]; } // create dot product object q->dp[i] = DOTPROD(_create)(h_sub,h_sub_len); } // save sub-sampled filter length q->h_sub_len = h_sub_len; // create window buffer q->w = WINDOW(_create)(q->h_sub_len); // set default scaling q->scale = 1; // reset object and return FIRPFB(_reset)(q); return q; } // create firpfb using kaiser window // _M : number of filters in the bank // _m : filter semi-length [samples] // _fc : filter cut-off frequency 0 < _fc < 0.5 // _As : filter stop-band suppression [dB] FIRPFB() FIRPFB(_create_kaiser)(unsigned int _M, unsigned int _m, float _fc, float _As) { // validate input if (_M == 0) { fprintf(stderr,"error: firpfb_%s_create_kaiser(), number of filters must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_m == 0) { fprintf(stderr,"error: firpfb_%s_create_kaiser(), filter delay must be greater than 0\n", EXTENSION_FULL); exit(1); } else if (_fc < 0.0f || _fc > 0.5f) { fprintf(stderr,"error: firpfb_%s_create_kaiser(), filter cut-off frequence must be in (0,0.5)\n", EXTENSION_FULL); exit(1); } else if (_As < 0.0f) { fprintf(stderr,"error: firpfb_%s_create_kaiser(), filter excess bandwidth factor must be in [0,1]\n", EXTENSION_FULL); exit(1); } // design filter using kaiser window unsigned int H_len = 2*_M*_m + 1; float Hf[H_len]; liquid_firdes_kaiser(H_len, _fc/(float)_M, _As, 0.0f, Hf); // copy coefficients to type-specific array (e.g. float complex) unsigned int i; TC Hc[H_len]; for (i=0; i 1 // _m : filter delay (symbols), _m > 0 // _beta : excess bandwidth factor, 0 < _beta < 1 FIRPFB() FIRPFB(_create_rnyquist)(int _type, unsigned int _M, unsigned int _k, unsigned int _m, float _beta) { // validate input if (_M == 0) { fprintf(stderr,"error: firpfb_%s_create_rnyquist(), number of filters must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_k < 2) { fprintf(stderr,"error: firpfb_%s_create_rnyquist(), filter samples/symbol must be greater than 1\n", EXTENSION_FULL); exit(1); } else if (_m == 0) { fprintf(stderr,"error: firpfb_%s_create_rnyquist(), filter delay must be greater than 0\n", EXTENSION_FULL); exit(1); } else if (_beta < 0.0f || _beta > 1.0f) { fprintf(stderr,"error: firpfb_%s_create_rnyquist(), filter excess bandwidth factor must be in [0,1]\n", EXTENSION_FULL); exit(1); } // generate square-root Nyquist filter unsigned int H_len = 2*_M*_k*_m + 1; float Hf[H_len]; liquid_firdes_prototype(_type,_M*_k,_m,_beta,0,Hf); // copy coefficients to type-specific array (e.g. float complex) unsigned int i; TC Hc[H_len]; for (i=0; i 1 // _m : filter delay (symbols), _m > 0 // _beta : excess bandwidth factor, 0 < _beta < 1 FIRPFB() FIRPFB(_create_drnyquist)(int _type, unsigned int _M, unsigned int _k, unsigned int _m, float _beta) { // validate input if (_M == 0) { fprintf(stderr,"error: firpfb_%s_create_drnyquist(), number of filters must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_k < 2) { fprintf(stderr,"error: firpfb_%s_create_drnyquist(), filter samples/symbol must be greater than 1\n", EXTENSION_FULL); exit(1); } else if (_m == 0) { fprintf(stderr,"error: firpfb_%s_create_drnyquist(), filter delay must be greater than 0\n", EXTENSION_FULL); exit(1); } else if (_beta < 0.0f || _beta > 1.0f) { fprintf(stderr,"error: firpfb_%s_create_drnyquist(), filter excess bandwidth factor must be in [0,1]\n", EXTENSION_FULL); exit(1); } // generate square-root Nyquist filter unsigned int H_len = 2*_M*_k*_m + 1; float Hf[H_len]; liquid_firdes_prototype(_type,_M*_k,_m,_beta,0,Hf); // compute derivative filter float dHf[H_len]; float HdH_max = 0.0f; unsigned int i; for (i=0; i HdH_max ) HdH_max = fabsf(Hf[i]*dHf[i]); } // copy coefficients to type-specific array (e.g. float complex) // and apply scaling factor for normalized response TC Hc[H_len]; for (i=0; ih_len || _M != _q->num_filters) { // filter length has changed: recreate entire filter FIRPFB(_destroy)(_q); _q = FIRPFB(_create)(_M,_h,_h_len); return _q; } // re-create each dotprod object TC h_sub[_q->h_sub_len]; unsigned int i, n; for (i=0; i<_q->num_filters; i++) { for (n=0; n<_q->h_sub_len; n++) { // load filter in reverse order h_sub[_q->h_sub_len-n-1] = _h[i + n*(_q->num_filters)]; } _q->dp[i] = DOTPROD(_recreate)(_q->dp[i],h_sub,_q->h_sub_len); } return _q; } // destroy firpfb object, freeing all internal memory void FIRPFB(_destroy)(FIRPFB() _q) { unsigned int i; for (i=0; i<_q->num_filters; i++) DOTPROD(_destroy)(_q->dp[i]); free(_q->dp); WINDOW(_destroy)(_q->w); free(_q); } // print firpfb object's parameters void FIRPFB(_print)(FIRPFB() _q) { printf("fir polyphase filterbank [%u] :\n", _q->num_filters); unsigned int i,n; for (i=0; i<_q->num_filters; i++) { printf(" bank %3u: ",i); for (n=0; n<_q->h_len; n++) { //printf("%6.4f+j%6.4f ", crealf(_q->dp[i]->h[n]), cimagf(_q->dp[i]->h[n])); } printf("\n"); } } // clear/reset firpfb object internal state void FIRPFB(_reset)(FIRPFB() _q) { WINDOW(_reset)(_q->w); } // set output scaling for filter void FIRPFB(_set_scale)(FIRPFB() _q, TC _scale) { _q->scale = _scale; } // push sample into firpfb internal buffer void FIRPFB(_push)(FIRPFB() _q, TI _x) { // push value into window buffer WINDOW(_push)(_q->w, _x); } // execute the filter on internal buffer and coefficients // _q : firpfb object // _i : index of filter to use // _y : pointer to output sample void FIRPFB(_execute)(FIRPFB() _q, unsigned int _i, TO * _y) { // validate input if (_i >= _q->num_filters) { fprintf(stderr,"error: firpfb_execute(), filterbank index (%u) exceeds maximum (%u)\n", _i, _q->num_filters); exit(1); } // read buffer TI *r; WINDOW(_read)(_q->w, &r); // execute dot product DOTPROD(_execute)(_q->dp[_i], r, _y); // apply scaling factor *_y *= _q->scale; } // execute the filter on a block of input samples; the // input and output buffers may be the same // _q : firpfb object // _i : index of filter to use // _x : pointer to input array [size: _n x 1] // _n : number of input, output samples // _y : pointer to output array [size: _n x 1] void FIRPFB(_execute_block)(FIRPFB() _q, unsigned int _i, TI * _x, unsigned int _n, TO * _y) { unsigned int i; for (i=0; i<_n; i++) { // push sample into filter FIRPFB(_push)(_q, _x[i]); // compute output at appropriate index FIRPFB(_execute)(_q, _i, &_y[i]); } } liquid-dsp-1.3.1/src/filter/src/fnyquist.c000066400000000000000000000256551317124540100204730ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Flipped Nyquist/root-Nyquist filter designs // // References: // [Beaulieu:2001] // [Assalini:2004] // #include #include #include #include #include "liquid.internal.h" // Design flipped Nyquist/root-Nyquist filter // _type : filter type (e.g. LIQUID_FIRFILT_FEXP) // _root : square-root Nyquist filter? // _k : samples/symbol // _m : symbol delay // _beta : rolloff factor (0 < beta <= 1) // _dt : fractional sample delay // _h : output coefficient buffer (length: 2*k*m+1) void liquid_firdes_fnyquist(liquid_firfilt_type _type, int _root, unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h) { // validate input if ( _k < 1 ) { fprintf(stderr,"error: liquid_firdes_fnyquist(): k must be greater than 0\n"); exit(1); } else if ( _m < 1 ) { fprintf(stderr,"error: liquid_firdes_fnyquist(): m must be greater than 0\n"); exit(1); } else if ( (_beta < 0.0f) || (_beta > 1.0f) ) { fprintf(stderr,"error: liquid_firdes_fnyquist(): beta must be in [0,1]\n"); exit(1); } else; unsigned int i; // derived values unsigned int h_len = 2*_k*_m+1; // filter length float H_prime[h_len]; // frequency response of Nyquist filter (real) float complex H[h_len]; // frequency response of Nyquist filter float complex h[h_len]; // impulse response of Nyquist filter // compute Nyquist filter frequency response switch (_type) { case LIQUID_FIRFILT_FEXP: liquid_firdes_fexp_freqresponse(_k, _m, _beta, H_prime); break; case LIQUID_FIRFILT_FSECH: liquid_firdes_fsech_freqresponse(_k, _m, _beta, H_prime); break; case LIQUID_FIRFILT_FARCSECH: liquid_firdes_farcsech_freqresponse(_k, _m, _beta, H_prime); break; default: fprintf(stderr,"error: liquid_firdes_fnyquist(), unknown/unsupported filter type\n"); exit(1); } // copy result to fft input buffer, computing square root // if required for (i=0; i 0.5f) f = f - 1.0f; // enforce even symmetry f = fabsf(f); if ( f < f0 ) { // pass band _H[i] = 1.0f; } else if (f > f0 && f < f2) { // transition band if ( f < f1) { _H[i] = expf(gamma*(B*(1-_beta) - f)); } else { _H[i] = 1.0f - expf(gamma*(f - (1+_beta)*B)); } } else { // stop band _H[i] = 0.0f; } } } // Design fsech Nyquist filter // _k : samples/symbol // _m : symbol delay // _beta : rolloff factor (0 < beta <= 1) // _dt : fractional sample delay // _h : output coefficient buffer (length: 2*k*m+1) void liquid_firdes_fsech(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h) { // compute resonse using generic function liquid_firdes_fnyquist(LIQUID_FIRFILT_FSECH, 0, _k, _m, _beta, _dt, _h); } // Design fsech square-root Nyquist filter // _k : samples/symbol // _m : symbol delay // _beta : rolloff factor (0 < beta <= 1) // _dt : fractional sample delay // _h : output coefficient buffer (length: 2*k*m+1) void liquid_firdes_rfsech(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h) { // compute resonse using generic function liquid_firdes_fnyquist(LIQUID_FIRFILT_FSECH, 1, _k, _m, _beta, _dt, _h); } // flipped exponential frequency response void liquid_firdes_fsech_freqresponse(unsigned int _k, unsigned int _m, float _beta, float * _H) { // TODO : validate input unsigned int i; unsigned int h_len = 2*_k*_m + 1; float f0 = 0.5f*(1.0f - _beta) / (float)_k; float f1 = 0.5f*(1.0f ) / (float)_k; float f2 = 0.5f*(1.0f + _beta) / (float)_k; float B = 0.5f/(float)_k; float gamma = logf(sqrtf(3.0f) + 2.0f) / (_beta*B); // compute frequency response of Nyquist filter for (i=0; i 0.5f) f = f - 1.0f; // enforce even symmetry f = fabsf(f); if ( f < f0 ) { // pass band _H[i] = 1.0f; } else if (f > f0 && f < f2) { // transition band if ( f < f1) { _H[i] = 1.0f / coshf(gamma*(f - B*(1-_beta))); } else { _H[i] = 1.0f - 1.0f / coshf(gamma*(B*(1+_beta) - f)); } } else { // stop band _H[i] = 0.0f; } } } // Design farcsech Nyquist filter // _k : samples/symbol // _m : symbol delay // _beta : rolloff factor (0 < beta <= 1) // _dt : fractional sample delay // _h : output coefficient buffer (length: 2*k*m+1) void liquid_firdes_farcsech(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h) { // compute resonse using generic function liquid_firdes_fnyquist(LIQUID_FIRFILT_FARCSECH, 0, _k, _m, _beta, _dt, _h); } // Design farcsech square-root Nyquist filter // _k : samples/symbol // _m : symbol delay // _beta : rolloff factor (0 < beta <= 1) // _dt : fractional sample delay // _h : output coefficient buffer (length: 2*k*m+1) void liquid_firdes_rfarcsech(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h) { // compute resonse using generic function liquid_firdes_fnyquist(LIQUID_FIRFILT_FARCSECH, 1, _k, _m, _beta, _dt, _h); } // hyperbolic arc-secant float liquid_asechf(float _z) { if (_z <= 0.0f || _z > 1.0f) { fprintf(stderr,"warning: liquid_asechf(), input out of range\n"); return 0.0f; } float z_inv = 1.0f / _z; return logf( sqrtf(z_inv - 1.0f)*sqrtf(z_inv + 1.0f) + z_inv ); } // flipped exponential frequency response void liquid_firdes_farcsech_freqresponse(unsigned int _k, unsigned int _m, float _beta, float * _H) { // TODO : validate input unsigned int i; unsigned int h_len = 2*_k*_m + 1; float f0 = 0.5f*(1.0f - _beta) / (float)_k; float f1 = 0.5f*(1.0f ) / (float)_k; float f2 = 0.5f*(1.0f + _beta) / (float)_k; float B = 0.5f/(float)_k; float gamma = logf(sqrtf(3.0f) + 2.0f) / (_beta*B); float zeta = 1.0f / (2.0f * _beta * B); // compute frequency response of Nyquist filter for (i=0; i 0.5f) f = f - 1.0f; // enforce even symmetry f = fabsf(f); if ( f < f0 ) { // pass band _H[i] = 1.0f; } else if (f > f0 && f < f2) { // transition band if ( f < f1) { _H[i] = 1.0f - (zeta/gamma)*liquid_asechf(zeta*(B*(1+_beta) - f)); } else { _H[i] = (zeta/gamma)*liquid_asechf(zeta*(f - B*(1-_beta))); } } else { // stop band _H[i] = 0.0f; } } } liquid-dsp-1.3.1/src/filter/src/gmsk.c000066400000000000000000000156751317124540100175530ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Finite impulse response GMSK transmit/receive filter design // #include #include #include #include #include "liquid.internal.h" // Design GMSK transmit filter // _k : samples/symbol // _m : symbol delay // _beta : rolloff factor (0 < beta <= 1) // _dt : fractional sample delay // _h : output coefficient buffer (length: 2*k*m+1) void liquid_firdes_gmsktx(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h) { // validate input if ( _k < 1 ) { fprintf(stderr,"error: liquid_firdes_gmsktx(): k must be greater than 0\n"); exit(1); } else if ( _m < 1 ) { fprintf(stderr,"error: liquid_firdes_gmsktx(): m must be greater than 0\n"); exit(1); } else if ( (_beta < 0.0f) || (_beta > 1.0f) ) { fprintf(stderr,"error: liquid_firdes_gmsktx(): beta must be in [0,1]\n"); exit(1); } else; // derived values unsigned int h_len = 2*_k*_m+1; // compute filter coefficients unsigned int i; float t; float c0 = 1.0f / sqrtf(logf(2.0f)); for (i=0; i 1.0f) ) { fprintf(stderr,"error: liquid_firdes_gmskrx(): beta must be in [0,1]\n"); exit(1); } else; unsigned int k = _k; unsigned int m = _m; float BT = _beta; // internal options float beta = BT; // prototype filter cut-off float delta = 1e-3f; // filter design correction factor liquid_firfilt_type prototype = LIQUID_FIRFILT_KAISER; // Nyquist prototype unsigned int i; // derived values unsigned int h_len = 2*k*m+1; // filter length // arrays float ht[h_len]; // transmit filter coefficients float hr[h_len]; // recieve filter coefficients // design transmit filter liquid_firdes_gmsktx(k,m,BT,0.0f,ht); // // start of filter design procedure // // 'internal' arrays float h_primef[h_len]; // temporary buffer for real 'prototype' coefficients float g_primef[h_len]; // temporary buffer for real 'gain' coefficient float complex h_tx[h_len]; // impulse response of transmit filter float complex h_prime[h_len]; // impulse response of 'prototype' filter float complex g_prime[h_len]; // impulse response of 'gain' filter float complex h_hat[h_len]; // impulse response of receive filter float complex H_tx[h_len]; // frequency response of transmit filter float complex H_prime[h_len]; // frequency response of 'prototype' filter float complex G_prime[h_len]; // frequency response of 'gain' filter float complex H_hat[h_len]; // frequency response of receive filter // create 'prototype' matched filter liquid_firdes_prototype(prototype,k,m,beta,0.0f,h_primef); // create 'gain' filter to improve stop-band rejection float fc = (0.7f + 0.1*beta) / (float)k; float As = 60.0f; liquid_firdes_kaiser(h_len, fc, As, 0.0f, g_primef); // copy to fft input buffer, shifting appropriately for (i=0; i #include #include #include "liquid.internal.h" // Compute group delay for a FIR filter // _h : filter coefficients array [size: _n x 1] // _n : filter length // _fc : frequency at which delay is evaluated (-0.5 < _fc < 0.5) float fir_group_delay(float * _h, unsigned int _n, float _fc) { // validate input if (_n == 0) { fprintf(stderr,"error: fir_group_delay(), length must be greater than zero\n"); exit(1); } else if (_fc < -0.5 || _fc > 0.5) { fprintf(stderr,"error: fir_group_delay(), _fc must be in [-0.5,0.5]\n"); exit(1); } unsigned int i; float complex t0=0.0f; float complex t1=0.0f; for (i=0; i<_n; i++) { t0 += _h[i] * cexpf(_Complex_I*2*M_PI*_fc*i) * i; t1 += _h[i] * cexpf(_Complex_I*2*M_PI*_fc*i); } return crealf(t0/t1); } // Compute group delay for an IIR filter // _b : filter coefficients array (numerator), [size: _nb x 1] // _nb : filter length (numerator) // _a : filter coefficients array (denominator), [size: _na x 1] // _na : filter length (denominator) // _fc : frequency at which delay is evaluated (-0.5 < _fc < 0.5) float iir_group_delay(float * _b, unsigned int _nb, float * _a, unsigned int _na, float _fc) { // validate input if (_nb == 0) { fprintf(stderr,"error: iir_group_delay(), numerator length must be greater than zero\n"); exit(1); } else if (_na == 0) { fprintf(stderr,"error: iir_group_delay(), denominator length must be greater than zero\n"); exit(1); } else if (_fc < -0.5 || _fc > 0.5) { fprintf(stderr,"error: iir_group_delay(), _fc must be in [-0.5,0.5]\n"); exit(1); } // compute c = conv(b,fliplr(a)) // c(z) = b(z)*a(1/z)*z^(-_na) unsigned int nc = _na + _nb - 1; float c[nc]; unsigned int i,j; for (i=0; i #include #include #include #include "liquid.internal.h" #define DEBUG_hM3 0 // Design root-Nyquist harris-Moerder filter using Parks-McClellan // algorithm // // _k : filter over-sampling rate (samples/symbol) // _m : filter delay (symbols) // _beta : filter excess bandwidth factor (0,1) // _dt : filter fractional sample delay // _h : resulting filter [size: 2*_k*_m+1] void liquid_firdes_hM3(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h) { if ( _k < 2 ) { fprintf(stderr,"error: liquid_firdes_hM3(): k must be greater than 1\n"); exit(1); } else if ( _m < 1 ) { fprintf(stderr,"error: liquid_firdes_hM3(): m must be greater than 0\n"); exit(1); } else if ( (_beta < 0.0f) || (_beta > 1.0f) ) { fprintf(stderr,"error: liquid_firdes_hM3(): beta must be in [0,1]\n"); exit(1); } else; unsigned int n=2*_k*_m+1; // filter length // float fc = 1.0 / (float)(2*_k); // filter cutoff float fp = fc*(1.0 - _beta); // pass-band float fs = fc*(1.0 + _beta); // stop-band // root nyquist unsigned int num_bands = 3; float bands[6] = {0.0f, fp, fc, fc, fs, 0.5f}; float des[3] = {1.0f, 1.0f/sqrtf(2.0f), 0.0f}; float weights[3] = {1.0f, 1.0f, 1.0f}; liquid_firdespm_btype btype = LIQUID_FIRDESPM_BANDPASS; liquid_firdespm_wtype wtype[3] = {LIQUID_FIRDESPM_FLATWEIGHT, LIQUID_FIRDESPM_FLATWEIGHT, LIQUID_FIRDESPM_EXPWEIGHT}; //unsigned int i; float h[n]; firdespm_run(n,num_bands,bands,des,weights,wtype,btype,h); // copy results memmove(_h, h, n*sizeof(float)); float isi_max; float isi_rms; liquid_filter_isi(h,_k,_m,&isi_rms,&isi_max); // iterate... float isi_rms_min = isi_rms; unsigned int p, pmax=100; for (p=0; p isi_rms_min) { // search complete break; } else { isi_rms_min = isi_rms; // copy results memmove(_h, h, n*sizeof(float)); } }; // normalize float e2 = 0.0f; unsigned int i; for (i=0; i #include #include // decimator structure struct IIRDECIM(_s) { unsigned int M; // decimation factor // TODO: use IIR polyphase filterbank IIRFILT() iirfilt; // filter object }; // create interpolator from external coefficients // _M : interpolation factor // _b : feed-back coefficients [size: _nb x 1] // _nb : feed-back coefficients length // _a : feed-forward coefficients [size: _na x 1] // _na : feed-forward coefficients length IIRDECIM() IIRDECIM(_create)(unsigned int _M, TC * _b, unsigned int _nb, TC * _a, unsigned int _na) { // validate input if (_M < 2) { fprintf(stderr,"error: iirinterp_%s_create(), interp factor must be greater than 1\n", EXTENSION_FULL); exit(1); } // allocate main object memory and set internal parameters IIRDECIM() q = (IIRDECIM()) malloc(sizeof(struct IIRDECIM(_s))); q->M = _M; // create filter q->iirfilt = IIRFILT(_create)(_b, _nb, _a, _na); // return interpolator object return q; } // create decimator with default Butterworth prototype // _M : decimation factor // _order : filter order IIRDECIM() IIRDECIM(_create_default)(unsigned int _M, unsigned int _order) { return IIRDECIM(_create_prototype)(_M, LIQUID_IIRDES_BUTTER, LIQUID_IIRDES_LOWPASS, LIQUID_IIRDES_SOS, _order, 0.5f / (float)_M, // fc 0.0f, // f0 0.1f, // pass-band ripple, 60.0f); // stop-band attenuation } // create interpolator from prototype // _M : interpolation factor IIRDECIM() IIRDECIM(_create_prototype)(unsigned int _M, liquid_iirdes_filtertype _ftype, liquid_iirdes_bandtype _btype, liquid_iirdes_format _format, unsigned int _order, float _fc, float _f0, float _Ap, float _As) { // validate input if (_M < 2) { fprintf(stderr,"error: iirinterp_%s_create_prototype(), interp factor must be greater than 1\n", EXTENSION_FULL); exit(1); } // allocate main object memory and set internal parameters IIRDECIM() q = (IIRDECIM()) malloc(sizeof(struct IIRDECIM(_s))); q->M = _M; // create filter q->iirfilt = IIRFILT(_create_prototype)(_ftype, _btype, _format, _order, _fc, _f0, _Ap, _As); // return interpolator object return q; } // destroy interpolator object void IIRDECIM(_destroy)(IIRDECIM() _q) { IIRFILT(_destroy)(_q->iirfilt); free(_q); } // print interpolator state void IIRDECIM(_print)(IIRDECIM() _q) { printf("interp():\n"); printf(" M : %u\n", _q->M); IIRFILT(_print)(_q->iirfilt); } // clear internal state void IIRDECIM(_reset)(IIRDECIM() _q) { IIRFILT(_reset)(_q->iirfilt); } // execute decimator // _q : decimator object // _x : input sample array [size: _M x 1] // _y : output sample pointer // _index : decimator output index [0,_M-1] void IIRDECIM(_execute)(IIRDECIM() _q, TI * _x, TO * _y) { TO v; // output value unsigned int i; for (i=0; i<_q->M; i++) { // run filter IIRFILT(_execute)(_q->iirfilt, _x[i], &v); // save output at appropriate index if (i==0) *_y = v; } } // execute decimator on block of _n*_M input samples // _q : decimator object // _x : input array [size: _n*_M x 1] // _n : number of _output_ samples // _y : output array [_sze: _n x 1] void IIRDECIM(_execute_block)(IIRDECIM() _q, TI * _x, unsigned int _n, TO * _y) { unsigned int i; for (i=0; i<_n; i++) { // execute _M input samples computing just one output each time IIRDECIM(_execute)(_q, &_x[i*_q->M], &_y[i]); } } // get system group delay at frequency _fc // _q : interpolator object // _f : frequency float IIRDECIM(_groupdelay)(IIRDECIM() _q, float _fc) { return IIRFILT(_groupdelay)(_q->iirfilt, _fc); } liquid-dsp-1.3.1/src/filter/src/iirdes.c000066400000000000000000000552611317124540100200640ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // iir (infinite impulse response) filter design // // References // [Constantinides:1967] A. G. Constantinides, "Frequency // Transformations for Digital Filters." IEEE Electronic // Letters, vol. 3, no. 11, pp 487-489, 1967. // #include #include #include #include #include #include "liquid.internal.h" #define LIQUID_IIRDES_DEBUG_PRINT 0 // Sorts array _z of complex numbers into complex conjugate pairs to // within a tolerance. Conjugate pairs are ordered by increasing real // component with the negative imaginary element first. All pure-real // elements are placed at the end of the array. // // Example: // v: liquid_cplxpair(v): // 10 + j*3 -3 - j*4 // 5 + j*0 3 + j*4 // -3 + j*4 10 - j*3 // 10 - j*3 10 + j*3 // 3 + j*0 3 + j*0 // -3 + j*4 5 + j*0 // // _z : complex array (size _n) // _n : number of elements in _z // _tol : tolerance for finding complex pairs // _p : resulting pairs, pure real values of _z at end void liquid_cplxpair(float complex * _z, unsigned int _n, float _tol, float complex * _p) { // validate input if (_tol < 0) { fprintf(stderr,"error: liquid_cplxpair(), tolerance must be positive\n"); exit(1); } // keep track of which elements have been paired unsigned char paired[_n]; memset(paired,0,sizeof(paired)); unsigned int num_pairs=0; unsigned int i,j,k=0; for (i=0; i<_n; i++) { // ignore value if already paired, or if imaginary // component is less than tolerance if (paired[i] || fabsf(cimagf(_z[i])) < _tol) continue; for (j=0; j<_n; j++) { // ignore value if already paired, or if imaginary // component is less than tolerance if (j==i || paired[j] || fabsf(cimagf(_z[j])) < _tol) continue; if ( fabsf(cimagf(_z[i])+cimagf(_z[j])) < _tol && fabsf(crealf(_z[i])-crealf(_z[j])) < _tol ) { // found complex conjugate pair _p[k++] = _z[i]; _p[k++] = _z[j]; paired[i] = 1; paired[j] = 1; num_pairs++; break; } } } assert(k <= _n); // sort through remaining unpaired values and ensure // they are purely real for (i=0; i<_n; i++) { if (paired[i]) continue; if (cimagf(_z[i]) > _tol) { fprintf(stderr,"warning, liquid_cplxpair(), complex numbers cannot be paired\n"); } else { _p[k++] = _z[i]; paired[i] = 1; } } // clean up result // * force pairs to be perfect conjugates with // negative imaginary component first // * complex conjugate pairs are ordered by // increasing real component // * pure-real elements are ordered by increasing // value liquid_cplxpair_cleanup(_p, _n, num_pairs); } // post-process cleanup used with liquid_cplxpair // // once pairs have been identified and ordered, this method // will clean up the result by ensuring the following: // * pairs are perfect conjugates // * pairs have negative imaginary component first // * pairs are ordered by increasing real component // * pure-real elements are ordered by increasing value // // _p : pre-processed complex array [size: _n x 1] // _n : array length // _num_pairs : number of complex conjugate pairs void liquid_cplxpair_cleanup(float complex * _p, unsigned int _n, unsigned int _num_pairs) { unsigned int i; unsigned int j; float complex tmp; // ensure perfect conjugates, with negative imaginary // element coming first for (i=0; i<_num_pairs; i++) { // ensure perfect conjugates _p[2*i+0] = cimagf(_p[2*i]) < 0 ? _p[2*i] : conjf(_p[2*i]); _p[2*i+1] = conjf(_p[2*i+0]); } // sort conjugate pairs for (i=0; i<_num_pairs; i++) { for (j=_num_pairs-1; j>i; j--) { if ( crealf(_p[2*(j-1)]) > crealf(_p[2*j]) ) { // swap pairs tmp = _p[2*(j-1)+0]; _p[2*(j-1)+0] = _p[2*j+0]; _p[2*j +0] = tmp; tmp = _p[2*(j-1)+1]; _p[2*(j-1)+1] = _p[2*j+1]; _p[2*j +1] = tmp; } } } // sort pure-real values for (i=2*_num_pairs; i<_n; i++) { for (j=_n-1; j>i; j--) { if ( crealf(_p[j-1]) > crealf(_p[j]) ) { // swap elements tmp = _p[j-1]; _p[j-1] = _p[j]; _p[j ] = tmp; } } } } // // new IIR design // // Compute frequency pre-warping factor. See [Constantinides:1967] // _btype : band type (e.g. LIQUID_IIRDES_HIGHPASS) // _fc : low-pass cutoff frequency // _f0 : center frequency (band-pass|stop cases only) float iirdes_freqprewarp(liquid_iirdes_bandtype _btype, float _fc, float _f0) { float m = 0.0f; if (_btype == LIQUID_IIRDES_LOWPASS) { // low pass m = tanf(M_PI * _fc); } else if (_btype == LIQUID_IIRDES_HIGHPASS) { // high pass m = -cosf(M_PI * _fc) / sinf(M_PI * _fc); } else if (_btype == LIQUID_IIRDES_BANDPASS) { // band pass m = (cosf(2*M_PI*_fc) - cosf(2*M_PI*_f0) )/ sinf(2*M_PI*_fc); } else if (_btype == LIQUID_IIRDES_BANDSTOP) { // band stop m = sinf(2*M_PI*_fc)/(cosf(2*M_PI*_fc) - cosf(2*M_PI*_f0)); } m = fabsf(m); return m; } // convert analog zeros, poles, gain to digital zeros, poles gain // _za : analog zeros (length: _nza) // _nza : number of analog zeros // _pa : analog poles (length: _npa) // _npa : number of analog poles // _ka : nominal gain (NOTE: this does not necessarily carry over from analog gain) // _m : frequency pre-warping factor // _zd : digital zeros (length: _npa) // _pd : digital poles (length: _npa) // _kd : digital gain // // The filter order is characterized by the number of analog // poles. The analog filter may have up to _npa zeros. // The number of digital zeros and poles is equal to _npa. void bilinear_zpkf(float complex * _za, unsigned int _nza, float complex * _pa, unsigned int _npa, float complex _ka, float _m, float complex * _zd, float complex * _pd, float complex * _kd) { unsigned int i; // filter order is equal to number of analog poles unsigned int n = _npa; float complex G = _ka; // nominal gain for (i=0; i= 0.5) { fprintf(stderr,"error: liquid_iirdes(), cutoff frequency out of range\n"); exit(1); } else if (_f0 < 0 || _f0 > 0.5) { fprintf(stderr,"error: liquid_iirdes(), center frequency out of range\n"); exit(1); } else if (_Ap <= 0) { fprintf(stderr,"error: liquid_iirdes(), pass-band ripple out of range\n"); exit(1); } else if (_As <= 0) { fprintf(stderr,"error: liquid_iirdes(), stop-band ripple out of range\n"); exit(1); } else if (_n == 0) { fprintf(stderr,"error: liquid_iirdes(), filter order must be > 0\n"); exit(1); } // number of analaog poles/zeros unsigned int npa = _n; unsigned int nza; // analog poles/zeros/gain float complex pa[_n]; float complex za[_n]; float complex ka; float complex k0 = 1.0f; // nominal digital gain // derived values unsigned int r = _n%2; // odd/even filter order unsigned int L = (_n-r)/2; // filter semi-length // specific filter variables float epsilon, Gp, Gs, ep, es; // compute zeros and poles of analog prototype switch (_ftype) { case LIQUID_IIRDES_BUTTER: // Butterworth filter design : no zeros, _n poles nza = 0; k0 = 1.0f; butter_azpkf(_n,za,pa,&ka); break; case LIQUID_IIRDES_CHEBY1: // Cheby-I filter design : no zeros, _n poles, pass-band ripple nza = 0; epsilon = sqrtf( powf(10.0f, _Ap / 10.0f) - 1.0f ); k0 = r ? 1.0f : 1.0f / sqrt(1.0f + epsilon*epsilon); cheby1_azpkf(_n,epsilon,za,pa,&ka); break; case LIQUID_IIRDES_CHEBY2: // Cheby-II filter design : _n-r zeros, _n poles, stop-band ripple nza = 2*L; epsilon = powf(10.0f, -_As/20.0f); k0 = 1.0f; cheby2_azpkf(_n,epsilon,za,pa,&ka); break; case LIQUID_IIRDES_ELLIP: // elliptic filter design : _n-r zeros, _n poles, pass/stop-band ripple nza = 2*L; Gp = powf(10.0f, -_Ap / 20.0f); // pass-band gain Gs = powf(10.0f, -_As / 20.0f); // stop-band gain ep = sqrtf(1.0f/(Gp*Gp) - 1.0f); // pass-band epsilon es = sqrtf(1.0f/(Gs*Gs) - 1.0f); // stop-band epsilon k0 = r ? 1.0f : 1.0f / sqrt(1.0f + ep*ep); ellip_azpkf(_n,ep,es,za,pa,&ka); break; case LIQUID_IIRDES_BESSEL: // Bessel filter design : no zeros, _n poles nza = 0; k0 = 1.0f; bessel_azpkf(_n,za,pa,&ka); break; default: fprintf(stderr,"error: liquid_iirdes(), unknown filter type\n"); exit(1); } #if LIQUID_IIRDES_DEBUG_PRINT unsigned int i; printf("poles (analog):\n"); for (i=0; i band-pass trasform iirdes_dzpk_lp2bp(zd, pd, // low-pass prototype zeros, poles _n, // filter order _f0, // center frequency zd1,pd1); // transformed zeros, poles (length: 2*n) // copy transformed zeros, poles memmove(zd, zd1, 2*_n*sizeof(float complex)); memmove(pd, pd1, 2*_n*sizeof(float complex)); // update paramters; filter order doubles which changes the // number of second-order sections and forces there to never // be any remainder (r=0 always). _n = 2*_n; // _n is now even #if LIQUID_IIRDES_DEBUG_PRINT r = _n % 2; // r is now zero L = (_n-r)/2; // L is now the original value of _n #endif } if (_format == LIQUID_IIRDES_TF) { // convert complex digital poles/zeros/gain into transfer // function : H(z) = B(z) / A(z) // where length(B,A) = low/high-pass ? _n + 1 : 2*_n + 1 iirdes_dzpk2tff(zd,pd,_n,kd,_B,_A); #if LIQUID_IIRDES_DEBUG_PRINT // print coefficients for (i=0; i<=_n; i++) printf("b[%3u] = %12.8f;\n", i, _B[i]); for (i=0; i<=_n; i++) printf("a[%3u] = %12.8f;\n", i, _A[i]); #endif } else { // convert complex digital poles/zeros/gain into second- // order sections form : // H(z) = prod { (b0 + b1*z^-1 + b2*z^-2) / (a0 + a1*z^-1 + a2*z^-2) } // where size(B,A) = low|high-pass : [3]x[L+r] // band-pass|stop : [3]x[2*L] iirdes_dzpk2sosf(zd,pd,_n,kd,_B,_A); #if LIQUID_IIRDES_DEBUG_PRINT // print coefficients printf("B [%u x 3] :\n", L+r); for (i=0; i 1.0) return 0; } return 1; } liquid-dsp-1.3.1/src/filter/src/iirdes.pll.c000066400000000000000000000075541317124540100206540ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // 2nd-order iir (infinite impulse response) phase-locked loop filter design // // References: // #include #include #include #include #include #include "liquid.internal.h" // design 2nd-order IIR filter (active lag) // 1 + t2 * s // F(s) = ------------ // 1 + t1 * s // // _w : filter bandwidth // _zeta : damping factor (1/sqrt(2) suggested) // _K : loop gain (1000 suggested) // _b : output feed-forward coefficients [size: 3 x 1] // _a : output feed-back coefficients [size: 3 x 1] void iirdes_pll_active_lag(float _w, float _zeta, float _K, float * _b, float * _a) { // validate input if (_w <= 0.0f) { fprintf(stderr,"error: iirdes_pll_active_lag(), bandwidth must be greater than 0\n"); exit(1); } else if (_zeta <= 0.0f) { fprintf(stderr,"error: iirdes_pll_active_lag(), damping factor must be greater than 0\n"); exit(1); } else if (_K <= 0.0f) { fprintf(stderr,"error: iirdes_pll_active_lag(), gain must be greater than 0\n"); exit(1); } float wn = _w; // natural frequency float t1 = _K/(wn*wn); // float t2 = 2*_zeta/wn - 1/_K; // _b[0] = 2*_K*(1.+t2/2.0f); _b[1] = 2*_K*2.; _b[2] = 2*_K*(1.-t2/2.0f); _a[0] = 1 + t1/2.0f; _a[1] = -t1; _a[2] = -1 + t1/2.0f; } // design 2nd-order IIR filter (active PI) // 1 + t2 * s // F(s) = ------------ // t1 * s // // _w : filter bandwidth // _zeta : damping factor (1/sqrt(2) suggested) // _K : loop gain (1000 suggested) // _b : output feed-forward coefficients [size: 3 x 1] // _a : output feed-back coefficients [size: 3 x 1] void iirdes_pll_active_PI(float _w, float _zeta, float _K, float * _b, float * _a) { // validate input if (_w <= 0.0f) { fprintf(stderr,"error: iirdes_pll_active_PI(), bandwidth must be greater than 0\n"); exit(1); } else if (_zeta <= 0.0f) { fprintf(stderr,"error: iirdes_pll_active_PI(), damping factor must be greater than 0\n"); exit(1); } else if (_K <= 0.0f) { fprintf(stderr,"error: iirdes_pll_active_PI(), gain must be greater than 0\n"); exit(1); } // loop filter (active lag) float wn = _w; // natural frequency float t1 = _K/(wn*wn); // float t2 = 2*_zeta/wn; // _b[0] = 2*_K*(1.+t2/2.0f); _b[1] = 2*_K*2.; _b[2] = 2*_K*(1.-t2/2.0f); _a[0] = t1/2.0f; _a[1] = -t1; _a[2] = t1/2.0f; } liquid-dsp-1.3.1/src/filter/src/iirfilt.c000066400000000000000000000511161317124540100202420ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2017 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // iirfilt : Infinite impulse response filter // // References: // [Pintelon:1990] Rik Pintelon and Johan Schoukens, "Real-Time // Integration and Differentiation of Analog Signals by Means of // Digital Filtering," IEEE Transactions on Instrumentation and // Measurement, vol 39 no. 6, December 1990. // #include #include #include // defined: // IIRFILT() name-mangling macro // TO output type // TC coefficients type // TI input type // WINDOW() window macro // DOTPROD() dotprod macro // PRINTVAL() print macro // use structured dot product? 0:no, 1:yes #define LIQUID_IIRFILT_USE_DOTPROD (1) struct IIRFILT(_s) { TC * b; // numerator (feed-forward coefficients) TC * a; // denominator (feed-back coefficients) TI * v; // internal filter state (buffer) unsigned int n; // filter length (order+1) unsigned int nb; // numerator length unsigned int na; // denominator length // filter structure type enum { IIRFILT_TYPE_NORM=0, IIRFILT_TYPE_SOS } type; #if LIQUID_IIRFILT_USE_DOTPROD DOTPROD() dpb; // numerator dot product DOTPROD() dpa; // denominator dot product #endif // second-order sections IIRFILTSOS() * qsos; // second-order sections filters unsigned int nsos; // number of second-order sections }; // initialize internal objects/arrays void IIRFILT(_init)(IIRFILT() _q) { _q->b = NULL; _q->a = NULL; _q->v = NULL; _q->qsos = NULL; _q->nsos = 0; #if LIQUID_IIRFILT_USE_DOTPROD _q->dpb = NULL; _q->dpa = NULL; #endif } // create iirfilt (infinite impulse response filter) object // _b : numerator, feed-forward coefficients [size: _nb x 1] // _nb : length of numerator // _a : denominator, feed-back coefficients [size: _na x 1] // _na : length of denominator IIRFILT() IIRFILT(_create)(TC * _b, unsigned int _nb, TC * _a, unsigned int _na) { // validate input if (_nb == 0) { fprintf(stderr,"error: iirfilt_%s_create(), numerator length cannot be zero\n", EXTENSION_FULL); exit(1); } else if (_na == 0) { fprintf(stderr,"error: iirfilt_%s_create(), denominator length cannot be zero\n", EXTENSION_FULL); exit(1); } // create structure and initialize IIRFILT() q = (IIRFILT()) malloc(sizeof(struct IIRFILT(_s))); IIRFILT(_init)(q); q->nb = _nb; q->na = _na; q->n = (q->na > q->nb) ? q->na : q->nb; q->type = IIRFILT_TYPE_NORM; // allocate memory for numerator, denominator q->a = (TC *) malloc((q->na)*sizeof(TC)); q->b = (TC *) malloc((q->nb)*sizeof(TC)); // normalize coefficients to _a[0] TC a0 = _a[0]; unsigned int i; #if 0 // read values in reverse order for (i=0; inb; i++) q->b[i] = _b[q->nb - i - 1]; for (i=0; ina; i++) q->a[i] = _a[q->na - i - 1]; #else for (i=0; inb; i++) q->b[i] = _b[i] / a0; for (i=0; ina; i++) q->a[i] = _a[i] / a0; #endif // create buffer and initialize q->v = (TI *) malloc((q->n)*sizeof(TI)); #if LIQUID_IIRFILT_USE_DOTPROD q->dpa = DOTPROD(_create)(q->a+1, q->na-1); q->dpb = DOTPROD(_create)(q->b, q->nb); #endif // reset internal state IIRFILT(_reset)(q); // return iirfilt object return q; } // create iirfilt (infinite impulse response filter) object based // on second-order sections form // _B : numerator, feed-forward coefficients [size: _nsos x 3] // _A : denominator, feed-back coefficients [size: _nsos x 3] // _nsos : number of second-order sections // // NOTE: The number of second-order sections can be computed from the // filter's order, n, as such: // r = n % 2 // L = (n-r)/2 // nsos = L+r IIRFILT() IIRFILT(_create_sos)(TC * _B, TC * _A, unsigned int _nsos) { // validate input if (_nsos == 0) { fprintf(stderr,"error: iirfilt_%s_create_sos(), filter must have at least one 2nd-order section\n", EXTENSION_FULL); exit(1); } // create structure and initialize IIRFILT() q = (IIRFILT()) malloc(sizeof(struct IIRFILT(_s))); IIRFILT(_init)(q); q->type = IIRFILT_TYPE_SOS; q->nsos = _nsos; q->qsos = (IIRFILTSOS()*) malloc( (q->nsos)*sizeof(IIRFILTSOS()) ); q->n = _nsos * 2; // create coefficients array and copy over q->b = (TC *) malloc(3*(q->nsos)*sizeof(TC)); q->a = (TC *) malloc(3*(q->nsos)*sizeof(TC)); memmove(q->b, _B, 3*(q->nsos)*sizeof(TC)); memmove(q->a, _A, 3*(q->nsos)*sizeof(TC)); TC at[3]; TC bt[3]; unsigned int i,k; for (i=0; insos; i++) { for (k=0; k<3; k++) { at[k] = q->a[3*i+k]; bt[k] = q->b[3*i+k]; } q->qsos[i] = IIRFILTSOS(_create)(bt,at); //q->qsos[i] = IIRFILT(_create)(q->b+3*i,3,q->a+3*i,3); } return q; } // create iirfilt (infinite impulse response filter) object based // on prototype // _ftype : filter type (e.g. LIQUID_IIRDES_BUTTER) // _btype : band type (e.g. LIQUID_IIRDES_BANDPASS) // _format : coefficients format (e.g. LIQUID_IIRDES_SOS) // _order : filter order // _fc : low-pass prototype cut-off frequency // _f0 : center frequency (band-pass, band-stop) // _Ap : pass-band ripple in dB // _As : stop-band ripple in dB IIRFILT() IIRFILT(_create_prototype)(liquid_iirdes_filtertype _ftype, liquid_iirdes_bandtype _btype, liquid_iirdes_format _format, unsigned int _order, float _fc, float _f0, float _Ap, float _As) { // derived values : compute filter length unsigned int N = _order; // effective order // filter order effectively doubles for band-pass, band-stop // filters due to doubling the number of poles and zeros as // a result of filter transformation if (_btype == LIQUID_IIRDES_BANDPASS || _btype == LIQUID_IIRDES_BANDSTOP) { N *= 2; } unsigned int r = N%2; // odd/even order unsigned int L = (N-r)/2; // filter semi-length // allocate memory for filter coefficients unsigned int h_len = (_format == LIQUID_IIRDES_SOS) ? 3*(L+r) : N+1; float B[h_len]; float A[h_len]; // design filter (compute coefficients) liquid_iirdes(_ftype, _btype, _format, _order, _fc, _f0, _Ap, _As, B, A); // move coefficients to type-specific arrays (e.g. float complex) TC Bc[h_len]; TC Ac[h_len]; unsigned int i; for (i=0; i= 1.0f) { fprintf(stderr,"error: iirfilt_%s_create_pll(), bandwidth must be in (0,1)\n", EXTENSION_FULL); exit(1); } else if (_zeta <= 0.0f || _zeta >= 1.0f) { fprintf(stderr,"error: iirfilt_%s_create_pll(), damping factor must be in (0,1)\n", EXTENSION_FULL); exit(1); } else if (_K <= 0.0f) { fprintf(stderr,"error: iirfilt_%s_create_pll(), loop gain must be greater than zero\n", EXTENSION_FULL); exit(1); } // compute loop filter coefficients float bf[3]; float af[3]; iirdes_pll_active_lag(_w, _zeta, _K, bf, af); // copy to type-specific array TC b[3]; TC a[3]; b[0] = bf[0]; b[1] = bf[1]; b[2] = bf[2]; a[0] = af[0]; a[1] = af[1]; a[2] = af[2]; // create and return filter object return IIRFILT(_create_sos)(b,a,1); } // destroy iirfilt object void IIRFILT(_destroy)(IIRFILT() _q) { #if LIQUID_IIRFILT_USE_DOTPROD if (_q->dpa != NULL) DOTPROD(_destroy)(_q->dpa); if (_q->dpb != NULL) DOTPROD(_destroy)(_q->dpb); #endif if (_q->b != NULL) free(_q->b); if (_q->a != NULL) free(_q->a); if (_q->v != NULL) free(_q->v); // if filter is comprised of cascaded second-order sections, // delete sub-filters separately if (_q->qsos != NULL) { unsigned int i; for (i=0; i<_q->nsos; i++) IIRFILTSOS(_destroy)(_q->qsos[i]); free(_q->qsos); } // free main object memory free(_q); } // print iirfilt object internals void IIRFILT(_print)(IIRFILT() _q) { printf("iir filter [%s]:\n", _q->type == IIRFILT_TYPE_NORM ? "normal" : "sos"); unsigned int i; if (_q->type == IIRFILT_TYPE_SOS) { for (i=0; i<_q->nsos; i++) IIRFILTSOS(_print)(_q->qsos[i]); } else { printf(" b :"); for (i=0; i<_q->nb; i++) PRINTVAL_TC(_q->b[i],%12.8f); printf("\n"); printf(" a :"); for (i=0; i<_q->na; i++) PRINTVAL_TC(_q->a[i],%12.8f); printf("\n"); #if 0 printf(" v :"); for (i=0; i<_q->n; i++) PRINTVAL(_q->v[i]); printf("\n"); #endif } } // clear/reset iirfilt object internals void IIRFILT(_reset)(IIRFILT() _q) { unsigned int i; if (_q->type == IIRFILT_TYPE_SOS) { // clear second-order sections for (i=0; i<_q->nsos; i++) { IIRFILTSOS(_reset)(_q->qsos[i]); } } else { // set internal buffer to zero for (i=0; i<_q->n; i++) _q->v[i] = 0; } } // execute normal iir filter using traditional numerator/denominator // form (not second-order sections form) // _q : iirfilt object // _x : input sample // _y : output sample void IIRFILT(_execute_norm)(IIRFILT() _q, TI _x, TO *_y) { unsigned int i; // advance buffer for (i=_q->n-1; i>0; i--) _q->v[i] = _q->v[i-1]; #if LIQUID_IIRFILT_USE_DOTPROD // compute new v TI v0; DOTPROD(_execute)(_q->dpa, _q->v+1, &v0); v0 = _x - v0; _q->v[0] = v0; // compute new y DOTPROD(_execute)(_q->dpb, _q->v, _y); #else // compute new v TI v0 = _x; for (i=1; i<_q->na; i++) v0 -= _q->a[i] * _q->v[i]; _q->v[0] = v0; // compute new y TO y0 = 0; for (i=0; i<_q->nb; i++) y0 += _q->b[i] * _q->v[i]; // set return value *_y = y0; #endif } // execute iir filter using second-order sections form // _q : iirfilt object // _x : input sample // _y : output sample void IIRFILT(_execute_sos)(IIRFILT() _q, TI _x, TO * _y) { TI t0 = _x; // intermediate input TO t1 = 0.; // intermediate output unsigned int i; for (i=0; i<_q->nsos; i++) { // run each filter separately IIRFILTSOS(_execute)(_q->qsos[i], t0, &t1); // output for filter n becomes input to filter n+1 t0 = t1; } *_y = t1; } // execute iir filter, switching to type-specific function // _q : iirfilt object // _x : input sample // _y : output sample void IIRFILT(_execute)(IIRFILT() _q, TI _x, TO * _y) { if (_q->type == IIRFILT_TYPE_NORM) IIRFILT(_execute_norm)(_q,_x,_y); else IIRFILT(_execute_sos)(_q,_x,_y); } // execute the filter on a block of input samples; the // input and output buffers may be the same // _q : filter object // _x : pointer to input array [size: _n x 1] // _n : number of input, output samples // _y : pointer to output array [size: _n x 1] void IIRFILT(_execute_block)(IIRFILT() _q, TI * _x, unsigned int _n, TO * _y) { unsigned int i; for (i=0; i<_n; i++) // compute output sample IIRFILT(_execute)(_q, _x[i], &_y[i]); } // get filter length (order + 1) unsigned int IIRFILT(_get_length)(IIRFILT() _q) { return _q->n; } // compute complex frequency response // _q : filter object // _fc : frequency // _H : output frequency response void IIRFILT(_freqresponse)(IIRFILT() _q, float _fc, float complex * _H) { unsigned int i; float complex H = 0.0f; if (_q->type == IIRFILT_TYPE_NORM) { // float complex Ha = 0.0f; float complex Hb = 0.0f; for (i=0; i<_q->nb; i++) Hb += _q->b[i] * cexpf(_Complex_I*2*M_PI*_fc*i); for (i=0; i<_q->na; i++) Ha += _q->a[i] * cexpf(_Complex_I*2*M_PI*_fc*i); // TODO : check to see if we need to take conjugate H = Hb / Ha; } else { H = 1.0f; // compute 3-point DFT for each second-order section for (i=0; i<_q->nsos; i++) { float complex Hb = _q->b[3*i+0] * cexpf(_Complex_I*2*M_PI*_fc*0) + _q->b[3*i+1] * cexpf(_Complex_I*2*M_PI*_fc*1) + _q->b[3*i+2] * cexpf(_Complex_I*2*M_PI*_fc*2); float complex Ha = _q->a[3*i+0] * cexpf(_Complex_I*2*M_PI*_fc*0) + _q->a[3*i+1] * cexpf(_Complex_I*2*M_PI*_fc*1) + _q->a[3*i+2] * cexpf(_Complex_I*2*M_PI*_fc*2); // TODO : check to see if we need to take conjugate H *= Hb / Ha; } } // set return value *_H = H; } // compute group delay in samples // _q : filter object // _fc : frequency float IIRFILT(_groupdelay)(IIRFILT() _q, float _fc) { float groupdelay = 0; unsigned int i; if (_q->type == IIRFILT_TYPE_NORM) { // compute group delay from regular transfer function form // copy coefficients float b[_q->nb]; float a[_q->na]; for (i=0; i<_q->nb; i++) b[i] = crealf(_q->b[i]); for (i=0; i<_q->na; i++) a[i] = crealf(_q->a[i]); groupdelay = iir_group_delay(b, _q->nb, a, _q->na, _fc); } else { // accumulate group delay from second-order sections for (i=0; i<_q->nsos; i++) groupdelay += IIRFILTSOS(_groupdelay)(_q->qsos[i], _fc) - 2; } return groupdelay; } liquid-dsp-1.3.1/src/filter/src/iirfiltsos.c000066400000000000000000000154151317124540100207710ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2017 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Infinite impulse response filter (second-order section) // #include #include #include // defined: // IIRFILTSOS() name-mangling macro // TO output type // TC coefficients type // TI input type // PRINTVAL() print macro(s) // use structured dot product? 0:no, 1:yes #define LIQUID_IIRFILTSOS_USE_DOTPROD (0) struct IIRFILTSOS(_s) { TC b[3]; // feed-forward coefficients TC a[3]; // feed-back coefficients // internal buffering TI x[3]; // Direct form I buffer (input) TO y[3]; // Direct form I buffer (output) TO v[3]; // Direct form II buffer #if LIQUID_IIRFILTSOS_USE_DOTPROD DOTPROD() dpb; // numerator dot product DOTPROD() dpa; // denominator dot product #endif }; // create iirfiltsos object IIRFILTSOS() IIRFILTSOS(_create)(TC * _b, TC * _a) { // create filter object IIRFILTSOS() q = (IIRFILTSOS()) malloc(sizeof(struct IIRFILTSOS(_s))); // set the internal coefficients IIRFILTSOS(_set_coefficients)(q, _b, _a); // clear filter state IIRFILTSOS(_reset)(q); return q; } // set internal filter coefficients // NOTE : this does not reset the internal state of the filter and // could result in instability if executed on existing filter! // explicitly set 2nd-order IIR filter coefficients // _q : iirfiltsos object // _b : feed-forward coefficients [size: _3 x 1] // _a : feed-back coefficients [size: _3 x 1] void IIRFILTSOS(_set_coefficients)(IIRFILTSOS() _q, TC * _b, TC * _a) { // retain a0 coefficient for normalization TC a0 = _a[0]; // copy feed-forward coefficients (numerator) _q->b[0] = _b[0] / a0; _q->b[1] = _b[1] / a0; _q->b[2] = _b[2] / a0; // copy feed-back coefficients (denominator) _q->a[0] = _a[0] / a0; // unity _q->a[1] = _a[1] / a0; _q->a[2] = _a[2] / a0; #if LIQUID_IIRFILTSOS_USE_DOTPROD _q->dpa = DOTPROD(_create)(_q->a+1, 2); _q->dpb = DOTPROD(_create)(_q->b, 3); #endif } // destroy iirfiltsos object, freeing all internal memory void IIRFILTSOS(_destroy)(IIRFILTSOS() _q) { #if LIQUID_IIRFILTSOS_USE_DOTPROD DOTPROD(_destroy)(_q->dpa); DOTPROD(_destroy)(_q->dpb); #endif free(_q); } // print iirfiltsos object properties to stdout void IIRFILTSOS(_print)(IIRFILTSOS() _q) { printf("iir filter | sos:\n"); printf(" b : "); PRINTVAL_TC(_q->b[0],%12.8f); printf(","); PRINTVAL_TC(_q->b[1],%12.8f); printf(","); PRINTVAL_TC(_q->b[2],%12.8f); printf("\n"); printf(" a : "); PRINTVAL_TC(_q->a[0],%12.8f); printf(","); PRINTVAL_TC(_q->a[1],%12.8f); printf(","); PRINTVAL_TC(_q->a[2],%12.8f); printf("\n"); } // clear/reset iirfiltsos object internals void IIRFILTSOS(_reset)(IIRFILTSOS() _q) { // set to zero _q->v[0] = 0; _q->v[1] = 0; _q->v[2] = 0; _q->x[0] = 0; _q->x[1] = 0; _q->x[2] = 0; _q->y[0] = 0; _q->y[1] = 0; _q->y[2] = 0; } // compute filter output // _q : iirfiltsos object // _x : input sample // _y : output sample pointer void IIRFILTSOS(_execute)(IIRFILTSOS() _q, TI _x, TO * _y) { // execute type-specific code IIRFILTSOS(_execute_df2)(_q,_x,_y); } // compute filter output, direct form I method // _q : iirfiltsos object // _x : input sample // _y : output sample pointer void IIRFILTSOS(_execute_df1)(IIRFILTSOS() _q, TI _x, TO * _y) { // advance buffer x _q->x[2] = _q->x[1]; _q->x[1] = _q->x[0]; _q->x[0] = _x; // advance buffer y _q->y[2] = _q->y[1]; _q->y[1] = _q->y[0]; #if LIQUID_IIRFILTSOS_USE_DOTPROD // NOTE: this is actually slower than the non-dotprod version // compute new v TI v; DOTPROD(_execute)(_q->dpb, _q->x, &v); // compute new y[0] TI y0; DOTPROD(_execute)(_q->dpa, _q->y+1, &y0); _q->y[0] = v - y0; #else // compute new v TI v = _q->x[0] * _q->b[0] + _q->x[1] * _q->b[1] + _q->x[2] * _q->b[2]; // compute new y[0] _q->y[0] = v - _q->y[1] * _q->a[1] - _q->y[2] * _q->a[2]; #endif // set output *_y = _q->y[0]; } // compute filter output, direct form II method // _q : iirfiltsos object // _x : input sample // _y : output sample pointer void IIRFILTSOS(_execute_df2)(IIRFILTSOS() _q, TI _x, TO * _y) { // advance buffer _q->v[2] = _q->v[1]; _q->v[1] = _q->v[0]; #if LIQUID_IIRFILTSOS_USE_DOTPROD // NOTE: this is actually slower than the non-dotprod version // compute new v TI v0; DOTPROD(_execute)(_q->dpa, _q->v+1, &v0); v0 = _x - v0; _q->v[0] = v0; // compute new y DOTPROD(_execute)(_q->dpb, _q->v, _y); #else // compute new v[0] _q->v[0] = _x - _q->a[1]*_q->v[1] - _q->a[2]*_q->v[2]; // compute output _y *_y = _q->b[0]*_q->v[0] + _q->b[1]*_q->v[1] + _q->b[2]*_q->v[2]; #endif } // compute group delay in samples // _q : filter object // _fc : frequency float IIRFILTSOS(_groupdelay)(IIRFILTSOS() _q, float _fc) { // copy coefficients float b[3]; float a[3]; unsigned int i; for (i=0; i<3; i++) { b[i] = crealf(_q->b[i]); a[i] = crealf(_q->a[i]); } return iir_group_delay(b, 3, a, 3, _fc) + 2.0; } liquid-dsp-1.3.1/src/filter/src/iirinterp.c000066400000000000000000000135331317124540100206060ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // infinite impulse response interpolator // #include #include #include struct IIRINTERP(_s) { unsigned int M; // interpolation factor // TODO: use IIR polyphase filterbank IIRFILT() iirfilt; // filter object }; // create interpolator from external coefficients // _M : interpolation factor // _b : feed-back coefficients [size: _nb x 1] // _nb : feed-back coefficients length // _a : feed-forward coefficients [size: _na x 1] // _na : feed-forward coefficients length IIRINTERP() IIRINTERP(_create)(unsigned int _M, TC * _b, unsigned int _nb, TC * _a, unsigned int _na) { // validate input if (_M < 2) { fprintf(stderr,"error: iirinterp_%s_create(), interp factor must be greater than 1\n", EXTENSION_FULL); exit(1); } // allocate main object memory and set internal parameters IIRINTERP() q = (IIRINTERP()) malloc(sizeof(struct IIRINTERP(_s))); q->M = _M; // create filter q->iirfilt = IIRFILT(_create)(_b, _nb, _a, _na); // return interpolator object return q; } // create decimator with default Butterworth prototype // _M : decimation factor // _order : filter order IIRINTERP() IIRINTERP(_create_default)(unsigned int _M, unsigned int _order) { return IIRINTERP(_create_prototype)(_M, LIQUID_IIRDES_BUTTER, LIQUID_IIRDES_LOWPASS, LIQUID_IIRDES_SOS, _order, 0.5f / (float)_M, // fc 0.0f, // f0 0.1f, // pass-band ripple, 60.0f); // stop-band attenuation } // create interpolator from prototype // _M : interpolation factor IIRINTERP() IIRINTERP(_create_prototype)(unsigned int _M, liquid_iirdes_filtertype _ftype, liquid_iirdes_bandtype _btype, liquid_iirdes_format _format, unsigned int _order, float _fc, float _f0, float _Ap, float _As) { // validate input if (_M < 2) { fprintf(stderr,"error: iirinterp_%s_create_prototype(), interp factor must be greater than 1\n", EXTENSION_FULL); exit(1); } // allocate main object memory and set internal parameters IIRINTERP() q = (IIRINTERP()) malloc(sizeof(struct IIRINTERP(_s))); q->M = _M; // create filter q->iirfilt = IIRFILT(_create_prototype)(_ftype, _btype, _format, _order, _fc, _f0, _Ap, _As); // return interpolator object return q; } // destroy interpolator object void IIRINTERP(_destroy)(IIRINTERP() _q) { IIRFILT(_destroy)(_q->iirfilt); free(_q); } // print interpolator state void IIRINTERP(_print)(IIRINTERP() _q) { printf("interp():\n"); printf(" M : %u\n", _q->M); IIRFILT(_print)(_q->iirfilt); } // clear internal state void IIRINTERP(_reset)(IIRINTERP() _q) { IIRFILT(_reset)(_q->iirfilt); } // execute interpolator // _q : interpolator object // _x : input sample // _y : output array [size: 1 x _M] void IIRINTERP(_execute)(IIRINTERP() _q, TI _x, TO * _y) { // TODO: use iirpfb unsigned int i; for (i=0; i<_q->M; i++) IIRFILT(_execute)(_q->iirfilt, i==0 ? _x : 0.0f, &_y[i]); } // execute interpolation on block of input samples // _q : iirinterp object // _x : input array [size: _n x 1] // _n : size of input array // _y : output sample array [size: _M*_n x 1] void IIRINTERP(_execute_block)(IIRINTERP() _q, TI * _x, unsigned int _n, TO * _y) { unsigned int i; for (i=0; i<_n; i++) { // execute one input at a time with an output stride _M IIRINTERP(_execute)(_q, _x[i], &_y[i*_q->M]); } } // get system group delay at frequency _fc // _q : interpolator object // _f : frequency float IIRINTERP(_groupdelay)(IIRINTERP() _q, float _fc) { return IIRFILT(_groupdelay)(_q->iirfilt, _fc) / (float) (_q->M); } liquid-dsp-1.3.1/src/filter/src/lpc.c000066400000000000000000000107371317124540100173620ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // lpc.c // // linear prediction coefficients // #include #include #include #include #include "liquid.internal.h" #define LIQUID_LEVINSON_MAXORDER (256) // compute the linear prediction coefficients for an input signal _x // _x : input signal [size: _n x 1] // _p : prediction filter order // _a : prediction filter [size: _p+1 x 1] // _e : prediction error variance [size: _p+1 x 1] void liquid_lpc(float * _x, unsigned int _n, unsigned int _p, float * _a, float * _g) { // validate input if (_p > _n) { fprintf(stderr,"error: liquid_lpc(), prediction filter length cannot exceed input signal length\n"); exit(1); } // compute auto-correlation with lags float r[_p+1]; // auto-correlation array unsigned int i; for (i=0; i<_p+1; i++) { unsigned int lag = i; unsigned int j; r[i] = 0.0f; for (j=lag; j<_n; j++) r[i] += _x[j] * _x[j-lag]; printf("r[%3u] = %12.8f\n", i, r[i]); } // solve the Toeplitz inversion using Levinson-Durbin recursion liquid_levinson(r,_p,_a,_g); } // solve the Yule-Walker equations using Levinson-Durbin recursion // for _symmetric_ autocorrelation // _r : autocorrelation array [size: _p+1 x 1] // _p : filter order // _a : output coefficients [size: _p+1 x 1] // _e : error variance [size: _p+1 x 1] // // NOTES: // By definition _a[0] = 1.0 void liquid_levinson(float * _r, unsigned int _p, float * _a, float * _e) { // check allocation length if (_p > LIQUID_LEVINSON_MAXORDER) { fprintf(stderr,"error: liquid_levinson(), filter order (%u) exceeds maximum (%u)\n", _p, LIQUID_LEVINSON_MAXORDER); exit(1); } // allocate arrays float a0[_p+1]; // temporary coefficients array, index [n] float a1[_p+1]; // temporary coefficients array, index [n-1] float e[_p+1]; // prediction error float k[_p+1]; // reflection coefficients // initialize k[0] = 1.0f; e[0] = _r[0]; unsigned int i; for (i=0; i<_p+1; i++) { a0[i] = (i==0) ? 1.0f : 0.0f; a1[i] = (i==0) ? 1.0f : 0.0f; } unsigned int n; for (n=1; n<_p+1; n++) { float q = 0.0f; for (i=0; i #include #include #include #include "liquid.internal.h" // // forward declaration of internal methods // // execute multi-stage interpolation void MSRESAMP(_interp_execute)(MSRESAMP() _q, TI * _x, unsigned int _nx, TO * _y, unsigned int * _num_written); // execute multi-stage decimation void MSRESAMP(_decim_execute)(MSRESAMP() _q, TI * _x, unsigned int _nx, TO * _y, unsigned int * _num_written); struct MSRESAMP(_s) { // user-defined parameters float rate; // re-sampling rate float As; // filter stop-band attenuation [dB] // type: interpolator or decimator int type; // run half-band resamplers as interp or decim // half-band resampler parameters unsigned int num_halfband_stages; // number of halfband stages MSRESAMP2() halfband_resamp; // multi-stage halfband resampler float rate_halfband; // halfband rate // arbitrary resampler parameters RESAMP() arbitrary_resamp; // arbitrary resampling object float rate_arbitrary; // clean-up resampling rate, in (0.5, 2.0) // internal buffers (ping-pong) unsigned int buffer_len; // length of each buffer T * buffer; // buffer[0] unsigned int buffer_index; // index of buffer }; // create msresamp object // TODO: add signal bandwidth parameter? // TODO: add center frequency parameter; facilitates DDS object synthesis // _r : resampling rate [output/input] // _As : stop-band attenuation MSRESAMP() MSRESAMP(_create)(float _r, float _As) { // validate input if (_r <= 0.0f) { fprintf(stderr,"error: msresamp_%s_create(), resampling rate must be greater than zero\n", EXTENSION_FULL); exit(1); } // create object MSRESAMP() q = (MSRESAMP()) malloc(sizeof(struct MSRESAMP(_s))); // set internal properties q->rate = _r; // composite rate q->As = _As; // stop-band suppression // decimation or interpolation? q->type = (q->rate > 1.0f) ? LIQUID_RESAMP_INTERP : LIQUID_RESAMP_DECIM; // compute derived values q->rate_arbitrary = q->rate; q->rate_halfband = 1.0f; q->num_halfband_stages = 0; switch(q->type) { case LIQUID_RESAMP_INTERP: while (q->rate_arbitrary > 2.0f) { q->num_halfband_stages++; q->rate_halfband *= 2.0f; q->rate_arbitrary *= 0.5f; } break; case LIQUID_RESAMP_DECIM: while (q->rate_arbitrary < 0.5f) { q->num_halfband_stages++; q->rate_halfband *= 0.5f; q->rate_arbitrary *= 2.0f; } break; default:; } // allocate memory for buffer q->buffer_len = 4 + (1 << q->num_halfband_stages); q->buffer = (T*) malloc( q->buffer_len*sizeof(T) ); // create single multi-stage half-band resampler object // TODO: compute appropriate cut-off frequency q->halfband_resamp = MSRESAMP2(_create)(q->type, q->num_halfband_stages, 0.4f, 0.0f, q->As); // create arbitrary resampler object // TODO: compute appropriate parameters q->arbitrary_resamp = RESAMP(_create)(q->rate_arbitrary, 7, 0.4f, q->As, 64); // reset object MSRESAMP(_reset)(q); // return main object return q; } // destroy msresamp object, freeing all internally-allocated memory void MSRESAMP(_destroy)(MSRESAMP() _q) { // free buffer free(_q->buffer); // destroy arbitrary resampler RESAMP(_destroy)(_q->arbitrary_resamp); // destroy multi-stage half-band resampler object MSRESAMP2(_destroy)(_q->halfband_resamp); // destroy main object free(_q); } // print msresamp object internals void MSRESAMP(_print)(MSRESAMP() _q) { printf("multi-stage resampler\n"); printf(" composite rate : %12.10f\n", _q->rate); printf(" type : %s\n", _q->type == LIQUID_RESAMP_INTERP ? "interp" : "decim"); printf(" num halfband stages : %u\n", _q->num_halfband_stages); printf(" halfband rate : %s%u\n", _q->type == LIQUID_RESAMP_INTERP ? "" : "1/", 1<<_q->num_halfband_stages); printf(" arbitrary rate : %12.10f\n", _q->rate_arbitrary); printf(" stages:\n"); //float delay_halfband = MSRESAMP2(_get_delay)(_q->halfband_resamp); //float delay_arbitrary = RESAMP(_get_delay)(_q->arbitrary_resamp); // print each stage unsigned int stage=0; float r = 1.0f; // accumulated rate // arbitrary (interpolator) if (_q->type == LIQUID_RESAMP_INTERP) { float rate = _q->rate_arbitrary; r *= rate; // update rate printf(" [%2u, r=%11.7f] : arbitrary, r=%12.8f\n", stage, r, rate); stage++; } // print stages of half-band resampling unsigned int i; for (i=0; i<_q->num_halfband_stages; i++) { float rate = _q->type == LIQUID_RESAMP_INTERP ? 2.0f : 0.5f; r *= rate; printf(" [%2u, r=%11.7f] : halfband, r=%5.1f\n", stage, r, rate); stage++; } // arbitrary (decimator) if (_q->type == LIQUID_RESAMP_DECIM) { float rate = _q->rate_arbitrary; r *= rate; printf(" [%2u, r=%11.7f] : arbitrary, r=%12.8f\n", stage, r, rate); stage++; } } // reset msresamp object internals, clear filters and nco phase void MSRESAMP(_reset)(MSRESAMP() _q) { // reset multi-stage half-band resampler object MSRESAMP2(_reset)(_q->halfband_resamp); // reset arbitrary resampler RESAMP(_reset)(_q->arbitrary_resamp); // reset buffer write pointer _q->buffer_index = 0; // TODO: clear internal buffers? } // get filter delay (output samples) float MSRESAMP(_get_delay)(MSRESAMP() _q) { float delay_halfband = MSRESAMP2(_get_delay)(_q->halfband_resamp); float delay_arbitrary = RESAMP(_get_delay)(_q->arbitrary_resamp); #if 0 printf("halfband : rate=%12.8f, delay=%12.8f\n", (float)(1<<_q->num_halfband_stages), delay_halfband); printf("arbitrary : rate=%12.8f, delay=%12.8f\n", _q->rate_arbitrary, delay_arbitrary); #endif // compute delay based on interpolation or decimation type if (_q->num_halfband_stages == 0) { // no half-band stages; just arbitrary resampler delay return delay_arbitrary; } else if (_q->type == LIQUID_RESAMP_INTERP) { // interpolation return delay_halfband / _q->rate_arbitrary + delay_arbitrary; } else { // decimation unsigned int M = 1 << _q->num_halfband_stages; return delay_halfband + M*delay_arbitrary; } return 0.0f; } // execute multi-stage resampler // _q : msresamp object // _x : input sample array // _y : output sample array // _ny : number of samples written to _y void MSRESAMP(_execute)(MSRESAMP() _q, TI * _x, unsigned int _nx, TO * _y, unsigned int * _ny) { switch(_q->type) { case LIQUID_RESAMP_INTERP: MSRESAMP(_interp_execute)(_q, _x, _nx, _y, _ny); break; case LIQUID_RESAMP_DECIM: MSRESAMP(_decim_execute)(_q, _x, _nx, _y, _ny); break; default:; } } // // internal methods // // execute multi-stage resampler as interpolator // _q : msresamp object // _x : input sample array // _y : output sample array // _nw : number of samples written to _y void MSRESAMP(_interp_execute)(MSRESAMP() _q, TI * _x, unsigned int _nx, TO * _y, unsigned int * _ny) { unsigned int i; unsigned int nw; unsigned int ny = 0; // operate one sample at a time so that we don't overflow the internal // buffer for (i=0; i<_nx; i++) { // run arbitrary resampler RESAMP(_execute)(_q->arbitrary_resamp, _x[i], _q->buffer, &nw); // run multi-stage half-band resampler on each output sample unsigned int k; for (k=0; khalfband_resamp, &_q->buffer[k], &_y[ny]); // increase output counter by halfband interpolation rate ny += 1 << _q->num_halfband_stages; } } // set return value for number of samples written *_ny = ny; } // execute multi-stage resampler as decimator // _q : msresamp object // _x : input sample array // _y : output sample array // _nw : number of samples written to _y void MSRESAMP(_decim_execute)(MSRESAMP() _q, TI * _x, unsigned int _nx, TO * _y, unsigned int * _ny) { unsigned int i; unsigned int M = 1 << _q->num_halfband_stages; unsigned int nw; // number of samples written for arbitrary resamp unsigned int ny = 0; // running counter of output samples TO halfband_output; // single half-band decimator output sample // write samples to buffer until it contains 2^num_halfband_stages // TODO: write block of samples for (i=0; i<_nx; i++) { // push sample into buffer _q->buffer[_q->buffer_index++] = _x[i]; // check if buffer has 'M' elements if (_q->buffer_index == M) { // run half-band decimation, producing a single output MSRESAMP2(_execute)(_q->halfband_resamp, _q->buffer, &halfband_output); // run resulting sample through arbitrary resampler RESAMP(_execute)(_q->arbitrary_resamp, halfband_output, &_y[ny], &nw); // increment output counter ny += nw; // reset buffer index _q->buffer_index = 0; } } // set return value for number of samples written *_ny = ny; } liquid-dsp-1.3.1/src/filter/src/msresamp2.c000066400000000000000000000302041317124540100205040ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // multi-stage half-band resampler // #include #include #include #include #include "liquid.internal.h" // // forward declaration of internal methods // struct MSRESAMP2(_s) { // user-defined parameters liquid_resamp_type type; // resampler type (e.g. LIQUID_RESAMP_INTERP) unsigned int num_stages; // number of half-band stages float fc; // initial cut-off frequency float f0; // initial center frequency float As; // stop-band attenuation // derived values unsigned int M; // integer resampling rate: 2^num_stages // half-band resamplers float * fc_stage; // cut-off frequency for each stage float * f0_stage; // center frequency for each stage float * As_stage; // stop-band attenuation for each stage unsigned int * m_stage; // filter semi-length for each stage RESAMP2() * resamp2; // array of half-band resamplers T * buffer0; // buffer[0] T * buffer1; // buffer[1] unsigned int buffer_index; // index of buffer float zeta; // scaling factor }; // execute multi-stage resampler as interpolator // _q : msresamp object // _x : input sample // _y : output sample array [size:2^_num_stages x 1] void MSRESAMP2(_interp_execute)(MSRESAMP2() _q, TI _x, TO * _y); // execute multi-stage resampler as decimator // _q : msresamp object // _x : input sample array [size: 2^_num_stages x 1] // _y : output sample pointer void MSRESAMP2(_decim_execute)(MSRESAMP2() _q, TI * _x, TO * _y); // create multi-stage half-band resampler // _type : resampler type (e.g. LIQUID_RESAMP_DECIM) // _num_stages : number of resampling stages // _fc : filter cut-off frequency 0 < _fc < 0.5 // _f0 : filter center frequency // _As : stop-band attenuation [dB] MSRESAMP2() MSRESAMP2(_create)(int _type, unsigned int _num_stages, float _fc, float _f0, float _As) { // validate input if (_num_stages > 16) { fprintf(stderr,"error: msresamp2_%s_create(), number of stages should not exceed 16\n", EXTENSION_FULL); exit(1); } // ensure cut-off frequency is valid if ( _fc <= 0.0f || _fc >= 0.5f ) { fprintf(stderr,"error: msresamp2_%s_create(), cut-off frequency must be in (0,0.5)\n", EXTENSION_FULL); exit(1); } else if ( _fc > 0.45f ) { fprintf(stderr,"warning: msresamp2_%s_create(), cut-off frequency greater than 0.45\n", EXTENSION_FULL); fprintf(stderr," >> truncating to 0.45\n"); _fc = 0.45f; } // check center frequency if ( _f0 != 0. ) { fprintf(stderr,"warning: msresamp2_%s_create(), non-zero center frequency not yet supported\n", EXTENSION_FULL); _f0 = 0.; } unsigned int i; // create object MSRESAMP2() q = (MSRESAMP2()) malloc(sizeof(struct MSRESAMP2(_s))); // set internal properties q->type = _type == LIQUID_RESAMP_INTERP ? LIQUID_RESAMP_INTERP : LIQUID_RESAMP_DECIM; q->num_stages = _num_stages; q->fc = _fc; q->f0 = _f0; q->As = _As; // derived values q->M = 1 << q->num_stages; q->zeta = 1.0f / (float)(q->M); // allocate memory for buffers q->buffer0 = (T*) malloc( q->M * sizeof(T) ); q->buffer1 = (T*) malloc( q->M * sizeof(T) ); // allocate arrays for half-band resampler parameters q->fc_stage = (float*) malloc(q->num_stages*sizeof(float) ); q->f0_stage = (float*) malloc(q->num_stages*sizeof(float) ); q->As_stage = (float*) malloc(q->num_stages*sizeof(float) ); q->m_stage = (unsigned int*) malloc(q->num_stages*sizeof(unsigned int)); // determine half-band resampler parameters float fc = q->fc; float f0 = q->f0; for (i=0; inum_stages; i++) { // compute parameters based on filter requirements; f0 = 0.5f*f0; // update center frequency fc = 0.5f*fc; // update cutoff frequency // estiamte required filter length float ft = (0.5f - fc)/2.0f; unsigned int h_len = estimate_req_filter_len(ft, q->As); unsigned int m = ceilf( (float)(h_len-1) / 4.0f ); q->fc_stage[i] = fc; // filter cut-of q->f0_stage[i] = f0; // filter center frequency q->As_stage[i] = q->As; // filter stop-band attenuation q->m_stage[i] = m < 3 ? 3 : m; // minimum 2 } // create half-band resampler objects q->resamp2 = (RESAMP2()*) malloc(q->num_stages*sizeof(RESAMP2())); for (i=0; inum_stages; i++) { // create half-band resampler q->resamp2[i] = RESAMP2(_create)(q->m_stage[i], q->f0_stage[i], q->As_stage[i]); } // reset object MSRESAMP2(_reset)(q); // return main object return q; } // destroy msresamp2 object, freeing all internally-allocated memory void MSRESAMP2(_destroy)(MSRESAMP2() _q) { // free buffers free(_q->buffer0); free(_q->buffer1); // free half-band resampler design parameter arrays free(_q->fc_stage); free(_q->f0_stage); free(_q->As_stage); free(_q->m_stage); // destroy/free half-band resampler objects unsigned int i; for (i=0; i<_q->num_stages; i++) RESAMP2(_destroy)(_q->resamp2[i]); // free half-band resampler array free(_q->resamp2); // destroy main object free(_q); } // print msresamp2 object internals void MSRESAMP2(_print)(MSRESAMP2() _q) { printf("multi-stage half-band resampler:\n"); printf(" type : %s\n", _q->type == LIQUID_RESAMP_DECIM ? "decimator" : "interpolator"); printf(" number of stages : %u stage%s\n", _q->num_stages, _q->num_stages == 1 ? "" : "s"); printf(" cut-off frequency, fc : %12.8f Fs\n", _q->fc); printf(" center frequency, f0 : %12.8f Fs\n", _q->f0); printf(" stop-band attenuation : %.2f dB\n", _q->As); // print each stage unsigned int i; for (i=0; i<_q->num_stages; i++) { printf(" stage[%2u] {m=%3u, As=%6.2f dB, fc=%6.3f, f0=%6.3f}\n", i, _q->m_stage[i], _q->As_stage[i], _q->fc_stage[i], _q->f0_stage[i]); } } // reset msresamp2 object internals, clear filters and nco phase void MSRESAMP2(_reset)(MSRESAMP2() _q) { // reset half-band resampler objects unsigned int i; for (i=0; i<_q->num_stages; i++) RESAMP2(_reset)(_q->resamp2[i]); // reset buffer write pointer _q->buffer_index = 0; // NOTE: not necessary to clear internal buffers } // get group delay (number of output samples) float MSRESAMP2(_get_delay)(MSRESAMP2() _q) { // initialize delay float delay = 0; unsigned int i; // add half-band resampling delay if (_q->type == LIQUID_RESAMP_INTERP) { // interpolator for (i=0; i<_q->num_stages; i++) { // filter semi-length unsigned int m = _q->m_stage[i]; delay *= 0.5f; delay += m; } } else { // decimator for (i=0; i<_q->num_stages; i++) { // filter semi-length unsigned int m = _q->m_stage[_q->num_stages-i-1]; delay *= 2; delay += 2*m - 1; } } return delay; } // execute multi-stage resampler as interpolator // _q : msresamp object // _x : input sample // _y : output sample array [size:2^_num_stages x 1] void MSRESAMP2(_execute)(MSRESAMP2() _q, TI * _x, TO * _y) { // switch resampling method based on type if (_q->num_stages == 0) { // pass through _y[0] = _x[0]; return; } else if (_q->type == LIQUID_RESAMP_INTERP) { // execute multi-stage resampler as interpolator MSRESAMP2(_interp_execute)(_q, _x[0], _y); } else { // execute multi-stage resampler as decimator MSRESAMP2(_decim_execute)(_q, _x, _y); } } // // internal methods // // execute multi-stage resampler as interpolator // _q : msresamp object // _x : input sample // _y : output sample array [size:2^_num_stages x 1] void MSRESAMP2(_interp_execute)(MSRESAMP2() _q, TI _x, TO * _y) { // buffer pointers (initialize BOTH to _q->buffer0); T * b0 = _q->buffer0; // input buffer pointer T * b1 = _q->buffer1; // output buffer pointer // set input sample in first buffer b0[0] = _x; unsigned int s; // half-band decimator stage counter unsigned int k; // number of inputs for this stage for (s=0; s<_q->num_stages; s++) { // compute number of inputs for this stage k = 1 << s; // set final stage output as supplied output pointer if (s == _q->num_stages-1) b1 = _y; // run half-band stages as interpolators unsigned int i; unsigned int g = _q->num_stages-s-1; // reversed resampler index for (i=0; iresamp2[g], b0[i], &b1[2*i]); // toggle output buffer pointers b0 = (s % 2) == 0 ? _q->buffer1 : _q->buffer0; b1 = (s % 2) == 0 ? _q->buffer0 : _q->buffer1; } } // execute multi-stage resampler as decimator // _q : msresamp object // _x : input sample array [size: 2^_num_stages x 1] // _y : output sample pointer void MSRESAMP2(_decim_execute)(MSRESAMP2() _q, TI * _x, TO * _y) { // buffer pointers (initialize BOTH to _q->buffer0); T * b0 = _x; // input buffer pointer T * b1 = _q->buffer1; // output buffer pointer unsigned int s; // half-band decimator stage counter unsigned int k; // number of outputs for this stage for (s=0; s<_q->num_stages; s++) { // compute number of outputs for this stage k = 1 << (_q->num_stages - s - 1); // run half-band stages as decimators unsigned int i; for (i=0; iresamp2[s], &b0[2*i], &b1[i]); // toggle output buffer pointers b0 = (s % 2) == 0 ? _q->buffer1 : _q->buffer0; b1 = (s % 2) == 0 ? _q->buffer0 : _q->buffer1; } // set single output sample and scale appropriately *_y = b0[0] * _q->zeta; } liquid-dsp-1.3.1/src/filter/src/rcos.c000066400000000000000000000051621317124540100175460ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Design raised-cosine filter // #include #include #include #include "liquid.internal.h" // Design Nyquist raised-cosine filter // _k : samples/symbol // _m : symbol delay // _beta : rolloff factor (0 < beta <= 1) // _dt : fractional sample delay // _h : output coefficient buffer (length: 2*k*m+1) void liquid_firdes_rcos(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h) { if ( _k < 1 ) { fprintf(stderr,"error: liquid_firdes_rcos(): k must be greater than 0\n"); exit(1); } else if ( _m < 1 ) { fprintf(stderr,"error: liquid_firdes_rcos(): m must be greater than 0\n"); exit(1); } else if ( (_beta < 0.0f) || (_beta > 1.0f) ) { fprintf(stderr,"error: liquid_firdes_rcos(): beta must be in [0,1]\n"); exit(1); } else; unsigned int n; float z, t1, t2, t3; float nf, kf, mf; unsigned int h_len = 2*_k*_m + 1; // Calculate filter coefficients for (n=0; n #include #include #include // defined: // TO output data type // TC coefficient data type // TI input data type // RESAMP() name-mangling macro // FIRPFB() firpfb macro // enable run-time debug printing of resampler #define DEBUG_RESAMP_PRINT 0 // internal: update timing void RESAMP(_update_timing_state)(RESAMP() _q); struct RESAMP(_s) { // filter design parameters unsigned int m; // filter semi-length, h_len = 2*m + 1 float As; // filter stop-band attenuation float fc; // filter cutoff frequency // resampling properties/states float rate; // resampling rate (ouput/input) float del; // fractional delay step // floating-point phase float tau; // accumulated timing phase, 0 <= tau < 1 float bf; // soft filterbank index, bf = tau*npfb = b + mu int b; // base filterbank index, 0 <= b < npfb float mu; // fractional filterbank interpolation value, 0 <= mu < 1 TO y0; // filterbank output at index b TO y1; // filterbank output at index b+1 // polyphase filterbank properties/object unsigned int npfb; // number of filters in the bank FIRPFB() f; // filterbank object (interpolator) enum { RESAMP_STATE_BOUNDARY, // boundary between input samples RESAMP_STATE_INTERP, // regular interpolation } state; }; // create arbitrary resampler // _rate : resampling rate // _m : prototype filter semi-length // _fc : prototype filter cutoff frequency, fc in (0, 0.5) // _As : prototype filter stop-band attenuation [dB] (e.g. 60) // _npfb : number of filters in polyphase filterbank RESAMP() RESAMP(_create)(float _rate, unsigned int _m, float _fc, float _As, unsigned int _npfb) { // validate input if (_rate <= 0) { fprintf(stderr,"error: resamp_%s_create(), resampling rate must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_m == 0) { fprintf(stderr,"error: resamp_%s_create(), filter semi-length must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_npfb == 0) { fprintf(stderr,"error: resamp_%s_create(), number of filter banks must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_fc <= 0.0f || _fc >= 0.5f) { fprintf(stderr,"error: resamp_%s_create(), filter cutoff must be in (0,0.5)\n", EXTENSION_FULL); exit(1); } else if (_As <= 0.0f) { fprintf(stderr,"error: resamp_%s_create(), filter stop-band suppression must be greater than zero\n", EXTENSION_FULL); exit(1); } // allocate memory for resampler RESAMP() q = (RESAMP()) malloc(sizeof(struct RESAMP(_s))); // set rate using formal method (specifies output stride // value 'del') RESAMP(_set_rate)(q, _rate); // set properties q->m = _m; // prototype filter semi-length q->fc = _fc; // prototype filter cutoff frequency q->As = _As; // prototype filter stop-band attenuation q->npfb = _npfb; // number of filters in bank // design filter unsigned int n = 2*q->m*q->npfb+1; float hf[n]; TC h[n]; liquid_firdes_kaiser(n,q->fc/((float)(q->npfb)),q->As,0.0f,hf); // normalize filter coefficients by DC gain unsigned int i; float gain=0.0f; for (i=0; inpfb)/(gain); // copy to type-specific array, applying gain for (i=0; if = FIRPFB(_create)(q->npfb,h,n-1); // reset object and return RESAMP(_reset)(q); return q; } // create arbitrary resampler object with a specified input // resampling rate and default parameters // m (filter semi-length) = 7 // fc (filter cutoff frequency) = 0.25 // As (filter stop-band attenuation) = 60 dB // npfb (number of filters in the bank) = 64 RESAMP() RESAMP(_create_default)(float _rate) { // validate input if (_rate <= 0) { fprintf(stderr,"error: resamp_%s_create_default(), resampling rate must be greater than zero\n", EXTENSION_FULL); exit(1); } // det default parameters unsigned int m = 7; float fc = 0.25f; float As = 60.0f; unsigned int npfb = 64; // create and return resamp object return RESAMP(_create)(_rate, m, fc, As, npfb); } // free arbitrary resampler object void RESAMP(_destroy)(RESAMP() _q) { // free polyphase filterbank FIRPFB(_destroy)(_q->f); // free main object memory free(_q); } // print resampler object void RESAMP(_print)(RESAMP() _q) { printf("resampler [rate: %f]\n", _q->rate); FIRPFB(_print)(_q->f); } // reset resampler object void RESAMP(_reset)(RESAMP() _q) { // clear filterbank FIRPFB(_reset)(_q->f); // reset states _q->state = RESAMP_STATE_INTERP;// input/output sample state _q->tau = 0.0f; // accumulated timing phase _q->bf = 0.0f; // soft-valued filterbank index _q->b = 0; // base filterbank index _q->mu = 0.0f; // fractional filterbank interpolation value _q->y0 = 0; // filterbank output at index b _q->y1 = 0; // filterbank output at index b+1 } // get resampler filter delay (semi-length m) unsigned int RESAMP(_get_delay)(RESAMP() _q) { return _q->m; } // set rate of arbitrary resampler // _q : resampling object // _rate : new sampling rate, _rate > 0 void RESAMP(_set_rate)(RESAMP() _q, float _rate) { if (_rate <= 0) { fprintf(stderr,"error: resamp_%s_set_rate(), resampling rate must be greater than zero\n", EXTENSION_FULL); exit(1); } // set internal rate _q->rate = _rate; // set output stride _q->del = 1.0f / _q->rate; } // adjust resampling rate void RESAMP(_adjust_rate)(RESAMP() _q, float _delta) { if (_delta > 0.1f || _delta < -0.1f) { fprintf(stderr,"error: resamp_%s_adjust_rate(), resampling rate must be in [-0.1,0.1]\n", EXTENSION_FULL); exit(1); } // adjust internal rate _q->rate += _delta; // clip rate if (_q->rate > 0.5f) _q->rate = 0.5f; if (_q->rate < -0.5f) _q->rate = -0.5f; // set output stride _q->del = 1.0f / _q->rate; } // set resampling timing phase // _q : resampling object // _tau : sample timing void RESAMP(_set_timing_phase)(RESAMP() _q, float _tau) { if (_tau > 1.0f || _tau < -1.0f) { fprintf(stderr,"error: resamp_%s_set_timing_phase(), timing phase must be in [-1,1], is %f\n.", EXTENSION_FULL, _tau); exit(1); } // set internal timing phase _q->tau = _tau; } // adjust resampling timing phase // _q : resampling object // _delta : sample timing adjustment void RESAMP(_adjust_timing_phase)(RESAMP() _q, float _delta) { if (_delta > 1.0f || _delta < -1.0f) { fprintf(stderr,"error: resamp_%s_adjust_timing_phase(), timing phase adjustment must be in [-1,1], is %f\n.", EXTENSION_FULL, _delta); exit(1); } // adjust internal timing phase _q->tau += _delta; } // run arbitrary resampler // _q : resampling object // _x : single input sample // _y : output array // _num_written: number of samples written to output void RESAMP(_execute)(RESAMP() _q, TI _x, TO * _y, unsigned int * _num_written) { // push input sample into filterbank FIRPFB(_push)(_q->f, _x); unsigned int n=0; while (_q->b < _q->npfb) { #if DEBUG_RESAMP_PRINT printf(" [%2u] : s=%1u, tau=%12.8f, b : %12.8f (%4d + %8.6f)\n", n+1, _q->state, _q->tau, _q->bf, _q->b, _q->mu); #endif switch (_q->state) { case RESAMP_STATE_BOUNDARY: // compute filterbank output FIRPFB(_execute)(_q->f, 0, &_q->y1); // interpolate _y[n++] = (1.0f - _q->mu)*_q->y0 + _q->mu*_q->y1; // update timing state RESAMP(_update_timing_state)(_q); _q->state = RESAMP_STATE_INTERP; break; case RESAMP_STATE_INTERP: // compute output at base index FIRPFB(_execute)(_q->f, _q->b, &_q->y0); // check to see if base index is last filter in the bank, in // which case the resampler needs an additional input sample // to finish the linear interpolation process if (_q->b == _q->npfb-1) { // last filter: need additional input sample _q->state = RESAMP_STATE_BOUNDARY; // set index to indicate new sample is needed _q->b = _q->npfb; } else { // do not need additional input sample; compute // output at incremented base index FIRPFB(_execute)(_q->f, _q->b+1, &_q->y1); // perform linear interpolation between filterbank outputs _y[n++] = (1.0f - _q->mu)*_q->y0 + _q->mu*_q->y1; // update timing state RESAMP(_update_timing_state)(_q); } break; default: fprintf(stderr,"error: resamp_%s_execute(), invalid/unknown state\n", EXTENSION_FULL); exit(1); } } // decrement timing phase by one sample _q->tau -= 1.0f; _q->bf -= (float)(_q->npfb); _q->b -= _q->npfb; // specify number of samples written *_num_written = n; } // execute arbitrary resampler on a block of samples // _q : resamp object // _x : input buffer [size: _nx x 1] // _nx : input buffer // _y : output sample array (pointer) // _ny : number of samples written to _y void RESAMP(_execute_block)(RESAMP() _q, TI * _x, unsigned int _nx, TO * _y, unsigned int * _ny) { // initialize number of output samples to zero unsigned int ny = 0; // number of samples written for each individual iteration unsigned int num_written; // iterate over each input sample unsigned int i; for (i=0; i<_nx; i++) { // run resampler on single input RESAMP(_execute)(_q, _x[i], &_y[ny], &num_written); // update output counter ny += num_written; } // set return value for number of output samples written *_ny = ny; } // // internal methods // // update timing state; increment output timing stride and // quantize filterbank indices void RESAMP(_update_timing_state)(RESAMP() _q) { // update high-resolution timing phase _q->tau += _q->del; // convert to high-resolution filterbank index _q->bf = _q->tau * (float)(_q->npfb); // split into integer filterbank index and fractional interpolation _q->b = (int)floorf(_q->bf); // base index _q->mu = _q->bf - (float)(_q->b); // fractional index } liquid-dsp-1.3.1/src/filter/src/resamp.fixed.c000066400000000000000000000125111317124540100211610ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Arbitrary resampler (fixed-point phase verions) // #include #include #include #include #define DEBUG_RESAMP_PRINT 0 // defined: // TO output data type // TC coefficient data type // TI input data type // RESAMP() name-mangling macro // FIRPFB() firpfb macro struct RESAMP(_s) { TC * h; unsigned int h_len; float As; // stop-band attenuation float fc; // filter cutoff float r; // rate int b; // filterbank index float del; // fractional delay step // fixed-point phase unsigned int theta; // sampling phase unsigned int d_theta; // phase differential unsigned int num_bits_phase; // number of bits in phase unsigned int max_phase; // maximum phase value unsigned int num_bits_npfb; // number of bits in npfb unsigned int num_shift_bits; // number of bits to shift to compute b unsigned int npfb; FIRPFB() f; #if 0 fir_prototype p; // prototype object #endif }; RESAMP() RESAMP(_create)(float _r, unsigned int _h_len, float _fc, float _As, unsigned int _npfb) { // validate input if (_r <= 0) { fprintf(stderr,"error: resamp_%s_create(), resampling rate must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_h_len == 0) { fprintf(stderr,"error: resamp_%s_create(), filter length must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_npfb == 0) { fprintf(stderr,"error: resamp_%s_create(), number of filter banks must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_fc <= 0.0f || _fc >= 0.5f) { fprintf(stderr,"error: resamp_%s_create(), filter cutoff must be in (0,0.5)\n", EXTENSION_FULL); exit(1); } else if (_As <= 0.0f) { fprintf(stderr,"error: resamp_%s_create(), filter stop-band suppression must be greater than zero\n", EXTENSION_FULL); exit(1); } RESAMP() q = (RESAMP()) malloc(sizeof(struct RESAMP(_s))); q->r = _r; q->As = _As; q->fc = _fc; q->h_len = _h_len; q->b = 0; q->del = 1.0f / q->r; q->num_bits_npfb = liquid_nextpow2(_npfb); q->npfb = 1<num_bits_npfb; q->num_bits_phase = 20; q->max_phase = 1 << q->num_bits_phase; q->num_shift_bits = q->num_bits_phase - q->num_bits_npfb; q->theta = 0; q->d_theta = (unsigned int)( q->max_phase * q->del ); // design filter unsigned int n = 2*_h_len*q->npfb+1; float hf[n]; TC h[n]; liquid_firdes_kaiser(n,q->fc/((float)(q->npfb)),q->As,0.0f,hf); // normalize filter coefficients by DC gain unsigned int i; float gain=0.0f; for (i=0; inpfb)/(gain); // copy to type-specific array for (i=0; if = FIRPFB(_create)(q->npfb,h,n-1); //for (i=0; if); free(_q); } void RESAMP(_print)(RESAMP() _q) { printf("resampler [rate: %f]\n", _q->r); FIRPFB(_print)(_q->f); } void RESAMP(_reset)(RESAMP() _q) { FIRPFB(_reset)(_q->f); _q->b = 0; _q->theta = 0; } void RESAMP(_setrate)(RESAMP() _q, float _rate) { // TODO : validate rate, validate this method _q->r = _rate; _q->del = 1.0f / _q->r; _q->d_theta = (unsigned int)( _q->max_phase * _q->del ); } void RESAMP(_execute)(RESAMP() _q, TI _x, TO * _y, unsigned int *_num_written) { FIRPFB(_push)(_q->f, _x); unsigned int n=0; //while (_q->tau < 1.0f) { while (_q->theta < _q->max_phase) { #if DEBUG_RESAMP_PRINT printf(" [%2u] : theta = %6u, b : %6u\n", n, _q->theta, _q->b); #endif FIRPFB(_execute)(_q->f, _q->b, &_y[n]); _q->theta += _q->d_theta; _q->b = _q->theta >> _q->num_shift_bits; n++; } _q->theta -= _q->max_phase; _q->b = _q->theta >> _q->num_shift_bits; *_num_written = n; } liquid-dsp-1.3.1/src/filter/src/resamp2.c000066400000000000000000000245031317124540100201510ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Halfband resampler (interpolator/decimator) // #include #include #include #include // defined: // RESAMP2() name-mangling macro // TO output data type // TC coefficient data type // TI input data type // WINDOW() window macro // DOTPROD() dotprod macro // PRINTVAL() print macro struct RESAMP2(_s) { TC * h; // filter prototype unsigned int m; // primitive filter length unsigned int h_len; // actual filter length: h_len = 4*m+1 float f0; // center frequency [-1.0 <= f0 <= 1.0] float As; // stop-band attenuation [dB] // filter component TC * h1; // filter branch coefficients DOTPROD() dp; // inner dot product object unsigned int h1_len; // filter length (2*m) // input buffers WINDOW() w0; // input buffer (even samples) WINDOW() w1; // input buffer (odd samples) // halfband filter operation unsigned int toggle; }; // create a resamp2 object // _m : filter semi-length (effective length: 4*_m+1) // _f0 : center frequency of half-band filter // _As : stop-band attenuation [dB], _As > 0 RESAMP2() RESAMP2(_create)(unsigned int _m, float _f0, float _As) { // validate input if (_m < 2) { fprintf(stderr,"error: resamp2_%s_create(), filter semi-length must be at least 2\n", EXTENSION_FULL); exit(1); } RESAMP2() q = (RESAMP2()) malloc(sizeof(struct RESAMP2(_s))); q->m = _m; q->f0 = _f0; q->As = _As; if ( q->f0 < -0.5f || q->f0 > 0.5f ) { fprintf(stderr,"error: resamp2_%s_create(), f0 (%12.4e) must be in (-1,1)\n", EXTENSION_FULL, q->f0); exit(1); } // change filter length as necessary q->h_len = 4*(q->m) + 1; q->h = (TC *) malloc((q->h_len)*sizeof(TC)); q->h1_len = 2*(q->m); q->h1 = (TC *) malloc((q->h1_len)*sizeof(TC)); // design filter prototype unsigned int i; float t, h1, h2; TC h3; float beta = kaiser_beta_As(q->As); for (i=0; ih_len; i++) { t = (float)i - (float)(q->h_len-1)/2.0f; h1 = sincf(t/2.0f); h2 = kaiser(i,q->h_len,beta,0); #if TC_COMPLEX == 1 h3 = cosf(2.0f*M_PI*t*q->f0) + _Complex_I*sinf(2.0f*M_PI*t*q->f0); #else h3 = cosf(2.0f*M_PI*t*q->f0); #endif q->h[i] = h1*h2*h3; } // resample, alternate sign, [reverse direction] unsigned int j=0; for (i=1; ih_len; i+=2) q->h1[j++] = q->h[q->h_len - i - 1]; // create dotprod object q->dp = DOTPROD(_create)(q->h1, 2*q->m); // create window buffers q->w0 = WINDOW(_create)(2*(q->m)); q->w1 = WINDOW(_create)(2*(q->m)); RESAMP2(_reset)(q); return q; } // re-create a resamp2 object with new properties // _q : original resamp2 object // _m : filter semi-length (effective length: 4*_m+1) // _f0 : center frequency of half-band filter // _As : stop-band attenuation [dB], _As > 0 RESAMP2() RESAMP2(_recreate)(RESAMP2() _q, unsigned int _m, float _f0, float _As) { // only re-design filter if necessary if (_m != _q->m) { // destroy resampler and re-create from scratch RESAMP2(_destroy)(_q); _q = RESAMP2(_create)(_m, _f0, _As); } else { // re-design filter prototype unsigned int i; float t, h1, h2; TC h3; float beta = kaiser_beta_As(_q->As); for (i=0; i<_q->h_len; i++) { t = (float)i - (float)(_q->h_len-1)/2.0f; h1 = sincf(t/2.0f); h2 = kaiser(i,_q->h_len,beta,0); #if TC_COMPLEX == 1 h3 = cosf(2.0f*M_PI*t*_q->f0) + _Complex_I*sinf(2.0f*M_PI*t*_q->f0); #else h3 = cosf(2.0f*M_PI*t*_q->f0); #endif _q->h[i] = h1*h2*h3; } // resample, alternate sign, [reverse direction] unsigned int j=0; for (i=1; i<_q->h_len; i+=2) _q->h1[j++] = _q->h[_q->h_len - i - 1]; // create dotprod object _q->dp = DOTPROD(_recreate)(_q->dp, _q->h1, 2*_q->m); } return _q; } // destroy a resamp2 object, clearing up all allocated memory void RESAMP2(_destroy)(RESAMP2() _q) { // destroy dotprod object DOTPROD(_destroy)(_q->dp); // destroy window buffers WINDOW(_destroy)(_q->w0); WINDOW(_destroy)(_q->w1); // free arrays free(_q->h); free(_q->h1); // free main object memory free(_q); } // print a resamp2 object's internals void RESAMP2(_print)(RESAMP2() _q) { printf("fir half-band resampler: [%u taps, f0=%12.8f]\n", _q->h_len, _q->f0); unsigned int i; for (i=0; i<_q->h_len; i++) { printf(" h(%4u) = ", i+1); PRINTVAL_TC(_q->h[i],%12.8f); printf(";\n"); } printf("---\n"); for (i=0; i<_q->h1_len; i++) { printf(" h1(%4u) = ", i+1); PRINTVAL_TC(_q->h1[i],%12.8f); printf(";\n"); } } // clear internal buffer void RESAMP2(_reset)(RESAMP2() _q) { WINDOW(_reset)(_q->w0); WINDOW(_reset)(_q->w1); _q->toggle = 0; } // get filter delay (samples) unsigned int RESAMP2(_get_delay)(RESAMP2() _q) { return 2*_q->m - 1; } // execute resamp2 as half-band filter // _q : resamp2 object // _x : input sample // _y0 : output sample pointer (low frequency) // _y1 : output sample pointer (high frequency) void RESAMP2(_filter_execute)(RESAMP2() _q, TI _x, TO * _y0, TO * _y1) { TI * r; // buffer read pointer TO yi; // delay branch TO yq; // filter branch if ( _q->toggle == 0 ) { // push sample into upper branch WINDOW(_push)(_q->w0, _x); // upper branch (delay) WINDOW(_index)(_q->w0, _q->m-1, &yi); // lower branch (filter) WINDOW(_read)(_q->w1, &r); DOTPROD(_execute)(_q->dp, r, &yq); } else { // push sample into lower branch WINDOW(_push)(_q->w1, _x); // upper branch (delay) WINDOW(_index)(_q->w1, _q->m-1, &yi); // lower branch (filter) WINDOW(_read)(_q->w0, &r); DOTPROD(_execute)(_q->dp, r, &yq); } // toggle flag _q->toggle = 1 - _q->toggle; // set return values, normalizing gain *_y0 = 0.5f*(yi + yq); // lower band *_y1 = 0.5f*(yi - yq); // upper band } // execute analysis half-band filterbank // _q : resamp2 object // _x : input array [size: 2 x 1] // _y : output array [size: 2 x 1] void RESAMP2(_analyzer_execute)(RESAMP2() _q, TI * _x, TO * _y) { TI * r; // buffer read pointer TO y0; // delay branch TO y1; // filter branch // compute filter branch WINDOW(_push)(_q->w1, 0.5*_x[0]); WINDOW(_read)(_q->w1, &r); DOTPROD(_execute)(_q->dp, r, &y1); // compute delay branch WINDOW(_push)(_q->w0, 0.5*_x[1]); WINDOW(_index)(_q->w0, _q->m-1, &y0); // set return value _y[0] = y1 + y0; _y[1] = y1 - y0; } // execute synthesis half-band filterbank // _q : resamp2 object // _x : input array [size: 2 x 1] // _y : output array [size: 2 x 1] void RESAMP2(_synthesizer_execute)(RESAMP2() _q, TI * _x, TO * _y) { TI * r; // buffer read pointer TI x0 = _x[0] + _x[1]; // delay branch input TI x1 = _x[0] - _x[1]; // filter branch input // compute delay branch WINDOW(_push)(_q->w0, x0); WINDOW(_index)(_q->w0, _q->m-1, &_y[0]); // compute second branch (filter) WINDOW(_push)(_q->w1, x1); WINDOW(_read)(_q->w1, &r); DOTPROD(_execute)(_q->dp, r, &_y[1]); } // execute half-band decimation // _q : resamp2 object // _x : input array [size: 2 x 1] // _y : output sample pointer void RESAMP2(_decim_execute)(RESAMP2() _q, TI * _x, TO * _y) { TI * r; // buffer read pointer TO y0; // delay branch TO y1; // filter branch // compute filter branch WINDOW(_push)(_q->w1, _x[0]); WINDOW(_read)(_q->w1, &r); DOTPROD(_execute)(_q->dp, r, &y1); // compute delay branch WINDOW(_push)(_q->w0, _x[1]); WINDOW(_index)(_q->w0, _q->m-1, &y0); // set return value *_y = y0 + y1; } // execute half-band interpolation // _q : resamp2 object // _x : input sample // _y : output array [size: 2 x 1] void RESAMP2(_interp_execute)(RESAMP2() _q, TI _x, TO * _y) { TI * r; // buffer read pointer // compute delay branch WINDOW(_push)(_q->w0, _x); WINDOW(_index)(_q->w0, _q->m-1, &_y[0]); // compute second branch (filter) WINDOW(_push)(_q->w1, _x); WINDOW(_read)(_q->w1, &r); DOTPROD(_execute)(_q->dp, r, &_y[1]); } liquid-dsp-1.3.1/src/filter/src/rkaiser.c000066400000000000000000000453321317124540100202430ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Design root-Nyquist Kaiser filter // // References // [Vaidyanathan:1993] Vaidyanathan, P. P., "Multirate Systems and // Filter Banks," 1993, Prentice Hall, Section 3.2.1 // #include #include #include #include "liquid.internal.h" #define DEBUG_RKAISER 0 // Design frequency-shifted root-Nyquist filter based on // the Kaiser-windowed sinc. // // _k : filter over-sampling rate (samples/symbol) // _m : filter delay (symbols) // _beta : filter excess bandwidth factor (0,1) // _dt : filter fractional sample delay // _h : resulting filter [size: 2*_k*_m+1] void liquid_firdes_rkaiser(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h) { // validate input if (_k < 2) { fprintf(stderr,"error: liquid_firdes_rkaiser(), k must be at least 2\n"); exit(1); } else if (_m < 1) { fprintf(stderr,"error: liquid_firdes_rkaiser(), m must be at least 1\n"); exit(1); } else if (_beta <= 0.0f || _beta >= 1.0f) { fprintf(stderr,"error: liquid_firdes_rkaiser(), beta must be in (0,1)\n"); exit(1); } else if (_dt < -1.0f || _dt > 1.0f) { fprintf(stderr,"error: liquid_firdes_rkaiser(), dt must be in [-1,1]\n"); exit(1); } // simply call internal method and ignore output rho value float rho; //liquid_firdes_rkaiser_bisection(_k,_m,_beta,_dt,_h,&rho); liquid_firdes_rkaiser_quadratic(_k,_m,_beta,_dt,_h,&rho); } // Design frequency-shifted root-Nyquist filter based on // the Kaiser-windowed sinc using approximation for rho. // // _k : filter over-sampling rate (samples/symbol) // _m : filter delay (symbols) // _beta : filter excess bandwidth factor (0,1) // _dt : filter fractional sample delay // _h : resulting filter [size: 2*_k*_m+1] void liquid_firdes_arkaiser(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h) { // validate input if (_k < 2) { fprintf(stderr,"error: liquid_firdes_arkaiser(), k must be at least 2\n"); exit(1); } else if (_m < 1) { fprintf(stderr,"error: liquid_firdes_arkaiser(), m must be at least 1\n"); exit(1); } else if (_beta <= 0.0f || _beta >= 1.0f) { fprintf(stderr,"error: liquid_firdes_arkaiser(), beta must be in (0,1)\n"); exit(1); } else if (_dt < -1.0f || _dt > 1.0f) { fprintf(stderr,"error: liquid_firdes_arkaiser(), dt must be in [-1,1]\n"); exit(1); } #if 0 // compute bandwidth adjustment estimate float rho_hat = rkaiser_approximate_rho(_m,_beta); // bandwidth correction factor #else // rho ~ c0 + c1*log(_beta) + c2*log^2(_beta) // c0 ~ 0.762886 + 0.067663*log(m) // c1 ~ 0.065515 // c2 ~ log( 1 - 0.088*m^-1.6 ) float c0 = 0.762886 + 0.067663*logf(_m); float c1 = 0.065515; float c2 = logf( 1 - 0.088*powf(_m,-1.6 ) ); float log_beta = logf(_beta); float rho_hat = c0 + c1*log_beta + c2*log_beta*log_beta; // ensure range is valid if (rho_hat <= 0.0f || rho_hat >= 1.0f) rho_hat = rkaiser_approximate_rho(_m,_beta); #endif unsigned int n=2*_k*_m+1; // filter length float kf = (float)_k; // samples/symbol (float) float del = _beta*rho_hat / kf; // transition bandwidth float As = estimate_req_filter_As(del, n); // stop-band suppression float fc = 0.5f*(1 + _beta*(1.0f-rho_hat))/kf; // filter cutoff #if DEBUG_RKAISER printf("rho-hat : %12.8f (compare to %12.8f)\n", rho_hat, rkaiser_approximate_rho(_m,_beta)); printf("fc : %12.8f\n", fc); printf("delta-f : %12.8f\n", del); printf("As : %12.8f dB\n", As); printf("alpha : %12.8f\n", kaiser_beta_As(As)); #endif // compute filter coefficients liquid_firdes_kaiser(n,fc,As,_dt,_h); // normalize coefficients float e2 = 0.0f; unsigned int i; for (i=0; i 1.0f) ) { fprintf(stderr,"error: rkaiser_approximate_rho(): beta must be in [0,1]\n"); exit(1); } else; // compute bandwidth adjustment estimate float c0=0.0f, c1=0.0f, c2=0.0f; switch (_m) { case 1: c0=0.75749731; c1=0.06134303; c2=-0.08729663; break; case 2: c0=0.81151861; c1=0.07437658; c2=-0.01427088; break; case 3: c0=0.84249538; c1=0.07684185; c2=-0.00536879; break; case 4: c0=0.86140782; c1=0.07144126; c2=-0.00558652; break; case 5: c0=0.87457740; c1=0.06578694; c2=-0.00650447; break; case 6: c0=0.88438797; c1=0.06074265; c2=-0.00736405; break; case 7: c0=0.89216620; c1=0.05669236; c2=-0.00791222; break; case 8: c0=0.89874983; c1=0.05361696; c2=-0.00815301; break; case 9: c0=0.90460032; c1=0.05167952; c2=-0.00807893; break; case 10: c0=0.91034430; c1=0.05130753; c2=-0.00746192; break; case 11: c0=0.91587675; c1=0.05180436; c2=-0.00670711; break; case 12: c0=0.92121875; c1=0.05273801; c2=-0.00588351; break; case 13: c0=0.92638195; c1=0.05400764; c2=-0.00508452; break; case 14: c0=0.93123555; c1=0.05516163; c2=-0.00437306; break; case 15: c0=0.93564993; c1=0.05596561; c2=-0.00388152; break; case 16: c0=0.93976742; c1=0.05662274; c2=-0.00348280; break; case 17: c0=0.94351703; c1=0.05694120; c2=-0.00318821; break; case 18: c0=0.94557273; c1=0.05227591; c2=-0.00400676; break; case 19: c0=0.95001614; c1=0.05681641; c2=-0.00300628; break; case 20: c0=0.95281708; c1=0.05637607; c2=-0.00304790; break; case 21: c0=0.95536256; c1=0.05575880; c2=-0.00312988; break; case 22: c0=0.95754206; c1=0.05426060; c2=-0.00385945; break; default: c0 = 0.056873*logf(_m+1e-3f) + 0.781388; c1 = 0.05426f; c2 = -0.00386f; } float b = logf(_beta); float rho_hat = c0 + c1*b + c2*b*b; // ensure estimate is in [0,1] if (rho_hat < 0.0f) { rho_hat = 0.0f; } else if (rho_hat > 1.0f) { rho_hat = 1.0f; } return rho_hat; } // Design frequency-shifted root-Nyquist filter based on // the Kaiser-windowed sinc. // // _k : filter over-sampling rate (samples/symbol) // _m : filter delay (symbols) // _beta : filter excess bandwidth factor (0,1) // _dt : filter fractional sample delay // _h : resulting filter [size: 2*_k*_m+1] // _rho : transition bandwidth adjustment, 0 < _rho < 1 void liquid_firdes_rkaiser_bisection(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h, float * _rho) { if ( _k < 1 ) { fprintf(stderr,"error: liquid_firdes_rkaiser_bisection(): k must be greater than 0\n"); exit(1); } else if ( _m < 1 ) { fprintf(stderr,"error: liquid_firdes_rkaiser_bisection(): m must be greater than 0\n"); exit(1); } else if ( (_beta < 0.0f) || (_beta > 1.0f) ) { fprintf(stderr,"error: liquid_firdes_rkaiser_bisection(): beta must be in [0,1]\n"); exit(1); } else; // algorithm: // 1. choose three initial points [x0, x1, x2] where x0 < x1 < x2 // 2. choose xa = 0.5*(x0 + x1), bisection of [x0 x1] // 3. choose xb = 0.5*(x1 + x2), bisection of [x1 x2] // 4. x0 < xa < x1 < xb < x2 // 5. evaluate points to obtain [y0, ya, y1, yb, y2] // 6. find minimum of three midpoints [ya, y1, yb] // 7. update initial points [x0, x1, x2] and go to step 2 unsigned int i; unsigned int n=2*_k*_m+1; // filter length // compute bandwidth adjustment estimate float rho_hat = rkaiser_approximate_rho(_m,_beta); // bandwidth adjustment float x0 = 0.5f * rho_hat; // lower bound, old: rho_hat*0.9f; float x1 = rho_hat; // midpoint: use initial estimate float x2 = 1.0f; // upper bound, old: 1.0f - 0.9f*(1.0f-rho_hat); //x1 = 0.5f*(x0 + x2); // bisect [x0,x1] // evaluate performance (ISI) of each bandwidth adjustment float y0 = liquid_firdes_rkaiser_internal_isi(_k,_m,_beta,_dt,x0,_h); float y1 = liquid_firdes_rkaiser_internal_isi(_k,_m,_beta,_dt,x1,_h); float y2 = liquid_firdes_rkaiser_internal_isi(_k,_m,_beta,_dt,x2,_h); // run parabolic search to find bandwidth adjustment x_hat which // minimizes the inter-symbol interference of the filter unsigned int p, pmax=14; float x_hat = rho_hat; float xa, xb; float ya, yb; #if DEBUG_RKAISER FILE * fid = fopen("rkaiser_debug.m", "w"); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"x = [%12.4e %12.4e %12.4e];\n", x0, x1, x2); fprintf(fid,"y = [%12.4e %12.4e %12.4e];\n", y0, y1, y2); #endif for (p=0; p y0 || y1 > y2) fprintf(stderr,"warning: liquid_firdes_rkaiser_bisection(): bounding region is ill-conditioned\n"); // choose midway points xa, xb and compute ISI xa = 0.5f*(x0 + x1); // bisect [x0,x1] xb = 0.5f*(x1 + x2); // bisect [x1,x2] ya = liquid_firdes_rkaiser_internal_isi(_k,_m,_beta,_dt,xa,_h); yb = liquid_firdes_rkaiser_internal_isi(_k,_m,_beta,_dt,xb,_h); #if DEBUG_RKAISER fprintf(fid,"x = [x %12.4e %12.4e];\n", xa, xb); fprintf(fid,"y = [y %12.4e %12.4e];\n", ya, yb); #endif // find the minimum of [ya,y1,yb], update bounds if (y1 < ya && y1 < yb) { x0 = xa; y0 = ya; x2 = xb; y2 = yb; } else if (ya < yb) { x2 = x1; y2 = y1; x1 = xa; y1 = ya; } else { x0 = x1; y0 = y1; x1 = xb; y1 = yb; } x_hat = x1; #if DEBUG_RKAISER float y_hat = liquid_firdes_rkaiser_internal_isi(_k,_m,_beta,_dt,x_hat,_h); printf(" %4u : rho=%12.8f, isi=%12.6f dB\n", p+1, x_hat, 20*log10f(y_hat)); #endif }; #if DEBUG_RKAISER fprintf(fid,"figure;\n"); fprintf(fid,"plot(x,20*log10(y),'x');\n"); fclose(fid); printf("results written to rkaiser_debug.m\n"); #endif // re-design filter with optimal value for rho liquid_firdes_rkaiser_internal_isi(_k,_m,_beta,_dt,x_hat,_h); // normalize filter magnitude float e2 = 0.0f; for (i=0; i 1.0f) ) { fprintf(stderr,"error: liquid_firdes_rkaiser_quadratic(): beta must be in [0,1]\n"); exit(1); } else; // algorithm: // 1. choose initial bounding points [x0,x2] where x0 < x2 // 2. choose x1 as bisection of [x0,x2]: x1 = 0.5*(x0+x2) // 3. choose x_hat as solution to quadratic equation (x0,y0), (x1,y1), (x2,y2) // 4. re-select boundary: (x0,y0) <- (x1,y1) if x_hat > x1 // (x2,y2) <- (x1,y1) otherwise // 5. go to step 2 unsigned int i; unsigned int n=2*_k*_m+1; // filter length // compute bandwidth adjustment estimate float rho_hat = rkaiser_approximate_rho(_m,_beta); float rho_opt = rho_hat; // bandwidth adjustment float x0; // lower bound float x1 = rho_hat; // initial estimate float x2; // upper bound // evaluate performance (ISI) of each bandwidth adjustment float y0; float y1; float y2; float y_opt = 0.0f; // run parabolic search to find bandwidth adjustment x_hat which // minimizes the inter-symbol interference of the filter unsigned int p, pmax=14; float x_hat = rho_hat; float dx = 0.2f; // bounding size float del = 0.0f; // computed step size float tol = 1e-6f; // tolerance #if DEBUG_RKAISER FILE * fid = fopen("rkaiser_debug.m", "w"); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"x = [];\n"); fprintf(fid,"y = [];\n"); #endif for (p=0; p= 1.0f) x2 = 0.99f; // evaluate all points y0 = liquid_firdes_rkaiser_internal_isi(_k,_m,_beta,_dt,x0,_h); y1 = liquid_firdes_rkaiser_internal_isi(_k,_m,_beta,_dt,x1,_h); y2 = liquid_firdes_rkaiser_internal_isi(_k,_m,_beta,_dt,x2,_h); // save optimum if (p==0 || y1 < y_opt) { rho_opt = x1; y_opt = y1; } #if DEBUG_RKAISER fprintf(fid,"x = [x %12.4e %12.4e %12.4e];\n", x0, x1, x2); fprintf(fid,"y = [y %12.4e %12.4e %12.4e];\n", y0, y1, y2); //printf(" %4u : [%8.4f %8.4f %8.4f] rho=%12.8f, isi=%12.6f dB\n", p+1, x0, x1, x2, x1, 20*log10f(y1)); printf(" %4u : [%8.4f,%8.2f] [%8.4f,%8.2f] [%8.4f,%8.2f]\n", p+1, x0, 20*log10f(y0), x1, 20*log10f(y1), x2, 20*log10f(y2)); #endif // compute minimum of quadratic function double ta = y0*(x1*x1 - x2*x2) + y1*(x2*x2 - x0*x0) + y2*(x0*x0 - x1*x1); double tb = y0*(x1 - x2) + y1*(x2 - x0) + y2*(x0 - x1); // update estimate x_hat = 0.5f * ta / tb; // ensure x_hat is within boundary (this will fail if y1 > y0 || y1 > y2) if (x_hat < x0 || x_hat > x2) { //fprintf(stderr,"warning: liquid_firdes_rkaiser_quadratic(), quadratic minimum outside boundary\n"); break; } // break if step size is sufficiently small del = x_hat - x1; if (p > 3 && fabsf(del) < tol) break; // update estimate, reduce bound x1 = x_hat; dx *= 0.5f; }; #if DEBUG_RKAISER fprintf(fid,"figure;\n"); fprintf(fid,"plot(x,20*log10(y),'x');\n"); fclose(fid); printf("results written to rkaiser_debug.m\n"); #endif // re-design filter with optimal value for rho liquid_firdes_rkaiser_internal_isi(_k,_m,_beta,_dt,rho_opt,_h); // normalize filter magnitude float e2 = 0.0f; for (i=0; i 1.0f) { fprintf(stderr,"warning: liquid_firdes_rkaiser_internal_isi(), rho > 1\n"); } unsigned int n=2*_k*_m+1; // filter length float kf = (float)_k; // samples/symbol (float) float del = _beta*_rho / kf; // transition bandwidth float As = estimate_req_filter_As(del, n); // stop-band suppression float fc = 0.5f*(1 + _beta*(1.0f-_rho))/kf; // filter cutoff // evaluate performance (ISI) float isi_max; float isi_rms; // compute filter liquid_firdes_kaiser(n,fc,As,_dt,_h); // compute filter ISI liquid_filter_isi(_h,_k,_m,&isi_rms,&isi_max); // return RMS of ISI return isi_rms; } liquid-dsp-1.3.1/src/filter/src/rrcos.c000066400000000000000000000062401317124540100177260ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Design root raised-cosine filter // #include #include #include // Design root-Nyquist raised-cosine filter // _k : samples/symbol // _m : symbol delay // _beta : rolloff factor (0 < beta <= 1) // _dt : fractional sample delay // _h : output coefficient buffer (length: 2*k*m+1) void liquid_firdes_rrcos(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h) { if ( _k < 1 ) { fprintf(stderr,"error: liquid_firdes_rrcos(): k must be greater than 0\n"); exit(1); } else if ( _m < 1 ) { fprintf(stderr,"error: liquid_firdes_rrcos(): m must be greater than 0\n"); exit(1); } else if ( (_beta < 0.0f) || (_beta > 1.0f) ) { fprintf(stderr,"error: liquid_firdes_rrcos(): beta must be in [0,1]\n"); exit(1); } else; unsigned int n; float z, t1, t2, t3, t4, T=1.0f; float nf, kf, mf; unsigned int h_len = 2*_k*_m + 1; // Calculate filter coefficients for (n=0; n #include #include #include #define DEBUG_SYMSYNC 0 #define DEBUG_SYMSYNC_PRINT 0 #define DEBUG_SYMSYNC_FILENAME "symsync_internal_debug.m" #define DEBUG_BUFFER_LEN (1024) // // forward declaration of internal methods // // step synchronizer // _q : symsync object // _x : input sample // _y : output sample array pointer // _ny : number of output samples written void SYMSYNC(_step)(SYMSYNC() _q, TI _x, TO * _y, unsigned int * _ny); // advance synchronizer's internal loop filter // _q : synchronizer object // _mf : matched-filter output // _dmf : derivative matched-filter output void SYMSYNC(_advance_internal_loop)(SYMSYNC() _q, TO _mf, TO _dmf); // print results to output debugging file // _q : synchronizer object // _filename : output filename void SYMSYNC(_output_debug_file)(SYMSYNC() _q, const char * _filename); // internal structure struct SYMSYNC(_s) { unsigned int h_len; // matched filter length unsigned int k; // samples/symbol (input) unsigned int k_out; // samples/symbol (output) unsigned int decim_counter; // decimation counter int is_locked; // synchronizer locked flag float rate; // internal resampling rate float del; // fractional delay step // floating-point timing phase float tau; // accumulated timing phase (0 <= tau <= 1) float tau_decim; // timing phase, retained for get_tau() method float bf; // soft filterbank index int b; // filterbank index // loop filter float q; // instantaneous timing error float q_hat; // filtered timing error float B[3]; // loop filter feed-forward coefficients float A[3]; // loop filter feed-back coefficients iirfiltsos_rrrf pll; // loop filter object (iir filter) float rate_adjustment; // internal rate adjustment factor unsigned int npfb; // number of filters in the bank FIRPFB() mf; // matched filter FIRPFB() dmf; // derivative matched filter #if DEBUG_SYMSYNC windowf debug_rate; windowf debug_del; windowf debug_tau; windowf debug_bsoft; windowf debug_b; windowf debug_q_hat; #endif }; // create synchronizer object from external coefficients // _k : samples per symbol // _M : number of filters in the bank // _h : matched filter coefficients // _h_len : length of matched filter SYMSYNC() SYMSYNC(_create)(unsigned int _k, unsigned int _M, TC * _h, unsigned int _h_len) { // validate input if (_k < 2) { fprintf(stderr,"error: symsync_%s_create(), input sample rate must be at least 2\n", EXTENSION_FULL); exit(1); } else if (_h_len == 0) { fprintf(stderr,"error: symsync_%s_create(), filter length must be greater than zero\n", EXTENSION_FULL); exit(1); } else if ( (_h_len-1) % _M ) { fprintf(stderr,"error: symsync_%s_create(), filter length must be of the form: h_len = m*_k*_M + 1 \n", EXTENSION_FULL); exit(1); } else if (_M == 0) { fprintf(stderr,"error: symsync_%s_create(), number of filter banks must be greater than zero\n", EXTENSION_FULL); exit(1); } // create main object SYMSYNC() q = (SYMSYNC()) malloc(sizeof(struct SYMSYNC(_s))); // set internal properties q->k = _k; // input samples per symbol q->npfb = _M; // number of filters in the polyphase filter bank // set output rate (nominally 1, full decimation) SYMSYNC(_set_output_rate)(q, 1); // set internal sub-filter length q->h_len = (_h_len-1)/q->npfb; // compute derivative filter TC dh[_h_len]; float hdh_max = 0.0f; unsigned int i; for (i=0; i<_h_len; i++) { if (i==0) { dh[i] = _h[i+1] - _h[_h_len-1]; } else if (i==_h_len-1) { dh[i] = _h[0] - _h[i-1]; } else { dh[i] = _h[i+1] - _h[i-1]; } // find maximum of h*dh if ( fabsf(_h[i]*dh[i]) > hdh_max || i==0 ) hdh_max = fabsf(_h[i]*dh[i]); } // apply scaling factor for normalized response for (i=0; i<_h_len; i++) dh[i] *= 0.06f / hdh_max; q->mf = FIRPFB(_create)(q->npfb, _h, _h_len); q->dmf = FIRPFB(_create)(q->npfb, dh, _h_len); // reset state and initialize loop filter q->A[0] = 1.0f; q->B[0] = 0.0f; q->A[1] = 0.0f; q->B[1] = 0.0f; q->A[2] = 0.0f; q->B[2] = 0.0f; q->pll = iirfiltsos_rrrf_create(q->B, q->A); SYMSYNC(_reset)(q); SYMSYNC(_set_lf_bw)(q, 0.01f); // unlock loop control SYMSYNC(_unlock)(q); #if DEBUG_SYMSYNC q->debug_rate = windowf_create(DEBUG_BUFFER_LEN); q->debug_del = windowf_create(DEBUG_BUFFER_LEN); q->debug_tau = windowf_create(DEBUG_BUFFER_LEN); q->debug_bsoft = windowf_create(DEBUG_BUFFER_LEN); q->debug_b = windowf_create(DEBUG_BUFFER_LEN); q->debug_q_hat = windowf_create(DEBUG_BUFFER_LEN); #endif // return main object return q; } // create square-root Nyquist symbol synchronizer // _type : filter type (e.g. LIQUID_RNYQUIST_RRC) // _k : samples/symbol // _m : symbol delay // _beta : rolloff factor (0 < beta <= 1) // _M : number of filters in the bank SYMSYNC() SYMSYNC(_create_rnyquist)(int _type, unsigned int _k, unsigned int _m, float _beta, unsigned int _M) { // validate input if (_k < 2) { fprintf(stderr,"error: symsync_%s_create_rnyquist(), samples/symbol must be at least 2\n", EXTENSION_FULL); exit(1); } else if (_m == 0) { fprintf(stderr,"error: symsync_%s_create_rnyquist(), filter delay (m) must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_beta < 0.0f || _beta > 1.0f) { fprintf(stderr,"error: symsync_%s_create_rnyquist(), filter excess bandwidth must be in [0,1]\n", EXTENSION_FULL); exit(1); } // allocate memory for filter coefficients unsigned int H_len = 2*_M*_k*_m + 1; float Hf[H_len]; // design square-root Nyquist pulse-shaping filter liquid_firdes_prototype(_type, _k*_M, _m, _beta, 0, Hf); // copy coefficients to type-specific array TC H[H_len]; unsigned int i; for (i=0; i 1.0f) { fprintf(stderr,"error: symsync_%s_create_kaiser(), filter excess bandwidth must be in [0,1]\n", EXTENSION_FULL); exit(1); } // allocate memory for filter coefficients unsigned int H_len = 2*_M*_k*_m + 1; float Hf[H_len]; // design interpolating filter whose bandwidth is outside the cut-off // frequency of input signal // TODO: use _beta to compute more accurate cut-off frequency float fc = 0.75f; // filter cut-off frequency (nominal) float As = 40.0f; // filter stop-band attenuation liquid_firdes_kaiser(H_len, fc / (float)(_k*_M), As, 0.0f, Hf); // copy coefficients to type-specific array, adjusting to relative // filter gain unsigned int i; TC H[H_len]; for (i=0; idebug_rate); windowf_destroy(_q->debug_del); windowf_destroy(_q->debug_tau); windowf_destroy(_q->debug_bsoft); windowf_destroy(_q->debug_b); windowf_destroy(_q->debug_q_hat); #endif // destroy filterbank objects FIRPFB(_destroy)(_q->mf); FIRPFB(_destroy)(_q->dmf); // destroy timing phase-locked loop filter iirfiltsos_rrrf_destroy(_q->pll); // free main object memory free(_q); } // print symsync object's parameters void SYMSYNC(_print)(SYMSYNC() _q) { printf("symsync_%s [rate: %f]\n", EXTENSION_FULL, _q->rate); FIRPFB(_print)(_q->mf); } // reset symsync internal state void SYMSYNC(_reset)(SYMSYNC() _q) { // reset polyphase filterbank FIRPFB(_reset)(_q->mf); // reset counters, etc. _q->rate = (float)_q->k / (float)_q->k_out; _q->del = _q->rate; _q->b = 0; // filterbank index _q->bf = 0.0f; // filterbank index (soft value) _q->tau = 0.0f; // instantaneous timing estimate _q->tau_decim = 0.0f; // instantaneous timing estaimte (decimated) _q->q = 0.0f; // timing error _q->q_hat = 0.0f; // filtered timing error _q->decim_counter = 0; // decimated output counter // reset timing phase-locked loop filter iirfiltsos_rrrf_reset(_q->pll); } // lock synchronizer object void SYMSYNC(_lock)(SYMSYNC() _q) { _q->is_locked = 1; } // unlock synchronizer object void SYMSYNC(_unlock)(SYMSYNC() _q) { _q->is_locked = 0; } // set synchronizer output rate (samples/symbol) // _q : synchronizer object // _k_out : output samples/symbol void SYMSYNC(_set_output_rate)(SYMSYNC() _q, unsigned int _k_out) { // validate input if (_k_out == 0) { fprintf(stderr,"error: symsync_%s_output_rate(), output rate must be greater than 0\n", EXTENSION_FULL); exit(1); } // set output rate _q->k_out = _k_out; _q->rate = (float)_q->k / (float)_q->k_out; _q->del = _q->rate; } // set synchronizer loop filter bandwidth // _q : synchronizer object // _bt : loop bandwidth void SYMSYNC(_set_lf_bw)(SYMSYNC() _q, float _bt) { // validate input if (_bt < 0.0f || _bt > 1.0f) { fprintf(stderr,"error: symsync_%s_set_lf_bt(), bandwidth must be in [0,1]\n", EXTENSION_FULL); exit(1); } // compute filter coefficients from bandwidth float alpha = 1.000f - _bt; float beta = 0.220f * _bt; float a = 0.500f; float b = 0.495f; _q->B[0] = beta; _q->B[1] = 0.00f; _q->B[2] = 0.00f; _q->A[0] = 1.00f - a*alpha; _q->A[1] = -b*alpha; _q->A[2] = 0.00f; // set internal parameters of 2nd-order IIR filter iirfiltsos_rrrf_set_coefficients(_q->pll, _q->B, _q->A); // update rate adjustment factor _q->rate_adjustment = 0.5*_bt; } // return instantaneous fractional timing offset estimate float SYMSYNC(_get_tau)(SYMSYNC() _q) { return _q->tau_decim; } // execute synchronizer on input data array // _q : synchronizer object // _x : input data array // _nx : number of input samples // _y : output data array // _ny : number of samples written to output buffer void SYMSYNC(_execute)(SYMSYNC() _q, TI * _x, unsigned int _nx, TO * _y, unsigned int * _ny) { unsigned int i, ny=0, k=0; for (i=0; i<_nx; i++) { SYMSYNC(_step)(_q, _x[i], &_y[ny], &k); ny += k; //printf("%u\n",k); } *_ny = ny; } // // internal methods // // step synchronizer with single input sample // _q : symsync object // _x : input sample // _y : output sample array pointer // _ny : number of output samples written void SYMSYNC(_step)(SYMSYNC() _q, TI _x, TO * _y, unsigned int * _ny) { // push sample into MF and dMF filterbanks FIRPFB(_push)(_q->mf, _x); FIRPFB(_push)(_q->dmf, _x); // matched and derivative matched-filter outputs TO mf; // matched filter output TO dmf; // derivative matched filter output unsigned int n=0; // continue loop until filterbank index rolls over while (_q->b < _q->npfb) { #if DEBUG_SYMSYNC_PRINT printf(" [%2u] : tau : %12.8f, b : %4u (%12.8f)\n", n, _q->tau, _q->b, _q->bf); #endif // compute filterbank output FIRPFB(_execute)(_q->mf, _q->b, &mf); // scale output by samples/symbol _y[n] = mf / (float)(_q->k); // check output count and determine if this is 'ideal' timing output if (_q->decim_counter == _q->k_out) { // reset counter _q->decim_counter = 0; #if DEBUG_SYMSYNC // save debugging variables windowf_push(_q->debug_rate, _q->rate); windowf_push(_q->debug_del, _q->del); windowf_push(_q->debug_tau, _q->tau); windowf_push(_q->debug_bsoft, _q->bf); windowf_push(_q->debug_b, _q->b); windowf_push(_q->debug_q_hat, _q->q_hat); #endif // if synchronizer is locked, don't update internal timing offset if (_q->is_locked) continue; // compute dMF output FIRPFB(_execute)(_q->dmf, _q->b, &dmf); // update internal state SYMSYNC(_advance_internal_loop)(_q, mf, dmf); _q->tau_decim = _q->tau; // save return value } // increment decimation counter _q->decim_counter++; // update states _q->tau += _q->del; // instantaneous fractional offset _q->bf = _q->tau * (float)(_q->npfb); // filterbank index (soft) _q->b = (int)roundf(_q->bf); // filterbank index n++; // number of output samples } // filterbank index rolled over; update states _q->tau -= 1.0f; // instantaneous fractional offset _q->bf -= (float)(_q->npfb); // filterbank index (soft) _q->b -= _q->npfb; // filterbank index // set output number of samples written *_ny = n; } // advance synchronizer's internal loop filter // _q : synchronizer object // _mf : matched-filter output // _dmf : derivative matched-filter output void SYMSYNC(_advance_internal_loop)(SYMSYNC() _q, TO _mf, TO _dmf) { // 1. compute timing error signal, clipping large levels #if 0 _q->q = crealf(_mf)*crealf(_dmf) + cimagf(_mf)*cimagf(_dmf); #else // TODO : use more efficient method to compute this _q->q = crealf( conjf(_mf)*_dmf ); // [Mengali:1997] Eq.~(8.3.5) #endif // constrain timing error if (_q->q > 1.0f) _q->q = 1.0f; // clip large positive values else if (_q->q < -1.0f) _q->q = -1.0f; // clip large negative values // 2. filter error signal through timing loop filter: retain large // portion of old estimate and small percent of new estimate iirfiltsos_rrrf_execute(_q->pll, _q->q, &_q->q_hat); // 3. update rate and timing phase _q->rate += _q->rate_adjustment * _q->q_hat; _q->del = _q->rate + _q->q_hat; #if DEBUG_SYMSYNC_PRINT printf("q : %12.8f, rate : %12.8f, del : %12.8f, q_hat : %12.8f\n", _q->q, _q->rate, _q->del, _q->q_hat); #endif } // print results to output debugging file // _q : synchronizer object // _filename : output filename void SYMSYNC(_output_debug_file)(SYMSYNC() _q, const char * _filename) { FILE * fid = fopen(_filename, "w"); if (!fid) { fprintf(stderr,"error: symsync_%s_output_debug_file(), could not open '%s' for writing\n", EXTENSION_FULL, _filename); return; } fprintf(fid,"%% %s, auto-generated file\n\n", DEBUG_SYMSYNC_FILENAME); fprintf(fid,"\n"); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"npfb = %u;\n",_q->npfb); fprintf(fid,"k = %u;\n",_q->k); fprintf(fid,"\n\n"); #if DEBUG_SYMSYNC fprintf(fid,"n = %u;\n", DEBUG_BUFFER_LEN); float * r; unsigned int i; // save filter responses FIRPFB(_reset)(_q->mf); FIRPFB(_reset)(_q->dmf); fprintf(fid,"h = [];\n"); fprintf(fid,"dh = [];\n"); fprintf(fid,"h_len = %u;\n", _q->h_len); for (i=0; i<_q->h_len; i++) { // push impulse if (i==0) { FIRPFB(_push)(_q->mf, 1.0f); FIRPFB(_push)(_q->dmf, 1.0f); } else { FIRPFB(_push)(_q->mf, 0.0f); FIRPFB(_push)(_q->dmf, 0.0f); } // compute output for all filters TO mf; // matched filter output TO dmf; // derivative matched filter output unsigned int n; for (n=0; n<_q->npfb; n++) { FIRPFB(_execute)(_q->mf, n, &mf); FIRPFB(_execute)(_q->dmf, n, &dmf); fprintf(fid,"h(%4u) = %12.8f; dh(%4u) = %12.8f;\n", i*_q->npfb+n+1, crealf(mf), i*_q->npfb+n+1, crealf(dmf)); } } // plot response fprintf(fid,"\n"); fprintf(fid,"figure;\n"); fprintf(fid,"th = [0:(h_len*npfb-1)]/(k*npfb) - h_len/(2*k);\n"); fprintf(fid,"m = abs(round(th(1)));\n"); //fprintf(fid,"plot(t,h,t,dh);\n"); fprintf(fid,"subplot(3,1,1),\n"); fprintf(fid," plot(th, h, 'LineWidth', 2, 'Color', [0 0.5 0.2]);\n"); fprintf(fid," ylabel('MF');\n"); fprintf(fid," axis([-m m -0.25 1.25]);\n"); fprintf(fid," grid on;\n"); fprintf(fid,"subplot(3,1,2),\n"); fprintf(fid," plot(th, dh, 'LineWidth', 2, 'Color', [0 0.2 0.5]);\n"); fprintf(fid," ylabel('dMF');\n"); fprintf(fid," axis([-m m -0.10 0.10]);\n"); fprintf(fid," grid on;\n"); fprintf(fid,"subplot(3,1,3),\n"); fprintf(fid," plot(th,-h.*dh, 'LineWidth', 2, 'Color', [0.5 0 0]);\n"); fprintf(fid," xlabel('Symbol Index');\n"); fprintf(fid," ylabel('-MF*dMF');\n"); fprintf(fid," axis([-m m -0.08 0.08]);\n"); fprintf(fid," grid on;\n"); // print rate buffer fprintf(fid,"rate = zeros(1,n);\n"); windowf_read(_q->debug_rate, &r); for (i=0; idebug_del, &r); for (i=0; idebug_tau, &r); for (i=0; idebug_bsoft, &r); for (i=0; idebug_b, &r); for (i=0; idebug_q_hat, &r); for (i=0; i float complex fftfilt_cccf_data_h13x256_h[] = { 0.101274943352 + -0.122793912888*_Complex_I, 0.058305418491 + -0.133282411098*_Complex_I, 0.040646758676 + -0.024372637272*_Complex_I, 0.079661983252 + -0.054072910547*_Complex_I, 0.001840994880 + 0.061087465286*_Complex_I, -0.087824678421 + -0.017600339651*_Complex_I, 0.218935108185 + -0.191448485851*_Complex_I, 0.063519352674 + 0.238570642471*_Complex_I, 0.062901532650 + 0.024227905273*_Complex_I, 0.047201344371 + -0.122910189629*_Complex_I, -0.052710837126 + -0.028337442875*_Complex_I, 0.155722010136 + -0.206684422493*_Complex_I, 0.158807659149 + -0.032457110286*_Complex_I}; float complex fftfilt_cccf_data_h13x256_x[] = { 0.033812573552 + 0.167574334145*_Complex_I, -0.180972433090 + 0.003268009797*_Complex_I, -0.158811461926 + 0.096975576878*_Complex_I, 0.089864820242 + -0.129931354523*_Complex_I, -0.048388853669 + 0.209818410873*_Complex_I, -0.174670159817 + -0.000558722531*_Complex_I, 0.184307169914 + -0.097096782923*_Complex_I, 0.055431371927 + -0.085229063034*_Complex_I, -0.005678167194 + -0.008018184453*_Complex_I, -0.069053018093 + 0.055740833282*_Complex_I, -0.064427644014 + 0.147326159477*_Complex_I, 0.257856726646 + -0.008164577186*_Complex_I, -0.001989185810 + -0.019182929397*_Complex_I, 0.034131622314 + -0.019393232465*_Complex_I, 0.107628858089 + 0.122120463848*_Complex_I, 0.023927879333 + 0.069706928730*_Complex_I, -0.053020107746 + -0.083087205887*_Complex_I, -0.080838572979 + -0.011525543034*_Complex_I, 0.031260085106 + 0.001133395731*_Complex_I, -0.001233685296 + -0.189275312424*_Complex_I, -0.038783121109 + 0.028758850694*_Complex_I, 0.036648643017 + -0.011882914603*_Complex_I, -0.020449468493 + 0.139192247391*_Complex_I, -0.075582921505 + -0.002107951231*_Complex_I, -0.181470632553 + -0.014771178365*_Complex_I, 0.026783564687 + -0.128984892368*_Complex_I, -0.047539860010 + 0.222328519821*_Complex_I, 0.005170624331 + 0.030745416880*_Complex_I, 0.053824990988 + -0.026686629653*_Complex_I, 0.099266970158 + -0.031245106459*_Complex_I, 0.039606907964 + -0.065418809652*_Complex_I, -0.127475917339 + 0.064139616489*_Complex_I, -0.042834937572 + -0.150583517551*_Complex_I, 0.139883732796 + 0.082940441370*_Complex_I, -0.064364117384 + -0.044677674770*_Complex_I, 0.055855596066 + 0.017247803509*_Complex_I, -0.173977994919 + -0.052533900738*_Complex_I, 0.027730098367 + 0.080870586634*_Complex_I, -0.091971349716 + -0.051875424385*_Complex_I, 0.051230835915 + -0.061945867538*_Complex_I, -0.044583868980 + -0.032021436095*_Complex_I, 0.068678015471 + -0.015937516093*_Complex_I, 0.019641043246 + 0.090001666546*_Complex_I, -0.050730788708 + -0.067964708805*_Complex_I, -0.117348599434 + 0.225804829597*_Complex_I, -0.024700947106 + -0.226277422905*_Complex_I, 0.044463178515 + 0.038473030925*_Complex_I, 0.146118962765 + 0.228452873230*_Complex_I, 0.148312568665 + -0.089482551813*_Complex_I, 0.002765571699 + 0.218297338486*_Complex_I, -0.058677202463 + -0.040143096447*_Complex_I, 0.151873219013 + 0.038929876685*_Complex_I, -0.054030978680 + 0.087771093845*_Complex_I, 0.053254860640 + -0.107342064381*_Complex_I, -0.004281488806 + -0.147849392891*_Complex_I, 0.124097406864 + -0.161590623856*_Complex_I, -0.083864957094 + 0.077308541536*_Complex_I, 0.091537797451 + 0.140995931625*_Complex_I, -0.099840551615 + 0.043124458194*_Complex_I, -0.121636021137 + 0.081380259991*_Complex_I, -0.011938279122 + 0.019365566969*_Complex_I, -0.029302325845 + -0.002548613772*_Complex_I, 0.039761963487 + 0.151991939545*_Complex_I, 0.057192808390 + -0.059029465914*_Complex_I, -0.095872926712 + -0.044790551066*_Complex_I, 0.095753777027 + -0.164024686813*_Complex_I, 0.037644055486 + -0.033171021938*_Complex_I, 0.071704179049 + 0.047472149134*_Complex_I, -0.072857999802 + 0.045551717281*_Complex_I, -0.004142929241 + -0.048290520906*_Complex_I, -0.180688798428 + 0.006293178350*_Complex_I, 0.038382813334 + 0.122165417671*_Complex_I, -0.050295007229 + -0.127239310741*_Complex_I, -0.109994089603 + -0.176806294918*_Complex_I, 0.085634392500 + -0.091329562664*_Complex_I, -0.137377023697 + 0.066401362419*_Complex_I, 0.109237027168 + -0.000195262639*_Complex_I, -0.111181199551 + 0.181575310230*_Complex_I, -0.088704961538 + 0.101208889484*_Complex_I, 0.227800679207 + 0.017428271472*_Complex_I, -0.072724056244 + -0.158883297443*_Complex_I, -0.046088048816 + 0.034102421999*_Complex_I, -0.086277353764 + 0.048207068443*_Complex_I, 0.189791500568 + 0.111536753178*_Complex_I, 0.043753921986 + 0.042386168242*_Complex_I, 0.175305640697 + -0.077729618549*_Complex_I, -0.090353775024 + -0.086115002632*_Complex_I, 0.163218414783 + 0.005952451378*_Complex_I, -0.010694872588 + 0.037079387903*_Complex_I, -0.067783647776 + 0.015387859941*_Complex_I, -0.001508052554 + 0.005860465765*_Complex_I, -0.103225553036 + -0.091570162773*_Complex_I, -0.181873428822 + -0.033351799846*_Complex_I, 0.014190819860 + -0.107816028595*_Complex_I, 0.049625259638 + -0.131252551079*_Complex_I, -0.003888563812 + -0.083181303740*_Complex_I, -0.044093203545 + 0.053719127178*_Complex_I, -0.059636509418 + -0.062606734037*_Complex_I, 0.043757092953 + 0.143932354450*_Complex_I, 0.023032055795 + -0.073675203323*_Complex_I, 0.074079465866 + -0.133735966682*_Complex_I, -0.016778314114 + -0.077572107315*_Complex_I, -0.213720870018 + -0.010327737033*_Complex_I, -0.011057607085 + 0.039916378260*_Complex_I, 0.108575832844 + -0.097652089596*_Complex_I, 0.169485592842 + 0.195236229897*_Complex_I, -0.094353854656 + -0.053460478783*_Complex_I, -0.111175501347 + -0.177497363091*_Complex_I, 0.004201298580 + -0.125308763981*_Complex_I, 0.051966518164 + 0.123850774765*_Complex_I, -0.096300393343 + -0.013914050162*_Complex_I, 0.106172311306 + -0.164844048023*_Complex_I, 0.124734151363 + -0.008266538382*_Complex_I, -0.008394107223 + 0.042837706208*_Complex_I, -0.269948434830 + -0.133680295944*_Complex_I, 0.077266824245 + 0.018269205093*_Complex_I, -0.018016268313 + -0.040084049106*_Complex_I, 0.095163732767 + 0.081313228607*_Complex_I, -0.208993816376 + -0.040263220668*_Complex_I, 0.064939141273 + -0.018769615889*_Complex_I, -0.037253284454 + -0.092296826839*_Complex_I, 0.123162364960 + 0.068240380287*_Complex_I, -0.132501530647 + -0.228929615021*_Complex_I, 0.168357527256 + -0.092901027203*_Complex_I, 0.088688296080 + -0.001608422026*_Complex_I, 0.221683001518 + 0.066785657406*_Complex_I, 0.083319008350 + -0.164619421959*_Complex_I, -0.057560896873 + 0.080689120293*_Complex_I, 0.017244935036 + -0.052605807781*_Complex_I, -0.103263401985 + 0.128316771984*_Complex_I, -0.048902520537 + 0.101460754871*_Complex_I, -0.101036417484 + 0.059622770548*_Complex_I, -0.006965886056 + 0.062334090471*_Complex_I, 0.098089504242 + 0.189659333229*_Complex_I, -0.170798206329 + 0.049062070251*_Complex_I, 0.165300846100 + 0.029215490818*_Complex_I, -0.075640136003 + -0.087369698286*_Complex_I, -0.013823843002 + 0.127059864998*_Complex_I, 0.095502263308 + 0.068228989840*_Complex_I, 0.171380794048 + -0.077519750595*_Complex_I, 0.129892742634 + -0.012643009424*_Complex_I, 0.023339818418 + 0.093716734648*_Complex_I, -0.058398854733 + 0.106715428829*_Complex_I, -0.013301552832 + 0.002579919435*_Complex_I, 0.088806277514 + -0.297042322159*_Complex_I, -0.046128720045 + 0.126318335533*_Complex_I, 0.051016080379 + -0.158195829391*_Complex_I, -0.137489342690 + 0.012126408517*_Complex_I, 0.076124078035 + 0.094534236193*_Complex_I, 0.055480271578 + 0.034476712346*_Complex_I, 0.197368288040 + -0.003630393744*_Complex_I, -0.132637274265 + 0.016389763355*_Complex_I, -0.018736995757 + 0.069434946775*_Complex_I, 0.024380022287 + 0.032195645571*_Complex_I, -0.110287964344 + 0.105914473534*_Complex_I, 0.180047070980 + 0.122122013569*_Complex_I, 0.021164430678 + -0.021511299908*_Complex_I, -0.083895099163 + -0.094187325239*_Complex_I, -0.085609924793 + -0.089779102802*_Complex_I, -0.026364889741 + -0.034728026390*_Complex_I, -0.039741188288 + 0.061549043655*_Complex_I, -0.182061326504 + -0.117300724983*_Complex_I, 0.051411151886 + -0.039550358057*_Complex_I, 0.115115880966 + 0.132340645790*_Complex_I, -0.172311210632 + 0.157257282734*_Complex_I, -0.066816413403 + 0.050810027122*_Complex_I, 0.075493675470 + -0.024358917773*_Complex_I, 0.037579393387 + -0.105334246159*_Complex_I, -0.032166060805 + 0.304082226753*_Complex_I, -0.115465772152 + -0.083099174500*_Complex_I, 0.213583827019 + -0.033120486140*_Complex_I, 0.049020007253 + 0.103692758083*_Complex_I, 0.039526313543 + 0.159559214115*_Complex_I, -0.014911358058 + -0.009031812847*_Complex_I, 0.140197467804 + 0.188218057156*_Complex_I, -0.014860840142 + -0.114006638527*_Complex_I, 0.111025202274 + -0.101571118832*_Complex_I, -0.031162160635 + -0.044938939810*_Complex_I, -0.088898491859 + -0.196167945862*_Complex_I, 0.074709993601 + -0.042812746763*_Complex_I, 0.020372083783 + -0.102141439915*_Complex_I, 0.036488103867 + 0.061840379238*_Complex_I, 0.113381445408 + -0.077737921476*_Complex_I, 0.003184536844 + 0.024977919459*_Complex_I, -0.130429613590 + -0.062496966124*_Complex_I, -0.109437787533 + 0.033421832323*_Complex_I, -0.107781338692 + -0.036825361848*_Complex_I, -0.121548032761 + -0.071893042326*_Complex_I, -0.032831138372 + 0.036911919713*_Complex_I, 0.101628661156 + 0.116993212700*_Complex_I, -0.052929800749 + -0.061160600185*_Complex_I, -0.155849313736 + -0.126586461067*_Complex_I, -0.093626201153 + -0.085899829865*_Complex_I, 0.093120694160 + 0.010586068779*_Complex_I, -0.071643483639 + 0.044553604722*_Complex_I, 0.096362644434 + -0.005238156021*_Complex_I, -0.191972267628 + 0.062410986423*_Complex_I, 0.175240826607 + 0.055103266239*_Complex_I, 0.217493343353 + 0.057524204254*_Complex_I, 0.137563228607 + 0.136677563190*_Complex_I, -0.002121994831 + -0.160035789013*_Complex_I, -0.106702613831 + 0.129322338104*_Complex_I, 0.077257323265 + 0.190817809105*_Complex_I, 0.030118304491 + 0.068840289116*_Complex_I, 0.001969731040 + -0.019872169197*_Complex_I, 0.038756659627 + -0.110168564320*_Complex_I, -0.094096481800 + 0.178715145588*_Complex_I, -0.045212453604 + -0.001988123916*_Complex_I, -0.050746786594 + -0.038362777233*_Complex_I, 0.085383939743 + 0.041049334407*_Complex_I, -0.044858980179 + 0.073414093256*_Complex_I, 0.074703049660 + 0.103927171230*_Complex_I, 0.055366307497 + -0.115881478786*_Complex_I, 0.133115530014 + -0.054990023375*_Complex_I, -0.060879433155 + -0.052990645170*_Complex_I, -0.014458604157 + 0.024620576203*_Complex_I, 0.035869082808 + 0.070715308189*_Complex_I, 0.001854417846 + -0.032330670953*_Complex_I, 0.217453384399 + -0.031029167771*_Complex_I, -0.012186873704 + 0.007021924853*_Complex_I, 0.082451862097 + -0.078747928143*_Complex_I, -0.079927939177 + -0.026517114043*_Complex_I, -0.049421241879 + -0.003672285378*_Complex_I, -0.050635516644 + -0.204359102249*_Complex_I, 0.114336001873 + -0.075574308634*_Complex_I, 0.017275553942 + -0.004209178686*_Complex_I, 0.093194973469 + -0.117229437828*_Complex_I, 0.055422365665 + 0.058078074455*_Complex_I, 0.051127582788 + -0.056875407696*_Complex_I, -0.033710032701 + -0.024449241161*_Complex_I, 0.098715597391 + 0.075275701284*_Complex_I, 0.049691435695 + -0.010312996805*_Complex_I, -0.143938088417 + -0.057803511620*_Complex_I, 0.004402134567 + -0.171495795250*_Complex_I, 0.050372958183 + -0.030280271173*_Complex_I, -0.066968792677 + 0.049716952443*_Complex_I, -0.030198466778 + -0.093219310045*_Complex_I, 0.020674671233 + 0.049302938581*_Complex_I, -0.082176977396 + 0.004003078118*_Complex_I, 0.051144361496 + -0.025944027305*_Complex_I, -0.136934876442 + 0.030611222982*_Complex_I, 0.072055798769 + 0.072714412212*_Complex_I, 0.006607705355 + -0.154940152168*_Complex_I, -0.055419456959 + 0.142084217072*_Complex_I, 0.127882242203 + -0.068437719345*_Complex_I, -0.028541901708 + 0.125126791000*_Complex_I, -0.071173512936 + 0.003831871226*_Complex_I, -0.040117982030 + -0.071510893106*_Complex_I, -0.036725261807 + 0.037219762802*_Complex_I, 0.018186755478 + 0.046204718947*_Complex_I, 0.145269620419 + 0.059547924995*_Complex_I, 0.040549764037 + 0.051019173861*_Complex_I, 0.017368020117 + 0.015167059004*_Complex_I, 0.018691918254 + -0.096917903423*_Complex_I, 0.085063648224 + 0.024469487369*_Complex_I, 0.107211554050 + -0.066898560524*_Complex_I}; float complex fftfilt_cccf_data_h13x256_y[] = { 0.024001474660 + 0.012819102986*_Complex_I, 0.006379486345 + 0.027817151043*_Complex_I, -0.008833116513 + 0.059620513709*_Complex_I, 0.001290360957 + 0.018691901680*_Complex_I, -0.019720088289 + 0.027870569701*_Complex_I, -0.000089104333 + 0.022554509191*_Complex_I, 0.048983753430 + 0.008870419475*_Complex_I, -0.059738782036 + 0.031503141884*_Complex_I, -0.072004160761 + 0.015777738903*_Complex_I, -0.011979216083 + -0.114153406857*_Complex_I, 0.084719374355 + 0.122759620341*_Complex_I, -0.002652524124 + 0.074081920456*_Complex_I, -0.010647425116 + -0.055247615062*_Complex_I, 0.009826036454 + 0.077018691837*_Complex_I, 0.043050527194 + -0.030195436945*_Complex_I, 0.096977257426 + 0.014196001707*_Complex_I, -0.069749349540 + 0.084922275308*_Complex_I, -0.020592821729 + -0.078815687497*_Complex_I, 0.015344750806 + 0.046911643882*_Complex_I, 0.003215160982 + -0.044654666098*_Complex_I, 0.045065388666 + -0.014762372700*_Complex_I, -0.000649914548 + 0.078685026348*_Complex_I, 0.004242245469 + -0.018256519858*_Complex_I, 0.068463378080 + 0.002186618045*_Complex_I, -0.013886532699 + -0.006164365808*_Complex_I, -0.023002266230 + -0.024231940574*_Complex_I, 0.059444806653 + 0.063727454712*_Complex_I, 0.005199838368 + -0.013523702394*_Complex_I, -0.014439329476 + 0.017624416202*_Complex_I, -0.021969811821 + 0.031968738864*_Complex_I, -0.099775723814 + -0.032339826558*_Complex_I, -0.023202788664 + -0.102402077252*_Complex_I, 0.039130993156 + 0.049187762643*_Complex_I, -0.024993065771 + 0.041659056463*_Complex_I, -0.035177096744 + 0.034267402820*_Complex_I, -0.012813786527 + 0.035585893453*_Complex_I, -0.010166359548 + -0.030098941996*_Complex_I, 0.035012509492 + 0.104480427481*_Complex_I, -0.067925226605 + -0.033727903935*_Complex_I, 0.038150929611 + -0.034144316119*_Complex_I, -0.031836563804 + 0.003970737127*_Complex_I, 0.022331990340 + -0.044052273250*_Complex_I, -0.024273008320 + 0.027787498353*_Complex_I, -0.035557076930 + -0.024109903696*_Complex_I, -0.015439201027 + 0.010120871946*_Complex_I, -0.005667692817 + 0.009808534446*_Complex_I, -0.023993809759 + -0.001976323260*_Complex_I, 0.033939569756 + 0.006322746502*_Complex_I, 0.038339628046 + -0.021022149468*_Complex_I, 0.000846072793 + 0.018029554697*_Complex_I, 0.053339414921 + 0.071529172443*_Complex_I, -0.104230849664 + -0.080895763503*_Complex_I, 0.071647820798 + -0.030732758724*_Complex_I, 0.101421268066 + 0.054142700304*_Complex_I, -0.070017141172 + -0.048691110375*_Complex_I, 0.071783266356 + 0.132628048489*_Complex_I, -0.125892768778 + -0.020392469132*_Complex_I, 0.077534371443 + -0.106386873570*_Complex_I, 0.118899511278 + 0.091045477209*_Complex_I, 0.019035177150 + 0.019334344232*_Complex_I, 0.072542950409 + 0.021775500164*_Complex_I, 0.018913391291 + -0.008423771096*_Complex_I, 0.068880105631 + 0.006805725914*_Complex_I, 0.070165826853 + -0.001076549347*_Complex_I, -0.092150026143 + 0.032247576962*_Complex_I, -0.065407227079 + -0.006168603538*_Complex_I, -0.051509544946 + -0.131615847220*_Complex_I, -0.001170276180 + -0.019427264753*_Complex_I, 0.083364051792 + 0.041323212038*_Complex_I, 0.007295606110 + 0.057364049960*_Complex_I, -0.057103564464 + 0.118719947312*_Complex_I, 0.004531748675 + -0.012147464062*_Complex_I, 0.012749373222 + -0.030480391526*_Complex_I, 0.011125930632 + 0.028825825693*_Complex_I, -0.043938238280 + 0.011854121979*_Complex_I, -0.075321232264 + -0.018064459135*_Complex_I, -0.060886977242 + -0.042110048390*_Complex_I, 0.056409867179 + -0.045351450134*_Complex_I, -0.018186918127 + 0.057805159108*_Complex_I, -0.000535255779 + 0.017342658310*_Complex_I, 0.044187556819 + -0.080806819744*_Complex_I, -0.077107500264 + 0.074314966560*_Complex_I, -0.000316037199 + -0.033151523412*_Complex_I, 0.004502285827 + 0.096977958968*_Complex_I, -0.093482268512 + 0.004941127824*_Complex_I, 0.021543628024 + -0.127138737110*_Complex_I, -0.024144738766 + 0.045799607631*_Complex_I, 0.073683578652 + -0.012636723694*_Complex_I, 0.037103315594 + -0.019525859806*_Complex_I, -0.000690801053 + 0.046026880071*_Complex_I, 0.026954746660 + 0.048691313027*_Complex_I, 0.007353638085 + 0.001105524364*_Complex_I, -0.054855624724 + 0.041421970378*_Complex_I, 0.022781842217 + -0.038200366123*_Complex_I, 0.008043522754 + -0.024654798773*_Complex_I, -0.026166674166 + 0.009031999284*_Complex_I, 0.015652619885 + -0.077945632696*_Complex_I, -0.049664412838 + -0.015226397097*_Complex_I, -0.011383210898 + -0.016385255644*_Complex_I, 0.020234061901 + -0.066780782463*_Complex_I, -0.046755003222 + -0.039668549878*_Complex_I, -0.003720962630 + -0.011626088440*_Complex_I, -0.053663894051 + 0.033112538916*_Complex_I, -0.121787017031 + 0.003208574048*_Complex_I, -0.028376450272 + -0.019370775859*_Complex_I, -0.047890954007 + -0.041473896341*_Complex_I, 0.011519092293 + -0.078183218332*_Complex_I, 0.028829438437 + 0.001487290342*_Complex_I, -0.075450909852 + 0.021430470386*_Complex_I, -0.034355836889 + -0.040885483718*_Complex_I, -0.058002545755 + -0.068146319622*_Complex_I, 0.075219933002 + -0.010912041314*_Complex_I, -0.036651133000 + 0.019765597603*_Complex_I, -0.098981225134 + -0.018643142319*_Complex_I, -0.032500295138 + -0.084155976688*_Complex_I, 0.049578122325 + -0.016429877737*_Complex_I, -0.013361520737 + 0.029138302084*_Complex_I, -0.043356913875 + -0.030952278560*_Complex_I, 0.014132503851 + -0.028805299647*_Complex_I, -0.017867267512 + 0.026284047653*_Complex_I, -0.083047255042 + -0.017096821986*_Complex_I, 0.008417904103 + -0.048597238033*_Complex_I, -0.089743880041 + -0.096283355401*_Complex_I, 0.035975823890 + -0.056271631450*_Complex_I, -0.015269531402 + 0.017064247022*_Complex_I, -0.053012454761 + -0.057229106407*_Complex_I, -0.020365053756 + -0.125161538208*_Complex_I, 0.066674345673 + 0.011158699255*_Complex_I, -0.036133831454 + -0.011201495817*_Complex_I, 0.016361003153 + -0.025706876818*_Complex_I, 0.044163879016 + 0.016897283579*_Complex_I, 0.016023914791 + 0.021215167172*_Complex_I, 0.029810334754 + 0.009766734291*_Complex_I, 0.035636470208 + 0.060987445145*_Complex_I, -0.006302550511 + -0.115013574847*_Complex_I, 0.051720848730 + -0.009461663454*_Complex_I, 0.047973920047 + -0.016849009904*_Complex_I, -0.046701499921 + 0.016919642862*_Complex_I, 0.043467132678 + -0.016102822186*_Complex_I, 0.067871787511 + 0.010066831600*_Complex_I, -0.035710415892 + 0.082788003225*_Complex_I, 0.069725504265 + -0.005507023393*_Complex_I, 0.015433685804 + 0.073521250471*_Complex_I, 0.063438026419 + 0.060901474404*_Complex_I, 0.041153827196 + -0.018596637068*_Complex_I, -0.048641595104 + 0.055630921150*_Complex_I, 0.070785738691 + -0.021001547792*_Complex_I, 0.030058519696 + 0.002719657788*_Complex_I, 0.033781571029 + 0.057641496421*_Complex_I, -0.011861512115 + -0.000934312027*_Complex_I, 0.026823353697 + -0.148020696569*_Complex_I, 0.149407622218 + -0.001917493861*_Complex_I, 0.031564264895 + -0.033648864447*_Complex_I, 0.013500408643 + 0.049606336179*_Complex_I, 0.018200592161 + 0.054843460925*_Complex_I, -0.042220409610 + -0.057168354901*_Complex_I, 0.087247514708 + -0.025386591035*_Complex_I, -0.028531902133 + 0.071536103147*_Complex_I, -0.025160173288 + -0.020151250712*_Complex_I, -0.022772795332 + -0.017187718098*_Complex_I, -0.029078837193 + 0.069628451313*_Complex_I, 0.049111894335 + -0.041621311215*_Complex_I, -0.023619794976 + 0.077908526801*_Complex_I, 0.000333911391 + 0.053474867787*_Complex_I, 0.029475675088 + -0.009019730084*_Complex_I, 0.034174066620 + 0.017898879791*_Complex_I, 0.065544425508 + 0.045084590196*_Complex_I, -0.090015977785 + 0.028850540224*_Complex_I, -0.012871094837 + -0.054608369039*_Complex_I, 0.047544364344 + 0.008538257328*_Complex_I, -0.063104697961 + 0.090294378190*_Complex_I, -0.011929275791 + 0.022601352310*_Complex_I, -0.047521622205 + 0.007445085519*_Complex_I, 0.022958962838 + -0.062917965176*_Complex_I, 0.214158563544 + 0.108130217870*_Complex_I, -0.073961792459 + 0.071479678221*_Complex_I, -0.015320084620 + -0.052303661814*_Complex_I, 0.077538995397 + 0.033838920671*_Complex_I, -0.034556396252 + 0.000838447098*_Complex_I, 0.000060541807 + -0.004333615826*_Complex_I, 0.019595150038 + 0.059919909742*_Complex_I, -0.060268723573 + -0.056864079389*_Complex_I, 0.125955282742 + -0.089792980055*_Complex_I, 0.104088003218 + 0.030894546232*_Complex_I, -0.057778045852 + -0.020383254417*_Complex_I, 0.072179136454 + -0.043422298997*_Complex_I, -0.033946126046 + 0.018129630965*_Complex_I, -0.049055572484 + -0.016390359113*_Complex_I, -0.025066786874 + -0.031503746350*_Complex_I, -0.027009840982 + 0.016252291912*_Complex_I, -0.042713013603 + -0.046577467289*_Complex_I, -0.046395432817 + -0.042034197104*_Complex_I, -0.066951975959 + -0.006293309275*_Complex_I, -0.076584206559 + -0.038789936400*_Complex_I, 0.005278362238 + -0.031661049359*_Complex_I, 0.006878243906 + 0.019853143294*_Complex_I, -0.074683265419 + 0.092712646012*_Complex_I, -0.048535905143 + 0.066894323514*_Complex_I, -0.011718308326 + -0.093940704974*_Complex_I, 0.054231403971 + -0.067545703916*_Complex_I, 0.027390269161 + 0.013522266374*_Complex_I, 0.027113327798 + 0.025183265482*_Complex_I, -0.041823544233 + 0.108944472361*_Complex_I, -0.030438012256 + -0.063572748831*_Complex_I, 0.066074070111 + -0.020231915298*_Complex_I, 0.069140337649 + 0.114893641537*_Complex_I, -0.005919906768 + 0.004293077149*_Complex_I, 0.056489424450 + 0.068597409742*_Complex_I, 0.027928885781 + -0.031072362986*_Complex_I, 0.033715956662 + 0.016500309835*_Complex_I, 0.066646875440 + 0.052841945423*_Complex_I, 0.059048505781 + -0.044714082918*_Complex_I, 0.083521538493 + 0.040432491516*_Complex_I, -0.015140885802 + 0.007398722932*_Complex_I, -0.018685866288 + -0.005688072534*_Complex_I, 0.037444281102 + -0.001275030615*_Complex_I, 0.009248759930 + 0.000917465357*_Complex_I, 0.037078087936 + 0.054897922621*_Complex_I, -0.032804989991 + -0.001205514200*_Complex_I, 0.049475279806 + -0.034629284571*_Complex_I, 0.040449266799 + -0.025094164230*_Complex_I, 0.028840625614 + -0.034271290637*_Complex_I, 0.022502076079 + 0.028207110264*_Complex_I, -0.095209370089 + -0.024287776579*_Complex_I, 0.036853780217 + -0.112642535014*_Complex_I, 0.011055463457 + 0.014755419711*_Complex_I, -0.007470671462 + -0.082840060740*_Complex_I, 0.049493876654 + -0.029503227741*_Complex_I, 0.003287878646 + -0.011760309552*_Complex_I, -0.052454911751 + -0.135685038742*_Complex_I, 0.100557451271 + -0.060727168658*_Complex_I, 0.030460767615 + -0.025297334320*_Complex_I, -0.041900949710 + -0.044189282191*_Complex_I, 0.002239369339 + 0.018583017194*_Complex_I, -0.094251314287 + -0.045638715401*_Complex_I, -0.043687223316 + -0.073236757137*_Complex_I, 0.042678054726 + -0.053958008845*_Complex_I, -0.000338320251 + -0.031016295417*_Complex_I, -0.017513369486 + 0.046863199684*_Complex_I, -0.017742806904 + -0.098421945495*_Complex_I, 0.035630421170 + -0.042774040828*_Complex_I, 0.023161832990 + 0.056833847742*_Complex_I, -0.035822048154 + -0.064590977441*_Complex_I, -0.008387640915 + 0.040501176809*_Complex_I, -0.068025770572 + -0.021755292254*_Complex_I, 0.001359162188 + -0.081310455090*_Complex_I, 0.012404768734 + 0.083535778559*_Complex_I, -0.038725035226 + -0.008917515519*_Complex_I, -0.038625918697 + -0.011541140189*_Complex_I, 0.023371955995 + 0.096714602422*_Complex_I, 0.017691840656 + -0.095198285220*_Complex_I, 0.045385440171 + 0.068921408368*_Complex_I, 0.002806803285 + 0.044993613294*_Complex_I, -0.033553704471 + -0.075678324986*_Complex_I, 0.033838944413 + 0.008301990809*_Complex_I, 0.001278998079 + -0.054009422018*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/fftfilt_cccf_data_h23x256.c000066400000000000000000000667171317124540100246070ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fftfilt_cccf_data_h23x256.c: autotest fftfilt data // #include float complex fftfilt_cccf_data_h23x256_h[] = { -0.113265895844 + -0.022710527480*_Complex_I, 0.017113091052 + -0.012686794996*_Complex_I, -0.115593445301 + -0.088176310062*_Complex_I, -0.013192173839 + 0.146348237991*_Complex_I, -0.103383064270 + -0.047336477041*_Complex_I, 0.075577318668 + -0.044972211123*_Complex_I, 0.142312300205 + -0.064133465290*_Complex_I, -0.221127843857 + 0.014621888101*_Complex_I, -0.058339691162 + -0.140489292145*_Complex_I, -0.038768473268 + 0.063463032246*_Complex_I, -0.066909837723 + -0.194865047932*_Complex_I, 0.113466823101 + -0.236079573631*_Complex_I, 0.025802928209 + -0.126112377644*_Complex_I, -0.025553426147 + -0.205878305435*_Complex_I, -0.036806601286 + 0.039826345444*_Complex_I, -0.069977194071 + -0.241963529587*_Complex_I, 0.067285501957 + -0.138619136810*_Complex_I, -0.216540384293 + -0.094396740198*_Complex_I, 0.053344154358 + -0.034197300673*_Complex_I, -0.094768559933 + -0.246735548973*_Complex_I, 0.026606693864 + -0.040954247117*_Complex_I, 0.048448944092 + 0.068329632282*_Complex_I, 0.053360801935 + 0.035232502222*_Complex_I}; float complex fftfilt_cccf_data_h23x256_x[] = { 0.045492258668 + 0.087591451406*_Complex_I, -0.360275936127 + -0.244660735130*_Complex_I, -0.076566338539 + 0.085396862030*_Complex_I, -0.010159610212 + -0.099646502733*_Complex_I, 0.106244933605 + -0.035118606687*_Complex_I, 0.004351182655 + 0.104901087284*_Complex_I, 0.060583090782 + 0.090451103449*_Complex_I, -0.009854796529 + -0.159225010872*_Complex_I, 0.123082661629 + -0.013109473884*_Complex_I, -0.042733341455 + 0.038194873929*_Complex_I, 0.059678620100 + -0.141551160812*_Complex_I, -0.004473050311 + 0.106543672085*_Complex_I, 0.099794340134 + -0.143291473389*_Complex_I, -0.044146090746 + 0.066736018658*_Complex_I, -0.059895306826 + 0.166889667511*_Complex_I, 0.076762962341 + -0.058477646112*_Complex_I, -0.031721797585 + -0.070060622692*_Complex_I, -0.030031725764 + 0.018004868925*_Complex_I, -0.132683742046 + 0.047249066830*_Complex_I, -0.017683801055 + -0.110559308529*_Complex_I, -0.089177983999 + 0.128147161007*_Complex_I, -0.058403855562 + -0.253948712349*_Complex_I, 0.155546200275 + -0.033433157206*_Complex_I, 0.019463591278 + 0.087873625755*_Complex_I, 0.175985527039 + 0.134090995789*_Complex_I, 0.005070775002 + 0.023215842247*_Complex_I, -0.183340942860 + 0.061269021034*_Complex_I, -0.282386708260 + 0.050984662771*_Complex_I, -0.150776374340 + 0.111193597317*_Complex_I, -0.092933952808 + 0.014530903101*_Complex_I, -0.025000396371 + -0.020265173912*_Complex_I, 0.130480492115 + 0.031612247229*_Complex_I, 0.100867581367 + -0.229012298584*_Complex_I, -0.082832515240 + 0.091525465250*_Complex_I, 0.048790007830 + 0.014641028643*_Complex_I, -0.072996783257 + -0.022627115250*_Complex_I, 0.076681035757 + -0.090442115068*_Complex_I, -0.036189466715 + -0.120588958263*_Complex_I, -0.100714707375 + -0.106518495083*_Complex_I, -0.321345973015 + -0.129095542431*_Complex_I, -0.041321143508 + -0.097576838732*_Complex_I, -0.074389326572 + 0.045334511995*_Complex_I, 0.136498391628 + 0.096301412582*_Complex_I, 0.191800594330 + -0.083850991726*_Complex_I, 0.163151848316 + -0.054458898306*_Complex_I, -0.001362276729 + -0.030826401711*_Complex_I, -0.030661305785 + -0.240707612038*_Complex_I, -0.255475115776 + 0.166176271439*_Complex_I, -0.087870460749 + 0.138075506687*_Complex_I, 0.063871967793 + -0.167130613327*_Complex_I, -0.167199540138 + -0.085400974751*_Complex_I, 0.050435560942 + -0.040156632662*_Complex_I, 0.057380825281 + 0.090105038881*_Complex_I, -0.040529885888 + -0.006345084310*_Complex_I, 0.112770903111 + 0.106182515621*_Complex_I, 0.128458249569 + 0.066667920351*_Complex_I, 0.083549374342 + -0.086842793226*_Complex_I, 0.144279420376 + 0.133334076405*_Complex_I, -0.137241375446 + 0.032534021139*_Complex_I, -0.023988795280 + 0.049458268285*_Complex_I, 0.076303368807 + 0.020058257878*_Complex_I, -0.154448091984 + -0.050609207153*_Complex_I, 0.165292298794 + 0.070755618811*_Complex_I, 0.005886135250 + -0.036164498329*_Complex_I, -0.037918183208 + -0.019724342227*_Complex_I, 0.026809751987 + -0.032598829269*_Complex_I, 0.063324218988 + 0.098319518566*_Complex_I, -0.047398203611 + -0.114408671856*_Complex_I, 0.121957802773 + 0.028821185231*_Complex_I, -0.135715365410 + 0.048073148727*_Complex_I, 0.029720014334 + 0.097452402115*_Complex_I, -0.148619377613 + 0.177626144886*_Complex_I, -0.122573924065 + 0.032197031379*_Complex_I, -0.005472518504 + 0.130435466766*_Complex_I, 0.055357205868 + 0.036867898703*_Complex_I, -0.037471351027 + 0.078105151653*_Complex_I, -0.080862498283 + -0.009199683368*_Complex_I, -0.132427692413 + -0.173398303986*_Complex_I, -0.048274517059 + -0.028256762028*_Complex_I, 0.063550901413 + -0.019138570130*_Complex_I, 0.018642249703 + 0.105512928963*_Complex_I, -0.034507310390 + 0.165678203106*_Complex_I, 0.157479083538 + -0.098934185505*_Complex_I, 0.110079026222 + 0.190422582626*_Complex_I, -0.123567688465 + -0.026369869709*_Complex_I, 0.010789130628 + -0.029063615203*_Complex_I, -0.083237224817 + 0.123224353790*_Complex_I, 0.008147761226 + 0.157242572308*_Complex_I, -0.115900576115 + 0.016479349136*_Complex_I, 0.014385309815 + -0.114978981018*_Complex_I, -0.010936866701 + 0.001918938756*_Complex_I, -0.042773860693 + -0.096163535118*_Complex_I, 0.159630239010 + -0.090808361769*_Complex_I, 0.099759966135 + 0.003752164543*_Complex_I, 0.082647228241 + 0.061170494556*_Complex_I, 0.068049144745 + 0.166794586182*_Complex_I, -0.025365993381 + -0.024766857922*_Complex_I, 0.069112539291 + -0.027834153175*_Complex_I, -0.044352179766 + -0.044707950950*_Complex_I, 0.067422634363 + -0.017061285675*_Complex_I, 0.070048046112 + 0.109582054615*_Complex_I, 0.037835836411 + 0.180136477947*_Complex_I, 0.032625645399 + 0.116918706894*_Complex_I, 0.049541047215 + 0.161158871651*_Complex_I, 0.027160745859 + -0.168793261051*_Complex_I, -0.052759623528 + -0.072317802906*_Complex_I, 0.184534084797 + 0.022903186083*_Complex_I, -0.010724669695 + 0.036121314764*_Complex_I, 0.245871329308 + 0.039303827286*_Complex_I, -0.024940526485 + 0.096528834105*_Complex_I, -0.078127902746 + -0.096756339073*_Complex_I, 0.043826240301 + -0.125324332714*_Complex_I, 0.009783142805 + -0.003001630120*_Complex_I, 0.064857578278 + -0.042588630319*_Complex_I, 0.081423562765 + 0.121582865715*_Complex_I, -0.118639636040 + 0.128098034859*_Complex_I, -0.111134576797 + 0.038534373045*_Complex_I, -0.289731216431 + -0.080021494627*_Complex_I, 0.069585120678 + 0.060569906235*_Complex_I, -0.051440721750 + -0.150054514408*_Complex_I, -0.039673271775 + 0.039142814279*_Complex_I, -0.017449636757 + -0.103529226780*_Complex_I, 0.046975213289 + -0.208591985703*_Complex_I, 0.141377413273 + 0.023652508855*_Complex_I, -0.061699587107 + -0.151958966255*_Complex_I, 0.007653100044 + -0.046074271202*_Complex_I, 0.135512828827 + 0.166977787018*_Complex_I, -0.042983511090 + 0.140523970127*_Complex_I, -0.174354147911 + 0.157390367985*_Complex_I, -0.180938804150 + -0.007540450245*_Complex_I, -0.006038622186 + 0.114250767231*_Complex_I, -0.183260941505 + -0.041695398092*_Complex_I, -0.087769675255 + -0.009365759790*_Complex_I, -0.077232390642 + -0.019897325337*_Complex_I, -0.017668469250 + -0.107637941837*_Complex_I, 0.186912357807 + 0.078892260790*_Complex_I, 0.199635422230 + 0.003066605330*_Complex_I, 0.005723394454 + -0.087536334991*_Complex_I, 0.036157646775 + 0.010726630688*_Complex_I, -0.013097931445 + 0.137133157253*_Complex_I, -0.200704836845 + -0.067425280809*_Complex_I, -0.018093538284 + -0.002605117485*_Complex_I, -0.046316248178 + 0.047676995397*_Complex_I, 0.065687131882 + -0.272353625298*_Complex_I, 0.182847750187 + 0.136976885796*_Complex_I, -0.060609722137 + 0.063969159126*_Complex_I, 0.065259736776 + -0.030771258473*_Complex_I, 0.093584728241 + -0.088571476936*_Complex_I, 0.055487519503 + -0.092523062229*_Complex_I, 0.040360233188 + -0.237069821358*_Complex_I, -0.054889243841 + 0.007436647266*_Complex_I, 0.146980488300 + -0.112567687035*_Complex_I, 0.033167552948 + 0.077278125286*_Complex_I, -0.123007047176 + -0.234244012833*_Complex_I, -0.023877808452 + -0.034760150313*_Complex_I, -0.073663645983 + -0.067232269049*_Complex_I, -0.021728573740 + 0.229374289513*_Complex_I, 0.075998270512 + -0.019796457887*_Complex_I, -0.117255151272 + 0.168271052837*_Complex_I, 0.157391369343 + -0.156538987160*_Complex_I, -0.144393324852 + 0.064253067970*_Complex_I, 0.182558035851 + 0.176998484135*_Complex_I, 0.022407060862 + 0.102678549290*_Complex_I, 0.053511500359 + 0.111569952965*_Complex_I, 0.035490038991 + 0.067579591274*_Complex_I, -0.069553595781 + 0.028308334947*_Complex_I, -0.077684468031 + 0.165951395035*_Complex_I, -0.171819615364 + 0.051840746403*_Complex_I, -0.169814157486 + -0.009480411559*_Complex_I, 0.002353400178 + 0.097526848316*_Complex_I, -0.035275432467 + 0.051336318254*_Complex_I, 0.073788845539 + -0.159921205044*_Complex_I, -0.062105762959 + 0.139204311371*_Complex_I, 0.046410915256 + 0.076092356443*_Complex_I, 0.015324105322 + 0.056624919176*_Complex_I, -0.032998785377 + 0.030960384011*_Complex_I, -0.033524742723 + -0.072809416056*_Complex_I, 0.034249174595 + 0.142128837109*_Complex_I, -0.017137683928 + 0.000054139068*_Complex_I, -0.152735805511 + -0.015746916831*_Complex_I, 0.076812589169 + 0.113819742203*_Complex_I, -0.269065928459 + 0.047783342004*_Complex_I, -0.006360206753 + -0.290388703346*_Complex_I, 0.056451249123 + -0.141728675365*_Complex_I, -0.074260264635 + 0.112913572788*_Complex_I, -0.097910881042 + 0.009142446518*_Complex_I, 0.008521752059 + -0.165642762184*_Complex_I, -0.068459671736 + -0.177522385120*_Complex_I, -0.057727193832 + -0.061166942120*_Complex_I, -0.014851769805 + 0.012171116471*_Complex_I, -0.106043231487 + 0.214376616478*_Complex_I, -0.056457644701 + 0.133102154732*_Complex_I, -0.001181100123 + -0.025020095706*_Complex_I, 0.013895004988 + 0.055028027296*_Complex_I, -0.094381314516 + -0.076402390003*_Complex_I, 0.059590637684 + -0.081801712513*_Complex_I, 0.004246252403 + 0.056055116653*_Complex_I, -0.044613176584 + -0.091410827637*_Complex_I, -0.037342968583 + -0.024862080812*_Complex_I, -0.190127372742 + 0.041265439987*_Complex_I, -0.006639320403 + 0.097943222523*_Complex_I, 0.138125526905 + -0.064016056061*_Complex_I, -0.098870986700 + -0.145059263706*_Complex_I, 0.114810085297 + -0.059086716175*_Complex_I, 0.000181899476 + -0.094249367714*_Complex_I, 0.086499345303 + -0.031394767761*_Complex_I, 0.131707870960 + 0.043413007259*_Complex_I, -0.162042534351 + 0.021535064280*_Complex_I, 0.103580415249 + -0.146205651760*_Complex_I, -0.052903598547 + 0.023014034331*_Complex_I, -0.198558521271 + -0.064298307896*_Complex_I, 0.111735153198 + -0.045897883177*_Complex_I, -0.166142654419 + -0.066890668869*_Complex_I, 0.135389423370 + 0.158303833008*_Complex_I, -0.067218714952 + -0.269701981544*_Complex_I, -0.029925772548 + -0.056027936935*_Complex_I, -0.090524566174 + -0.035552933812*_Complex_I, -0.095090520382 + -0.213347554207*_Complex_I, 0.065363866091 + -0.078422772884*_Complex_I, 0.142836868763 + 0.045737281442*_Complex_I, -0.066659629345 + 0.091496753693*_Complex_I, -0.050436902046 + 0.038852605224*_Complex_I, 0.056302917004 + 0.035658785701*_Complex_I, -0.261968922615 + 0.072266608477*_Complex_I, -0.000278761820 + -0.066401851177*_Complex_I, -0.191342055798 + 0.103529000282*_Complex_I, -0.049295476079 + 0.036229848862*_Complex_I, -0.042302805185 + -0.063734227419*_Complex_I, -0.050776159763 + 0.063683301210*_Complex_I, -0.091268771887 + 0.292417860031*_Complex_I, -0.054572415352 + 0.059356063604*_Complex_I, 0.058717763424 + 0.045334947109*_Complex_I, 0.004559407011 + -0.066553068161*_Complex_I, -0.037161919475 + 0.062294793129*_Complex_I, -0.234697723389 + -0.031746768951*_Complex_I, 0.045789924264 + -0.090054887533*_Complex_I, 0.107681131363 + -0.112842118740*_Complex_I, 0.136971771717 + -0.095520716906*_Complex_I, 0.093264913559 + 0.091368728876*_Complex_I, -0.091999745369 + 0.012484084070*_Complex_I, 0.023904198408 + 0.167766880989*_Complex_I, 0.192737889290 + -0.014556410909*_Complex_I, 0.106241250038 + 0.018227040768*_Complex_I, 0.024921812117 + 0.071124422550*_Complex_I, 0.052874428034 + -0.094483900070*_Complex_I, 0.060024052858 + -0.120348191261*_Complex_I, 0.151742827892 + 0.044160097837*_Complex_I, -0.035461589694 + 0.040138626099*_Complex_I, 0.068723130226 + 0.084313547611*_Complex_I, 0.089995771646 + 0.131840264797*_Complex_I, -0.138497865200 + 0.083961331844*_Complex_I, 0.012439595908 + 0.069563353062*_Complex_I, 0.032783246040 + 0.022058516741*_Complex_I, -0.022213153541 + -0.033352825046*_Complex_I, -0.111178684235 + 0.004780802876*_Complex_I, -0.256052374840 + -0.011545106769*_Complex_I}; float complex fftfilt_cccf_data_h23x256_y[] = { -0.003163473368 + -0.010954277402*_Complex_I, 0.037140370260 + 0.036815583414*_Complex_I, 0.003807251283 + -0.021686181791*_Complex_I, 0.005314097986 + 0.079501236423*_Complex_I, 0.042112632196 + -0.063838542514*_Complex_I, 0.017204891832 + 0.033074981292*_Complex_I, -0.018245137527 + -0.013306853145*_Complex_I, -0.071746576920 + 0.012804254640*_Complex_I, 0.038716740288 + 0.025468078675*_Complex_I, -0.021154025874 + 0.034169668261*_Complex_I, 0.077447054430 + -0.009547926751*_Complex_I, -0.016338142895 + 0.132246349074*_Complex_I, -0.116081376657 + 0.043341402708*_Complex_I, 0.006899278182 + 0.004113954837*_Complex_I, -0.096053480940 + 0.077818095714*_Complex_I, 0.036459684176 + -0.026251748476*_Complex_I, 0.009672547486 + 0.040691758623*_Complex_I, -0.055593734133 + 0.042208131016*_Complex_I, 0.040988977939 + 0.032815266125*_Complex_I, 0.003252391576 + -0.027032799374*_Complex_I, -0.056555124191 + 0.108792895823*_Complex_I, 0.027780168593 + -0.058523157109*_Complex_I, -0.023467358131 + -0.032855820386*_Complex_I, -0.160897508497 + -0.123678772528*_Complex_I, 0.089287852799 + -0.007143354758*_Complex_I, -0.016099534679 + 0.002581265491*_Complex_I, -0.000986708318 + 0.015164729493*_Complex_I, -0.064404987562 + -0.057663923465*_Complex_I, 0.132601153086 + -0.001252362087*_Complex_I, -0.048228851544 + 0.135111186832*_Complex_I, 0.134924898703 + -0.062012201527*_Complex_I, -0.074853441754 + 0.026496948899*_Complex_I, -0.129226783274 + -0.004790572963*_Complex_I, 0.103893760072 + 0.022506218947*_Complex_I, -0.035460676841 + 0.047688216908*_Complex_I, 0.178180257360 + -0.013109362819*_Complex_I, 0.018161301104 + 0.109487688153*_Complex_I, 0.094671736324 + 0.013921482693*_Complex_I, -0.048072372913 + 0.137711693833*_Complex_I, 0.062880576088 + 0.175933352879*_Complex_I, -0.009910181192 + 0.111994156930*_Complex_I, 0.044512102038 + 0.006301021902*_Complex_I, 0.066098606944 + -0.028081191959*_Complex_I, 0.087466319032 + 0.008238268753*_Complex_I, -0.001367800660 + 0.038967292120*_Complex_I, -0.067421987215 + 0.145539459508*_Complex_I, 0.075984112068 + 0.175244098743*_Complex_I, -0.027482814927 + 0.090963593261*_Complex_I, -0.061982865075 + -0.001782549283*_Complex_I, -0.051388866943 + 0.091286306431*_Complex_I, -0.125038294673 + 0.006669602361*_Complex_I, -0.266499054163 + 0.031401157713*_Complex_I, -0.005097555860 + 0.090581995126*_Complex_I, -0.055547492377 + 0.112501253551*_Complex_I, 0.012659187846 + 0.026503690407*_Complex_I, -0.054554809518 + -0.047656993760*_Complex_I, -0.092937843107 + 0.022881558123*_Complex_I, -0.072930225245 + 0.008805379158*_Complex_I, 0.001689423379 + 0.180348978422*_Complex_I, -0.127921044291 + -0.059030091461*_Complex_I, 0.022023172094 + 0.056579583536*_Complex_I, -0.121613219261 + -0.108837221417*_Complex_I, -0.067796732417 + -0.119754222994*_Complex_I, 0.022160633596 + 0.172479032134*_Complex_I, -0.021149818992 + -0.088048810494*_Complex_I, 0.061930559225 + 0.033755437249*_Complex_I, 0.009953383045 + 0.044238688316*_Complex_I, 0.122661863617 + -0.104781716997*_Complex_I, 0.038138937124 + -0.063310924046*_Complex_I, -0.085849386817 + 0.029133930890*_Complex_I, 0.062239172444 + -0.126085383157*_Complex_I, 0.056320988469 + -0.024245019681*_Complex_I, 0.008584244317 + -0.122838573365*_Complex_I, 0.076110822106 + -0.085361591999*_Complex_I, 0.020719355889 + -0.055555782582*_Complex_I, 0.000653411740 + -0.069873018399*_Complex_I, 0.066178767484 + -0.026066404349*_Complex_I, 0.028671545965 + 0.078431187056*_Complex_I, 0.065121750679 + -0.050089915985*_Complex_I, 0.057324656071 + -0.014133997391*_Complex_I, 0.030288156492 + 0.026307763098*_Complex_I, 0.111873889736 + -0.050023831315*_Complex_I, 0.004746208895 + 0.091571031089*_Complex_I, 0.010352530872 + -0.069569373081*_Complex_I, 0.103204479415 + 0.119216440805*_Complex_I, 0.100504774459 + -0.026045891638*_Complex_I, 0.137774605021 + 0.123356174384*_Complex_I, -0.002645216707 + -0.014199931832*_Complex_I, 0.171062973870 + 0.005021494304*_Complex_I, 0.017869576969 + 0.051069516929*_Complex_I, 0.012047989391 + -0.064461915154*_Complex_I, 0.127717671510 + 0.063350643190*_Complex_I, 0.004050235012 + 0.103983488965*_Complex_I, 0.032899906611 + -0.046472299982*_Complex_I, 0.065807936567 + -0.000393539350*_Complex_I, 0.028480795150 + -0.035085883796*_Complex_I, 0.020035985982 + 0.094697203202*_Complex_I, -0.032243593542 + -0.034371463214*_Complex_I, 0.130710337771 + -0.076446903504*_Complex_I, -0.000290058651 + 0.063994722962*_Complex_I, 0.029367046198 + -0.059754919406*_Complex_I, -0.013496796316 + 0.021741636806*_Complex_I, -0.030554614083 + -0.122446936946*_Complex_I, 0.076444606322 + -0.050687378688*_Complex_I, -0.098301236592 + -0.042289531263*_Complex_I, 0.110549679961 + -0.093097947505*_Complex_I, -0.006461769800 + 0.063465854253*_Complex_I, 0.009417608596 + -0.044048779916*_Complex_I, -0.064257503698 + -0.070341963349*_Complex_I, -0.059122879906 + -0.064698906559*_Complex_I, -0.042900235147 + -0.196073457626*_Complex_I, 0.040029224882 + -0.029654181156*_Complex_I, 0.032819760175 + -0.111413861187*_Complex_I, 0.113350177210 + -0.032359925542*_Complex_I, 0.126474793881 + -0.075277469455*_Complex_I, -0.036790802258 + -0.012416828849*_Complex_I, -0.013341048450 + -0.171411636672*_Complex_I, 0.071226482453 + -0.028621067255*_Complex_I, 0.025788824745 + -0.122676045849*_Complex_I, 0.138882083097 + -0.112136069734*_Complex_I, 0.079803890033 + -0.056689245330*_Complex_I, -0.083660222940 + 0.021037488864*_Complex_I, 0.038027034035 + -0.045614580284*_Complex_I, -0.173039872932 + -0.036333257565*_Complex_I, 0.109185737875 + -0.018739181874*_Complex_I, -0.011116564421 + -0.012659167774*_Complex_I, 0.027848471825 + 0.042226423184*_Complex_I, 0.009983998202 + 0.009652509701*_Complex_I, 0.034939989540 + 0.049003327190*_Complex_I, -0.003271145352 + 0.117508812071*_Complex_I, -0.089674168530 + 0.022069310635*_Complex_I, 0.075219548196 + 0.009686118261*_Complex_I, -0.009264365949 + 0.096686949696*_Complex_I, -0.015282640313 + -0.022970528637*_Complex_I, 0.056453107756 + 0.038101951682*_Complex_I, -0.075215301245 + -0.009549458275*_Complex_I, 0.016786191325 + 0.119063467526*_Complex_I, -0.063461158126 + -0.044766698681*_Complex_I, 0.013715934436 + 0.023246048562*_Complex_I, -0.007187144049 + 0.139644946690*_Complex_I, 0.001093160636 + 0.038143526761*_Complex_I, 0.089982542957 + 0.104701345525*_Complex_I, 0.006438088218 + 0.016301123978*_Complex_I, 0.024550427000 + 0.007223414838*_Complex_I, 0.001998203885 + 0.128506017977*_Complex_I, 0.027388452832 + -0.021862288446*_Complex_I, 0.121924019581 + -0.034718387256*_Complex_I, 0.065573770757 + 0.084008890431*_Complex_I, -0.010812132830 + 0.041404645847*_Complex_I, -0.001516024489 + -0.046108309651*_Complex_I, 0.021914893505 + 0.163215448624*_Complex_I, -0.168800712098 + 0.059209648111*_Complex_I, 0.043105911919 + -0.060137086361*_Complex_I, -0.189708356977 + 0.061129252073*_Complex_I, -0.012670229735 + -0.164593804221*_Complex_I, -0.027215975709 + 0.001464776717*_Complex_I, -0.032021988907 + -0.005641085087*_Complex_I, 0.084676334643 + 0.050890486174*_Complex_I, -0.025518610180 + -0.026683394670*_Complex_I, -0.196695068885 + -0.118334531757*_Complex_I, 0.005134576502 + 0.041058905955*_Complex_I, -0.234700560083 + -0.074871902832*_Complex_I, -0.003394269991 + -0.025828554844*_Complex_I, -0.095398073839 + -0.137794198564*_Complex_I, -0.115844189635 + -0.016811394953*_Complex_I, -0.086433951444 + -0.096085417783*_Complex_I, -0.135882412437 + 0.086996893482*_Complex_I, 0.086188594393 + -0.052027988864*_Complex_I, -0.032660999389 + 0.079110677785*_Complex_I, 0.048555777064 + -0.071192412508*_Complex_I, 0.002384862118 + -0.024747258783*_Complex_I, 0.103707359507 + -0.071240112258*_Complex_I, 0.066653972959 + 0.034897982205*_Complex_I, 0.104312888231 + -0.035974080403*_Complex_I, 0.138638211048 + -0.049974123076*_Complex_I, 0.194165435108 + -0.049828755020*_Complex_I, 0.053154926316 + -0.036358363591*_Complex_I, 0.220675128214 + -0.030961835182*_Complex_I, -0.023703599067 + 0.107776938666*_Complex_I, 0.144905982977 + 0.004212434062*_Complex_I, 0.095439650368 + 0.010795170803*_Complex_I, 0.121879552506 + -0.015505102444*_Complex_I, 0.116627097083 + 0.007939429200*_Complex_I, 0.121158143520 + 0.140391060505*_Complex_I, 0.023773742208 + -0.003915558406*_Complex_I, 0.249689399352 + 0.106009483142*_Complex_I, 0.042459283114 + 0.116551334180*_Complex_I, -0.032000595442 + 0.043069200952*_Complex_I, 0.083807567711 + -0.048271370782*_Complex_I, 0.106133277971 + 0.107195381079*_Complex_I, -0.032758866155 + 0.055589876920*_Complex_I, 0.083113455874 + 0.056268033253*_Complex_I, 0.062805062701 + 0.052981580201*_Complex_I, -0.072300786192 + -0.022099642616*_Complex_I, -0.023071207539 + 0.069870175640*_Complex_I, -0.028038066616 + 0.115260700432*_Complex_I, 0.064595548137 + 0.179516005676*_Complex_I, -0.096265563941 + 0.042171225905*_Complex_I, -0.009166713003 + 0.047707628475*_Complex_I, -0.074476545197 + 0.078481428604*_Complex_I, 0.020402514454 + 0.097206670167*_Complex_I, 0.009603470518 + 0.137727809796*_Complex_I, -0.061724978115 + 0.088460708343*_Complex_I, -0.018787857770 + 0.022957577259*_Complex_I, 0.060840793373 + 0.153201719382*_Complex_I, -0.090761100879 + 0.063269553381*_Complex_I, 0.048643003688 + 0.073091682104*_Complex_I, 0.042574315610 + -0.003350831677*_Complex_I, -0.040962206275 + -0.040240568604*_Complex_I, 0.091461005901 + 0.091406021898*_Complex_I, -0.072777125035 + 0.062929145258*_Complex_I, 0.050350001022 + 0.069452557434*_Complex_I, -0.053002534268 + 0.128785684713*_Complex_I, -0.138610817453 + -0.082977870570*_Complex_I, 0.003075555607 + 0.064767936471*_Complex_I, -0.086047615737 + 0.023981557378*_Complex_I, -0.050138686326 + -0.027308987428*_Complex_I, 0.076446905787 + 0.037104333404*_Complex_I, -0.133192170848 + 0.118044932479*_Complex_I, 0.031944935119 + -0.022005963244*_Complex_I, -0.145840989397 + -0.032141552759*_Complex_I, -0.094264666257 + 0.034400727372*_Complex_I, -0.108437970582 + 0.098296799443*_Complex_I, -0.077001723208 + -0.045921410112*_Complex_I, 0.064828536127 + 0.008649034614*_Complex_I, -0.049541743659 + 0.128627939884*_Complex_I, -0.054927512176 + -0.017342218621*_Complex_I, -0.045962424214 + 0.135024314150*_Complex_I, -0.103035351086 + -0.015043817667*_Complex_I, -0.037360852174 + 0.060401543729*_Complex_I, -0.015995655894 + -0.111740685081*_Complex_I, 0.032349781494 + 0.177898564863*_Complex_I, -0.021316438598 + -0.060576452528*_Complex_I, 0.017301344278 + 0.053102820051*_Complex_I, -0.014246232246 + 0.154624061894*_Complex_I, 0.059824941825 + 0.104996100396*_Complex_I, 0.011889122729 + 0.118361813218*_Complex_I, 0.043309441161 + -0.055415600686*_Complex_I, 0.074309063231 + 0.029407405713*_Complex_I, 0.062659426432 + 0.086580925759*_Complex_I, 0.141493640931 + 0.127665018203*_Complex_I, 0.091935455312 + 0.098230420374*_Complex_I, 0.153585132414 + 0.041819978162*_Complex_I, -0.036769194301 + -0.001909617998*_Complex_I, 0.081816172969 + 0.145221737468*_Complex_I, -0.074164721966 + 0.103001561704*_Complex_I, -0.001976310011 + -0.051318733615*_Complex_I, -0.009827887129 + -0.043930466173*_Complex_I, 0.054370258297 + -0.141481458488*_Complex_I, -0.015471769405 + 0.047001209676*_Complex_I, -0.056006669211 + -0.098678088820*_Complex_I, 0.009040689393 + -0.031336560460*_Complex_I, -0.039683698505 + -0.042155900675*_Complex_I, 0.017353066695 + -0.086277701489*_Complex_I, -0.002902182702 + -0.059776504802*_Complex_I, -0.044568379057 + -0.090648234378*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/fftfilt_cccf_data_h4x256.c000066400000000000000000000650251317124540100245150ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fftfilt_cccf_data_h4x256.c: autotest fftfilt data // #include float complex fftfilt_cccf_data_h4x256_h[] = { -0.135231339931 + 0.062977480888*_Complex_I, -0.157240438461 + 0.037726294994*_Complex_I, 0.169742667675 + -0.043306457996*_Complex_I, -0.001679791883 + -0.031882059574*_Complex_I}; float complex fftfilt_cccf_data_h4x256_x[] = { -0.145331311226 + 0.109500586987*_Complex_I, 0.008576134592 + -0.169542956352*_Complex_I, 0.047844916582 + 0.149058306217*_Complex_I, 0.177120888233 + 0.170329642296*_Complex_I, -0.004175573960 + 0.072688925266*_Complex_I, -0.027152365446 + 0.035960051417*_Complex_I, 0.094344460964 + -0.033645594120*_Complex_I, -0.010391099006 + -0.035192406178*_Complex_I, -0.180138766766 + -0.031795871258*_Complex_I, -0.203700375557 + -0.138529646397*_Complex_I, -0.019561575353 + -0.144657015800*_Complex_I, -0.118808639050 + -0.027752715349*_Complex_I, 0.056749093533 + -0.025054290891*_Complex_I, 0.116542947292 + -0.007720955461*_Complex_I, -0.074969446659 + 0.100591087341*_Complex_I, 0.001408090629 + -0.042336615920*_Complex_I, 0.240100383759 + -0.161245095730*_Complex_I, -0.085952699184 + 0.084794622660*_Complex_I, -0.015006904304 + 0.035609281063*_Complex_I, 0.000034478516 + -0.187320244312*_Complex_I, 0.052339464426 + -0.004798505455*_Complex_I, 0.093824869394 + -0.070545089245*_Complex_I, 0.149086785316 + 0.108725130558*_Complex_I, -0.156761336327 + 0.005509132892*_Complex_I, -0.125493848324 + -0.043598395586*_Complex_I, -0.121326863766 + 0.007096276432*_Complex_I, 0.003544984013 + 0.166835379601*_Complex_I, -0.037431293726 + -0.020329789817*_Complex_I, -0.085911118984 + -0.079901820421*_Complex_I, 0.122742509842 + 0.014822798967*_Complex_I, 0.110778486729 + -0.071227872372*_Complex_I, -0.007605559379 + -0.128052246571*_Complex_I, -0.066244971752 + -0.047825807333*_Complex_I, -0.030502566695 + -0.254250669479*_Complex_I, 0.157666409016 + -0.093531721830*_Complex_I, 0.043991112709 + 0.067102664709*_Complex_I, -0.063667005301 + 0.055537760258*_Complex_I, 0.035860368609 + -0.217314362526*_Complex_I, -0.154697167873 + -0.051928877831*_Complex_I, -0.154008638859 + 0.137628376484*_Complex_I, -0.021988071501 + -0.136372375488*_Complex_I, 0.118345403671 + -0.299838876724*_Complex_I, 0.066200459003 + 0.107628118992*_Complex_I, -0.022814218700 + 0.042800396681*_Complex_I, 0.039931696653 + 0.066364485025*_Complex_I, -0.038531854749 + -0.120103299618*_Complex_I, 0.017913374305 + 0.016456928849*_Complex_I, 0.001270754635 + 0.030759117007*_Complex_I, 0.235941290855 + 0.024339741468*_Complex_I, 0.074259299040 + 0.054985857010*_Complex_I, -0.117393791676 + -0.024225908518*_Complex_I, 0.195164024830 + -0.100901556015*_Complex_I, -0.074234390259 + -0.041768211126*_Complex_I, 0.042385265231 + -0.228795623779*_Complex_I, -0.089356112480 + 0.027445358038*_Complex_I, -0.273647761345 + -0.094072991610*_Complex_I, 0.067754048109 + -0.066324621439*_Complex_I, -0.071163922548 + 0.011088901013*_Complex_I, 0.002260415070 + -0.033153522015*_Complex_I, -0.163043868542 + 0.147372353077*_Complex_I, 0.130338788033 + 0.113823711872*_Complex_I, -0.018929108977 + -0.134858226776*_Complex_I, 0.005879180133 + 0.110552978516*_Complex_I, -0.177987158298 + -0.145397603512*_Complex_I, 0.112013733387 + -0.243533611298*_Complex_I, -0.065134996176 + -0.161895787716*_Complex_I, -0.100013601780 + -0.185575771332*_Complex_I, -0.039732664824 + -0.033335423470*_Complex_I, -0.004159386829 + -0.118040883541*_Complex_I, 0.101805281639 + 0.084620487690*_Complex_I, -0.150429344177 + -0.084105199575*_Complex_I, 0.062221693993 + 0.047454631329*_Complex_I, 0.138085842133 + -0.076058888435*_Complex_I, 0.254889655113 + -0.163386595249*_Complex_I, -0.025463542342 + -0.060935062170*_Complex_I, 0.061728596687 + -0.006239769980*_Complex_I, -0.083425503969 + 0.069602411985*_Complex_I, 0.039149901271 + -0.118299651146*_Complex_I, 0.103384292126 + -0.022438082099*_Complex_I, -0.008195941895 + 0.049835348129*_Complex_I, -0.049642279744 + -0.038572207093*_Complex_I, 0.112285923958 + 0.046880367398*_Complex_I, -0.052668154240 + 0.054064834118*_Complex_I, -0.009626910090 + -0.040556022525*_Complex_I, 0.002097596042 + -0.216656374931*_Complex_I, 0.057758331299 + -0.002327759005*_Complex_I, -0.008833542466 + -0.014824745059*_Complex_I, 0.040581482649 + 0.045436677337*_Complex_I, 0.194773435593 + 0.044354414940*_Complex_I, -0.028676524758 + -0.018726617098*_Complex_I, -0.019215075672 + -0.038972333074*_Complex_I, 0.200048685074 + 0.008784489334*_Complex_I, -0.116677081585 + -0.295071172714*_Complex_I, -0.077746075392 + -0.031134122610*_Complex_I, 0.078498488665 + 0.007961921394*_Complex_I, -0.081279265881 + 0.114860057831*_Complex_I, -0.014656324685 + -0.145551848412*_Complex_I, 0.129554140568 + 0.086291736364*_Complex_I, 0.123636543751 + -0.061629927158*_Complex_I, 0.040432214737 + 0.095078992844*_Complex_I, 0.021615064144 + 0.087291020155*_Complex_I, -0.036054989696 + 0.058331966400*_Complex_I, 0.031770968437 + 0.150715994835*_Complex_I, 0.036789077520 + 0.006291696429*_Complex_I, 0.207829833031 + -0.195549118519*_Complex_I, -0.069425356388 + 0.034547394514*_Complex_I, 0.121964550018 + -0.175282227993*_Complex_I, -0.076088452339 + 0.189335298538*_Complex_I, -0.238275814056 + 0.164852106571*_Complex_I, -0.105275332928 + 0.048049694300*_Complex_I, 0.025219294429 + 0.148977017403*_Complex_I, -0.116340065002 + 0.047728052735*_Complex_I, -0.001223530248 + 0.002220938914*_Complex_I, -0.095514726639 + 0.177518546581*_Complex_I, -0.024929241836 + 0.051844847202*_Complex_I, 0.003478102759 + -0.047746166587*_Complex_I, -0.179150342941 + -0.217488384247*_Complex_I, -0.004914051294 + -0.154762375355*_Complex_I, 0.097842323780 + -0.024203261733*_Complex_I, -0.103857576847 + -0.032823368907*_Complex_I, -0.092790353298 + 0.061397796869*_Complex_I, 0.047670701146 + 0.110239303112*_Complex_I, 0.073129659891 + 0.008005330712*_Complex_I, 0.215736103058 + -0.160301959515*_Complex_I, 0.012318083644 + 0.165701925755*_Complex_I, -0.092335480452 + 0.060041588545*_Complex_I, 0.057762295008 + 0.212985706329*_Complex_I, -0.116756439209 + 0.080165004730*_Complex_I, -0.016070105135 + 0.102566015720*_Complex_I, -0.031425985694 + 0.048826861382*_Complex_I, -0.138180553913 + -0.015630686283*_Complex_I, -0.040541607141 + 0.086674833298*_Complex_I, -0.017452953756 + -0.181320679188*_Complex_I, 0.011673089117 + 0.072657525539*_Complex_I, -0.015449254215 + 0.112104630470*_Complex_I, 0.071193879843 + -0.032887244225*_Complex_I, 0.016030588746 + -0.007359164953*_Complex_I, 0.007357457280 + 0.054825830460*_Complex_I, -0.068202400208 + -0.091296017170*_Complex_I, 0.030967503786 + -0.193203377724*_Complex_I, 0.036832565069 + -0.081849122047*_Complex_I, -0.046027070284 + -0.027470356226*_Complex_I, -0.125437974930 + 0.032441046834*_Complex_I, 0.011070625484 + -0.092022657394*_Complex_I, 0.137458860874 + 0.151134181023*_Complex_I, -0.117661428452 + -0.008656930178*_Complex_I, 0.163053572178 + -0.070776551962*_Complex_I, -0.119681096077 + -0.012249100208*_Complex_I, 0.127253675461 + 0.107909095287*_Complex_I, -0.051333457232 + -0.116273534298*_Complex_I, -0.071138489246 + 0.072735458612*_Complex_I, 0.037040272355 + -0.050955241919*_Complex_I, -0.200804090500 + -0.217231678963*_Complex_I, -0.109212982655 + 0.012372082472*_Complex_I, -0.029450660944 + 0.118574059010*_Complex_I, 0.099285334349 + -0.000237483322*_Complex_I, 0.276025676727 + -0.017251548171*_Complex_I, 0.088983309269 + 0.013136875629*_Complex_I, 0.163659727573 + -0.066418147087*_Complex_I, 0.104050731659 + 0.028489127755*_Complex_I, 0.016449892521 + -0.020746667683*_Complex_I, -0.126559376717 + -0.070659190416*_Complex_I, -0.237141442299 + 0.089611142874*_Complex_I, 0.068004012108 + 0.173722803593*_Complex_I, -0.047145104408 + -0.175941777229*_Complex_I, -0.123525714874 + -0.166570901871*_Complex_I, 0.001423638687 + 0.157464015484*_Complex_I, 0.079405152798 + -0.025422385335*_Complex_I, 0.081756842136 + 0.121069538593*_Complex_I, -0.128136157990 + 0.139459896088*_Complex_I, 0.007735489309 + -0.027935725451*_Complex_I, -0.092589050531 + -0.109762561321*_Complex_I, -0.016260780394 + -0.015316626430*_Complex_I, -0.158776199818 + 0.127178168297*_Complex_I, -0.026575049758 + 0.238629913330*_Complex_I, 0.152634930611 + -0.165786969662*_Complex_I, 0.108250701427 + -0.051711326838*_Complex_I, 0.076149952412 + -0.090032291412*_Complex_I, 0.074367189407 + -0.029565215111*_Complex_I, 0.061409753561 + -0.112582445145*_Complex_I, -0.097367572784 + -0.113927245140*_Complex_I, 0.026321750879 + 0.138302946091*_Complex_I, -0.001476241183 + -0.069936299324*_Complex_I, -0.114703190327 + 0.070511698723*_Complex_I, -0.006401912868 + -0.010170778632*_Complex_I, 0.082021260262 + -0.036617666483*_Complex_I, 0.381905221939 + 0.054933649302*_Complex_I, -0.047172623873 + -0.016221418977*_Complex_I, 0.075080448389 + 0.044649630785*_Complex_I, 0.006743746251 + -0.057219368219*_Complex_I, 0.072658914328 + -0.113842511177*_Complex_I, 0.063461345434 + 0.108319532871*_Complex_I, -0.085157209635 + 0.127499580383*_Complex_I, -0.110658645630 + 0.026664611697*_Complex_I, 0.087542557716 + -0.198326361179*_Complex_I, -0.187630629539 + -0.076032394171*_Complex_I, 0.158300364017 + -0.183700358868*_Complex_I, -0.117931878567 + -0.157972729206*_Complex_I, 0.048598474264 + -0.121435344219*_Complex_I, 0.090523117781 + -0.092027544975*_Complex_I, -0.126598548889 + -0.115896356106*_Complex_I, -0.050347799063 + 0.063965880871*_Complex_I, 0.009061803669 + -0.003273813799*_Complex_I, -0.138404893875 + -0.058004939556*_Complex_I, -0.027039816976 + 0.123541855812*_Complex_I, -0.260724592209 + 0.070059484243*_Complex_I, -0.071726894379 + 0.118393385410*_Complex_I, -0.103354132175 + -0.048656904697*_Complex_I, -0.079942697287 + -0.007439111173*_Complex_I, 0.010002358258 + 0.217011165619*_Complex_I, -0.107096755505 + -0.032441377640*_Complex_I, -0.038857096434 + -0.075556772947*_Complex_I, 0.103407859802 + -0.010233432055*_Complex_I, -0.017742788792 + -0.016240037978*_Complex_I, -0.061273831129 + 0.003164015338*_Complex_I, -0.120957195759 + 0.053525984287*_Complex_I, -0.102713096142 + -0.067174482346*_Complex_I, 0.033584815264 + 0.006909974664*_Complex_I, -0.067435938120 + -0.001113843173*_Complex_I, 0.151518130302 + -0.022716298699*_Complex_I, -0.092082822323 + -0.080135297775*_Complex_I, 0.027139824629 + 0.071895372868*_Complex_I, -0.115053045750 + 0.071924138069*_Complex_I, 0.011123746634 + -0.015718665719*_Complex_I, 0.101550316811 + 0.003213942051*_Complex_I, 0.087435191870 + -0.074827837944*_Complex_I, 0.098427033424 + 0.153796470165*_Complex_I, -0.030665528774 + 0.086529731750*_Complex_I, -0.015693670511 + -0.002731614932*_Complex_I, 0.133912920952 + 0.264183211327*_Complex_I, -0.000968740415 + 0.156215214729*_Complex_I, -0.018345800042 + -0.029062193632*_Complex_I, -0.049218568206 + -0.058449655771*_Complex_I, 0.045136275887 + 0.035753569007*_Complex_I, 0.011435703933 + 0.002002427541*_Complex_I, 0.021104848385 + -0.311103820801*_Complex_I, 0.005841723830 + -0.030350989103*_Complex_I, -0.064211606979 + 0.203191661835*_Complex_I, -0.071606880426 + 0.014993095398*_Complex_I, 0.072429609299 + 0.168000137806*_Complex_I, -0.038637900352 + -0.050586193800*_Complex_I, 0.168560516834 + 0.112749493122*_Complex_I, 0.140708494186 + -0.139942800999*_Complex_I, 0.044472098351 + 0.057332044840*_Complex_I, -0.113584566116 + 0.036734291911*_Complex_I, -0.115594518185 + 0.096241426468*_Complex_I, -0.132571578026 + 0.076662874222*_Complex_I, -0.088810175657 + 0.180961203575*_Complex_I, -0.134494102001 + 0.108674275875*_Complex_I, -0.066532063484 + 0.080732357502*_Complex_I, -0.001597549021 + 0.199119567871*_Complex_I, -0.171998977661 + 0.006639727950*_Complex_I, 0.157607150078 + -0.054489070177*_Complex_I, -0.109499049187 + -0.023027896881*_Complex_I, -0.172086226940 + 0.121059966087*_Complex_I, 0.119662201405 + -0.004805976152*_Complex_I}; float complex fftfilt_cccf_data_h4x256_y[] = { 0.012757276827 + -0.023960510977*_Complex_I, 0.028238533774 + 0.000766892287*_Complex_I, -0.030736578281 + 0.034719058493*_Complex_I, -0.049977138490 + -0.058212812777*_Complex_I, -0.029132843102 + -0.006952447936*_Complex_I, 0.041434724419 + 0.001305867219*_Complex_I, -0.000154542372 + 0.010398927205*_Complex_I, -0.010671035217 + 0.020245277403*_Complex_I, 0.045073710539 + -0.010894785162*_Complex_I, 0.061276520757 + -0.004366387666*_Complex_I, 0.015952866275 + 0.035222286704*_Complex_I, -0.014939304199 + 0.009382470283*_Complex_I, -0.000027323374 + -0.010136557087*_Complex_I, -0.049199930734 + 0.015765195506*_Complex_I, -0.006368245652 + -0.015589575903*_Complex_I, 0.029022969544 + -0.020956220654*_Complex_I, -0.029749689836 + 0.060255058887*_Complex_I, -0.023648414328 + 0.012506271275*_Complex_I, 0.042523255991 + -0.060078254361*_Complex_I, -0.003653249612 + 0.029899901014*_Complex_I, 0.002128348980 + 0.042692956028*_Complex_I, -0.023239979421 + -0.013201242246*_Complex_I, -0.036395878395 + 0.006550682393*_Complex_I, 0.005937946446 + -0.039787300481*_Complex_I, 0.071765960434 + 0.000338344221*_Complex_I, 0.014183242345 + -0.003691402540*_Complex_I, -0.014927275586 + -0.025008346274*_Complex_I, -0.021975526648 + -0.015174616793*_Complex_I, 0.031559403980 + 0.039201077146*_Complex_I, -0.002930033110 + 0.012825110045*_Complex_I, -0.048982592713 + 0.010293962046*_Complex_I, 0.013434665977 + 0.032290621601*_Complex_I, 0.033982791965 + 0.001317652206*_Complex_I, 0.023064195315 + 0.012663899061*_Complex_I, -0.018428432947 + 0.056613928236*_Complex_I, -0.049039654309 + -0.025292660627*_Complex_I, 0.010320821686 + -0.041716388907*_Complex_I, 0.023878576192 + 0.025126876135*_Complex_I, 0.020413632469 + 0.043472532575*_Complex_I, 0.036996565632 + -0.062485539135*_Complex_I, -0.004910190919 + -0.013287275246*_Complex_I, -0.010096052144 + 0.103664702556*_Complex_I, -0.028018937736 + 0.023708913702*_Complex_I, -0.011287655176 + -0.076741200437*_Complex_I, -0.001467109023 + -0.001917661318*_Complex_I, 0.005293144320 + 0.010848041931*_Complex_I, 0.018185964149 + 0.026525130926*_Complex_I, -0.015239532128 + -0.026094016726*_Complex_I, -0.034810813866 + 0.010226757752*_Complex_I, -0.049480455827 + 0.006882194797*_Complex_I, 0.045731930549 + -0.016140007390*_Complex_I, 0.014701121326 + 0.023870809774*_Complex_I, -0.033559313643 + 0.022713731523*_Complex_I, 0.050108362232 + 0.015581007741*_Complex_I, -0.005632120264 + 0.018308311284*_Complex_I, 0.052024517749 + -0.050433653230*_Complex_I, 0.020247348485 + 0.025265853477*_Complex_I, -0.048724807310 + 0.005688999390*_Complex_I, 0.018642648578 + -0.005112453077*_Complex_I, -0.000164879106 + -0.021983711442*_Complex_I, -0.005295938220 + -0.039983291504*_Complex_I, -0.036089961107 + 0.036124313440*_Complex_I, 0.032332494429 + 0.024537918792*_Complex_I, 0.022487700299 + -0.035126580906*_Complex_I, 0.035179302371 + 0.075476289976*_Complex_I, -0.022415275427 + 0.042965211229*_Complex_I, 0.045691989716 + 0.001526190095*_Complex_I, 0.004179917382 + -0.000409395803*_Complex_I, -0.014563762228 + -0.005376713067*_Complex_I, -0.027925684190 + 0.012934585830*_Complex_I, -0.000374846557 + -0.026098719210*_Complex_I, 0.032612571524 + 0.015336583912*_Complex_I, -0.052107302856 + 0.002717865097*_Complex_I, -0.032834640384 + 0.065614047849*_Complex_I, -0.005080334534 + 0.020989805546*_Complex_I, 0.031881162655 + -0.029694607868*_Complex_I, -0.015170864143 + -0.028448915975*_Complex_I, 0.020955734615 + 0.001553519861*_Complex_I, -0.025709904149 + 0.043093492818*_Complex_I, -0.013558366662 + -0.019060063112*_Complex_I, 0.021290614364 + -0.015390877095*_Complex_I, -0.008998068093 + 0.010479790493*_Complex_I, -0.024201210119 + -0.017983452805*_Complex_I, 0.030041436100 + -0.000867601449*_Complex_I, 0.011111929170 + 0.043244016918*_Complex_I, -0.001398590030 + 0.033219709577*_Complex_I, -0.017169337706 + -0.032498137528*_Complex_I, -0.003608831698 + -0.004190317460*_Complex_I, -0.039540681605 + -0.003316647474*_Complex_I, -0.018843962328 + 0.007361859229*_Complex_I, 0.046631096565 + 0.003646629910*_Complex_I, -0.027706090091 + 0.008592625414*_Complex_I, -0.002924156406 + 0.033883252714*_Complex_I, 0.075079733805 + 0.034815167989*_Complex_I, -0.030357014457 + -0.045596609600*_Complex_I, -0.032642221938 + -0.016644239862*_Complex_I, 0.032402948921 + -0.001883868205*_Complex_I, -0.023858913130 + 0.039323855789*_Complex_I, -0.041457486487 + -0.014233573157*_Complex_I, -0.007459151809 + 0.013792354132*_Complex_I, 0.002485997247 + -0.043959018212*_Complex_I, 0.003318269056 + -0.012519460724*_Complex_I, 0.000093169055 + -0.016480871965*_Complex_I, -0.016900119114 + -0.010406925321*_Complex_I, -0.007971836056 + 0.065190143824*_Complex_I, -0.006820219290 + 0.027753423502*_Complex_I, 0.031106376763 + -0.020043621536*_Complex_I, -0.031071266484 + 0.004339971697*_Complex_I, 0.040991447377 + -0.102820217268*_Complex_I, 0.031948560681 + -0.016199124342*_Complex_I, -0.025194033136 + 0.010324013232*_Complex_I, -0.006991588793 + -0.016219922197*_Complex_I, 0.028959571857 + 0.015200024042*_Complex_I, -0.011128094874 + -0.018331258759*_Complex_I, 0.010033408771 + -0.036038577315*_Complex_I, -0.003951805923 + 0.031887379901*_Complex_I, 0.043011761476 + 0.038394544247*_Complex_I, 0.047003249222 + 0.040511060053*_Complex_I, -0.046451986806 + 0.004395040215*_Complex_I, -0.012529114947 + -0.014584931709*_Complex_I, 0.036884371074 + -0.020832501744*_Complex_I, -0.021101612528 + -0.029213061508*_Complex_I, -0.036011838357 + 0.005793889985*_Complex_I, -0.015900637518 + 0.056267590724*_Complex_I, -0.023781635996 + 0.008199383119*_Complex_I, 0.030327057536 + -0.078422708418*_Complex_I, -0.005177131563 + -0.017104662921*_Complex_I, -0.014188045903 + -0.035985384502*_Complex_I, 0.032146074117 + 0.004602106645*_Complex_I, -0.009821272669 + -0.008851465116*_Complex_I, 0.027236042210 + 0.006241896038*_Complex_I, 0.022418389996 + -0.007040618186*_Complex_I, -0.005638389798 + 0.012513644070*_Complex_I, 0.000036227705 + 0.039661942810*_Complex_I, -0.017530818413 + -0.055992409201*_Complex_I, -0.009980130825 + 0.003409352124*_Complex_I, -0.007128899287 + 0.029065621717*_Complex_I, 0.007569712793 + -0.013550165086*_Complex_I, 0.012981701430 + -0.004450356742*_Complex_I, 0.025509754347 + 0.048348739912*_Complex_I, -0.011201724949 + 0.032065969619*_Complex_I, -0.000655974814 + -0.016732426150*_Complex_I, 0.019689483222 + -0.025854936465*_Complex_I, 0.011124510152 + -0.000398237810*_Complex_I, -0.047061637319 + 0.015558558157*_Complex_I, -0.011720140733 + -0.036972797597*_Complex_I, 0.028160356014 + 0.036264888172*_Complex_I, -0.021771924689 + 0.010389295245*_Complex_I, 0.019810005650 + -0.024476888982*_Complex_I, -0.033191779573 + -0.001651714148*_Complex_I, 0.043581774082 + 0.018672171512*_Complex_I, -0.003880433403 + -0.026649182116*_Complex_I, 0.024387701876 + 0.043399010529*_Complex_I, 0.060278802711 + 0.009923457700*_Complex_I, -0.031958233338 + -0.053227946939*_Complex_I, -0.037844853987 + 0.000125803799*_Complex_I, -0.051129681909 + 0.048362994750*_Complex_I, -0.034939691771 + 0.013353255240*_Complex_I, 0.013495424238 + 0.002533014678*_Complex_I, -0.024433814805 + 0.008923172086*_Complex_I, 0.006819321217 + -0.017933176852*_Complex_I, 0.036263988877 + 0.000691266276*_Complex_I, 0.051618724746 + -0.028316128600*_Complex_I, -0.011460974644 + -0.049249657052*_Complex_I, -0.038203479805 + 0.025707308664*_Complex_I, 0.063567349796 + 0.074586008729*_Complex_I, 0.005400590167 + -0.029955963800*_Complex_I, -0.049012787288 + -0.037393461959*_Complex_I, -0.028249615420 + 0.026654301221*_Complex_I, 0.008517579272 + -0.050945600372*_Complex_I, 0.033776936755 + -0.007976718780*_Complex_I, 0.007283043274 + 0.040108239951*_Complex_I, 0.026628003403 + 0.013587396181*_Complex_I, -0.004776533268 + -0.040224248409*_Complex_I, 0.001966163699 + -0.058690841656*_Complex_I, -0.036928601088 + 0.022515059406*_Complex_I, -0.018983384206 + 0.092142143476*_Complex_I, 0.006683303356 + -0.005118852801*_Complex_I, -0.006178795549 + 0.007657773084*_Complex_I, -0.004596093747 + 0.004602055322*_Complex_I, 0.023277809619 + 0.018778205222*_Complex_I, 0.011819463018 + -0.026895362189*_Complex_I, -0.029906188199 + -0.028279608383*_Complex_I, 0.020930036213 + 0.019813673820*_Complex_I, 0.017967997243 + -0.027321140175*_Complex_I, -0.026039058237 + 0.028575862467*_Complex_I, -0.065707150276 + 0.027564172049*_Complex_I, -0.042699371771 + -0.004553530531*_Complex_I, 0.060963634866 + -0.010306512109*_Complex_I, -0.018398404569 + -0.009004454205*_Complex_I, 0.012682078281 + 0.035081253992*_Complex_I, -0.022569581502 + -0.002483099277*_Complex_I, -0.005011260632 + -0.059832394695*_Complex_I, 0.033576764841 + -0.020322773572*_Complex_I, 0.011459245426 + 0.047090396734*_Complex_I, 0.010458010526 + 0.044772209285*_Complex_I, 0.029840259776 + 0.005715793160*_Complex_I, -0.033675797644 + 0.041554808951*_Complex_I, 0.042385066649 + 0.007945594638*_Complex_I, -0.042488207826 + 0.012628049489*_Complex_I, 0.011808820611 + 0.006893400628*_Complex_I, 0.034485946031 + -0.019260139612*_Complex_I, -0.025110072757 + -0.027865545511*_Complex_I, 0.011809921801 + 0.017253366676*_Complex_I, 0.023347768774 + -0.013960810328*_Complex_I, 0.004312140053 + -0.050475400734*_Complex_I, 0.039740495297 + -0.014728639995*_Complex_I, -0.013385038021 + 0.002586440528*_Complex_I, 0.024990035834 + 0.031120474272*_Complex_I, -0.017924227058 + -0.032258326607*_Complex_I, -0.008503405616 + -0.030526995261*_Complex_I, 0.039069831028 + 0.047795375707*_Complex_I, -0.017060972790 + 0.016758758851*_Complex_I, -0.023173891050 + -0.001084414363*_Complex_I, 0.026255359508 + -0.007252038830*_Complex_I, 0.018286656103 + -0.022933031391*_Complex_I, 0.024368811798 + -0.006580655348*_Complex_I, -0.004301769439 + 0.024140294549*_Complex_I, -0.014786161819 + -0.007103599240*_Complex_I, -0.004382808422 + 0.013351241103*_Complex_I, -0.016799676739 + 0.015974782469*_Complex_I, 0.034117502850 + -0.007152515247*_Complex_I, -0.016030168590 + -0.041660273222*_Complex_I, 0.020183324735 + 0.001275076977*_Complex_I, -0.029259335107 + 0.025057117273*_Complex_I, -0.019506766368 + 0.019348724623*_Complex_I, -0.017064727586 + -0.003715333530*_Complex_I, -0.011048527087 + -0.053833523722*_Complex_I, 0.024686830410 + 0.003799560503*_Complex_I, -0.028896024708 + -0.014835494620*_Complex_I, -0.040702141102 + -0.056626153309*_Complex_I, 0.032680942933 + 0.017723655112*_Complex_I, 0.029116465637 + 0.030527344293*_Complex_I, 0.002198173782 + 0.000971254919*_Complex_I, -0.021900155002 + -0.010625879853*_Complex_I, 0.022293892586 + 0.049298267413*_Complex_I, 0.012631626403 + 0.052532172470*_Complex_I, -0.013732381568 + -0.080618502666*_Complex_I, 0.000893373321 + -0.046464687935*_Complex_I, -0.012758518468 + 0.013919376550*_Complex_I, -0.014235454439 + -0.011924506441*_Complex_I, -0.001743292107 + 0.029502693438*_Complex_I, -0.044487788769 + 0.006911727783*_Complex_I, 0.005476613431 + 0.035516199946*_Complex_I, 0.025026369628 + -0.054869348705*_Complex_I, 0.031378831930 + -0.026801186271*_Complex_I, 0.011708942324 + -0.028570090261*_Complex_I, 0.004475361885 + -0.022218736038*_Complex_I, 0.002560834562 + -0.032693273555*_Complex_I, 0.016389708983 + 0.001391247264*_Complex_I, -0.017112703198 + -0.015433616304*_Complex_I, 0.011474238974 + -0.022409486851*_Complex_I, 0.019950525436 + 0.045615249829*_Complex_I, -0.029025601300 + 0.019024103552*_Complex_I, 0.058627375247 + -0.038320734588*_Complex_I, -0.014973530138 + -0.021441866237*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/fftfilt_cccf_data_h7x256.c000066400000000000000000000652531317124540100245230ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fftfilt_cccf_data_h7x256.c: autotest fftfilt data // #include float complex fftfilt_cccf_data_h7x256_h[] = { -0.007281364501 + 0.082790547609*_Complex_I, 0.009967260063 + -0.094733065367*_Complex_I, 0.081317949295 + -0.022636219859*_Complex_I, -0.065424275398 + -0.051597696543*_Complex_I, 0.014696654677 + -0.083596301079*_Complex_I, -0.061433798075 + 0.010713580251*_Complex_I, -0.225753474236 + 0.128715121746*_Complex_I}; float complex fftfilt_cccf_data_h7x256_x[] = { -0.224034833908 + -0.008699086308*_Complex_I, -0.049732953310 + -0.031826138496*_Complex_I, 0.076697158813 + 0.011335625499*_Complex_I, -0.036047935486 + 0.081799823046*_Complex_I, -0.034496423602 + 0.116949427128*_Complex_I, 0.041598823667 + 0.101615536213*_Complex_I, 0.210013437271 + -0.035565614700*_Complex_I, -0.012152856588 + -0.011570352316*_Complex_I, -0.028147217631 + 0.166729998589*_Complex_I, -0.167404901981 + 0.187454140186*_Complex_I, -0.026512432098 + 0.261313009262*_Complex_I, 0.102972781658 + -0.004534423724*_Complex_I, 0.059284800291 + 0.183526933193*_Complex_I, 0.030326950550 + -0.089217764139*_Complex_I, -0.018447282910 + -0.049126222730*_Complex_I, 0.113261175156 + 0.002915558405*_Complex_I, -0.135392773151 + 0.014876940846*_Complex_I, 0.004361338913 + 0.021383246779*_Complex_I, -0.202443695068 + -0.054077798128*_Complex_I, -0.004843016341 + 0.108202099800*_Complex_I, 0.001668977737 + 0.194661521912*_Complex_I, -0.010195496678 + 0.196535933018*_Complex_I, 0.034973055124 + -0.061964601278*_Complex_I, -0.102277493477 + 0.223646140099*_Complex_I, -0.023419928551 + 0.070746564865*_Complex_I, -0.159975051880 + -0.097339767218*_Complex_I, 0.106308436394 + -0.067826884985*_Complex_I, 0.009907814115 + -0.101035916805*_Complex_I, 0.091246986389 + -0.126393759251*_Complex_I, 0.155365455151 + 0.032811716199*_Complex_I, -0.050400662422 + 0.005999959260*_Complex_I, 0.098249650002 + 0.119454848766*_Complex_I, 0.043273428082 + 0.037401539087*_Complex_I, -0.023780041933 + -0.059200626612*_Complex_I, -0.123366844654 + 0.054930090904*_Complex_I, 0.036521813273 + -0.093353188038*_Complex_I, -0.127803146839 + -0.129888510704*_Complex_I, 0.010239485651 + -0.006050923839*_Complex_I, 0.073504078388 + 0.019415560365*_Complex_I, -0.071594107151 + 0.259088206291*_Complex_I, -0.164907193184 + -0.230266833305*_Complex_I, -0.047658449411 + -0.051974463463*_Complex_I, 0.126409828663 + 0.080523037910*_Complex_I, -0.015694612265 + -0.041679582000*_Complex_I, 0.247366762161 + 0.014814090729*_Complex_I, -0.128671801090 + 0.043787026405*_Complex_I, 0.059505617619 + -0.051679652929*_Complex_I, -0.031817299128 + -0.116028845310*_Complex_I, -0.059748482704 + 0.052395486832*_Complex_I, 0.057849615812 + 0.112650203705*_Complex_I, 0.024142844975 + -0.127626419067*_Complex_I, -0.021054366231 + -0.034706163406*_Complex_I, 0.115030443668 + -0.228685379028*_Complex_I, 0.046825522184 + -0.056672191620*_Complex_I, 0.033698257804 + 0.121798670292*_Complex_I, 0.054840600491 + -0.057236319780*_Complex_I, 0.099697828293 + 0.019323211908*_Complex_I, -0.155612981319 + -0.004370240867*_Complex_I, -0.004620010406 + -0.084638983011*_Complex_I, 0.070532739162 + 0.011928464472*_Complex_I, -0.109211897850 + -0.102859199047*_Complex_I, -0.081594198942 + -0.078812837601*_Complex_I, 0.043022164702 + -0.170342290401*_Complex_I, -0.121134638786 + 0.000720720459*_Complex_I, -0.113152539730 + 0.049016854167*_Complex_I, -0.044530594349 + -0.051119738817*_Complex_I, 0.072675555944 + 0.022612531483*_Complex_I, 0.079078042507 + -0.004720374569*_Complex_I, 0.139414632320 + -0.062684261799*_Complex_I, 0.047556161880 + 0.004797710106*_Complex_I, 0.099456727505 + -0.072699415684*_Complex_I, 0.042401811481 + 0.080890959501*_Complex_I, 0.153871464729 + -0.013893789053*_Complex_I, 0.071284359694 + 0.021137169003*_Complex_I, -0.167169976234 + -0.071725249290*_Complex_I, -0.107850408554 + -0.217037105560*_Complex_I, -0.074640941620 + -0.056393194199*_Complex_I, -0.088496351242 + -0.011706933379*_Complex_I, -0.055197536945 + 0.114396464825*_Complex_I, -0.016207906604 + 0.147190082073*_Complex_I, 0.027984252572 + -0.018767827749*_Complex_I, -0.159589684010 + -0.021223792434*_Complex_I, 0.258048582077 + -0.011464864016*_Complex_I, -0.028931617737 + 0.055535191298*_Complex_I, 0.090275204182 + -0.104534256458*_Complex_I, 0.007160897553 + -0.012574975193*_Complex_I, 0.074187409878 + -0.067596536875*_Complex_I, -0.129586255550 + -0.095341777802*_Complex_I, 0.025683063269 + 0.037984248996*_Complex_I, -0.097140216827 + 0.072665137053*_Complex_I, -0.060703277588 + -0.020677544177*_Complex_I, -0.111789143085 + 0.069817501307*_Complex_I, 0.058083856106 + 0.050827920437*_Complex_I, 0.050110381842 + -0.096382743120*_Complex_I, -0.003128097579 + 0.086557382345*_Complex_I, -0.162541246414 + -0.290272450447*_Complex_I, 0.149705743790 + -0.195581960678*_Complex_I, -0.037328532338 + -0.068566280603*_Complex_I, -0.028459328413 + -0.020298738778*_Complex_I, 0.030010712147 + -0.021110333502*_Complex_I, 0.040339571238 + 0.037839868665*_Complex_I, 0.014134916663 + -0.117352914810*_Complex_I, -0.077330631018 + -0.119114518166*_Complex_I, -0.022596450150 + 0.134884607792*_Complex_I, 0.031885313988 + -0.092574226856*_Complex_I, 0.050890713930 + -0.056063300371*_Complex_I, -0.065839445591 + 0.059127074480*_Complex_I, 0.234607529640 + -0.133058774471*_Complex_I, 0.102069032192 + -0.076372599602*_Complex_I, -0.075891935825 + -0.020809832215*_Complex_I, -0.090930736065 + -0.085748946667*_Complex_I, 0.017342594266 + 0.031213536859*_Complex_I, 0.038657885790 + 0.025738736987*_Complex_I, 0.060605341196 + -0.119861590862*_Complex_I, 0.073895943165 + -0.044689002633*_Complex_I, 0.105450510979 + -0.160455989838*_Complex_I, -0.124542450905 + 0.046032539010*_Complex_I, 0.045331561565 + 0.000319873891*_Complex_I, 0.024264129996 + 0.026674240828*_Complex_I, -0.105825412273 + -0.020621740818*_Complex_I, 0.088798046112 + -0.188584482670*_Complex_I, -0.106230950356 + 0.102003884315*_Complex_I, 0.094149869680 + 0.040696659684*_Complex_I, -0.034001356363 + 0.107437086105*_Complex_I, -0.018224966526 + 0.112718844414*_Complex_I, 0.017100249231 + -0.115852773190*_Complex_I, -0.033193737268 + -0.000597832398*_Complex_I, 0.000483878236 + -0.106654667854*_Complex_I, -0.058922708035 + 0.047018918395*_Complex_I, -0.062014073133 + -0.023304754496*_Complex_I, 0.044369766116 + -0.168211150169*_Complex_I, 0.130730128288 + -0.172116661072*_Complex_I, 0.145810830593 + -0.078202575445*_Complex_I, 0.064167177677 + -0.028775659204*_Complex_I, -0.080559664965 + 0.030702465773*_Complex_I, 0.099988013506 + 0.068486881256*_Complex_I, 0.037929025292 + -0.016449454427*_Complex_I, 0.170670747757 + -0.075250750780*_Complex_I, 0.063665509224 + 0.095736193657*_Complex_I, -0.004959807545 + 0.029583230615*_Complex_I, 0.001406790875 + 0.107474470139*_Complex_I, -0.118572568893 + -0.044207367301*_Complex_I, 0.006175531074 + 0.128024518490*_Complex_I, -0.140851879120 + -0.023605427146*_Complex_I, -0.107514488697 + 0.124532020092*_Complex_I, 0.002869207598 + -0.137480175495*_Complex_I, 0.107076263428 + 0.171094465256*_Complex_I, -0.154599738121 + 0.276871156693*_Complex_I, 0.101584804058 + 0.051078712940*_Complex_I, 0.080567914248 + 0.072715389729*_Complex_I, -0.118250894547 + 0.203802919388*_Complex_I, -0.204971146584 + -0.016665045917*_Complex_I, -0.066708135605 + -0.131536126137*_Complex_I, -0.121210551262 + 0.006252479553*_Complex_I, 0.061139965057 + 0.027922019362*_Complex_I, -0.019852848351 + 0.013758929074*_Complex_I, 0.124678170681 + 0.068077403307*_Complex_I, 0.114459848404 + -0.033342263103*_Complex_I, 0.177140033245 + -0.072824108601*_Complex_I, 0.044942480326 + -0.185283625126*_Complex_I, 0.130411398411 + 0.241176652908*_Complex_I, 0.184130918980 + -0.040936833620*_Complex_I, -0.000141406199 + 0.054715901613*_Complex_I, -0.069603371620 + 0.036669918895*_Complex_I, -0.061578559875 + 0.032855123281*_Complex_I, 0.056589269638 + -0.058769983053*_Complex_I, 0.182259237766 + 0.049186679721*_Complex_I, 0.065936774015 + 0.027898868918*_Complex_I, -0.065557408333 + -0.070153760910*_Complex_I, 0.054138237238 + -0.027161026001*_Complex_I, -0.018398490548 + -0.110003650188*_Complex_I, 0.002755430155 + 0.078435707092*_Complex_I, 0.013758489490 + -0.113180506229*_Complex_I, -0.051234912872 + -0.005474814028*_Complex_I, -0.104593336582 + 0.080550593138*_Complex_I, 0.007267350703 + -0.125861871243*_Complex_I, 0.107477843761 + 0.046790626645*_Complex_I, 0.039212217927 + -0.116215384007*_Complex_I, 0.124826478958 + -0.081632637978*_Complex_I, 0.125280117989 + 0.320632147789*_Complex_I, -0.007471156120 + 0.104660058022*_Complex_I, -0.115239381790 + -0.076022726297*_Complex_I, -0.094622492790 + -0.057151579857*_Complex_I, -0.168905770779 + -0.250946950912*_Complex_I, -0.108807468414 + 0.001907045953*_Complex_I, 0.070568650961 + 0.086386668682*_Complex_I, -0.001869313978 + 0.037941047549*_Complex_I, -0.025408759713 + 0.082414060831*_Complex_I, 0.144938981533 + 0.203817605972*_Complex_I, 0.069982367754 + 0.049768888950*_Complex_I, 0.016490152478 + 0.074179810286*_Complex_I, 0.105687451363 + -0.110984444618*_Complex_I, 0.113551545143 + 0.109880757332*_Complex_I, -0.057247632742 + 0.134226346016*_Complex_I, -0.147579395771 + 0.089595174789*_Complex_I, -0.066095471382 + -0.101449275017*_Complex_I, -0.099719625711 + 0.069632160664*_Complex_I, -0.010588133335 + 0.072132295370*_Complex_I, 0.121390247345 + 0.038519486785*_Complex_I, -0.018545143306 + -0.181026077271*_Complex_I, 0.063769525290 + -0.064973735809*_Complex_I, -0.069635564089 + -0.033288177848*_Complex_I, -0.191137075424 + -0.041628292203*_Complex_I, 0.078501302004 + 0.084461838007*_Complex_I, 0.057879024744 + -0.055903303623*_Complex_I, -0.024872413278 + -0.012924948335*_Complex_I, 0.030974438787 + 0.053028428555*_Complex_I, 0.108443212509 + 0.096264117956*_Complex_I, 0.020256328583 + 0.141622221470*_Complex_I, -0.014323671162 + 0.037487837672*_Complex_I, -0.054792886972 + -0.018909129500*_Complex_I, 0.112955272198 + -0.105722856522*_Complex_I, 0.076327735186 + -0.023400066793*_Complex_I, 0.050041192770 + -0.111338639259*_Complex_I, -0.152574229240 + 0.112567448616*_Complex_I, -0.100790119171 + 0.151508641243*_Complex_I, -0.132981181145 + -0.022067332268*_Complex_I, -0.039436492324 + -0.142156898975*_Complex_I, 0.272883749008 + -0.021410278976*_Complex_I, 0.016576641798 + 0.044247716665*_Complex_I, -0.043560856581 + 0.035046094656*_Complex_I, 0.048125803471 + 0.009931682050*_Complex_I, 0.067209833860 + 0.107492733002*_Complex_I, -0.046075564623 + 0.075197333097*_Complex_I, -0.102803206444 + 0.086919504404*_Complex_I, 0.082356423140 + 0.014404250681*_Complex_I, -0.008545895666 + 0.062289041281*_Complex_I, -0.137773501873 + -0.077222770452*_Complex_I, 0.011148673296 + 0.004276630655*_Complex_I, -0.013848714530 + 0.030436140299*_Complex_I, -0.032711941004 + -0.004091787338*_Complex_I, -0.068230164051 + -0.041420990229*_Complex_I, -0.153997719288 + -0.011947461963*_Complex_I, 0.104870522022 + 0.007879497856*_Complex_I, -0.012260202318 + 0.097705692053*_Complex_I, 0.105240559578 + 0.005197756737*_Complex_I, -0.052444481850 + 0.019592680037*_Complex_I, -0.111304521561 + -0.082899254560*_Complex_I, 0.143180394173 + 0.084308052063*_Complex_I, -0.081846255064 + 0.013113263249*_Complex_I, -0.046875402331 + 0.172497475147*_Complex_I, -0.101886129379 + 0.027100220323*_Complex_I, -0.120501518250 + -0.011151956767*_Complex_I, -0.069285804033 + -0.066505169868*_Complex_I, 0.135213494301 + -0.155834245682*_Complex_I, 0.120262145996 + -0.073802947998*_Complex_I, 0.083161532879 + 0.151243543625*_Complex_I, 0.032715103030 + 0.113134217262*_Complex_I, 0.029656037688 + 0.049728840590*_Complex_I, -0.002572274208 + -0.116174411774*_Complex_I, -0.028744161129 + 0.043948829174*_Complex_I, -0.039567849040 + 0.071218341589*_Complex_I, -0.008260916919 + -0.064960545301*_Complex_I, 0.065007799864 + -0.006339413673*_Complex_I, -0.060093468428 + 0.035650527477*_Complex_I, 0.056396996975 + 0.005192263052*_Complex_I}; float complex fftfilt_cccf_data_h7x256_y[] = { 0.002351481406 + -0.018484625365*_Complex_I, -0.000060077369 + 0.017251119786*_Complex_I, -0.023422599244 + 0.015025306572*_Complex_I, 0.004772403706 + -0.000066271937*_Complex_I, 0.002043987108 + 0.022957322244*_Complex_I, 0.006971825136 + 0.011730423896*_Complex_I, 0.075044907061 + -0.010178051817*_Complex_I, 0.030543599209 + -0.014597024085*_Complex_I, -0.004187564049 + -0.012444862513*_Complex_I, -0.008030018509 + -0.052716125275*_Complex_I, -0.014464683212 + -0.025509129789*_Complex_I, -0.010946291967 + 0.010946463449*_Complex_I, -0.019083957948 + 0.052439959673*_Complex_I, 0.066017066062 + -0.011801681075*_Complex_I, 0.012681132555 + -0.044881829563*_Complex_I, 0.013761162913 + -0.101272173584*_Complex_I, -0.025754029961 + -0.084604999250*_Complex_I, -0.029077685715 + 0.014810788777*_Complex_I, -0.052203914324 + -0.045501878664*_Complex_I, 0.002605824684 + 0.042542814124*_Complex_I, -0.020042313554 + 0.020106358559*_Complex_I, -0.001164073801 + 0.033904434250*_Complex_I, 0.054491738690 + 0.009310176063*_Complex_I, 0.008515506861 + -0.011753395733*_Complex_I, 0.094828569883 + -0.026525642698*_Complex_I, 0.008210310591 + -0.020111342169*_Complex_I, -0.019624361168 + -0.039339738841*_Complex_I, -0.014390113878 + -0.046568094370*_Complex_I, 0.022417994509 + 0.019882474081*_Complex_I, -0.042352866908 + -0.063076024765*_Complex_I, 0.006168688437 + -0.049455732212*_Complex_I, 0.024885397093 + 0.019187383987*_Complex_I, -0.027570701811 + 0.012482396648*_Complex_I, 0.034892258750 + 0.024754673210*_Complex_I, -0.019859377031 + 0.024455238102*_Complex_I, -0.017573930231 + 0.012206492330*_Complex_I, -0.000030036343 + -0.018861530511*_Complex_I, -0.047303454990 + -0.008979343421*_Complex_I, -0.032862144074 + 0.013096445775*_Complex_I, -0.003290051529 + 0.000967363362*_Complex_I, 0.056330016511 + -0.016207422066*_Complex_I, -0.009913108504 + 0.058827181838*_Complex_I, 0.034154084481 + -0.006877816529*_Complex_I, 0.020659033034 + 0.020329190951*_Complex_I, -0.033737500188 + 0.029784749533*_Complex_I, -0.014787869426 + -0.101188110643*_Complex_I, 0.104978906788 + 0.041126486668*_Complex_I, -0.014250954609 + -0.012495039834*_Complex_I, -0.033482494554 + -0.025221829498*_Complex_I, -0.021831072247 + 0.022276580945*_Complex_I, -0.039699732339 + 0.032109615994*_Complex_I, 0.015186398989 + -0.019223783117*_Complex_I, 0.015617783227 + 0.023435548030*_Complex_I, 0.008665069769 + 0.010930457080*_Complex_I, -0.019797730380 + -0.050654536825*_Complex_I, -0.031473081271 + -0.002299268225*_Complex_I, -0.012475915927 + 0.033630086770*_Complex_I, 0.012117088154 + -0.022047521436*_Complex_I, 0.018953771446 + 0.084550384232*_Complex_I, -0.038474316372 + 0.008379280035*_Complex_I, -0.004152321333 + -0.040424140749*_Complex_I, -0.015770397680 + 0.041094196479*_Complex_I, -0.032229291824 + 0.007648330888*_Complex_I, 0.017449905676 + -0.027618778546*_Complex_I, -0.006186370902 + 0.022452120667*_Complex_I, -0.030800615243 + 0.036816080788*_Complex_I, 0.022326504033 + 0.029342855626*_Complex_I, 0.033861836665 + 0.027757022091*_Complex_I, 0.033294890809 + 0.063126561257*_Complex_I, 0.026195622962 + -0.034339699352*_Complex_I, 0.036201082469 + -0.036428336260*_Complex_I, -0.008587770526 + -0.012485601384*_Complex_I, -0.015622310942 + -0.008490102192*_Complex_I, -0.031068211782 + 0.008958937995*_Complex_I, -0.007527617323 + -0.009025029679*_Complex_I, -0.003515003755 + 0.009061780897*_Complex_I, -0.050680655889 + 0.006806632206*_Complex_I, -0.037393296454 + -0.018572129400*_Complex_I, -0.068556095005 + 0.055060185831*_Complex_I, -0.034772327965 + 0.025392795717*_Complex_I, 0.068529963519 + 0.033603853922*_Complex_I, 0.068141793595 + 0.036809357702*_Complex_I, 0.044397919943 + 0.034591392907*_Complex_I, 0.016558611126 + -0.038538049919*_Complex_I, 0.039037787845 + -0.030382584037*_Complex_I, -0.047508232653 + -0.037136167083*_Complex_I, 0.022633104346 + -0.021161468084*_Complex_I, 0.019417536232 + -0.025786181928*_Complex_I, -0.073279279420 + 0.029450944763*_Complex_I, -0.028480466565 + -0.024506456063*_Complex_I, 0.002785948604 + 0.049355785551*_Complex_I, -0.027211045311 + 0.018218457773*_Complex_I, 0.010057004283 + 0.043364801389*_Complex_I, 0.052591845448 + 0.024521644529*_Complex_I, -0.007103268409 + -0.008581702223*_Complex_I, 0.054820608058 + -0.043395183529*_Complex_I, 0.007024973331 + 0.024411987870*_Complex_I, -0.021388284266 + -0.082405595490*_Complex_I, -0.016087426094 + 0.012722301935*_Complex_I, -0.051447296267 + 0.037652130140*_Complex_I, -0.020486080157 + -0.013825054104*_Complex_I, 0.077051270037 + 0.059321440673*_Complex_I, -0.007177045570 + 0.063268745704*_Complex_I, -0.007356525502 + -0.002336907547*_Complex_I, 0.015196504414 + 0.005533310901*_Complex_I, -0.020595977716 + 0.027771059823*_Complex_I, -0.024966648066 + -0.018445080957*_Complex_I, 0.039144080425 + 0.064591816908*_Complex_I, 0.010537647232 + -0.002822061917*_Complex_I, 0.002315709356 + -0.065572625222*_Complex_I, -0.004442911821 + 0.023522751103*_Complex_I, -0.037537461559 + 0.002025051546*_Complex_I, -0.015345245866 + -0.018745889894*_Complex_I, -0.028196845561 + 0.086992050424*_Complex_I, -0.020218420272 + 0.034974063899*_Complex_I, 0.039213934957 + -0.014112442962*_Complex_I, 0.010679269036 + -0.019758241192*_Complex_I, -0.019147387264 + -0.013125586740*_Complex_I, -0.043295632029 + 0.009486453379*_Complex_I, 0.005284847258 + 0.018994059412*_Complex_I, -0.002085765180 + 0.059479538243*_Complex_I, -0.029236803469 + 0.019741499311*_Complex_I, 0.035349982194 + -0.019550030169*_Complex_I, -0.041053561980 + 0.019272334294*_Complex_I, 0.004781302105 + -0.011012070475*_Complex_I, 0.045646671834 + 0.021045605276*_Complex_I, 0.012770406300 + 0.038111716908*_Complex_I, 0.027329675786 + -0.046058315366*_Complex_I, -0.039771978581 + 0.000217202102*_Complex_I, -0.009660565931 + -0.044728920362*_Complex_I, -0.009225975226 + 0.004924878144*_Complex_I, 0.002703841656 + 0.032097754317*_Complex_I, 0.004813881897 + -0.003380733447*_Complex_I, 0.004987905899 + 0.008151460089*_Complex_I, -0.013488990428 + -0.042016257678*_Complex_I, -0.009691719041 + 0.004147526727*_Complex_I, -0.001915632244 + 0.039683487703*_Complex_I, 0.003401771653 + 0.072636903863*_Complex_I, -0.039215694844 + 0.021883077630*_Complex_I, 0.017168617098 + -0.011912327212*_Complex_I, -0.007318874653 + -0.021289530606*_Complex_I, -0.021564667106 + -0.032135038803*_Complex_I, -0.018800999207 + 0.028531206788*_Complex_I, -0.021400100758 + 0.015792926127*_Complex_I, -0.021993149924 + 0.008754610031*_Complex_I, 0.006936290706 + 0.000597376601*_Complex_I, -0.021466822342 + 0.006078512969*_Complex_I, 0.032723812926 + -0.038751398566*_Complex_I, 0.024881623268 + 0.028431503514*_Complex_I, 0.023419199688 + -0.017541455668*_Complex_I, 0.050912833475 + -0.066376947294*_Complex_I, 0.054697680345 + 0.030926451912*_Complex_I, -0.032668768209 + -0.026228308942*_Complex_I, -0.011814848889 + -0.099139861759*_Complex_I, -0.019161603567 + 0.029704427790*_Complex_I, -0.036750148181 + 0.005099535581*_Complex_I, 0.009675516891 + -0.040182618193*_Complex_I, 0.058423255788 + -0.009856816276*_Complex_I, 0.059012388904 + 0.021583146036*_Complex_I, 0.037149929970 + -0.044837871667*_Complex_I, -0.043274833420 + -0.019633669057*_Complex_I, 0.003526349344 + -0.033434222301*_Complex_I, -0.050076212918 + -0.003722989863*_Complex_I, -0.025867292105 + -0.013323971651*_Complex_I, -0.021737697568 + 0.042999651371*_Complex_I, 0.007346070802 + 0.030458687290*_Complex_I, -0.075005823056 + -0.018314546864*_Complex_I, -0.022152256082 + 0.019384502494*_Complex_I, 0.017499070564 + -0.019824208197*_Complex_I, 0.001505234864 + -0.027164808784*_Complex_I, 0.011030624309 + -0.041209715189*_Complex_I, -0.026294492121 + 0.019222017912*_Complex_I, -0.050856019432 + 0.008735996115*_Complex_I, -0.027403486053 + 0.008700019502*_Complex_I, 0.006815542339 + -0.009666401504*_Complex_I, 0.006105705172 + 0.040222173395*_Complex_I, -0.012075903008 + 0.033397015302*_Complex_I, 0.012019759958 + -0.021944616302*_Complex_I, 0.017925084955 + 0.052323963578*_Complex_I, -0.030587094207 + -0.037431463625*_Complex_I, 0.042390892393 + -0.046071078594*_Complex_I, 0.020356789621 + 0.037541180532*_Complex_I, -0.029260492422 + -0.016824122043*_Complex_I, 0.038403000345 + 0.018077265958*_Complex_I, -0.050358282861 + 0.031195025615*_Complex_I, -0.103007313184 + -0.046673399500*_Complex_I, -0.015001996713 + 0.007412936952*_Complex_I, 0.030614255358 + 0.024026842526*_Complex_I, 0.030514848064 + 0.031032426681*_Complex_I, 0.103356759873 + 0.027622431036*_Complex_I, 0.043667006406 + -0.014369006727*_Complex_I, 0.002636002600 + -0.019049360571*_Complex_I, -0.002989929744 + -0.026987627040*_Complex_I, -0.001094610254 + -0.070463253033*_Complex_I, -0.052461850294 + -0.027889438408*_Complex_I, -0.019216539397 + -0.007771079643*_Complex_I, -0.022329844508 + -0.013265024739*_Complex_I, -0.001032810892 + 0.043621747952*_Complex_I, -0.037166418731 + 0.024063055407*_Complex_I, 0.025171222560 + -0.045359590807*_Complex_I, 0.034025739768 + -0.022421529929*_Complex_I, 0.025417150018 + -0.024301770390*_Complex_I, 0.015009353323 + -0.045864470900*_Complex_I, -0.057523653826 + 0.003583092215*_Complex_I, -0.034434260403 + 0.016881949843*_Complex_I, 0.035644457860 + 0.058158734255*_Complex_I, -0.011112332655 + 0.028514917481*_Complex_I, 0.027994412412 + -0.000205339299*_Complex_I, 0.041965151118 + -0.028140201223*_Complex_I, -0.010670315886 + -0.004680002358*_Complex_I, 0.008782107185 + 0.015284218025*_Complex_I, 0.025707610980 + -0.002674567128*_Complex_I, -0.018895101407 + -0.019624170860*_Complex_I, -0.019911769609 + -0.024108802516*_Complex_I, -0.050134730896 + -0.049361961836*_Complex_I, -0.012519484934 + -0.027194287781*_Complex_I, 0.005428457404 + 0.015715697375*_Complex_I, -0.005238127738 + 0.060099693736*_Complex_I, -0.019908892893 + 0.058463294088*_Complex_I, 0.020429924866 + 0.006302169131*_Complex_I, 0.039448100593 + -0.046219948910*_Complex_I, -0.015700342290 + -0.047106832460*_Complex_I, 0.029509140574 + -0.026543641019*_Complex_I, 0.028367751154 + 0.020535031374*_Complex_I, -0.052572208167 + 0.041630709393*_Complex_I, -0.001077487262 + -0.000376269684*_Complex_I, 0.009826813537 + -0.019618490100*_Complex_I, 0.019631481777 + -0.007463103449*_Complex_I, -0.034282389268 + 0.002382911984*_Complex_I, -0.002559574060 + -0.045197738751*_Complex_I, 0.021242907296 + -0.020034144666*_Complex_I, -0.026802493199 + 0.013457289582*_Complex_I, 0.000954596220 + -0.020243773142*_Complex_I, 0.034013053731 + 0.024387771984*_Complex_I, -0.020040092793 + -0.001711964654*_Complex_I, 0.022898948260 + 0.014147183418*_Complex_I, 0.004346236707 + -0.000881433760*_Complex_I, 0.056049489865 + -0.020165330024*_Complex_I, 0.010340548926 + 0.003943868642*_Complex_I, -0.020562812005 + -0.025528198571*_Complex_I, -0.012419521606 + -0.000626407753*_Complex_I, -0.026985254984 + 0.006236327937*_Complex_I, 0.035672449990 + 0.000476818088*_Complex_I, 0.034040270392 + 0.009473149874*_Complex_I, -0.021617320834 + 0.027702717665*_Complex_I, 0.010577232861 + -0.016439967770*_Complex_I, -0.018705783473 + -0.051973816043*_Complex_I, 0.017231348174 + -0.025014597024*_Complex_I, 0.027788678270 + -0.014081809821*_Complex_I, 0.035390113297 + -0.001427819683*_Complex_I, -0.010424664995 + 0.044346140061*_Complex_I, -0.018385369373 + 0.007862320395*_Complex_I, -0.032248235088 + -0.015582515953*_Complex_I, -0.037693834890 + -0.014701063462*_Complex_I, -0.006787010773 + -0.016420585935*_Complex_I, 0.026470441729 + 0.040610897283*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/fftfilt_crcf_data_h13x256.c000066400000000000000000000651151317124540100246140ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fftfilt_crcf_data_h13x256.c: autotest fftfilt data // #include float fftfilt_crcf_data_h13x256_h[] = { 0.078415364027, -0.038823145628, -0.051182097197, -0.126747608185, -0.044354891777, 0.008586834371, 0.093218648434, 0.013351599872, 0.104246592522, -0.147247779369, -0.015137273073, -0.079225271940, 0.060841810703}; float complex fftfilt_crcf_data_h13x256_x[] = { 0.085537636280 + -0.046111658216*_Complex_I, 0.225455975533 + -0.212855386734*_Complex_I, -0.057062256336 + 0.128235316277*_Complex_I, -0.133161616325 + 0.161920166016*_Complex_I, -0.111347568035 + 0.016286674142*_Complex_I, -0.123166453838 + -0.175749886036*_Complex_I, -0.127994334698 + -0.038678660989*_Complex_I, 0.001753777266 + 0.177034842968*_Complex_I, -0.060360968113 + 0.043074116111*_Complex_I, -0.019538708031 + 0.103789019585*_Complex_I, -0.014221027493 + -0.063071894646*_Complex_I, 0.068899226189 + -0.026364141703*_Complex_I, 0.115704405308 + -0.004594086856*_Complex_I, 0.007105919719 + -0.147161698341*_Complex_I, -0.108864045143 + 0.057467007637*_Complex_I, -0.068811172247 + -0.147289085388*_Complex_I, -0.230341863632 + -0.117713248730*_Complex_I, 0.212086534500 + 0.075316011906*_Complex_I, 0.111719250679 + -0.054894649982*_Complex_I, -0.058907771111 + 0.011760091782*_Complex_I, 0.040262156725 + 0.204210424423*_Complex_I, 0.056027442217 + -0.155560147762*_Complex_I, 0.086805480719 + -0.004523682222*_Complex_I, 0.036359512806 + 0.141219484806*_Complex_I, -0.220814013481 + -0.062183243036*_Complex_I, 0.153262519836 + -0.046371394396*_Complex_I, 0.026782101393 + -0.145832955837*_Complex_I, 0.065809303522 + 0.160269105434*_Complex_I, -0.350135111809 + -0.025641095638*_Complex_I, -0.014225926995 + -0.006095404923*_Complex_I, 0.025032842159 + 0.079940289259*_Complex_I, -0.153848528862 + 0.047698283195*_Complex_I, -0.074249881506 + -0.036540001631*_Complex_I, -0.058573323488 + -0.038949799538*_Complex_I, -0.004152575880 + 0.284297037125*_Complex_I, -0.135746490955 + 0.021615330875*_Complex_I, 0.016607114673 + -0.020308291912*_Complex_I, 0.152347302437 + 0.127957522869*_Complex_I, -0.010453918576 + 0.027730533481*_Complex_I, 0.014759464562 + 0.026369267702*_Complex_I, 0.082868421078 + 0.018653041124*_Complex_I, 0.036655226350 + 0.110286545753*_Complex_I, -0.089152860641 + -0.036632573605*_Complex_I, 0.039231717587 + 0.077600806952*_Complex_I, -0.081070268154 + -0.003452447802*_Complex_I, 0.000562082976 + 0.017119739950*_Complex_I, 0.144655835629 + 0.104714202881*_Complex_I, 0.014049226046 + 0.166446399689*_Complex_I, 0.088486814499 + -0.014644494653*_Complex_I, 0.057762199640 + -0.093236494064*_Complex_I, 0.047099858522 + -0.028719729185*_Complex_I, 0.106528282166 + 0.020991277695*_Complex_I, 0.138301646709 + -0.257377123833*_Complex_I, 0.080518740416 + 0.154109323025*_Complex_I, -0.024190089107 + -0.061511921883*_Complex_I, 0.000458766706 + 0.001026612055*_Complex_I, 0.099718827009 + -0.065688782930*_Complex_I, -0.029233866930 + -0.195329236984*_Complex_I, -0.066604834795 + 0.089790678024*_Complex_I, -0.068512433767 + 0.076835018396*_Complex_I, 0.050179117918 + 0.095668357611*_Complex_I, -0.025827249885 + 0.161506593227*_Complex_I, -0.044248852134 + -0.043011960387*_Complex_I, -0.065869921446 + -0.124157130718*_Complex_I, -0.022857676446 + 0.034576061368*_Complex_I, -0.092982125282 + 0.081510609388*_Complex_I, 0.197520732880 + 0.040147519112*_Complex_I, 0.064278131723 + -0.020518574119*_Complex_I, -0.044479858875 + -0.093625146151*_Complex_I, 0.006783248484 + 0.080368715525*_Complex_I, 0.015499952435 + 0.014531745017*_Complex_I, 0.097499859333 + 0.031322878599*_Complex_I, 0.075692665577 + 0.103051352501*_Complex_I, -0.127897429466 + 0.147205972672*_Complex_I, -0.227601456642 + -0.086447989941*_Complex_I, 0.079460048676 + 0.009285532683*_Complex_I, -0.104196500778 + -0.062360990047*_Complex_I, -0.003569463268 + -0.159094834328*_Complex_I, -0.015271052718 + 0.053798562288*_Complex_I, 0.038455364108 + 0.154173243046*_Complex_I, 0.055872535706 + -0.233663058281*_Complex_I, -0.008917537332 + 0.091611146927*_Complex_I, 0.086029797792 + -0.039757794142*_Complex_I, 0.049558714032 + -0.151712751389*_Complex_I, 0.080167847872 + 0.034949752688*_Complex_I, -0.050086444616 + 0.050132060051*_Complex_I, 0.083901208639 + 0.046979528666*_Complex_I, -0.132237958908 + 0.095516347885*_Complex_I, 0.091105806828 + 0.120565533638*_Complex_I, 0.043457311392 + -0.141374385357*_Complex_I, -0.013054405153 + -0.100194096565*_Complex_I, -0.159590744972 + 0.033074292541*_Complex_I, 0.000640281662 + -0.032389008999*_Complex_I, 0.003084850125 + 0.021032336354*_Complex_I, -0.185569190979 + 0.124299430847*_Complex_I, -0.011914233118 + -0.237578940392*_Complex_I, -0.171687960625 + -0.104329741001*_Complex_I, -0.069582682848 + -0.225686883926*_Complex_I, -0.113897264004 + 0.090501463413*_Complex_I, 0.093735665083 + 0.154317796230*_Complex_I, 0.014358232915 + -0.103527617455*_Complex_I, -0.008946143836 + 0.126785087585*_Complex_I, -0.137021541595 + -0.133091437817*_Complex_I, -0.093204009533 + -0.052661812305*_Complex_I, -0.017306408286 + 0.105603075027*_Complex_I, -0.070221811533 + -0.083750408888*_Complex_I, 0.026400086284 + -0.231271290779*_Complex_I, -0.067720073462 + 0.057201570272*_Complex_I, -0.048747465014 + -0.065235435963*_Complex_I, 0.043681365252 + -0.104784011841*_Complex_I, -0.090612548590 + -0.275935935974*_Complex_I, -0.003840988874 + 0.110235190392*_Complex_I, 0.175717639923 + 0.039627754688*_Complex_I, -0.095855474472 + -0.109507787228*_Complex_I, -0.103805732727 + 0.047046291828*_Complex_I, 0.102693021297 + -0.121691584587*_Complex_I, 0.205679154396 + 0.105767965317*_Complex_I, -0.076863563061 + -0.109635329247*_Complex_I, 0.008887568116 + -0.008115684241*_Complex_I, 0.115569293499 + -0.002244588919*_Complex_I, 0.114743447304 + 0.110550260544*_Complex_I, -0.207589817047 + 0.076551246643*_Complex_I, 0.001820044219 + 0.039755198359*_Complex_I, 0.120840430260 + 0.207095527649*_Complex_I, 0.060907727480 + 0.108076405525*_Complex_I, -0.068012183905 + -0.004220475256*_Complex_I, -0.075779396296 + 0.192010104656*_Complex_I, 0.176728832722 + -0.014139008522*_Complex_I, 0.003537797555 + -0.008619928360*_Complex_I, 0.105585181713 + -0.044047874212*_Complex_I, -0.042796334624 + 0.104850161076*_Complex_I, -0.051997685432 + 0.156431221962*_Complex_I, 0.020244561136 + 0.167572557926*_Complex_I, 0.145088231564 + 0.027772811055*_Complex_I, 0.037466460466 + 0.109766936302*_Complex_I, -0.098527204990 + -0.032260373235*_Complex_I, 0.009477450699 + -0.035027536750*_Complex_I, -0.016112615168 + 0.085437601805*_Complex_I, 0.143263375759 + 0.075950628519*_Complex_I, 0.106226658821 + 0.103723526001*_Complex_I, 0.000303745759 + -0.010642482340*_Complex_I, 0.108046162128 + -0.032960096002*_Complex_I, -0.003579319268 + 0.113042652607*_Complex_I, 0.004739668965 + -0.090823930502*_Complex_I, -0.075828909874 + -0.005588034540*_Complex_I, -0.085471099615 + -0.016970762610*_Complex_I, 0.011292902380 + -0.025727859139*_Complex_I, -0.003472129628 + -0.066497987509*_Complex_I, 0.052674955130 + 0.053410953283*_Complex_I, 0.171188580990 + 0.164189565182*_Complex_I, -0.031832432747 + -0.106380403042*_Complex_I, 0.104630780220 + -0.005379130691*_Complex_I, 0.146008169651 + -0.016912537813*_Complex_I, 0.001029302273 + 0.191088676453*_Complex_I, -0.189716017246 + -0.017046442628*_Complex_I, -0.098682647943 + 0.001545182616*_Complex_I, 0.017514893413 + -0.091537868977*_Complex_I, 0.046101492643 + -0.087318551540*_Complex_I, 0.006703664362 + -0.168205010891*_Complex_I, -0.017618760467 + 0.027586823702*_Complex_I, -0.131682169437 + 0.043349444866*_Complex_I, 0.050538945198 + 0.176133990288*_Complex_I, -0.053573626280 + -0.126223480701*_Complex_I, 0.196893954277 + -0.158274137974*_Complex_I, -0.148222410679 + 0.046666064858*_Complex_I, 0.095723485947 + 0.036118236184*_Complex_I, -0.072401177883 + -0.081512874365*_Complex_I, 0.057588219643 + 0.215086269379*_Complex_I, 0.082906532288 + 0.065297931433*_Complex_I, -0.031125253439 + 0.089076888561*_Complex_I, -0.022213415802 + -0.206439447403*_Complex_I, -0.128299164772 + 0.021574760973*_Complex_I, 0.044257754087 + 0.042379784584*_Complex_I, 0.201319956779 + -0.054105019569*_Complex_I, 0.028415796161 + -0.068978685141*_Complex_I, -0.011957987398 + 0.176460993290*_Complex_I, 0.090524059534 + -0.115864157677*_Complex_I, -0.107446074486 + -0.129327297211*_Complex_I, 0.089880418777 + 0.060228496790*_Complex_I, -0.030561709404 + 0.026375296712*_Complex_I, 0.098281121254 + -0.215652251244*_Complex_I, -0.007009872049 + -0.074216008186*_Complex_I, -0.004887212813 + 0.159088206291*_Complex_I, 0.056175363064 + 0.101569080353*_Complex_I, -0.062076961994 + -0.057750892639*_Complex_I, -0.126010406017 + 0.065122300386*_Complex_I, -0.049417442083 + 0.079578405619*_Complex_I, 0.104471850395 + -0.222810673714*_Complex_I, 0.008511145413 + 0.109938132763*_Complex_I, 0.037150239944 + 0.084586590528*_Complex_I, 0.050007992983 + -0.057158488035*_Complex_I, -0.035429692268 + 0.058791869879*_Complex_I, -0.155366706848 + 0.118630039692*_Complex_I, 0.047825142741 + -0.105882799625*_Complex_I, -0.109545922279 + -0.002970626391*_Complex_I, 0.130073928833 + 0.085777258873*_Complex_I, -0.039974737167 + 0.114924871922*_Complex_I, 0.082493311167 + -0.066850924492*_Complex_I, 0.094225972891 + -0.016298688948*_Complex_I, -0.196156990528 + -0.039484533668*_Complex_I, 0.221052432060 + 0.012097968161*_Complex_I, 0.011275211722 + -0.101457715034*_Complex_I, 0.009068550915 + 0.102877616882*_Complex_I, 0.233158087730 + 0.028579771519*_Complex_I, 0.103334558010 + 0.013103367388*_Complex_I, 0.113383591175 + 0.299872016907*_Complex_I, 0.003663517535 + -0.053204262257*_Complex_I, 0.016009953618 + -0.204974889755*_Complex_I, -0.129484927654 + -0.081961399317*_Complex_I, 0.043841245770 + -0.172690594196*_Complex_I, 0.016576626897 + 0.178835308552*_Complex_I, 0.021964907646 + -0.018969631195*_Complex_I, 0.040968599916 + 0.013126873970*_Complex_I, -0.139588427544 + 0.084010922909*_Complex_I, -0.119654500484 + 0.023274496198*_Complex_I, -0.069549763203 + 0.014241448045*_Complex_I, 0.061426883936 + 0.037087076902*_Complex_I, -0.101361310482 + -0.062185329199*_Complex_I, -0.112329518795 + -0.115670502186*_Complex_I, 0.134469640255 + 0.146243238449*_Complex_I, 0.069860440493 + -0.059987205267*_Complex_I, 0.002678702772 + 0.026742336154*_Complex_I, -0.100598180294 + 0.019916568696*_Complex_I, 0.112527644634 + 0.158179092407*_Complex_I, -0.044148188829 + 0.048926886916*_Complex_I, -0.036606773734 + -0.143591856956*_Complex_I, 0.058808875084 + 0.019581055641*_Complex_I, 0.036360570788 + 0.014478833973*_Complex_I, 0.175481355190 + 0.010096323490*_Complex_I, 0.108694136143 + -0.070673483610*_Complex_I, 0.090956181288 + -0.025260141492*_Complex_I, -0.051956391335 + -0.102067518234*_Complex_I, -0.136262392998 + -0.047263675928*_Complex_I, -0.003427351639 + -0.120171773434*_Complex_I, -0.056164652109 + 0.211695027351*_Complex_I, 0.122092783451 + 0.066175770760*_Complex_I, 0.058047491312 + 0.006997314841*_Complex_I, -0.052954304218 + -0.022754417360*_Complex_I, 0.142856597900 + 0.108723735809*_Complex_I, -0.034428742528 + -0.054634892941*_Complex_I, -0.060924202204 + 0.031046575308*_Complex_I, -0.200955986977 + -0.117396569252*_Complex_I, -0.088245415688 + 0.019958937168*_Complex_I, -0.020239216089 + 0.041008698940*_Complex_I, 0.016120427847 + -0.252910399437*_Complex_I, -0.005489441007 + -0.005252978206*_Complex_I, 0.146177339554 + -0.124855351448*_Complex_I, 0.008751311898 + 0.021546928585*_Complex_I, -0.045790722966 + -0.055281382799*_Complex_I, 0.020690375566 + 0.076892906427*_Complex_I, 0.021331049502 + -0.009237347543*_Complex_I, 0.055180394650 + -0.023450747132*_Complex_I, -0.200542330742 + -0.096801882982*_Complex_I, 0.010742266476 + 0.088201242685*_Complex_I, 0.072365719080 + 0.038520815969*_Complex_I, 0.174543678761 + -0.139873552322*_Complex_I}; float complex fftfilt_crcf_data_h13x256_y[] = { 0.006707464887 + -0.003615862465*_Complex_I, 0.014358372283 + -0.014900933014*_Complex_I, -0.017605463388 + 0.020679426057*_Complex_I, -0.030607580793 + 0.024457457884*_Complex_I, -0.033011059558 + 0.017451711642*_Complex_I, -0.000552862047 + -0.029909500040*_Complex_I, 0.029762551415 + -0.029380501742*_Complex_I, 0.053098771667 + -0.004223742190*_Complex_I, 0.027764068736 + 0.025733123329*_Complex_I, 0.019184165051 + 0.011649528617*_Complex_I, -0.045468748657 + 0.015676561918*_Complex_I, -0.015208315362 + -0.029868068751*_Complex_I, -0.005074731196 + -0.025633738248*_Complex_I, 0.016953787198 + -0.036545469115*_Complex_I, -0.015051143400 + 0.040438104378*_Complex_I, -0.000389921114 + 0.040583727841*_Complex_I, -0.018476482937 + 0.001605043113*_Complex_I, 0.059276110787 + 0.008087486852*_Complex_I, 0.032014951529 + -0.026016763072*_Complex_I, 0.028169341465 + 0.019691597843*_Complex_I, -0.027575406956 + 0.014924607884*_Complex_I, -0.044969293038 + -0.034038723353*_Complex_I, -0.035957879305 + 0.009864897267*_Complex_I, 0.015551833890 + -0.025044401657*_Complex_I, -0.025072135741 + 0.016447641694*_Complex_I, 0.067713809538 + 0.015047662589*_Complex_I, -0.014827314512 + -0.006159133526*_Complex_I, 0.017417617315 + 0.018940542198*_Complex_I, -0.051497901101 + 0.013839514218*_Complex_I, 0.006425931128 + -0.012107460374*_Complex_I, 0.003778314165 + 0.004734451148*_Complex_I, 0.024107174779 + -0.007035831300*_Complex_I, -0.010365520171 + -0.022195343173*_Complex_I, 0.051580386373 + -0.008087616648*_Complex_I, -0.021776665000 + -0.003115102667*_Complex_I, 0.023266451034 + 0.047344342773*_Complex_I, -0.053848275959 + -0.026819242730*_Complex_I, 0.063009256294 + -0.009944000506*_Complex_I, 0.006746963810 + -0.032158195839*_Complex_I, 0.003429372021 + -0.000544080428*_Complex_I, -0.021562011789 + -0.003250402475*_Complex_I, -0.014790441461 + -0.003085695467*_Complex_I, 0.010008967449 + 0.023823269718*_Complex_I, -0.008293948136 + -0.022998494726*_Complex_I, 0.011452965518 + -0.020435253906*_Complex_I, 0.025061888640 + -0.008646415119*_Complex_I, 0.009417229303 + 0.002491707097*_Complex_I, -0.001052856194 + 0.014974027706*_Complex_I, -0.009405958690 + -0.029993691331*_Complex_I, -0.014721142637 + -0.008638802539*_Complex_I, -0.036054668791 + -0.043505364136*_Complex_I, 0.002937162197 + 0.016396266668*_Complex_I, -0.004075444532 + -0.014475666608*_Complex_I, 0.011656769213 + 0.056296896866*_Complex_I, -0.011068622206 + 0.001107236820*_Complex_I, -0.029464500491 + 0.023806584861*_Complex_I, -0.001234548257 + -0.043088390782*_Complex_I, -0.013592614491 + -0.029832033410*_Complex_I, 0.009582371751 + 0.002336669503*_Complex_I, -0.007665271794 + 0.050333730164*_Complex_I, 0.006935919041 + 0.000935532598*_Complex_I, -0.003952523598 + 0.051259768228*_Complex_I, -0.006392118058 + -0.064666858821*_Complex_I, -0.009497007771 + -0.021680677945*_Complex_I, 0.009619420930 + -0.042495568141*_Complex_I, -0.014045975317 + 0.022418973657*_Complex_I, 0.028464744316 + 0.062481882056*_Complex_I, 0.001067687053 + 0.012760185564*_Complex_I, 0.016381591820 + -0.014605527050*_Complex_I, -0.034415502412 + -0.026979376550*_Complex_I, -0.017681907434 + -0.024441169492*_Complex_I, -0.005897651761 + 0.007001263045*_Complex_I, 0.033278467741 + 0.020304401627*_Complex_I, -0.015372239067 + 0.016871371540*_Complex_I, 0.004123217473 + -0.031815284855*_Complex_I, -0.015306721649 + -0.031111950511*_Complex_I, 0.004503865148 + -0.033058697462*_Complex_I, 0.029142795487 + 0.022150281542*_Complex_I, 0.019772837268 + 0.022699222634*_Complex_I, 0.015820827834 + 0.046069967481*_Complex_I, -0.023442270401 + -0.016297278519*_Complex_I, -0.026038769435 + 0.011214015864*_Complex_I, -0.021468228990 + -0.057542563457*_Complex_I, 0.034028743864 + -0.002254875536*_Complex_I, -0.006908951528 + 0.001680565517*_Complex_I, 0.007793730477 + 0.032660744962*_Complex_I, -0.019663600279 + 0.025988218786*_Complex_I, -0.003368100468 + 0.026542388675*_Complex_I, 0.013438824633 + -0.047413054472*_Complex_I, -0.004063114270 + -0.015525778855*_Complex_I, 0.018830244631 + -0.044104705319*_Complex_I, -0.032245213510 + 0.016288658540*_Complex_I, 0.007245432060 + 0.024854569789*_Complex_I, -0.027446572547 + 0.041850280938*_Complex_I, 0.029419010658 + 0.028727610740*_Complex_I, -0.010452476889 + -0.044041749123*_Complex_I, 0.030615778213 + -0.021544600594*_Complex_I, -0.006420674173 + -0.051315896975*_Complex_I, 0.016696184929 + 0.047238754510*_Complex_I, 0.005689845758 + 0.063096109099*_Complex_I, 0.028255169043 + 0.036125238544*_Complex_I, 0.012724807027 + -0.010983186848*_Complex_I, -0.042681639075 + -0.046834116871*_Complex_I, -0.000989952691 + -0.059638193499*_Complex_I, -0.014509988842 + 0.030996292286*_Complex_I, 0.058136967808 + 0.004841843998*_Complex_I, 0.016711224472 + 0.056418115581*_Complex_I, 0.042240824058 + 0.015983263464*_Complex_I, -0.022083897958 + -0.024086928202*_Complex_I, -0.001789727311 + 0.023860817657*_Complex_I, -0.029894590649 + -0.040496551187*_Complex_I, 0.018773801669 + 0.051847548401*_Complex_I, 0.031709831384 + 0.011373889090*_Complex_I, -0.004023229281 + 0.020313196377*_Complex_I, -0.001577893158 + -0.019338873041*_Complex_I, -0.016653147805 + 0.001029965867*_Complex_I, 0.022914141726 + -0.002104645021*_Complex_I, 0.004474041805 + 0.010394883929*_Complex_I, -0.007920863082 + -0.015181966976*_Complex_I, -0.013430955196 + 0.050824400632*_Complex_I, 0.008429368466 + 0.016663178667*_Complex_I, -0.040384189162 + -0.005524017450*_Complex_I, 0.002595592227 + -0.002667437393*_Complex_I, 0.009304373200 + -0.026400357126*_Complex_I, 0.048184754654 + 0.020873671678*_Complex_I, -0.030489638011 + -0.058480052355*_Complex_I, -0.016679991101 + 0.018809245099*_Complex_I, -0.008746544102 + -0.035440693217*_Complex_I, 0.015062452407 + 0.019391877795*_Complex_I, -0.022136074513 + -0.020072882619*_Complex_I, 0.000436956008 + 0.007335145893*_Complex_I, -0.008872275506 + 0.020549897080*_Complex_I, -0.002241620183 + 0.006218861440*_Complex_I, -0.001175415969 + -0.040479462629*_Complex_I, 0.000083899519 + -0.021882526156*_Complex_I, 0.025794092443 + -0.065356864610*_Complex_I, -0.035076022000 + -0.002349257653*_Complex_I, -0.003341037071 + -0.006590144581*_Complex_I, -0.014034503634 + 0.051948837186*_Complex_I, 0.030633439581 + 0.013809324577*_Complex_I, -0.002962173263 + -0.011885141436*_Complex_I, -0.000277152583 + -0.057872949989*_Complex_I, -0.041128587589 + -0.009986479197*_Complex_I, -0.032666587947 + -0.028631352014*_Complex_I, -0.000937363608 + 0.018495486941*_Complex_I, 0.007753441209 + 0.008806508191*_Complex_I, 0.037266455064 + 0.010636476395*_Complex_I, 0.006587066115 + -0.001705926814*_Complex_I, 0.003108159036 + -0.006628853141*_Complex_I, 0.010939472752 + 0.006955405461*_Complex_I, -0.035625089431 + 0.003442599966*_Complex_I, -0.008902105887 + -0.028853630235*_Complex_I, -0.032226114328 + -0.009004482236*_Complex_I, -0.005180831436 + 0.005500644217*_Complex_I, -0.013588249735 + 0.016986170136*_Complex_I, -0.001619772072 + 0.000519931731*_Complex_I, 0.016514152427 + -0.020852436461*_Complex_I, 0.046615752684 + -0.000490623097*_Complex_I, 0.005417795160 + -0.036933916369*_Complex_I, 0.007190900949 + 0.046477922845*_Complex_I, -0.045185383594 + 0.017921427684*_Complex_I, -0.014537612941 + 0.075949416617*_Complex_I, -0.029141623074 + -0.059957316195*_Complex_I, 0.049424271568 + -0.033258736817*_Complex_I, 0.012029563939 + -0.050271746506*_Complex_I, 0.023861869121 + 0.035334845394*_Complex_I, -0.046542548410 + 0.016947426572*_Complex_I, 0.004060617093 + 0.071512899954*_Complex_I, -0.014037223962 + -0.012127913597*_Complex_I, 0.039889046850 + 0.005706366222*_Complex_I, -0.028460519816 + -0.096256824265*_Complex_I, 0.022664509438 + -0.011714722989*_Complex_I, -0.050769105818 + 0.012359859521*_Complex_I, 0.066087653016 + 0.054750882096*_Complex_I, -0.020633352616 + 0.001005601365*_Complex_I, 0.024688652114 + 0.040909798080*_Complex_I, -0.040302384002 + -0.048949559759*_Complex_I, -0.040499641156 + 0.001157352899*_Complex_I, 0.003027817515 + -0.057483585836*_Complex_I, -0.004425501836 + 0.047349196316*_Complex_I, 0.050482303632 + -0.003841475384*_Complex_I, 0.006892893469 + 0.023406378381*_Complex_I, -0.016436659880 + -0.003310696286*_Complex_I, -0.033973819400 + 0.045991336264*_Complex_I, -0.006077224480 + -0.023680985792*_Complex_I, -0.024572808359 + -0.010230339465*_Complex_I, 0.032481213736 + -0.024751506834*_Complex_I, -0.000140080804 + -0.013756951783*_Complex_I, 0.045204061251 + -0.001863065274*_Complex_I, -0.014671178560 + 0.022868286772*_Complex_I, -0.008200142546 + 0.040201740584*_Complex_I, -0.028297364362 + 0.011407262105*_Complex_I, -0.031979428685 + -0.029902785287*_Complex_I, 0.007876129419 + -0.034552491520*_Complex_I, 0.011879957596 + 0.002102523326*_Complex_I, 0.065685674192 + -0.021696600034*_Complex_I, -0.004436318677 + 0.044689761692*_Complex_I, 0.006444035464 + -0.009625205044*_Complex_I, -0.031610428157 + -0.001954799840*_Complex_I, -0.028459000697 + -0.034725990869*_Complex_I, -0.011174251949 + 0.010299896743*_Complex_I, 0.023757183405 + -0.012151501352*_Complex_I, -0.001899448573 + 0.033748924229*_Complex_I, 0.045121542184 + 0.003981235350*_Complex_I, -0.039350108228 + 0.019225662049*_Complex_I, 0.000272360769 + -0.022187283938*_Complex_I, -0.039963184290 + -0.025512380416*_Complex_I, -0.048539833099 + -0.045287358543*_Complex_I, 0.014614456311 + -0.006244097705*_Complex_I, -0.005955795663 + -0.016811959796*_Complex_I, 0.034965200850 + 0.085058210904*_Complex_I, 0.019869783149 + 0.033565877203*_Complex_I, -0.007450313153 + 0.019794672596*_Complex_I, -0.024234527340 + -0.013904685967*_Complex_I, -0.056857838231 + -0.065401336188*_Complex_I, 0.008081702581 + -0.037938012149*_Complex_I, 0.013228639879 + 0.003618896346*_Complex_I, 0.047207180558 + 0.006639688435*_Complex_I, 0.005206139690 + 0.048614164213*_Complex_I, 0.012317627070 + -0.009658873466*_Complex_I, -0.008051197208 + 0.015338520918*_Complex_I, -0.017767221557 + -0.001246156194*_Complex_I, -0.012973491018 + -0.004457537375*_Complex_I, -0.001247711756 + -0.000324872382*_Complex_I, 0.015217577217 + -0.018849976281*_Complex_I, -0.000220920310 + -0.022284388072*_Complex_I, 0.007337925412 + -0.022911190749*_Complex_I, 0.026359365671 + 0.027517236286*_Complex_I, 0.008511664801 + -0.000024345933*_Complex_I, -0.006523939632 + 0.027431135887*_Complex_I, -0.045640085613 + -0.016594833325*_Complex_I, -0.011370492419 + 0.008910655275*_Complex_I, -0.045188661133 + -0.014169350102*_Complex_I, 0.006126649841 + -0.018848731487*_Complex_I, 0.020184591301 + 0.049393686574*_Complex_I, 0.050790767045 + 0.013516083838*_Complex_I, 0.030911878104 + 0.013274684518*_Complex_I, -0.032128201429 + -0.056563309721*_Complex_I, -0.024604150985 + -0.007862317966*_Complex_I, -0.053074476432 + -0.026948064488*_Complex_I, -0.016714258122 + 0.036960212668*_Complex_I, 0.003641941365 + -0.017652191591*_Complex_I, 0.014976615622 + 0.055005028639*_Complex_I, 0.047122774118 + -0.019075872589*_Complex_I, 0.027958265929 + -0.005155130760*_Complex_I, 0.006577988759 + -0.021876641490*_Complex_I, 0.018186494518 + 0.020647216102*_Complex_I, -0.047150707407 + 0.008796453305*_Complex_I, -0.018231362190 + 0.025611832961*_Complex_I, -0.044254892960 + -0.000932158388*_Complex_I, 0.029538101318 + 0.008693714282*_Complex_I, 0.025472319724 + -0.006973878349*_Complex_I, 0.012287778194 + -0.046541397503*_Complex_I, -0.003318140133 + 0.036850102200*_Complex_I, 0.015644777552 + -0.006720827246*_Complex_I, 0.011761450619 + 0.045924263037*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/fftfilt_crcf_data_h23x256.c000066400000000000000000000654251317124540100246210ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fftfilt_crcf_data_h23x256.c: autotest fftfilt data // #include float fftfilt_crcf_data_h23x256_h[] = { 0.175772392750, 0.016595666111, -0.074416112900, 0.010717856884, -0.091077792645, 0.152976071835, -0.025270926952, 0.021845243871, -0.001858575456, -0.090402913094, -0.054905104637, 0.135398101807, -0.000730551640, 0.029069179296, -0.117681956291, 0.088986778259, -0.005193765089, 0.047553667426, -0.093419462442, 0.060808116198, 0.138476681709, 0.104599690437, 0.007943090051}; float complex fftfilt_crcf_data_h23x256_x[] = { 0.155103063583 + -0.039989483356*_Complex_I, 0.089731889963 + 0.007783630490*_Complex_I, 0.031814819574 + -0.092475223541*_Complex_I, -0.052295821905 + 0.059911632538*_Complex_I, -0.128601908684 + -0.137423527241*_Complex_I, -0.005442334712 + 0.136688292027*_Complex_I, -0.110040140152 + 0.129731595516*_Complex_I, 0.070668441057 + 0.014537031949*_Complex_I, -0.043719315529 + -0.018183282018*_Complex_I, -0.023593281209 + -0.088085335493*_Complex_I, 0.079267203808 + -0.050603461266*_Complex_I, 0.091274780035 + -0.041612377763*_Complex_I, -0.063425219059 + 0.028925007582*_Complex_I, 0.029070848227 + -0.047291010618*_Complex_I, -0.016231997311 + -0.220043921471*_Complex_I, 0.001723764278 + -0.110049223900*_Complex_I, 0.044714280963 + -0.016450446844*_Complex_I, -0.050305968523 + 0.038971278071*_Complex_I, -0.118738901615 + -0.027668058872*_Complex_I, -0.065542882681 + -0.056009286642*_Complex_I, 0.087729597092 + -0.011164753139*_Complex_I, 0.078783208132 + -0.036137032509*_Complex_I, -0.024815648794 + -0.187882483006*_Complex_I, 0.157861471176 + -0.075281244516*_Complex_I, 0.002852580696 + -0.062035644054*_Complex_I, 0.010516438633 + 0.137531483173*_Complex_I, 0.028980562091 + -0.067520070076*_Complex_I, 0.022702263296 + 0.036881408095*_Complex_I, -0.072563153505 + -0.135415744781*_Complex_I, -0.130733311176 + -0.031472635269*_Complex_I, -0.132395064831 + -0.013236595690*_Complex_I, -0.050313913822 + -0.001110552903*_Complex_I, -0.182336819172 + 0.011559166759*_Complex_I, 0.034110882878 + -0.085457748175*_Complex_I, 0.010640498996 + 0.024029432237*_Complex_I, -0.031135216355 + -0.075218772888*_Complex_I, -0.113621425629 + -0.020260357857*_Complex_I, 0.035748475790 + -0.047527408600*_Complex_I, 0.158889925480 + -0.108263909817*_Complex_I, 0.058575540781 + 0.029335317016*_Complex_I, -0.012806682289 + 0.062627220154*_Complex_I, 0.017389293015 + 0.082187730074*_Complex_I, -0.155518913269 + -0.130875742435*_Complex_I, -0.110213851929 + 0.189839553833*_Complex_I, 0.052800035477 + 0.166894078255*_Complex_I, -0.017228771746 + 0.002264509723*_Complex_I, 0.126624763012 + 0.014616450667*_Complex_I, 0.074029338360 + 0.130479073524*_Complex_I, 0.039149993658 + -0.081848907471*_Complex_I, -0.174016666412 + -0.002245875075*_Complex_I, -0.060786378384 + 0.087645614147*_Complex_I, 0.057222455740 + -0.064347177744*_Complex_I, -0.158683681488 + 0.064550727606*_Complex_I, 0.058903807402 + -0.197414779663*_Complex_I, 0.022170741856 + 0.005642867088*_Complex_I, -0.019022856653 + 0.026909428835*_Complex_I, 0.054943174124 + -0.010510860384*_Complex_I, -0.130231952667 + -0.085019159317*_Complex_I, 0.057500022650 + -0.036732053757*_Complex_I, 0.105791926384 + 0.016274939477*_Complex_I, 0.116283416748 + -0.056632959843*_Complex_I, 0.009825258702 + 0.019144052267*_Complex_I, 0.196307218075 + -0.048692828417*_Complex_I, 0.010651530325 + 0.008062589169*_Complex_I, 0.064581054449 + -0.010377624631*_Complex_I, 0.089088356495 + 0.044110041857*_Complex_I, -0.000476853596 + -0.038994494081*_Complex_I, 0.105319905281 + -0.132293283939*_Complex_I, 0.009918146580 + -0.041363826394*_Complex_I, 0.036220628023 + -0.030043822527*_Complex_I, 0.025852039456 + 0.067388910055*_Complex_I, -0.083622449636 + -0.035971945524*_Complex_I, -0.100427985191 + 0.044513091445*_Complex_I, -0.185684227943 + -0.040250685811*_Complex_I, -0.117641401291 + -0.084515213966*_Complex_I, 0.041368806362 + 0.039818888903*_Complex_I, -0.237114048004 + 0.125617718697*_Complex_I, -0.054697531462 + 0.033353772759*_Complex_I, -0.074546104670 + -0.125889337063*_Complex_I, 0.033940449357 + 0.015348845720*_Complex_I, -0.045566964149 + 0.039473927021*_Complex_I, -0.015814815462 + -0.096754157543*_Complex_I, 0.140625333786 + 0.088005954027*_Complex_I, -0.109252071381 + -0.058004480600*_Complex_I, 0.006840997189 + 0.123340046406*_Complex_I, -0.043643641472 + 0.077158600092*_Complex_I, -0.073954302073 + 0.095201927423*_Complex_I, -0.024249210954 + 0.057317435741*_Complex_I, 0.018241013587 + 0.081239950657*_Complex_I, -0.091524779797 + -0.259817528725*_Complex_I, -0.026682430506 + -0.034324991703*_Complex_I, 0.088583648205 + -0.007783739269*_Complex_I, 0.183037674427 + 0.111340200901*_Complex_I, -0.076495563984 + -0.089935213327*_Complex_I, 0.016016796231 + 0.185418581963*_Complex_I, 0.090234714746 + -0.036095014215*_Complex_I, 0.016144131124 + 0.097066044807*_Complex_I, 0.012245001644 + 0.095291149616*_Complex_I, -0.161877584457 + -0.052310425043*_Complex_I, -0.033721217513 + -0.012814992666*_Complex_I, 0.091250944138 + 0.131859993935*_Complex_I, -0.128745031357 + -0.084740310907*_Complex_I, -0.061492395401 + -0.099420046806*_Complex_I, 0.012414894253 + -0.015323466063*_Complex_I, 0.012217399478 + 0.012398956716*_Complex_I, 0.050523018837 + -0.087095749378*_Complex_I, -0.015820150077 + -0.054119426012*_Complex_I, -0.055258476734 + 0.020015104115*_Complex_I, 0.063105708361 + 0.042238712311*_Complex_I, 0.017720183730 + 0.017351190746*_Complex_I, -0.141501569748 + -0.117573750019*_Complex_I, -0.006765382737 + 0.056032115221*_Complex_I, -0.004831269756 + -0.002968831547*_Complex_I, -0.032051759958 + -0.190994548798*_Complex_I, 0.036215576530 + 0.173437201977*_Complex_I, -0.189757418633 + -0.055692046881*_Complex_I, -0.059237557650 + 0.126770603657*_Complex_I, 0.038132804632 + -0.074801898003*_Complex_I, 0.088674974442 + -0.053153961897*_Complex_I, -0.078639388084 + 0.046550104022*_Complex_I, -0.018440252542 + 0.040226161480*_Complex_I, -0.001557452139 + 0.011683121324*_Complex_I, -0.251441335678 + 0.073139393330*_Complex_I, -0.205929875374 + 0.018797023594*_Complex_I, -0.004785243422 + 0.018977609277*_Complex_I, -0.008223478496 + 0.016689766943*_Complex_I, -0.013542374969 + 0.098333865404*_Complex_I, 0.174354946613 + -0.053679537773*_Complex_I, 0.070709151030 + 0.105750656128*_Complex_I, -0.004860538989 + -0.093827313185*_Complex_I, 0.008115487546 + 0.105573391914*_Complex_I, -0.086253505945 + -0.016359496117*_Complex_I, 0.260078501701 + 0.011332800239*_Complex_I, -0.106663954258 + -0.106564879417*_Complex_I, 0.103312873840 + -0.263231492043*_Complex_I, -0.054847794771 + 0.040892100334*_Complex_I, 0.110823535919 + -0.184762966633*_Complex_I, -0.071165961027 + -0.055934780836*_Complex_I, -0.178788268566 + -0.044872501493*_Complex_I, -0.046904963255 + -0.092374777794*_Complex_I, 0.162701845169 + 0.020701634884*_Complex_I, -0.101515638828 + 0.074363875389*_Complex_I, 0.057615011930 + -0.117078483105*_Complex_I, 0.020440319180 + 0.002894190140*_Complex_I, -0.066558498144 + 0.002631408162*_Complex_I, 0.016302645206 + 0.071249717474*_Complex_I, -0.062377142906 + 0.063173556328*_Complex_I, 0.115204286575 + 0.057497209311*_Complex_I, 0.094178062677 + 0.013675969839*_Complex_I, 0.039668846130 + -0.104888665676*_Complex_I, -0.077536809444 + 0.030107039213*_Complex_I, 0.019500632584 + -0.077639460564*_Complex_I, -0.036470189691 + 0.141290163994*_Complex_I, -0.202891373634 + -0.006020304561*_Complex_I, 0.142597723007 + 0.001829937287*_Complex_I, 0.042515522242 + -0.033903941512*_Complex_I, -0.160332143307 + 0.167697465420*_Complex_I, 0.065906691551 + -0.046222153306*_Complex_I, -0.014665135741 + 0.029732593894*_Complex_I, -0.161926984787 + -0.039980190992*_Complex_I, 0.216635417938 + -0.084111690521*_Complex_I, 0.111900138855 + -0.088012528419*_Complex_I, 0.131331551075 + -0.075983870029*_Complex_I, -0.110518038273 + 0.217655158043*_Complex_I, -0.019964502752 + 0.029798141122*_Complex_I, -0.077271521091 + 0.017983873188*_Complex_I, 0.192190217972 + -0.034995573759*_Complex_I, 0.121502757072 + -0.071480178833*_Complex_I, 0.082723850012 + -0.001845339499*_Complex_I, -0.072242385149 + -0.005906258896*_Complex_I, -0.176676702499 + 0.110248458385*_Complex_I, 0.080035436153 + 0.107154047489*_Complex_I, 0.023038166761 + -0.114933979511*_Complex_I, -0.139963030815 + -0.063580548763*_Complex_I, -0.024152973294 + -0.165445506573*_Complex_I, 0.175627219677 + 0.068415731192*_Complex_I, 0.062092590332 + -0.063827121258*_Complex_I, 0.058578062057 + 0.007875456661*_Complex_I, 0.076061081886 + -0.132551908493*_Complex_I, 0.104943084717 + -0.084286916256*_Complex_I, 0.019696915150 + 0.003201137111*_Complex_I, 0.079270011187 + 0.105154144764*_Complex_I, 0.067746007442 + 0.087236845493*_Complex_I, -0.095283645391 + -0.162002611160*_Complex_I, -0.049992722273 + 0.118607068062*_Complex_I, 0.107323861122 + -0.174439251423*_Complex_I, -0.132320475578 + 0.017735700309*_Complex_I, 0.010226617008 + -0.197343289852*_Complex_I, -0.065331441164 + -0.169277667999*_Complex_I, -0.067106610537 + 0.003877854347*_Complex_I, 0.149599671364 + -0.130133831501*_Complex_I, -0.082966232300 + -0.140549242496*_Complex_I, -0.121567571163 + 0.111494851112*_Complex_I, -0.040895500779 + 0.242881941795*_Complex_I, 0.046610686183 + 0.190598750114*_Complex_I, -0.241175961494 + 0.038187211752*_Complex_I, 0.091600197554 + 0.075727856159*_Complex_I, 0.138635289669 + 0.048851582408*_Complex_I, 0.142762672901 + 0.008544234186*_Complex_I, 0.129457914829 + 0.013422895968*_Complex_I, -0.118289554119 + 0.265937256813*_Complex_I, 0.010878042877 + -0.077647930384*_Complex_I, -0.070324224234 + 0.039972990751*_Complex_I, -0.041980904341 + 0.067246806622*_Complex_I, -0.150996875763 + 0.028954780102*_Complex_I, 0.023831695318 + -0.059671503305*_Complex_I, -0.060499125719 + 0.022479967773*_Complex_I, 0.042781451344 + -0.012739011645*_Complex_I, -0.058961522579 + 0.108779168129*_Complex_I, -0.123040950298 + -0.084437525272*_Complex_I, -0.031985121965 + 0.144360256195*_Complex_I, 0.009733268619 + -0.105923128128*_Complex_I, -0.133637535572 + -0.006438682973*_Complex_I, 0.049610015750 + -0.120102596283*_Complex_I, 0.112718105316 + 0.129998087883*_Complex_I, -0.142268264294 + -0.013222855330*_Complex_I, 0.119939064980 + 0.084782326221*_Complex_I, -0.002139478363 + 0.143925952911*_Complex_I, -0.017734520137 + 0.060474181175*_Complex_I, -0.115593242645 + 0.266750621796*_Complex_I, -0.122079384327 + 0.060140782595*_Complex_I, -0.116746783257 + 0.058306437731*_Complex_I, -0.035461139679 + -0.199710798264*_Complex_I, -0.012796324492 + -0.006662363559*_Complex_I, -0.168765580654 + -0.080484443903*_Complex_I, 0.109565150738 + -0.066066616774*_Complex_I, 0.167375874519 + -0.095793098211*_Complex_I, 0.063125562668 + -0.015197466314*_Complex_I, -0.131772887707 + 0.043374121189*_Complex_I, 0.108676636219 + 0.016854281723*_Complex_I, -0.158170187473 + 0.066611725092*_Complex_I, 0.186592674255 + -0.119178080559*_Complex_I, 0.258357715607 + 0.035161945224*_Complex_I, -0.267501235008 + 0.113799548149*_Complex_I, -0.121099197865 + -0.008966898173*_Complex_I, -0.080716609955 + 0.092299455404*_Complex_I, 0.052158069611 + 0.009480424225*_Complex_I, 0.042302635312 + -0.107537162304*_Complex_I, -0.149109280109 + 0.086092722416*_Complex_I, -0.047981733084 + 0.051883894205*_Complex_I, 0.129582881927 + 0.080048167706*_Complex_I, 0.020590978861 + 0.052324140072*_Complex_I, -0.127634072304 + 0.003840797022*_Complex_I, -0.015030093491 + 0.081028074026*_Complex_I, -0.151265537739 + 0.073973071575*_Complex_I, 0.065107202530 + -0.102953696251*_Complex_I, 0.020201592147 + -0.043066096306*_Complex_I, -0.041327267885 + -0.084052354097*_Complex_I, 0.039087793231 + -0.027260744572*_Complex_I, 0.149368381500 + 0.085757601261*_Complex_I, -0.045472341776 + -0.007366366684*_Complex_I, -0.014300452173 + 0.070052427053*_Complex_I, -0.030928212404 + 0.008410415053*_Complex_I, 0.102823138237 + 0.089631778002*_Complex_I, -0.046347615123 + 0.012207016349*_Complex_I, -0.022019737959 + 0.008490467072*_Complex_I}; float complex fftfilt_crcf_data_h23x256_y[] = { 0.027262836609 + -0.007029047174*_Complex_I, 0.018346427661 + 0.000704495242*_Complex_I, -0.004460839644 + -0.013149554871*_Complex_I, -0.013679299641 + 0.007988293987*_Complex_I, -0.039004795515 + -0.012553764367*_Complex_I, 0.016696266867 + 0.009469516192*_Complex_I, -0.003513172567 + 0.046564035001*_Complex_I, 0.020372582455 + -0.027609901195*_Complex_I, 0.006199293336 + 0.013118588352*_Complex_I, -0.042660178683 + -0.048881324868*_Complex_I, 0.012162311731 + 0.006692219554*_Complex_I, 0.005999545171 + 0.012678334008*_Complex_I, 0.016925234916 + 0.011802413052*_Complex_I, 0.012643874018 + -0.002379618949*_Complex_I, -0.019843625969 + -0.042091077177*_Complex_I, -0.002447170334 + -0.066361916522*_Complex_I, 0.027635184820 + 0.025233499033*_Complex_I, -0.023950232537 + 0.018344717328*_Complex_I, -0.001523383406 + 0.047987234347*_Complex_I, -0.037208867735 + -0.060587103130*_Complex_I, 0.040881005070 + -0.012194712051*_Complex_I, 0.051353615432 + -0.030052114039*_Complex_I, 0.039843962567 + -0.018530512464*_Complex_I, -0.011241859913 + 0.003314208877*_Complex_I, -0.023931715066 + -0.008536051326*_Complex_I, -0.046474201238 + 0.019213392371*_Complex_I, 0.026420531301 + 0.008903961274*_Complex_I, -0.003321242652 + -0.005089987861*_Complex_I, 0.018094294321 + 0.009055610544*_Complex_I, -0.065634402614 + -0.053749750040*_Complex_I, -0.023600007069 + 0.001972776975*_Complex_I, 0.029460287631 + -0.022729601752*_Complex_I, -0.005045917714 + 0.054578580699*_Complex_I, -0.007148429271 + -0.055204501924*_Complex_I, 0.010660749874 + -0.059471864271*_Complex_I, -0.028011323273 + -0.066785744888*_Complex_I, 0.011622802421 + 0.013720590963*_Complex_I, -0.036631828451 + 0.003833520561*_Complex_I, 0.047864856646 + -0.017738859345*_Complex_I, -0.007990385588 + -0.035672288313*_Complex_I, 0.004986325822 + 0.029278794046*_Complex_I, -0.016889528458 + -0.015755301985*_Complex_I, -0.010143232206 + -0.021096571154*_Complex_I, -0.009806462106 + -0.047616138372*_Complex_I, 0.051880472016 + 0.035421818987*_Complex_I, 0.004878725946 + -0.006588080806*_Complex_I, 0.059514317675 + 0.025245817016*_Complex_I, -0.041213052806 + 0.001434752292*_Complex_I, -0.031520998781 + -0.026425494383*_Complex_I, -0.042062234079 + -0.023223262575*_Complex_I, -0.031771373601 + -0.001999239137*_Complex_I, 0.003008538314 + 0.007873584524*_Complex_I, -0.044522016963 + 0.031453229897*_Complex_I, -0.004123811253 + -0.100618757520*_Complex_I, 0.000868379196 + -0.007049767471*_Complex_I, -0.035358534934 + 0.039935982082*_Complex_I, 0.001096892916 + -0.008139914684*_Complex_I, -0.045888282337 + -0.028654012806*_Complex_I, 0.054241028654 + -0.040641857373*_Complex_I, 0.076384681516 + -0.009290596232*_Complex_I, -0.014394459295 + 0.031937206347*_Complex_I, 0.029290098261 + 0.000294924311*_Complex_I, -0.024684029149 + 0.000989628106*_Complex_I, -0.016171486419 + 0.031195541518*_Complex_I, -0.014868511208 + 0.014303327420*_Complex_I, 0.021852231291 + 0.016723227953*_Complex_I, 0.020272353403 + 0.015401209854*_Complex_I, 0.071528405043 + 0.017807463305*_Complex_I, -0.020235058791 + -0.039855986142*_Complex_I, -0.034484804762 + 0.000496010405*_Complex_I, 0.007189500129 + 0.020495810669*_Complex_I, -0.021931884508 + 0.027723824179*_Complex_I, -0.045456425035 + -0.019096529483*_Complex_I, -0.017800090999 + -0.040386165849*_Complex_I, -0.031040929546 + -0.045937861114*_Complex_I, 0.065367936599 + 0.021960412702*_Complex_I, -0.060220212620 + 0.045242058344*_Complex_I, -0.015791818114 + -0.002107138847*_Complex_I, -0.016776877211 + -0.047286567469*_Complex_I, 0.014399266122 + -0.042073854865*_Complex_I, 0.056679887935 + 0.012644277043*_Complex_I, -0.008511751801 + 0.004971041195*_Complex_I, 0.081952669986 + 0.012577593191*_Complex_I, -0.012764140374 + -0.011967000266*_Complex_I, -0.003336654686 + -0.001262645566*_Complex_I, 0.016350375874 + 0.032350783323*_Complex_I, 0.010862760597 + -0.035926563231*_Complex_I, 0.029863051593 + 0.043664156677*_Complex_I, -0.012277218714 + -0.028013771036*_Complex_I, -0.021453932268 + -0.061946366678*_Complex_I, 0.031514206628 + -0.020671975000*_Complex_I, -0.023541686556 + 0.038816659613*_Complex_I, 0.015568416177 + 0.034767821284*_Complex_I, -0.053493562550 + 0.010727696220*_Complex_I, -0.041010374462 + -0.065258809696*_Complex_I, 0.005288272932 + 0.024477688872*_Complex_I, -0.046902277134 + -0.000092205057*_Complex_I, 0.001627461508 + 0.080137549979*_Complex_I, -0.065128047455 + -0.060262053915*_Complex_I, 0.006596006298 + 0.065336899466*_Complex_I, 0.000058721241 + -0.040094018767*_Complex_I, -0.036305854351 + -0.003934363665*_Complex_I, 0.008450440041 + -0.033595118529*_Complex_I, 0.029549628861 + 0.041310102659*_Complex_I, -0.031905285980 + -0.031000918152*_Complex_I, 0.011726181555 + 0.060113189533*_Complex_I, -0.047367175488 + -0.048891971737*_Complex_I, 0.019495535591 + 0.085142512409*_Complex_I, 0.018357043313 + -0.001756917795*_Complex_I, -0.044850116879 + -0.007540707159*_Complex_I, -0.040509844673 + -0.092704738011*_Complex_I, 0.045015777649 + 0.044308907043*_Complex_I, 0.033412972066 + 0.006857384940*_Complex_I, -0.013027623910 + -0.030790116518*_Complex_I, -0.000975157484 + 0.037733658737*_Complex_I, -0.022753324517 + 0.023070309941*_Complex_I, 0.021078444893 + 0.032118433292*_Complex_I, 0.010443833730 + 0.016807510307*_Complex_I, -0.038157141667 + -0.083720289418*_Complex_I, 0.015884591663 + 0.080444457603*_Complex_I, -0.014224915913 + 0.005135806833*_Complex_I, -0.025232136903 + 0.004144801774*_Complex_I, -0.077288630878 + -0.005906892810*_Complex_I, -0.034553210182 + -0.017846341663*_Complex_I, 0.035746673427 + -0.012259253660*_Complex_I, 0.036525883688 + -0.010525857333*_Complex_I, -0.014488296110 + -0.014305379613*_Complex_I, -0.015958243599 + 0.045987466851*_Complex_I, 0.003179382534 + -0.018266667088*_Complex_I, 0.029305351113 + 0.000580102615*_Complex_I, -0.043259878864 + -0.037454506754*_Complex_I, -0.028365132804 + 0.065377160248*_Complex_I, 0.070378428765 + -0.056958149428*_Complex_I, 0.004867726670 + 0.005962596169*_Complex_I, -0.037918405464 + -0.091858574411*_Complex_I, -0.019631672181 + 0.051212141219*_Complex_I, -0.057622870703 + -0.011592712757*_Complex_I, 0.039759648837 + 0.003839054841*_Complex_I, -0.059496690769 + -0.007464198304*_Complex_I, 0.020562373454 + -0.038245564570*_Complex_I, 0.032578387575 + 0.008176063763*_Complex_I, -0.022640669374 + 0.032133098133*_Complex_I, -0.059754420752 + -0.022200850890*_Complex_I, -0.021917765961 + 0.061715182774*_Complex_I, -0.070723789096 + -0.036769285459*_Complex_I, 0.040897570713 + 0.020449142350*_Complex_I, -0.078688142274 + 0.044106118254*_Complex_I, 0.132511709017 + -0.002283572710*_Complex_I, 0.031006482035 + 0.023633310053*_Complex_I, 0.000719650304 + -0.060425994891*_Complex_I, -0.068488182320 + 0.011823413272*_Complex_I, 0.033571377809 + 0.001638620807*_Complex_I, 0.013415095820 + 0.063237008575*_Complex_I, 0.003843590843 + -0.032020775100*_Complex_I, 0.005708962317 + -0.073909950927*_Complex_I, 0.043060259091 + -0.039410177301*_Complex_I, -0.031531087064 + -0.004760009337*_Complex_I, -0.001506462543 + -0.004643974469*_Complex_I, -0.069117792716 + -0.013243456525*_Complex_I, -0.008999132078 + -0.025213996567*_Complex_I, 0.076230704310 + -0.038893791301*_Complex_I, -0.016693801234 + 0.016189526184*_Complex_I, 0.053793442954 + -0.046315507571*_Complex_I, -0.022323859813 + 0.074471398757*_Complex_I, -0.077019541390 + 0.000776612640*_Complex_I, 0.028852092849 + -0.003754892925*_Complex_I, 0.030634254859 + -0.031119630463*_Complex_I, 0.070978930378 + 0.018366156735*_Complex_I, 0.011314850738 + 0.020679865086*_Complex_I, -0.009529937549 + 0.025881841685*_Complex_I, -0.099579012075 + -0.013132370673*_Complex_I, 0.044640476208 + 0.044583555144*_Complex_I, 0.016522002764 + -0.063707510591*_Complex_I, 0.003035671136 + -0.013751873371*_Complex_I, -0.026798937752 + -0.022117369500*_Complex_I, 0.007823238214 + 0.038428718991*_Complex_I, -0.033760635042 + 0.056366436739*_Complex_I, 0.061213467638 + -0.037917433069*_Complex_I, -0.019400770671 + 0.002314675027*_Complex_I, 0.030275097259 + -0.065680749303*_Complex_I, -0.012116792287 + 0.011848118163*_Complex_I, 0.036218177449 + -0.012568718012*_Complex_I, 0.060643006355 + 0.043892825588*_Complex_I, 0.017806428565 + -0.022264383863*_Complex_I, -0.048473906401 + 0.014501335500*_Complex_I, -0.031370768130 + -0.040223039246*_Complex_I, 0.019781480670 + 0.021758320109*_Complex_I, 0.063634947558 + -0.007457977030*_Complex_I, 0.020848525728 + -0.052882085833*_Complex_I, -0.063823888094 + 0.004319709113*_Complex_I, 0.038427723737 + -0.024772513569*_Complex_I, -0.035206635151 + -0.007553598958*_Complex_I, 0.005557463302 + 0.057023731153*_Complex_I, -0.026365483732 + 0.001677431571*_Complex_I, -0.027214665101 + 0.003259544495*_Complex_I, 0.006634141929 + -0.021760848241*_Complex_I, 0.046788459295 + -0.032219612690*_Complex_I, 0.049439176247 + 0.058001544517*_Complex_I, 0.045244742233 + -0.058913353130*_Complex_I, 0.024261567778 + 0.012176684918*_Complex_I, -0.050667381589 + 0.023733558523*_Complex_I, 0.045349821935 + 0.040847998957*_Complex_I, 0.026718102874 + -0.059402465947*_Complex_I, -0.038454788567 + -0.000221349180*_Complex_I, -0.000891207880 + -0.009195003923*_Complex_I, 0.012516609339 + 0.056222305600*_Complex_I, -0.035084845543 + -0.052719626538*_Complex_I, -0.021230335164 + -0.038700055773*_Complex_I, -0.042702491469 + -0.012596339115*_Complex_I, 0.001037928882 + -0.021134005956*_Complex_I, 0.021394370180 + -0.031996808591*_Complex_I, -0.018110589131 + -0.004361916553*_Complex_I, -0.042616962178 + -0.045478200889*_Complex_I, 0.015593771645 + 0.075086774578*_Complex_I, 0.027412734674 + 0.021799498978*_Complex_I, -0.092513052262 + 0.111578027869*_Complex_I, 0.023261460083 + -0.018008166583*_Complex_I, -0.005433496503 + 0.062765792378*_Complex_I, 0.077096470007 + -0.046336297254*_Complex_I, 0.013100162132 + 0.106964173517*_Complex_I, -0.057225839702 + 0.011100170701*_Complex_I, -0.011950150953 + 0.042976543657*_Complex_I, 0.009438239329 + -0.043586074813*_Complex_I, -0.035007068103 + 0.014223415436*_Complex_I, -0.044707188095 + -0.007302556287*_Complex_I, -0.006824766721 + 0.022952180881*_Complex_I, 0.017261515635 + -0.031023982394*_Complex_I, 0.009883747796 + 0.006683863273*_Complex_I, -0.030856485749 + -0.017782855219*_Complex_I, -0.009108501465 + 0.015353290050*_Complex_I, -0.038083572506 + 0.029801645641*_Complex_I, 0.028040003683 + -0.001971697544*_Complex_I, 0.034858486128 + -0.004199899994*_Complex_I, -0.047963189034 + -0.015741737165*_Complex_I, -0.009310592393 + 0.022863663510*_Complex_I, -0.082864799372 + 0.027670042319*_Complex_I, 0.018363359405 + 0.035364489440*_Complex_I, 0.108637353728 + -0.051587108396*_Complex_I, -0.037281254062 + 0.067821136010*_Complex_I, -0.061231969683 + 0.036908299475*_Complex_I, -0.020972301615 + 0.096608850141*_Complex_I, -0.079111323581 + 0.024466271096*_Complex_I, 0.045843637768 + -0.077335246433*_Complex_I, -0.011031555894 + 0.001143494701*_Complex_I, -0.050696885867 + -0.000991623122*_Complex_I, -0.025631881174 + -0.020905755095*_Complex_I, 0.042787270331 + -0.022375533820*_Complex_I, 0.040540034730 + -0.032482851465*_Complex_I, 0.045207009532 + -0.015041815894*_Complex_I, -0.041989439384 + 0.052327580958*_Complex_I, -0.060932225937 + -0.002610819103*_Complex_I, 0.056802692214 + 0.015432577360*_Complex_I, 0.066574027053 + -0.021238051145*_Complex_I, -0.000873772321 + 0.003555393272*_Complex_I, -0.047364452139 + 0.039519457621*_Complex_I, -0.075184690098 + 0.032775776752*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/fftfilt_crcf_data_h4x256.c000066400000000000000000000646251317124540100245410ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fftfilt_crcf_data_h4x256.c: autotest fftfilt data // #include float fftfilt_crcf_data_h4x256_h[] = { 0.155624401569, 0.118511450291, -0.168462336063, 0.090250796080}; float complex fftfilt_crcf_data_h4x256_x[] = { 0.038939061761 + 0.066255682707*_Complex_I, 0.119283056259 + 0.056196963787*_Complex_I, -0.040920588374 + -0.079775565863*_Complex_I, -0.227900600433 + -0.102529621124*_Complex_I, -0.174213981628 + -0.108522331715*_Complex_I, 0.153431594372 + -0.030162647367*_Complex_I, 0.014127536118 + 0.246407699585*_Complex_I, -0.018383954465 + 0.021154025197*_Complex_I, -0.191331315041 + -0.127723705769*_Complex_I, 0.010609115660 + 0.052530884743*_Complex_I, -0.112432408333 + 0.010107874870*_Complex_I, 0.025136622787 + -0.032320749760*_Complex_I, 0.018991956115 + 0.133092260361*_Complex_I, -0.039405971766 + -0.013498529792*_Complex_I, -0.019806520641 + -0.002817103267*_Complex_I, -0.078604698181 + 0.026840734482*_Complex_I, 0.028549847007 + -0.017006455362*_Complex_I, 0.020842596889 + -0.121898579597*_Complex_I, -0.055000007153 + -0.101676058769*_Complex_I, 0.036740297079 + -0.151041173935*_Complex_I, 0.067903089523 + -0.193994557858*_Complex_I, 0.197223436832 + 0.051035022736*_Complex_I, -0.015651342273 + 0.007457277179*_Complex_I, -0.125625634193 + 0.145215332508*_Complex_I, 0.255927467346 + -0.039666593075*_Complex_I, -0.014654898643 + -0.154769206047*_Complex_I, -0.142057240009 + 0.149415183067*_Complex_I, -0.015665143728 + -0.008279455453*_Complex_I, -0.024408347905 + -0.026021143794*_Complex_I, -0.062624055147 + -0.200754070282*_Complex_I, -0.056015121937 + 0.040550091863*_Complex_I, 0.070212632418 + 0.062178546190*_Complex_I, -0.109208559990 + -0.118423628807*_Complex_I, 0.086101102829 + 0.087447303534*_Complex_I, 0.121767687798 + 0.103217923641*_Complex_I, -0.083848309517 + -0.039586529136*_Complex_I, 0.051707124710 + 0.150204086304*_Complex_I, -0.014533403516 + -0.031855377555*_Complex_I, 0.009939355403 + 0.151125979424*_Complex_I, -0.118441712856 + 0.029392868280*_Complex_I, 0.068562531471 + 0.169217157364*_Complex_I, -0.035535854101 + -0.091208106279*_Complex_I, 0.110526537895 + 0.046102252603*_Complex_I, -0.004789924249 + 0.014031916857*_Complex_I, 0.207642221451 + 0.005212478340*_Complex_I, -0.079558753967 + 0.078763872385*_Complex_I, 0.019427961111 + 0.118139207363*_Complex_I, 0.027059462667 + 0.004347201437*_Complex_I, -0.150222861767 + -0.019229063392*_Complex_I, 0.060692095757 + 0.119515848160*_Complex_I, -0.025792115927 + -0.000083122792*_Complex_I, 0.113421833515 + 0.125912785530*_Complex_I, -0.001560413372 + -0.150379800797*_Complex_I, 0.152954483032 + -0.063023918867*_Complex_I, -0.028765177727 + -0.036037924886*_Complex_I, -0.061254453659 + 0.052871614695*_Complex_I, 0.022947111726 + 0.146198511124*_Complex_I, -0.103656053543 + 0.085682183504*_Complex_I, 0.153891849518 + -0.088169473410*_Complex_I, -0.321221590042 + 0.123748040199*_Complex_I, -0.049486947060 + 0.162590062618*_Complex_I, 0.006993473321 + 0.179711341858*_Complex_I, 0.009347584099 + 0.202764987946*_Complex_I, 0.095177561045 + 0.070498406887*_Complex_I, -0.122608697414 + 0.114908039570*_Complex_I, 0.143189716339 + -0.046278029680*_Complex_I, 0.037571176887 + 0.071948003769*_Complex_I, -0.095956790447 + -0.205198740959*_Complex_I, 0.072236007452 + -0.040830844641*_Complex_I, 0.122828471661 + -0.117571306229*_Complex_I, 0.157875216007 + -0.039508357644*_Complex_I, -0.007820869237 + 0.116631805897*_Complex_I, -0.002049682848 + -0.058560395241*_Complex_I, -0.101921010017 + -0.107374680042*_Complex_I, -0.195360040665 + -0.201392173767*_Complex_I, 0.173241472244 + -0.001343925763*_Complex_I, 0.028210636973 + -0.149001765251*_Complex_I, -0.095708668232 + 0.070712405443*_Complex_I, 0.155656027794 + -0.047673809528*_Complex_I, -0.113691759109 + -0.093889063597*_Complex_I, 0.001799738780 + -0.111104428768*_Complex_I, 0.115965354443 + -0.018809084594*_Complex_I, -0.019960752130 + -0.186925411224*_Complex_I, 0.149933063984 + 0.044130250812*_Complex_I, 0.010008703917 + -0.031899172068*_Complex_I, 0.085326123238 + -0.005660134554*_Complex_I, -0.209100413322 + 0.130333411694*_Complex_I, -0.102446043491 + -0.034337127209*_Complex_I, -0.010648646951 + 0.011874027550*_Complex_I, 0.037817972898 + -0.044123852253*_Complex_I, 0.101257121563 + 0.028343737125*_Complex_I, 0.007420848310 + 0.154019880295*_Complex_I, 0.141882646084 + 0.096156585217*_Complex_I, -0.017362400889 + 0.036749580503*_Complex_I, 0.023864392936 + -0.022486045957*_Complex_I, 0.149045646191 + -0.053199940920*_Complex_I, 0.084901583195 + 0.083841896057*_Complex_I, -0.027361977100 + -0.115613818169*_Complex_I, -0.133944833279 + 0.016144460440*_Complex_I, 0.111774182320 + -0.136482322216*_Complex_I, -0.044260403514 + 0.111417186260*_Complex_I, 0.001404425409 + -0.104211735725*_Complex_I, 0.095043230057 + 0.095729255676*_Complex_I, -0.143477213383 + -0.080443674326*_Complex_I, 0.184766137600 + 0.017212320864*_Complex_I, -0.045734372735 + -0.227365469933*_Complex_I, 0.031908345222 + 0.080422180891*_Complex_I, 0.089475703239 + 0.117917668819*_Complex_I, -0.143735373020 + 0.151164078712*_Complex_I, -0.158408689499 + -0.105965197086*_Complex_I, 0.041039618850 + -0.014203602076*_Complex_I, -0.084943604469 + -0.084828513861*_Complex_I, -0.032031357288 + -0.010720796138*_Complex_I, -0.019809050858 + -0.082033938169*_Complex_I, -0.297199916840 + 0.071534729004*_Complex_I, 0.041559013724 + -0.176234781742*_Complex_I, 0.077450340986 + 0.043274927139*_Complex_I, 0.188104069233 + 0.034578007460*_Complex_I, 0.091451799870 + -0.117644202709*_Complex_I, -0.116885960102 + 0.047494077682*_Complex_I, 0.021910847723 + -0.104368901253*_Complex_I, -0.170243906975 + -0.038744941354*_Complex_I, -0.006665949523 + -0.076677244902*_Complex_I, -0.123132240772 + -0.028003439307*_Complex_I, -0.008512797952 + 0.119553911686*_Complex_I, 0.007796970755 + -0.034775868058*_Complex_I, -0.020194862783 + 0.033565041423*_Complex_I, 0.000060333178 + 0.190958213806*_Complex_I, -0.126177227497 + -0.069941896200*_Complex_I, -0.031391653419 + -0.108642828465*_Complex_I, 0.049086883664 + 0.125198578835*_Complex_I, -0.098606723547 + 0.157826316357*_Complex_I, -0.037816497684 + -0.075405150652*_Complex_I, 0.154469418526 + -0.071843087673*_Complex_I, -0.180931842327 + 0.056550979614*_Complex_I, 0.049642735720 + 0.229578256607*_Complex_I, -0.013776327670 + 0.000968252402*_Complex_I, -0.131162738800 + 0.062030094862*_Complex_I, 0.115592253208 + -0.122473180294*_Complex_I, -0.143930578232 + 0.208317732811*_Complex_I, 0.025780442357 + 0.038679277897*_Complex_I, -0.186121022701 + 0.000732171116*_Complex_I, 0.001518380083 + -0.024754013121*_Complex_I, -0.026928266883 + -0.122094595432*_Complex_I, 0.102070283890 + 0.129774129391*_Complex_I, -0.046998295188 + 0.174012136459*_Complex_I, 0.114306473732 + -0.074029159546*_Complex_I, -0.041995987296 + 0.163119518757*_Complex_I, 0.167517042160 + -0.009892838448*_Complex_I, 0.114438354969 + 0.017925891280*_Complex_I, -0.095674896240 + 0.076540869474*_Complex_I, -0.062672561407 + -0.038445192575*_Complex_I, -0.217370772362 + -0.030016162992*_Complex_I, 0.005625271797 + -0.027812755108*_Complex_I, -0.152692675591 + -0.136305415630*_Complex_I, 0.084204858541 + 0.203144884109*_Complex_I, -0.056856244802 + -0.032040473819*_Complex_I, -0.015420150757 + 0.110550451279*_Complex_I, 0.011531084776 + 0.136303079128*_Complex_I, 0.059582346678 + -0.063924384117*_Complex_I, -0.066680252552 + 0.154493486881*_Complex_I, 0.034608376026 + 0.051702314615*_Complex_I, 0.113737416267 + 0.039248380065*_Complex_I, 0.158740794659 + 0.019757434726*_Complex_I, -0.039499655366 + -0.000118957297*_Complex_I, -0.054218810797 + 0.061152768135*_Complex_I, 0.020386171341 + -0.226112961769*_Complex_I, 0.027872058749 + -0.079996037483*_Complex_I, -0.139904499054 + 0.015143483877*_Complex_I, 0.013777624071 + -0.018682165444*_Complex_I, 0.005936894938 + -0.001314791571*_Complex_I, 0.157291007042 + -0.008614261448*_Complex_I, -0.079033893347 + -0.041999083757*_Complex_I, 0.084690928459 + 0.051340937614*_Complex_I, 0.001056097262 + 0.008219049126*_Complex_I, -0.028290018439 + 0.131245112419*_Complex_I, 0.102844524384 + -0.111723649502*_Complex_I, 0.123529279232 + -0.021718944609*_Complex_I, -0.029516366124 + -0.034146314859*_Complex_I, 0.048669779301 + 0.046512207389*_Complex_I, 0.038022220135 + 0.079673200846*_Complex_I, 0.175985097885 + 0.215863847733*_Complex_I, 0.106522679329 + 0.155265355110*_Complex_I, 0.033522182703 + 0.035048177838*_Complex_I, 0.014340730011 + -0.097587269545*_Complex_I, -0.051011729240 + 0.074478018284*_Complex_I, 0.048653256893 + 0.180682408810*_Complex_I, -0.143753635883 + -0.177901697159*_Complex_I, 0.077370518446 + -0.033802193403*_Complex_I, 0.080779671669 + 0.048105204105*_Complex_I, 0.062754058838 + 0.065103608370*_Complex_I, 0.195216703415 + -0.269327521324*_Complex_I, 0.035685497522 + 0.128597819805*_Complex_I, -0.152576267719 + 0.002838765644*_Complex_I, 0.037064149976 + 0.005790404975*_Complex_I, 0.028551298380 + -0.260332655907*_Complex_I, -0.112396037579 + -0.135177958012*_Complex_I, -0.015914693475 + 0.063825702667*_Complex_I, 0.158389151096 + 0.117301619053*_Complex_I, -0.063320201635 + 0.147249364853*_Complex_I, 0.257527685165 + -0.037165626884*_Complex_I, 0.047737368941 + -0.188134491444*_Complex_I, 0.014590293169 + -0.009723882377*_Complex_I, 0.026365819573 + -0.025334075093*_Complex_I, -0.102777397633 + 0.233691811562*_Complex_I, 0.072789901495 + -0.054794228077*_Complex_I, -0.129656755924 + -0.084271728992*_Complex_I, -0.022544041276 + -0.037263685465*_Complex_I, 0.004222166538 + -0.032020455599*_Complex_I, -0.040505915880 + 0.015989097953*_Complex_I, 0.076600146294 + 0.028494662046*_Complex_I, 0.165050017834 + 0.060545289516*_Complex_I, -0.201356935501 + -0.007056738436*_Complex_I, -0.144541025162 + -0.020850527287*_Complex_I, -0.060554254055 + -0.035383135080*_Complex_I, -0.083671200275 + 0.002356898040*_Complex_I, 0.009340242296 + -0.031346979737*_Complex_I, 0.099454361200 + -0.127831709385*_Complex_I, -0.167506957054 + 0.087425726652*_Complex_I, -0.039634212852 + -0.083207929134*_Complex_I, -0.225357127190 + 0.072750198841*_Complex_I, -0.006095945090 + -0.048631900549*_Complex_I, -0.011678160727 + -0.136811399460*_Complex_I, 0.182721781731 + -0.034160619974*_Complex_I, -0.137553799152 + 0.036647570133*_Complex_I, -0.020456752181 + -0.038014954329*_Complex_I, 0.128560674191 + -0.011797984689*_Complex_I, 0.093237119913 + 0.134914875031*_Complex_I, 0.109499740601 + 0.181737196445*_Complex_I, 0.177813911438 + 0.024316579103*_Complex_I, 0.149165189266 + -0.090540468693*_Complex_I, 0.132123124599 + -0.023848700523*_Complex_I, -0.173898208141 + 0.013859193027*_Complex_I, -0.238600111008 + 0.217159080505*_Complex_I, -0.000013622420 + -0.006076892465*_Complex_I, -0.008374422789 + -0.236851501465*_Complex_I, -0.283055114746 + 0.141181695461*_Complex_I, -0.089649707079 + 0.020758484304*_Complex_I, 0.095366454124 + 0.158369851112*_Complex_I, 0.015813191235 + -0.056471478939*_Complex_I, 0.127879250050 + 0.081945985556*_Complex_I, 0.035356411338 + -0.067337626219*_Complex_I, -0.245302104950 + -0.055383253098*_Complex_I, -0.136766076088 + -0.014186948538*_Complex_I, -0.141382408142 + -0.000181592884*_Complex_I, -0.047739619017 + -0.041759270430*_Complex_I, -0.023178872466 + 0.034544199705*_Complex_I, 0.061150830984 + 0.075226747990*_Complex_I, -0.058196645975 + 0.033970293403*_Complex_I, -0.145030462742 + 0.039564606547*_Complex_I, -0.199735391140 + 0.212692308426*_Complex_I, -0.083191102743 + 0.161805856228*_Complex_I, 0.098720330000 + -0.211091256142*_Complex_I, 0.051044720411 + -0.086010062695*_Complex_I, -0.118900668621 + -0.002717586420*_Complex_I, -0.069598269463 + -0.110835444927*_Complex_I}; float complex fftfilt_crcf_data_h4x256_y[] = { 0.006059868184 + 0.010311000972*_Complex_I, 0.023178078930 + 0.016597675907*_Complex_I, 0.001208400606 + -0.016916628103*_Complex_I, -0.056896873822 + -0.028897872629*_Complex_I, -0.036461808619 + -0.010528658122*_Complex_I, 0.037930900295 + -0.007482611703*_Complex_I, 0.029162273827 + 0.043800977293*_Complex_I, -0.042757112462 + 0.027781259560*_Complex_I, -0.020487164712 + -0.061602550704*_Complex_I, -0.016651889059 + 0.011713200441*_Complex_I, 0.014333029188 + 0.031224344773*_Complex_I, -0.028467695798 + -0.024208640112*_Complex_I, 0.025832696718 + 0.019920182397*_Complex_I, -0.018263455064 + 0.020029328938*_Complex_I, -0.008683265862 + -0.027376146840*_Complex_I, -0.006227647384 + 0.018128890559*_Complex_I, -0.005092271511 + -0.000209362331*_Complex_I, 0.018081477268 + -0.025761751836*_Complex_I, -0.017992967322 + -0.024982308404*_Complex_I, -0.001734990008 + -0.016554996144*_Complex_I, 0.026068014213 + -0.041963253019*_Complex_I, 0.027586922248 + 0.001220122229*_Complex_I, 0.012814232728 + 0.026257959070*_Complex_I, -0.048501690424 + -0.002622820479*_Complex_I, 0.045376716710 + 0.014386270946*_Complex_I, 0.047800317199 + -0.052577099490*_Complex_I, -0.078296298763 + 0.024698851676*_Complex_I, 0.006293167971 + 0.038911765139*_Complex_I, 0.016953644799 + -0.044169610042*_Complex_I, -0.022820292108 + -0.019446419914*_Complex_I, -0.013440891814 + -0.013844717016*_Complex_I, 0.012635287358 + 0.045953219949*_Complex_I, -0.004889948433 + -0.036010114541*_Complex_I, -0.016426625652 + -0.007240686790*_Complex_I, 0.053888265216 + 0.051988318810*_Complex_I, -0.022978930110 + -0.019347527890*_Complex_I, -0.014632670495 + 0.009187820283*_Complex_I, 0.028981046972 + 0.028827768992*_Complex_I, -0.016453648195 + -0.009132783918*_Complex_I, -0.010139552985 + 0.041406876217*_Complex_I, -0.006352754502 + 0.001483701581*_Complex_I, 0.023445201384 + 0.014547612472*_Complex_I, -0.009250442382 + -0.029488557351*_Complex_I, 0.024527507249 + 0.038284467295*_Complex_I, 0.009919837691 + -0.013523965732*_Complex_I, 0.023008727191 + 0.014672234378*_Complex_I, -0.041817346662 + 0.028108049584*_Complex_I, 0.038656077865 + 0.001879063803*_Complex_I, -0.030624607394 + -0.015270823004*_Complex_I, -0.011163069470 + 0.026250535961*_Complex_I, 0.030927857953 + 0.017782771893*_Complex_I, -0.009187521194 + -0.002284106361*_Complex_I, 0.023021457646 + 0.002319743817*_Complex_I, 0.002183457008 + -0.048848851834*_Complex_I, 0.024149575692 + 0.023619625148*_Complex_I, -0.038849588696 + 0.001002466517*_Complex_I, 0.014961889285 + 0.029401021704*_Complex_I, -0.005688927643 + 0.018501108984*_Complex_I, 0.002270910497 + -0.023424239102*_Complex_I, -0.012218835419 + 0.007569433759*_Complex_I, -0.081049834844 + 0.062554661642*_Complex_I, 0.063226186616 + 0.018432005055*_Complex_I, -0.018370298666 + 0.036631089037*_Complex_I, 0.010275373508 + 0.019400535292*_Complex_I, -0.008744823687 + 0.008298191463*_Complex_I, -0.007436928001 + 0.012839303011*_Complex_I, 0.052061411111 + -0.007282750818*_Complex_I, -0.045668210091 + -0.005240621957*_Complex_I, 0.006463364693 + -0.046969833961*_Complex_I, 0.047231835108 + 0.017925737087*_Complex_I, 0.018296593037 + -0.031722900784*_Complex_I, 0.003320288626 + 0.029589882902*_Complex_I, -0.016756503569 + 0.000753544241*_Complex_I, -0.000538421251 + -0.046863924905*_Complex_I, -0.042842141445 + -0.023675331266*_Complex_I, 0.020793064630 + -0.011272959088*_Complex_I, 0.048633718156 + 0.000888764564*_Complex_I, -0.058367383027 + -0.024603242648*_Complex_I, 0.023764054076 + 0.025940916726*_Complex_I, 0.019423147902 + -0.045621226585*_Complex_I, -0.048053653552 + -0.014004397126*_Complex_I, 0.051461188295 + -0.004580127799*_Complex_I, 0.000072882267 + -0.021075898269*_Complex_I, 0.001594299020 + -0.022143698521*_Complex_I, 0.033154983906 + 0.030058007048*_Complex_I, -0.012594575098 + -0.028965724511*_Complex_I, -0.010583515338 + 0.028968867756*_Complex_I, -0.054194842002 + 0.008176900584*_Complex_I, 0.029128076149 + -0.024688556963*_Complex_I, 0.003010233851 + 0.012087666948*_Complex_I, 0.012788000724 + -0.005917484080*_Complex_I, 0.005823040482 + 0.035833156760*_Complex_I, 0.009314948304 + 0.024460365458*_Complex_I, 0.022001107298 + -0.006273716153*_Complex_I, -0.021575905979 + -0.001442477527*_Complex_I, 0.041753275685 + -0.008456774704*_Complex_I, 0.025289151882 + 0.013847773473*_Complex_I, -0.017151178833 + -0.001123303791*_Complex_I, -0.024939022931 + -0.030114627959*_Complex_I, 0.013792691837 + 0.007716695455*_Complex_I, 0.026453740944 + -0.011989457656*_Complex_I, -0.035945169446 + 0.021435504561*_Complex_I, 0.032501406199 + -0.028539713517*_Complex_I, -0.015295973874 + 0.026437256451*_Complex_I, -0.004134027099 + -0.032386805528*_Complex_I, 0.047527752256 + -0.011152387256*_Complex_I, -0.044529397603 + -0.024589491243*_Complex_I, 0.042085917317 + 0.067737759803*_Complex_I, -0.021267753978 + 0.003431390108*_Complex_I, -0.053880077452 + -0.011182616288*_Complex_I, 0.019902772754 + -0.029591806606*_Complex_I, 0.005358033182 + 0.016609146898*_Complex_I, -0.036261790964 + -0.018892239095*_Complex_I, 0.011134802022 + -0.001028496419*_Complex_I, -0.050869309200 + -0.004439202137*_Complex_I, -0.028307773042 + -0.006096679489*_Complex_I, 0.065257591616 + -0.033605740720*_Complex_I, 0.004628677817 + 0.046654745363*_Complex_I, 0.027227886379 + -0.037405943501*_Complex_I, -0.032050718154 + -0.008470442952*_Complex_I, -0.008872103935 + 0.012325554139*_Complex_I, 0.004047059830 + -0.037017014389*_Complex_I, -0.035453440267 + 0.005344037694*_Complex_I, 0.010704785090 + -0.016337463075*_Complex_I, -0.030159066222 + 0.024707243754*_Complex_I, 0.020346072551 + 0.006553876216*_Complex_I, -0.011897480047 + -0.021565463012*_Complex_I, -0.004465715862 + 0.050343859162*_Complex_I, -0.015523348770 + 0.002953074058*_Complex_I, -0.021671519813 + -0.054336385799*_Complex_I, 0.025180402141 + 0.035625240780*_Complex_I, -0.015627538530 + 0.051389004055*_Complex_I, -0.028673608441 + -0.023927002620*_Complex_I, 0.040599172161 + -0.035405429827*_Complex_I, -0.012379694629 + 0.027233362371*_Complex_I, -0.043152122115 + 0.047727396912*_Complex_I, 0.048160488676 + 0.011347729858*_Complex_I, -0.046736949340 + -0.023803373100*_Complex_I, 0.009245777592 + 0.008847967472*_Complex_I, 0.012152552309 + 0.007542499150*_Complex_I, -0.044355838252 + 0.056937859612*_Complex_I, 0.008769479148 + -0.041449112921*_Complex_I, -0.039154058148 + 0.008519281894*_Complex_I, 0.029670337728 + -0.018567039979*_Complex_I, -0.004360041436 + 0.009962611552*_Complex_I, 0.009455849568 + 0.060794526263*_Complex_I, -0.007406255544 + -0.023779500426*_Complex_I, 0.024140392564 + -0.000990198094*_Complex_I, -0.002405235069 + 0.045967822672*_Complex_I, 0.055053080500 + -0.032543394298*_Complex_I, -0.033337576595 + 0.030424287480*_Complex_I, -0.025251956775 + -0.000824714706*_Complex_I, -0.014809843352 + -0.020503870649*_Complex_I, -0.022962265375 + 0.005498838976*_Complex_I, 0.007866492401 + -0.022921694981*_Complex_I, -0.025557031391 + 0.017436967625*_Complex_I, 0.027361670922 + 0.039540920716*_Complex_I, -0.037103850469 + -0.033116749204*_Complex_I, 0.017144745074 + 0.058045180011*_Complex_I, 0.008105425889 + -0.015309983982*_Complex_I, -0.006650118444 + 0.003482516084*_Complex_I, -0.011513157356 + 0.049425701442*_Complex_I, 0.038412271512 + -0.019560238313*_Complex_I, 0.026334973579 + 0.012959388879*_Complex_I, -0.003371545788 + 0.000377270846*_Complex_I, -0.029595884162 + 0.009716579081*_Complex_I, 0.017727723120 + -0.026138227085*_Complex_I, 0.012322519379 + -0.049558984658*_Complex_I, -0.026796988722 + 0.036486852957*_Complex_I, -0.017291674519 + -0.008043280034*_Complex_I, 0.028640846159 + -0.012189476909*_Complex_I, 0.010234405721 + 0.003017545570*_Complex_I, 0.006584481357 + -0.009021558338*_Complex_I, -0.022148247256 + 0.004345047986*_Complex_I, 0.037711072166 + 0.013661393387*_Complex_I, -0.025677561015 + 0.008959528481*_Complex_I, 0.020117937550 + 0.001416082797*_Complex_I, 0.036273540108 + -0.037988612000*_Complex_I, -0.009832458294 + 0.022778259426*_Complex_I, -0.007452052832 + -0.003232619018*_Complex_I, 0.027806123164 + 0.021703539285*_Complex_I, 0.021030743738 + 0.032118581494*_Complex_I, 0.035420951705 + 0.040521245842*_Complex_I, -0.008374298228 + -0.005319284142*_Complex_I, 0.004142265794 + -0.017707830367*_Complex_I, -0.002272597722 + 0.008133912171*_Complex_I, 0.002135690771 + 0.056547995055*_Complex_I, -0.006717788148 + -0.027626980558*_Complex_I, -0.017795801727 + -0.050060314493*_Complex_I, 0.050348648898 + 0.049756863364*_Complex_I, -0.006668519461 + 0.005471354270*_Complex_I, 0.031191975857 + -0.045353001209*_Complex_I, 0.025407683165 + -0.018531409391*_Complex_I, -0.046738508420 + 0.066929291225*_Complex_I, -0.000707147993 + -0.044733357800*_Complex_I, 0.037759803940 + -0.028700053973*_Complex_I, -0.034121953222 + -0.052608653720*_Complex_I, -0.017261681450 + 0.038291536957*_Complex_I, 0.044274419912 + 0.025096236007*_Complex_I, 0.001453954093 + 0.013865033987*_Complex_I, 0.004454502807 + -0.002333726953*_Complex_I, 0.062910894997 + -0.047902277474*_Complex_I, -0.041170383580 + -0.004258984080*_Complex_I, 0.021032411606 + 0.023244356831*_Complex_I, -0.011019598807 + 0.018024590663*_Complex_I, -0.003977275574 + 0.022558085902*_Complex_I, 0.008142338448 + -0.061263169770*_Complex_I, -0.040412311920 + 0.014535332123*_Complex_I, 0.026396971660 + -0.000147948023*_Complex_I, -0.013707137421 + -0.002634559956*_Complex_I, 0.004374543380 + 0.008360519390*_Complex_I, 0.041968579789 + 0.007215835772*_Complex_I, -0.028335666347 + 0.002719860858*_Complex_I, -0.067248700384 + -0.011709090114*_Complex_I, 0.022263469171 + -0.001324450231*_Complex_I, -0.014020557910 + -0.000950863534*_Complex_I, -0.011306257165 + -0.000520086651*_Complex_I, 0.025214827331 + -0.027199113964*_Complex_I, -0.023406560837 + 0.003949552479*_Complex_I, -0.041930892788 + 0.016117503991*_Complex_I, -0.002573727540 + -0.024804241879*_Complex_I, -0.036096841921 + 0.022961064703*_Complex_I, 0.031847322765 + -0.046819879524*_Complex_I, 0.007740249190 + -0.006771536473*_Complex_I, 0.001665062016 + 0.020313331769*_Complex_I, -0.051320971549 + -0.008165457704*_Complex_I, 0.057246239219 + -0.015598020100*_Complex_I, 0.020777735323 + 0.029309410804*_Complex_I, 0.004586628235 + 0.042828336116*_Complex_I, 0.036544916785 + 0.001529339266*_Complex_I, 0.034254870037 + -0.029648210991*_Complex_I, 0.018166856966 + -0.002136023066*_Complex_I, -0.020485570645 + 0.016777734021*_Complex_I, -0.066536421479 + 0.031283983440*_Complex_I, 0.012940550380 + 0.020303008580*_Complex_I, 0.023195801416 + -0.072912377311*_Complex_I, -0.066574302932 + 0.014524209319*_Complex_I, -0.046087408784 + 0.059314287035*_Complex_I, 0.051145158090 + -0.018053503400*_Complex_I, 0.003319584852 + 0.019225038270*_Complex_I, -0.002381437087 + -0.018745607253*_Complex_I, 0.026600447010 + 0.023038482211*_Complex_I, -0.054100537802 + -0.035500673450*_Complex_I, -0.044770266493 + 0.009968159227*_Complex_I, 0.006304211224 + 0.001543141693*_Complex_I, -0.023283661455 + -0.009128698496*_Complex_I, 0.002209473868 + -0.000822823133*_Complex_I, 0.002052052541 + 0.022819476191*_Complex_I, -0.002213516155 + 0.004613633607*_Complex_I, -0.041860771422 + 0.000627854778*_Complex_I, -0.032948617085 + 0.038855531028*_Complex_I, -0.017437619533 + 0.046788113461*_Complex_I, 0.026062969909 + -0.045935009629*_Complex_I, 0.015631583001 + -0.046464537818*_Complex_I, -0.036593182213 + 0.039547933437*_Complex_I, -0.024611804187 + -0.022132462723*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/fftfilt_crcf_data_h7x256.c000066400000000000000000000647211317124540100245410ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fftfilt_crcf_data_h7x256.c: autotest fftfilt data // #include float fftfilt_crcf_data_h7x256_h[] = { -0.040934386849, 0.135112583637, 0.002939097211, 0.060173767805, -0.080519974232, 0.155969536304, 0.169374001026}; float complex fftfilt_crcf_data_h7x256_x[] = { 0.040651902556 + 0.099964648485*_Complex_I, -0.099666911364 + 0.065967345238*_Complex_I, 0.160125207901 + 0.220931744576*_Complex_I, 0.040764364600 + -0.044899615645*_Complex_I, -0.134997522831 + 0.246626877785*_Complex_I, 0.081977373362 + -0.136002039909*_Complex_I, 0.110743105412 + 0.054145228863*_Complex_I, 0.044197705388 + -0.067522579432*_Complex_I, -0.109018945694 + -0.106943678856*_Complex_I, 0.006750953943 + -0.091825586557*_Complex_I, 0.074130672216 + 0.058626526594*_Complex_I, -0.109099924564 + -0.185111522675*_Complex_I, 0.050862681866 + -0.099265706539*_Complex_I, 0.139591431618 + -0.009831842780*_Complex_I, 0.098799163103 + 0.068593806028*_Complex_I, -0.134761643410 + -0.071746927500*_Complex_I, 0.040908864141 + -0.077851450443*_Complex_I, 0.009703576565 + 0.085823422670*_Complex_I, -0.088899284601 + -0.024389025569*_Complex_I, 0.131887495518 + 0.003364508972*_Complex_I, -0.016711652279 + -0.064561820030*_Complex_I, -0.028739383817 + 0.119105470181*_Complex_I, -0.037841024995 + 0.130922996998*_Complex_I, -0.036886861920 + 0.049854472280*_Complex_I, 0.195188224316 + 0.196104526520*_Complex_I, 0.090881633759 + -0.049584397674*_Complex_I, 0.095823466778 + -0.010633364320*_Complex_I, -0.026297450066 + 0.112273478508*_Complex_I, 0.064357328415 + -0.151258838177*_Complex_I, 0.083770233393 + -0.010217200220*_Complex_I, -0.085294854641 + -0.001434229873*_Complex_I, -0.024482454360 + -0.028102940321*_Complex_I, 0.007926462591 + 0.049879977107*_Complex_I, -0.019109925628 + -0.122103679180*_Complex_I, 0.065177565813 + -0.099032187462*_Complex_I, -0.029712364078 + 0.058807843924*_Complex_I, 0.014222274721 + -0.111795830727*_Complex_I, -0.013231332600 + -0.097048926353*_Complex_I, -0.042737719417 + -0.082051867247*_Complex_I, -0.000470168283 + 0.065859609842*_Complex_I, -0.012786905468 + 0.140206325054*_Complex_I, 0.101196074486 + 0.024098466337*_Complex_I, 0.029521119595 + 0.073089057207*_Complex_I, 0.036042726040 + -0.055842936039*_Complex_I, 0.006287913024 + 0.163206160069*_Complex_I, 0.162955164909 + -0.168543994427*_Complex_I, 0.025857266784 + 0.046382865310*_Complex_I, 0.105994081497 + -0.114217007160*_Complex_I, 0.166455543041 + -0.042309248447*_Complex_I, -0.055975890160 + -0.082556062937*_Complex_I, 0.100109672546 + 0.042784979939*_Complex_I, -0.133630573750 + 0.026788604259*_Complex_I, -0.124175155163 + 0.100820934772*_Complex_I, -0.018217980862 + 0.020558734238*_Complex_I, 0.020028033853 + -0.023399496078*_Complex_I, 0.041591683030 + 0.234618091583*_Complex_I, 0.114061284065 + 0.076200354099*_Complex_I, -0.044339376688 + 0.155996751785*_Complex_I, -0.137206864357 + 0.152004182339*_Complex_I, -0.125251030922 + -0.189576375484*_Complex_I, -0.096886903048 + 0.100963902473*_Complex_I, 0.045814022422 + -0.153462719917*_Complex_I, 0.018112409115 + 0.033487904072*_Complex_I, -0.094020819664 + -0.066115939617*_Complex_I, -0.183385014534 + -0.106691968441*_Complex_I, 0.008264037967 + -0.041415163875*_Complex_I, -0.061662602425 + -0.034961605072*_Complex_I, 0.125767064095 + 0.063457810879*_Complex_I, 0.017231588066 + -0.019841212034*_Complex_I, 0.129437744617 + -0.025927716494*_Complex_I, -0.060927426815 + 0.096969240904*_Complex_I, -0.015513072908 + 0.036051341891*_Complex_I, -0.111995267868 + 0.039143866301*_Complex_I, -0.073930400610 + 0.029889217019*_Complex_I, -0.175347507000 + 0.054301995039*_Complex_I, 0.052788543701 + 0.158147716522*_Complex_I, 0.015504409373 + 0.139973330498*_Complex_I, -0.031992411613 + -0.023225200176*_Complex_I, 0.025022339821 + -0.131516921520*_Complex_I, 0.018602204323 + 0.044248020649*_Complex_I, -0.173263669014 + -0.001720846072*_Complex_I, -0.067457306385 + -0.031605756283*_Complex_I, -0.120310330391 + 0.084929233789*_Complex_I, -0.217696404457 + 0.025325486064*_Complex_I, -0.051374822855 + 0.090975987911*_Complex_I, 0.090311527252 + -0.099616253376*_Complex_I, -0.032548421621 + 0.022745725513*_Complex_I, 0.136037707329 + 0.054802763462*_Complex_I, 0.137908041477 + -0.013432055712*_Complex_I, -0.055867260695 + 0.124781918526*_Complex_I, -0.042160874605 + -0.145593822002*_Complex_I, -0.119642519951 + 0.119596099854*_Complex_I, 0.139787364006 + 0.183254098892*_Complex_I, -0.134095728397 + -0.062589937449*_Complex_I, -0.132995867729 + -0.087235867977*_Complex_I, -0.066653913260 + -0.209919691086*_Complex_I, 0.103792250156 + -0.098301386833*_Complex_I, -0.047595480084 + -0.060045230389*_Complex_I, -0.112747573853 + -0.090008395910*_Complex_I, -0.209859752655 + -0.037542074919*_Complex_I, 0.126466608047 + -0.080237525702*_Complex_I, 0.016278307140 + 0.020775717497*_Complex_I, -0.172989428043 + -0.065381830931*_Complex_I, -0.146700656414 + -0.139556598663*_Complex_I, -0.016435039043 + 0.061182838678*_Complex_I, 0.033882060647 + -0.038332518935*_Complex_I, -0.062427771091 + -0.101914501190*_Complex_I, 0.005463292450 + -0.123674154282*_Complex_I, -0.021189038455 + 0.067074733973*_Complex_I, -0.026172134280 + -0.118123090267*_Complex_I, -0.056077581644 + -0.012562614679*_Complex_I, -0.044715997577 + -0.070106768608*_Complex_I, -0.131478667259 + -0.141248393059*_Complex_I, 0.029736247659 + -0.026428756118*_Complex_I, -0.037444081903 + -0.068290340900*_Complex_I, 0.001371991076 + 0.079103118181*_Complex_I, 0.096291542053 + -0.006254652143*_Complex_I, 0.011948133260 + -0.061023879051*_Complex_I, 0.012181475013 + -0.016896595061*_Complex_I, 0.018844342232 + -0.121562480927*_Complex_I, -0.075810509920 + -0.044127961993*_Complex_I, -0.065980046988 + -0.120858967304*_Complex_I, 0.017340828478 + 0.001790644042*_Complex_I, -0.158844494820 + -0.130223393440*_Complex_I, 0.112532448769 + -0.015026393533*_Complex_I, 0.207700538635 + 0.072319573164*_Complex_I, -0.005225989595 + -0.052219772339*_Complex_I, -0.040421813726 + -0.137831771374*_Complex_I, -0.173290038109 + 0.160280382633*_Complex_I, 0.051121586561 + -0.104382145405*_Complex_I, -0.088693290949 + 0.112509071827*_Complex_I, 0.035253915191 + -0.128079938889*_Complex_I, 0.069757878780 + -0.118046510220*_Complex_I, 0.072834354639 + 0.093183624744*_Complex_I, 0.098304384947 + -0.038691642880*_Complex_I, 0.043434667587 + -0.021110518277*_Complex_I, 0.053629237413 + 0.059115654230*_Complex_I, 0.016377405822 + -0.074930238724*_Complex_I, -0.082616806030 + -0.107039499283*_Complex_I, 0.063279908895 + 0.085305947065*_Complex_I, -0.034898114204 + 0.129442250729*_Complex_I, -0.014594067633 + -0.068186104298*_Complex_I, -0.013007178903 + 0.240023064613*_Complex_I, -0.017352801561 + -0.107890737057*_Complex_I, -0.104129159451 + 0.294831180573*_Complex_I, 0.034248217940 + -0.020147347450*_Complex_I, -0.068929183483 + -0.145515120029*_Complex_I, 0.021941699088 + -0.150268518925*_Complex_I, 0.106213212013 + 0.050292271376*_Complex_I, -0.139671075344 + -0.032991030812*_Complex_I, -0.077905637026 + -0.102883970737*_Complex_I, 0.060987144709 + 0.119357335567*_Complex_I, 0.035836818814 + -0.036872345209*_Complex_I, 0.104147458076 + 0.079617452621*_Complex_I, -0.002261339687 + -0.082611733675*_Complex_I, -0.012895359099 + 0.065233492851*_Complex_I, 0.006274250150 + 0.018203525245*_Complex_I, 0.133517765999 + 0.130283260345*_Complex_I, -0.197759151459 + -0.014819876850*_Complex_I, -0.113921284676 + -0.029470649362*_Complex_I, 0.057060551643 + 0.010812921077*_Complex_I, -0.017510490119 + -0.139960432053*_Complex_I, -0.051596522331 + -0.019726826251*_Complex_I, 0.128962993622 + 0.032193422318*_Complex_I, -0.085369610786 + 0.007678684592*_Complex_I, -0.040599119663 + 0.058400410414*_Complex_I, 0.034683728218 + 0.006657131016*_Complex_I, -0.062493687868 + 0.258592700958*_Complex_I, 0.030317050219 + -0.182111239433*_Complex_I, -0.029376697540 + 0.052327275276*_Complex_I, -0.109441542625 + -0.079162907600*_Complex_I, -0.090063333511 + -0.016401563585*_Complex_I, -0.209231019020 + 0.104617154598*_Complex_I, 0.033998718858 + 0.114239072800*_Complex_I, 0.016250103712 + -0.094514828920*_Complex_I, -0.065307158232 + -0.109144735336*_Complex_I, 0.044777354598 + 0.034570571780*_Complex_I, 0.047505182028 + 0.106286907196*_Complex_I, 0.032323399186 + -0.060076057911*_Complex_I, 0.009413731098 + 0.113497722149*_Complex_I, -0.001863899827 + 0.103868281841*_Complex_I, -0.136217641830 + 0.035371488333*_Complex_I, 0.035117888451 + -0.181699144840*_Complex_I, 0.012568083405 + 0.029830288887*_Complex_I, 0.222174477577 + -0.128343975544*_Complex_I, -0.073185539246 + 0.019389149547*_Complex_I, 0.101314771175 + 0.003134848550*_Complex_I, 0.029810345173 + 0.106935989857*_Complex_I, 0.062490916252 + -0.069559586048*_Complex_I, 0.149825906754 + 0.072701114416*_Complex_I, 0.123934853077 + -0.025215783715*_Complex_I, 0.009782531857 + -0.153410112858*_Complex_I, 0.160168147087 + 0.089273881912*_Complex_I, 0.168133974075 + 0.006127674505*_Complex_I, 0.045770967007 + -0.068010586500*_Complex_I, 0.031379061937 + -0.011051291972*_Complex_I, 0.158589434624 + -0.111993229389*_Complex_I, -0.076348328590 + -0.078152877092*_Complex_I, -0.134444558620 + -0.117534625530*_Complex_I, -0.079543095827 + -0.066662031412*_Complex_I, -0.071512258053 + -0.002769588307*_Complex_I, 0.044172352552 + -0.001636494324*_Complex_I, 0.106910932064 + 0.067301118374*_Complex_I, -0.189863562584 + -0.210064339638*_Complex_I, 0.160713946819 + -0.175641644001*_Complex_I, 0.107809066772 + -0.015213376284*_Complex_I, 0.122092103958 + -0.030190780759*_Complex_I, -0.003812288493 + -0.100728774071*_Complex_I, -0.106180906296 + 0.040024718642*_Complex_I, -0.023936416209 + 0.098257493973*_Complex_I, 0.036565282941 + 0.003215969726*_Complex_I, -0.103855776787 + -0.073435127735*_Complex_I, -0.050348949432 + 0.062807798386*_Complex_I, -0.112694954872 + 0.127760851383*_Complex_I, -0.090150475502 + 0.123642957211*_Complex_I, 0.045266637206 + -0.160168957710*_Complex_I, 0.026377058029 + 0.006977221370*_Complex_I, 0.102039659023 + -0.043179959059*_Complex_I, 0.013855941594 + 0.044194161892*_Complex_I, -0.218561863899 + -0.144262731075*_Complex_I, -0.137404084206 + 0.063279211521*_Complex_I, 0.238168430328 + 0.085272878408*_Complex_I, -0.048531836271 + 0.178845489025*_Complex_I, -0.144287097454 + 0.058967697620*_Complex_I, -0.049209004641 + -0.025680020452*_Complex_I, 0.024836380780 + -0.005075773597*_Complex_I, 0.102902829647 + 0.135188984871*_Complex_I, 0.011638478935 + -0.053264147043*_Complex_I, 0.022318521142 + -0.005398513377*_Complex_I, -0.073730462790 + -0.112155592442*_Complex_I, -0.006353335828 + -0.047271516919*_Complex_I, -0.009832777083 + -0.083933675289*_Complex_I, -0.189570760727 + -0.024030640721*_Complex_I, 0.170936667919 + -0.021397763491*_Complex_I, 0.027291259170 + 0.065315496922*_Complex_I, 0.021211113036 + 0.016976553202*_Complex_I, 0.009872701019 + -0.091594105959*_Complex_I, 0.057232087851 + -0.185351312160*_Complex_I, 0.200562620163 + -0.098748236895*_Complex_I, 0.055897176266 + -0.010039170831*_Complex_I, -0.127369284630 + -0.044656923413*_Complex_I, 0.137353527546 + 0.299679923058*_Complex_I, 0.045141702890 + -0.044110915065*_Complex_I, -0.004061393067 + -0.012276126444*_Complex_I, -0.177904891968 + 0.037945824862*_Complex_I, 0.154672491550 + -0.095904517174*_Complex_I, -0.175321102142 + 0.007050059736*_Complex_I, -0.146184301376 + -0.079787492752*_Complex_I, 0.189255583286 + 0.028883567452*_Complex_I, -0.122478711605 + -0.069346314669*_Complex_I, -0.046293541789 + 0.053173589706*_Complex_I, -0.007427679747 + 0.097887659073*_Complex_I, 0.015306715667 + 0.002264038287*_Complex_I, -0.000068226655 + 0.105025970936*_Complex_I, 0.003785865381 + -0.108235859871*_Complex_I, -0.007453963161 + 0.090025615692*_Complex_I}; float complex fftfilt_crcf_data_h7x256_y[] = { -0.001664060705 + -0.004091991592*_Complex_I, 0.009572387490 + 0.010806149100*_Complex_I, -0.019901401209 + 0.000163118771*_Complex_I, 0.022119513679 + 0.037897731040*_Complex_I, 0.002233819268 + -0.019592330428*_Complex_I, 0.002525225428 + 0.062331636862*_Complex_I, -0.012953756015 + -0.013138017071*_Complex_I, 0.010082536290 + 0.073767533264*_Complex_I, 0.060041705276 + -0.002211361863*_Complex_I, -0.028964339812 + 0.034181387304*_Complex_I, -0.018779359256 + -0.002983805531*_Complex_I, 0.035540274574 + -0.000359767320*_Complex_I, 0.018230003371 + -0.019050266810*_Complex_I, -0.004763113580 + -0.030748598959*_Complex_I, -0.014980219026 + -0.052722939755*_Complex_I, 0.043826553194 + 0.014698974734*_Complex_I, -0.019748368274 + -0.017846203362*_Complex_I, -0.011106427606 + -0.056159008955*_Complex_I, 0.019392753020 + -0.015821591090*_Complex_I, 0.034983837452 + 0.006944986235*_Complex_I, 0.011247676464 + 0.014886292150*_Complex_I, -0.023269214094 + -0.046261333224*_Complex_I, 0.021153525557 + 0.012909728412*_Complex_I, -0.027534552856 + 0.022575118010*_Complex_I, -0.007955539149 + 0.007852778474*_Complex_I, 0.042312648793 + 0.017460367142*_Complex_I, 0.002444803765 + -0.005588089285*_Complex_I, 0.018236124634 + 0.042201155890*_Complex_I, -0.028316282736 + 0.032506714358*_Complex_I, 0.027833124697 + 0.022694313405*_Complex_I, 0.052935514738 + 0.031327141782*_Complex_I, 0.026052595484 + -0.027272295746*_Complex_I, 0.008104080597 + 0.021431694747*_Complex_I, -0.004512749861 + 0.007815877639*_Complex_I, 0.024134102168 + -0.041085781838*_Complex_I, 0.013299793171 + -0.012836542385*_Complex_I, -0.024458533812 + -0.003758988445*_Complex_I, 0.004926203119 + -0.004067048560*_Complex_I, -0.008670506918 + -0.009165691319*_Complex_I, 0.004383190990 + -0.061656974229*_Complex_I, 0.004798093293 + -0.001521204143*_Complex_I, -0.010192016400 + 0.013551533652*_Complex_I, 0.016184999222 + -0.022825917758*_Complex_I, -0.006827691414 + -0.013869452441*_Complex_I, 0.004506159339 + -0.027475686016*_Complex_I, -0.014160870823 + 0.064266780404*_Complex_I, 0.034386845087 + -0.005930865931*_Complex_I, 0.018854367860 + 0.040245466115*_Complex_I, 0.027504376699 + -0.033177621818*_Complex_I, 0.020613311216 + 0.029686212518*_Complex_I, 0.019605341108 + -0.022282553995*_Complex_I, 0.051946574188 + -0.010220239313*_Complex_I, -0.008537785955 + -0.011901108333*_Complex_I, 0.038021151548 + -0.003863047727*_Complex_I, -0.000285452285 + -0.017843481523*_Complex_I, 0.010371007070 + -0.016105029388*_Complex_I, 0.006025408264 + 0.033055735207*_Complex_I, -0.021980650718 + 0.021798423647*_Complex_I, -0.023022513053 + 0.051363849161*_Complex_I, -0.009988970700 + 0.014282686356*_Complex_I, -0.015333264002 + 0.006580976190*_Complex_I, 0.004814453158 + 0.067575161384*_Complex_I, 0.021078361301 + -0.008218606426*_Complex_I, -0.018224318008 + 0.078249889963*_Complex_I, -0.037359896117 + -0.025653924650*_Complex_I, -0.064316968357 + -0.014904552890*_Complex_I, -0.013278818311 + -0.017987895509*_Complex_I, -0.006335027346 + -0.029308988553*_Complex_I, 0.019772938592 + 0.010742017022*_Complex_I, -0.051503658033 + -0.028040995216*_Complex_I, 0.002794574067 + -0.025427598795*_Complex_I, -0.024524259323 + -0.007221318106*_Complex_I, 0.017882433375 + 0.007567005700*_Complex_I, -0.002250551860 + 0.019747472870*_Complex_I, 0.023938973082 + -0.011112496998*_Complex_I, -0.019139308840 + 0.011136397615*_Complex_I, -0.002187533851 + 0.036491286044*_Complex_I, -0.021134226221 + 0.033399966516*_Complex_I, -0.018505797162 + 0.019092652268*_Complex_I, -0.040662996211 + -0.010428531884*_Complex_I, -0.014960045707 + 0.026857740562*_Complex_I, -0.005153165788 + 0.043765214305*_Complex_I, -0.007957971301 + 0.025585809340*_Complex_I, -0.020982171142 + -0.017767345049*_Complex_I, -0.010632593672 + -0.017190118051*_Complex_I, -0.036959052593 + 0.031325636500*_Complex_I, -0.029896295979 + -0.024658675955*_Complex_I, -0.025453655228 + 0.011865474671*_Complex_I, -0.032120802983 + 0.013036366771*_Complex_I, -0.032795629447 + 0.021107115286*_Complex_I, 0.010773771971 + 0.024117992872*_Complex_I, 0.006601385448 + -0.042746141925*_Complex_I, -0.020772448711 + 0.029219872585*_Complex_I, 0.070536673110 + 0.016052326150*_Complex_I, -0.001423170033 + 0.031759755912*_Complex_I, -0.013628227138 + -0.003553860969*_Complex_I, -0.058771606883 + -0.049123627122*_Complex_I, 0.020108788723 + 0.037188142016*_Complex_I, 0.007949063332 + 0.010951582458*_Complex_I, -0.038626115166 + -0.024020666588*_Complex_I, -0.078006273376 + -0.045266963734*_Complex_I, 0.017751019078 + -0.063270144075*_Complex_I, 0.016258961397 + -0.015778900175*_Complex_I, -0.018458853139 + -0.029074158472*_Complex_I, -0.080688576156 + -0.034942123609*_Complex_I, -0.031578691749 + -0.015054873307*_Complex_I, 0.036145679578 + -0.014310450501*_Complex_I, -0.021959415316 + -0.000580080691*_Complex_I, -0.047396546182 + -0.059828747217*_Complex_I, -0.035670847715 + -0.003606200086*_Complex_I, 0.006553370474 + -0.010100243677*_Complex_I, -0.011536306226 + -0.007568475396*_Complex_I, -0.010414782074 + -0.052787147602*_Complex_I, -0.022759606756 + -0.019938883855*_Complex_I, -0.000682229297 + -0.011460511608*_Complex_I, -0.022518239866 + -0.037363417124*_Complex_I, -0.007962730587 + 0.007463843703*_Complex_I, -0.020202765636 + -0.034000570007*_Complex_I, -0.013134852636 + -0.025359042386*_Complex_I, 0.005789769049 + -0.019359516099*_Complex_I, -0.007477326398 + -0.017065274446*_Complex_I, 0.007535152908 + 0.014947146624*_Complex_I, 0.008478526310 + -0.033064163294*_Complex_I, 0.006495736538 + -0.000621013504*_Complex_I, -0.018881009743 + -0.042515704819*_Complex_I, 0.003959382518 + -0.023006182258*_Complex_I, -0.005478138646 + -0.022439956712*_Complex_I, 0.012649989781 + -0.011810626415*_Complex_I, -0.016784136514 + -0.039783192634*_Complex_I, -0.052016102486 + -0.007841932680*_Complex_I, 0.059471950363 + -0.013592303981*_Complex_I, 0.013914799172 + 0.044984722860*_Complex_I, 0.011486842937 + -0.061671443344*_Complex_I, -0.036780337271 + -0.003311742125*_Complex_I, -0.006092641235 + 0.007927763608*_Complex_I, 0.007902421446 + -0.001011649739*_Complex_I, -0.006795769455 + 0.008805976503*_Complex_I, 0.023605170020 + -0.038943989870*_Complex_I, 0.023625556066 + -0.009183727558*_Complex_I, 0.013693690762 + -0.003169361400*_Complex_I, 0.029827583427 + -0.013202113602*_Complex_I, 0.005499368566 + 0.025768234920*_Complex_I, 0.020555898301 + -0.006579736075*_Complex_I, -0.018397046470 + 0.008180231852*_Complex_I, -0.000311933642 + -0.045290959470*_Complex_I, -0.009854739488 + 0.094914113403*_Complex_I, -0.001041015584 + -0.010428696751*_Complex_I, -0.019479887241 + 0.038746806007*_Complex_I, 0.003949972577 + -0.023915676515*_Complex_I, -0.005952904345 + 0.028280800121*_Complex_I, -0.020794732314 + 0.049370817714*_Complex_I, -0.013758601114 + -0.029866172207*_Complex_I, -0.018665194668 + -0.036784877494*_Complex_I, 0.027598854453 + -0.029032203867*_Complex_I, 0.020417636582 + 0.032869611698*_Complex_I, -0.038033374173 + -0.047062159994*_Complex_I, -0.002307491697 + 0.016775992609*_Complex_I, 0.002741426303 + 0.000401399904*_Complex_I, 0.047873297365 + 0.035012972663*_Complex_I, -0.002960979438 + -0.003970085476*_Complex_I, -0.013174401910 + -0.001911987889*_Complex_I, -0.015764753015 + 0.009609419552*_Complex_I, 0.030869778703 + 0.004752229880*_Complex_I, -0.007925303167 + 0.018384260100*_Complex_I, -0.036144266243 + -0.012421792859*_Complex_I, -0.021583982780 + 0.005519018931*_Complex_I, 0.011692092106 + -0.008831839761*_Complex_I, -0.019409391330 + -0.038426827460*_Complex_I, 0.006223391109 + 0.046989172728*_Complex_I, 0.018999067344 + -0.023638921178*_Complex_I, -0.026744966281 + 0.035209035395*_Complex_I, -0.005797132267 + -0.030721098320*_Complex_I, -0.012007029920 + 0.052541286005*_Complex_I, -0.040002533893 + 0.015828735411*_Complex_I, 0.007259346684 + 0.002315325843*_Complex_I, -0.022414689402 + -0.003834870337*_Complex_I, -0.024299572844 + -0.033955598422*_Complex_I, -0.045734353675 + -0.001347407015*_Complex_I, -0.030146751771 + 0.053501404395*_Complex_I, 0.020367548034 + 0.003025664117*_Complex_I, -0.006737275010 + -0.018512929694*_Complex_I, -0.000605709571 + -0.012347963683*_Complex_I, -0.006890463622 + 0.046621939143*_Complex_I, 0.016047502033 + -0.019923449202*_Complex_I, -0.008396903768 + 0.010041927047*_Complex_I, 0.047436458062 + 0.003595322623*_Complex_I, -0.037015474086 + 0.041649052012*_Complex_I, 0.007016220323 + -0.036370210637*_Complex_I, -0.012617538063 + 0.002683467470*_Complex_I, 0.051168439092 + -0.028397908806*_Complex_I, 0.035205638612 + -0.001881106820*_Complex_I, 0.021551345104 + -0.005936731955*_Complex_I, 0.020923031070 + 0.002729234686*_Complex_I, 0.024976448430 + 0.011252084504*_Complex_I, 0.045876193259 + -0.003769034340*_Complex_I, 0.058950819572 + 0.017386610345*_Complex_I, 0.017620108715 + -0.032126491912*_Complex_I, 0.040499252854 + -0.028610567370*_Complex_I, 0.047208712591 + 0.014810229612*_Complex_I, 0.027499183980 + -0.028800252172*_Complex_I, -0.012932302613 + -0.018166904753*_Complex_I, 0.016403288642 + -0.020622110742*_Complex_I, 0.022373704021 + -0.028689811011*_Complex_I, -0.009452243729 + -0.008680644929*_Complex_I, -0.058678992249 + -0.051174770891*_Complex_I, -0.005006438141 + -0.031267299630*_Complex_I, -0.015215097299 + -0.020119691971*_Complex_I, 0.066084164099 + 0.016564502968*_Complex_I, -0.013768201897 + -0.023474209345*_Complex_I, -0.021803271593 + -0.062476214596*_Complex_I, 0.028932477041 + -0.022490403547*_Complex_I, 0.040341712936 + 0.006962852165*_Complex_I, 0.015330216728 + -0.030617975708*_Complex_I, -0.015573978799 + -0.015495893724*_Complex_I, -0.042595498240 + 0.029811952687*_Complex_I, -0.007383005008 + 0.050473873697*_Complex_I, -0.007960910417 + -0.029841422966*_Complex_I, -0.022273885029 + -0.003249632656*_Complex_I, -0.002824822559 + 0.003348401440*_Complex_I, -0.024087272328 + 0.065990131062*_Complex_I, -0.028057881818 + -0.029151797322*_Complex_I, -0.024558131583 + -0.015268822223*_Complex_I, 0.039877624209 + -0.013405850916*_Complex_I, 0.028823486535 + 0.037004255305*_Complex_I, -0.023970193031 + -0.005435181200*_Complex_I, -0.088636699560 + -0.013757698161*_Complex_I, 0.008098637338 + 0.006870343753*_Complex_I, 0.054927003829 + 0.056475265541*_Complex_I, -0.024306265176 + 0.034672928541*_Complex_I, -0.021853531429 + 0.018230890552*_Complex_I, -0.021682656382 + -0.032466179919*_Complex_I, 0.019989585378 + 0.020908798620*_Complex_I, 0.019423343509 + -0.002219973236*_Complex_I, -0.021632746497 + -0.006294932050*_Complex_I, 0.013621743308 + -0.025286913038*_Complex_I, -0.020772874190 + -0.012989704190*_Complex_I, 0.025482399527 + -0.014215236725*_Complex_I, -0.044300771406 + -0.017049381631*_Complex_I, -0.006816700080 + -0.032915524093*_Complex_I, 0.057073619573 + -0.013791458776*_Complex_I, 0.023935306468 + 0.010113795207*_Complex_I, -0.010074654341 + -0.020758506394*_Complex_I, 0.014148879115 + 0.005089223239*_Complex_I, 0.035479315734 + -0.053250867185*_Complex_I, 0.068075559099 + -0.000004138871*_Complex_I, -0.049122106052 + -0.026433363499*_Complex_I, 0.023522704576 + 0.028855355307*_Complex_I, 0.002677137744 + 0.051086576447*_Complex_I, 0.002630815479 + -0.030154181511*_Complex_I, -0.021284842311 + 0.018492273061*_Complex_I, -0.014785053010 + -0.025361228004*_Complex_I, 0.015700956081 + -0.004007983078*_Complex_I, -0.076870199719 + -0.004459394713*_Complex_I, 0.013883703469 + -0.003931123862*_Complex_I, 0.016113428385 + 0.014312499105*_Complex_I, -0.025629511396 + -0.029198167224*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/fftfilt_rrrf_data_h13x256.c000066400000000000000000000270471317124540100246540ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fftfilt_rrrf_data_h13x256.c: autotest fftfilt data // float fftfilt_rrrf_data_h13x256_h[] = { -0.039212104678, -0.045289030671, -0.184304034710, 0.077858728170, 0.040869677067, 0.142814588547, -0.108285641670, 0.089570593834, -0.172709572315, 0.001841047592, 0.074960124493, -0.114357507229, 0.043473127484}; float fftfilt_rrrf_data_h13x256_x[] = { 0.122770094872, 0.089148938656, 0.017954966426, -0.028631305695, -0.024217808247, -0.019191932678, 0.124998247623, -0.010905320942, -0.182813262939, 0.022872561216, -0.167512893677, 0.004144698754, -0.091696554422, 0.145599734783, 0.149157440662, 0.111943149567, -0.083463251591, 0.074205029011, 0.057325953245, 0.098762345314, -0.056830596924, 0.129721879959, 0.070393782854, 0.044613954425, -0.041217750311, -0.047065210342, 0.042085236311, 0.065604847670, 0.011089600623, 0.055663853884, 0.010694834590, -0.107917737961, 0.091816771030, -0.071010309458, 0.225902843475, -0.193409955502, 0.134397053719, 0.006444688141, -0.100715303421, 0.013986042142, 0.037019279599, -0.018146976829, 0.038268235326, 0.124087500572, -0.065513682365, 0.243372726440, 0.070982813835, -0.114888060093, 0.083260691166, 0.078598594666, 0.119385373592, 0.124578750134, 0.229874610901, 0.068851232529, -0.152908086777, 0.022878190875, -0.038320010900, -0.019077518582, -0.187935698032, 0.000150304066, 0.107031500340, -0.054503691196, -0.189286994934, 0.106510078907, 0.016531120241, -0.062976771593, -0.034572181106, 0.116243016720, 0.014939060807, -0.104378926754, 0.035551485419, -0.211227297783, 0.056110930443, -0.069913518429, 0.050586497784, 0.100069129467, 0.307702898979, 0.186338675022, 0.197983598709, 0.070847284794, -0.168327832222, -0.115514957905, -0.069601941109, 0.079878026247, 0.015964616835, 0.128264808655, 0.015298053622, 0.210790205002, 0.040280216932, 0.091706073284, 0.090860366821, -0.034307426214, -0.043785154819, 0.100965428352, 0.062400549650, 0.122274744511, -0.063038861752, -0.173100697994, -0.167581903934, 0.088559448719, -0.130531704426, -0.021028609574, 0.060926514864, 0.078577047586, 0.197759902477, 0.019897483289, -0.015052948892, -0.156514930725, 0.121016633511, 0.080825585127, 0.026895985007, -0.032256072760, -0.033008736372, 0.101098561287, -0.004690715298, -0.097240817547, 0.124587404728, -0.080275380611, -0.170625138283, 0.064333653450, -0.082882106304, 0.055449581146, 0.036299997568, -0.036278706789, 0.075224477053, 0.005092585459, 0.031370615959, 0.020764264464, 0.049643722177, 0.021591423452, -0.040642136335, 0.027282950282, 0.134740507603, -0.029146528244, 0.034743618965, -0.014017164707, -0.070363909006, 0.020523373783, 0.000458177784, -0.068270605803, 0.180056059361, -0.119201040268, -0.046510973573, -0.058247959614, 0.155885064602, -0.083602911234, -0.119938647747, -0.114219510555, 0.161393058300, 0.232402944565, -0.151511478424, 0.066477537155, -0.115181660652, -0.164413774014, 0.031050026417, -0.038917222619, 0.093678462505, -0.040763008595, -0.004956462234, 0.044149956107, 0.113123583794, -0.092754375935, -0.027752390504, 0.137882554531, 0.035738137364, -0.051311886311, 0.134906625748, 0.123595929146, 0.159623205662, 0.014216412604, -0.078501766920, -0.046537932754, 0.066755509377, -0.061657583714, 0.008335828036, 0.009980520606, 0.106155145168, -0.010150838643, -0.012183431536, 0.101287877560, 0.024197725952, -0.060843515396, -0.240097737312, 0.065998744965, -0.050199592113, -0.055537813902, 0.165046787262, 0.133701193333, -0.018093936145, -0.113999474049, -0.069255769253, -0.081180727482, 0.070946794748, 0.136880230904, 0.025476306677, -0.102032244205, -0.024109381437, -0.016868881881, 0.167234003544, 0.171832489967, -0.030091801286, 0.011118320376, -0.008921170235, 0.101217842102, -0.048454919457, 0.151966249943, 0.198045432568, 0.040109497309, 0.016406393051, 0.089656168222, 0.035927999020, -0.033026877046, -0.054043507576, 0.211845135689, -0.036055120826, 0.160977423191, -0.197179889679, 0.040342581272, 0.150020170212, -0.073872137070, -0.164493560791, 0.124404942989, 0.031155037880, -0.061415308714, 0.000370543310, -0.019733832777, 0.089461517334, 0.229397058487, 0.149904847145, -0.119740092754, -0.233863234520, -0.029367747903, 0.070431739092, 0.001778364740, 0.166927957535, -0.018398888409, -0.102967965603, 0.006021655723, 0.067407786846, -0.140168070793, 0.011420756578, 0.095064306259, 0.020388415456, -0.112541508675, -0.085077953339, 0.125045490265, 0.210480499268, -0.117026185989, -0.089133924246, 0.147170877457, 0.107982301712, 0.096577769518, -0.058198565245, 0.027206465602, 0.002091913670, -0.088938659430}; float fftfilt_rrrf_data_h13x256_y[] = { -0.004814073811, -0.009055856107, -0.027368544867, -0.006562254910, 0.010895739671, 0.029701022061, -0.001626673446, -0.000844726806, -0.037111011029, 0.004419375864, 0.047068466895, 0.003910634431, 0.012396721813, -0.025213063245, 0.000635157075, -0.085524325904, 0.041146455184, -0.050979327116, 0.077630920989, -0.003623999480, -0.004841852073, -0.028754487596, 0.001410758665, -0.034036822601, 0.014107997579, -0.022709798205, 0.025617017445, -0.003252183639, -0.003963481395, -0.036270671993, -0.021399438537, 0.017388718079, -0.000128062767, 0.028859143315, -0.030391114442, 0.001543784470, -0.046555566322, 0.058215460338, -0.063274785430, 0.077974731120, -0.057110585904, 0.054791309007, -0.060943087255, 0.010461367165, 0.008954983539, -0.076741190112, 0.063566034944, -0.058742851449, 0.008267455413, 0.026477649501, 0.013490128892, -0.071421597975, -0.011335301312, -0.030890897000, -0.062240856218, 0.083426871968, 0.015357553814, -0.000362231866, 0.008918381045, -0.028650443960, 0.017482443006, -0.052161386060, 0.020679845153, -0.025369370715, 0.045526628268, -0.011020145844, 0.002644272584, 0.006285259524, -0.004936878581, -0.019116352540, 0.039400594243, 0.000124031921, 0.002039447415, 0.062249843178, -0.043579179266, -0.001996355335, -0.069473606074, 0.023450651628, -0.118043698351, 0.033847857380, 0.001708993883, 0.047506531454, 0.075888786942, 0.008727973204, -0.040651907871, -0.077531568445, -0.017930168448, -0.069340649806, 0.041402166708, -0.040029272550, 0.025336666274, -0.018448259990, 0.033311907821, -0.013731300546, 0.016338663490, -0.049502280186, -0.034415215410, 0.005555120775, 0.018242670176, 0.047690282789, 0.041262648570, -0.072855941506, 0.009723921419, -0.029262747157, -0.011884300184, -0.027377242282, 0.003541591160, 0.004992461263, 0.044689949294, 0.066697897821, -0.089113718326, 0.005326909592, -0.042616477087, 0.036692093307, -0.004180374377, -0.003271218876, -0.009369454837, -0.002500828958, 0.016544265383, 0.002187635659, 0.029976595593, -0.018441944452, -0.020909152277, 0.007956140844, -0.021637777770, -0.014177920945, 0.055566577829, -0.042960866797, 0.006896087167, 0.024767376727, -0.043457653016, 0.034935882911, -0.015575911379, -0.009819491182, -0.018887628248, -0.001068307187, 0.006963055931, 0.013680239410, 0.005809808354, 0.005066455307, -0.040283759818, 0.017470897286, -0.022805491441, 0.015206465884, 0.019136018024, 0.021643961761, -0.071515530177, 0.078236064221, -0.029742524131, 0.032918640371, -0.053023950617, -0.047312921105, 0.034250312751, 0.032284357688, 0.068808863735, -0.015296681918, 0.000837419600, -0.075314366704, 0.024501519621, 0.005869076899, -0.039416548615, 0.069295643723, -0.060264925779, 0.046170239698, -0.002067325538, -0.026442474538, -0.007890011691, 0.000037015562, -0.035959976850, -0.016139843757, -0.002858263222, 0.006428619035, 0.027561864469, 0.042341971465, -0.058543104834, -0.007599628510, -0.014902259564, -0.011133330016, -0.020432058943, 0.017048024915, -0.016928345566, 0.012963663673, 0.008408004748, 0.018403366116, 0.046619907266, -0.038433448340, 0.007648025051, -0.059208853553, -0.011295552139, -0.025495843506, 0.062840766336, 0.041709165483, -0.000905313483, 0.033310202711, -0.082126428402, -0.037682258830, 0.020034347469, 0.049244781989, -0.001378192350, -0.008849598752, -0.050136739148, -0.035155204482, 0.024111310154, 0.038903294513, -0.003167046710, -0.032326890373, 0.004090324360, -0.075671618163, 0.006238782693, -0.017653047474, 0.025665426828, -0.012204527876, 0.007845325954, 0.005183653849, -0.034222431570, -0.037618568932, 0.013395877564, -0.045882750561, 0.072052386700, -0.040677327938, 0.025524603777, -0.058679392496, 0.073277528966, -0.045606738121, -0.018120414293, 0.035599866018, -0.037821283601, 0.009959320327, -0.008944663864, -0.071448196749, -0.002389984851, 0.105394267739, 0.040560858684, -0.015716980196, -0.051319091715, -0.053534618918, -0.028961761656, 0.040242569747, 0.040510770959, 0.011016182224, -0.040345662543, 0.048481523965, -0.035361728505, -0.024831493953, 0.018886824467, 0.026390411027, -0.016368948643, -0.009813816544, -0.035846470146, 0.008843767444, 0.038479236659, -0.019424751909, -0.036842320539, -0.011401190478, 0.012789717510, 0.024104726420}; liquid-dsp-1.3.1/src/filter/tests/data/fftfilt_rrrf_data_h23x256.c000066400000000000000000000273571317124540100246610ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fftfilt_rrrf_data_h23x256.c: autotest fftfilt data // float fftfilt_rrrf_data_h23x256_h[] = { -0.118176388741, -0.025418123603, -0.059258782864, 0.142066907883, 0.004454790801, -0.016711865366, 0.005629793927, -0.123983550072, 0.173112368584, -0.160880231857, 0.054240733385, -0.031276765466, 0.154612803459, -0.006389370561, 0.079528987408, -0.002910712734, -0.159243178368, 0.022829471529, -0.113626921177, -0.095083606243, -0.122057342529, 0.104624044895, 0.011057048291}; float fftfilt_rrrf_data_h23x256_x[] = { 0.059350812435, -0.000424881605, -0.049009537697, -0.034536927938, 0.103308689594, -0.055876135826, -0.148367643356, -0.111977064610, 0.067770421505, 0.043956550956, 0.143173515797, 0.004022727162, 0.111428678036, 0.028413870931, 0.166605424881, 0.038992109895, -0.010133068264, 0.076038408279, 0.105890285969, 0.147610998154, -0.047342804074, 0.055655419827, -0.013745918870, -0.016829429567, -0.062561410666, 0.095859551430, 0.019820876420, 0.037723916769, 0.054752278328, 0.057050412893, 0.207521724701, -0.130268049240, 0.165039086342, -0.194032716751, 0.189072954655, -0.137876522541, 0.047114580870, -0.072617882490, -0.100785088539, 0.064732289314, -0.073995077610, 0.019561932981, 0.046311601996, -0.104536223412, -0.033436897397, 0.151995897293, 0.031935700774, -0.028941801190, 0.078559994698, -0.047812539339, 0.130064833164, -0.056572306156, -0.042208436131, 0.085643953085, -0.080961161852, 0.057486045361, 0.020754659176, 0.070619314909, 0.158251059055, 0.088375788927, -0.043805596232, 0.127501475811, 0.115190374851, -0.044433131814, 0.034547865391, -0.044843772054, -0.062454062700, 0.030952209234, 0.040272334218, -0.046460473537, 0.054621320963, -0.026183435321, -0.025449073315, 0.053822481632, 0.173386669159, 0.039320838451, 0.080104076862, -0.057773065567, -0.145702457428, -0.104137754440, 0.001670002751, -0.015087755024, 0.030506807566, 0.050601142645, -0.168711090088, 0.072758728266, -0.085856407881, 0.036477252841, 0.033204284310, -0.074460619688, -0.132449066639, -0.005033437908, 0.051431566477, -0.000122980447, 0.104783654213, 0.086071228981, 0.087956553698, 0.018256981671, 0.273954725266, -0.047239318490, 0.061503499746, 0.006188166887, -0.009299278259, 0.085814112425, 0.131504595280, -0.038905382156, -0.043368801475, 0.201532816887, 0.094288158417, 0.092639130354, 0.049885711074, -0.063641804457, -0.134385573864, -0.129504549503, 0.116876983643, 0.034869593382, 0.110995888710, 0.209363675117, 0.089506244659, 0.032240226865, -0.035387760401, -0.011358998716, -0.217154717445, -0.075535118580, 0.154909908772, 0.035121211410, -0.009927383065, -0.017504146695, -0.041967305541, 0.001003832649, 0.014955335855, 0.081758105755, 0.026359021664, -0.056244474649, -0.145741295815, 0.020014302433, 0.017129588127, -0.074675554037, -0.048099777102, 0.079832047224, 0.177468204498, -0.064336484671, 0.007799343765, 0.058800733089, -0.015487244725, 0.040828344226, -0.009191709757, 0.097432601452, -0.064271640778, 0.010111794621, -0.088703465462, 0.031145793200, 0.060152173042, -0.041082245111, 0.033332934976, -0.040413409472, 0.004355887696, 0.058080500364, 0.014798428118, -0.067486256361, -0.059195333719, -0.058406758308, -0.032816353440, -0.179800736904, -0.068667584658, -0.086956882477, 0.275450372696, 0.033261230588, -0.055281239748, 0.144350075722, -0.202899336815, -0.041189083457, 0.045112118125, -0.064310503006, 0.123022067547, 0.007392913103, 0.059860253334, -0.088910865784, 0.246307659149, 0.136940467358, 0.148684620857, -0.067826855183, 0.044850471616, 0.021945165098, -0.050006192923, -0.015575663745, -0.011492988467, -0.215618276596, 0.015057675540, -0.014546294510, -0.091270244122, -0.014081606269, -0.005267200246, 0.008527950943, 0.084022140503, 0.050226074457, -0.086916053295, 0.009611618519, 0.078965556622, -0.269776344299, 0.251430296898, -0.083879828453, 0.058131092787, 0.093344569206, -0.009404690564, -0.180945825577, 0.026505178213, 0.178118884563, -0.036366626620, 0.119481074810, -0.046089172363, 0.012725484371, 0.105508100986, 0.139382028580, -0.145310318470, 0.066300112009, -0.155467641354, -0.186421251297, 0.136932229996, 0.091225856543, -0.057187086344, 0.073608285189, 0.008684530854, -0.131529307365, -0.020294201374, 0.129804944992, 0.146946787834, -0.069120013714, -0.056884109974, -0.069945359230, -0.075904464722, 0.096382999420, -0.052887690067, -0.023378646374, -0.020363801718, 0.052989178896, 0.097394061089, -0.095514106750, 0.114465987682, 0.149921727180, -0.145940053463, 0.116530537605, -0.002146193571, -0.033402639627, 0.088303333521, 0.014771881700, 0.033233019710, -0.034135624766, -0.053486305475, 0.064908540249, 0.001977766119, 0.061249178648, -0.045406821370, 0.009912858903, 0.121469497681, 0.103848683834}; float fftfilt_rrrf_data_h23x256_y[] = { -0.007013864682, -0.001458375313, 0.002285512965, 0.013784144279, -0.008222504569, -0.001932445802, 0.008048223230, 0.028296439689, 0.006779838852, -0.027075112618, -0.038021355416, -0.008207405447, 0.022727377225, 0.003661135507, -0.025140469834, -0.012236287908, 0.016448242015, -0.022041432338, 0.003765875876, -0.086743626880, 0.008804356573, -0.012282203678, 0.096545010469, -0.016051310432, 0.025673500424, 0.031954762710, 0.010291226924, -0.004617541860, -0.078915357449, 0.016347541321, -0.078243227224, 0.053416005824, -0.073942376885, 0.075168320113, -0.105443090203, 0.032685403487, -0.054354778278, -0.017947992570, 0.028325854650, -0.066017207222, 0.127152882603, -0.129786378633, 0.153392128443, -0.101101386787, 0.089515971822, -0.098153948006, -0.018623281322, -0.007210919422, -0.052842605245, 0.032639231668, -0.084346314422, 0.075150470719, -0.077797755022, 0.090483672403, -0.028648123276, -0.018159951111, 0.048359402647, -0.037666024522, 0.028960325781, -0.033371992052, 0.026921999056, -0.009095421681, -0.003055504078, 0.008517976100, -0.047205023338, 0.015219099504, -0.029899324803, 0.037376834246, -0.058818185973, 0.016202491134, 0.027713179518, 0.010360717592, 0.018872350014, -0.007238271158, -0.026777182477, -0.042586692131, -0.005396798853, -0.053278897967, 0.003600267191, 0.021901335336, -0.013091061698, -0.047316523688, 0.018443222297, -0.025150770998, 0.036826636675, 0.013809067598, 0.036530318086, -0.025825991720, 0.047029879857, -0.018694842890, -0.024991556586, 0.021396439314, -0.100068124600, 0.002032355704, -0.058647750333, 0.054049505689, -0.025341189676, 0.067615154602, -0.044899284658, 0.021135756051, -0.004151297683, -0.010694122753, 0.009371387806, -0.029794165824, 0.013390817044, -0.059682815079, 0.111820810826, -0.059861745262, 0.045667041385, -0.016011228532, 0.043233291738, -0.024093786781, 0.036936965515, -0.007311481950, -0.104248864495, 0.022282329467, -0.092586037340, -0.017084241199, -0.042839250540, 0.036605764530, 0.013232172340, 0.027382131751, 0.061010646729, -0.075041791947, -0.032923246322, -0.064505588738, -0.062494604045, -0.014118814560, 0.041292311729, 0.082239901043, -0.005253566244, 0.046726579388, 0.010585548464, -0.055116829572, -0.057026861265, -0.032618339372, -0.034378961584, -0.034963708479, 0.058675519175, 0.029871506017, -0.031900560694, 0.023355935441, -0.001213445200, 0.026491853482, -0.027623272659, -0.003191991347, -0.004121011628, -0.029001573940, 0.026187127755, -0.056189942809, 0.041920449009, -0.012905850771, 0.030518693114, 0.033991468359, 0.003919996873, 0.023741085525, -0.055324780487, 0.059796004556, -0.070732526849, 0.002634444280, 0.006125322170, 0.020783019394, -0.008248981557, -0.019686458368, 0.030194556929, -0.000581311209, -0.020507462528, -0.044154988493, 0.008251496795, 0.032183839802, 0.053024468712, -0.042724151114, 0.042587433931, -0.075197608106, 0.019796200862, -0.044058022099, -0.054716564872, 0.056900772003, -0.025187522741, 0.065664264024, -0.010713761704, 0.060761984311, -0.016047173875, 0.028406749588, -0.011879920533, -0.118533899059, 0.071371773260, -0.012801056424, 0.063748099223, -0.029818945809, 0.059673780884, 0.002981467618, 0.014900750827, 0.005863349123, -0.039271388965, -0.047804844624, -0.005476117492, -0.002941660427, -0.084269578445, -0.007723144927, -0.019565778540, 0.026971812744, -0.069210853637, 0.071362335146, -0.034155620576, 0.049871029844, 0.102419559566, -0.067458257439, 0.053173633928, -0.083831072696, 0.070644801531, -0.073425276208, 0.065129431849, -0.109383680801, 0.028592225091, 0.086994019490, -0.034044742467, 0.053289338054, -0.050965593897, 0.008752040612, -0.097246591796, 0.115066726542, -0.074721917181, 0.057622211485, 0.035793970560, -0.018555134605, -0.047793260188, -0.023063158221, -0.035765778569, 0.000988835923, 0.043336509870, -0.077241994534, 0.019293408578, 0.033162609969, 0.051320440605, -0.043008262694, 0.032451189832, -0.017267827022, -0.043257260696, 0.050857662915, -0.017938260516, -0.027199631897, 0.002448747593, 0.004648939335, -0.022984164695, -0.052488307553, 0.014620583398, 0.060946098284, -0.005975541627, 0.036790785823, -0.003976400632, -0.031985970920, 0.020296749161, 0.022385014193, -0.041326326661, -0.052361612870}; liquid-dsp-1.3.1/src/filter/tests/data/fftfilt_rrrf_data_h4x256.c000066400000000000000000000265571317124540100246010ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fftfilt_rrrf_data_h4x256.c: autotest fftfilt data // float fftfilt_rrrf_data_h4x256_h[] = { -0.103940248489, -0.125938880444, 0.019687046111, 0.038741669059}; float fftfilt_rrrf_data_h4x256_x[] = { -0.059766334295, -0.066150742769, -0.115301787853, 0.034305834770, -0.116833734512, 0.037061965466, -0.058715832233, 0.103076207638, 0.134518480301, 0.079880267382, 0.012277089804, 0.043612530828, 0.034223002195, 0.113585817814, 0.069119685888, -0.130585312843, -0.169095098972, 0.012008042634, -0.133639252186, 0.173219811916, -0.083090245724, 0.129079174995, 0.023044827580, 0.088738435507, 0.102692329884, 0.009038489312, 0.159331941605, 0.072815608978, 0.078159433603, 0.087989467382, -0.150272154808, 0.144541347027, 0.013840167224, 0.008892998844, 0.118263459206, 0.026517456770, -0.071624934673, -0.036617729068, -0.005045709386, -0.113883030415, -0.208834385872, 0.086749321222, -0.013728235662, 0.043468075991, -0.096142125130, 0.020740854740, -0.034397336841, 0.085756975412, 0.007817015052, 0.026385569572, 0.146892285347, -0.156527042389, 0.141406416893, -0.023495438695, 0.049500951171, -0.035764679313, 0.071550452709, -0.003587320819, -0.186498534679, -0.080298507214, 0.134777379036, -0.081320983171, 0.001440288033, -0.026431754231, 0.076391905546, -0.008682205528, -0.218401527405, -0.006006127596, -0.150505733490, 0.031596601009, -0.030527853966, 0.192572534084, -0.008412856609, 0.041643416882, -0.028573197126, 0.172620558739, 0.092417323589, 0.038117933273, -0.115529227257, -0.017371174693, -0.128486943245, 0.049849176407, 0.064552265406, 0.094295257330, 0.016759039462, 0.093557018042, 0.020290662348, 0.005136798322, 0.054379999638, -0.015200743079, 0.015589100122, 0.080561774969, -0.027493861318, -0.097876155376, -0.090297585726, 0.048021733761, 0.026696670055, -0.154493343830, 0.041202291846, -0.082294452190, -0.036641538143, -0.046914353967, 0.022663275898, -0.076259374619, -0.156308090687, -0.068274164200, -0.126401603222, -0.200392508507, 0.018104647100, -0.017743445933, -0.141112804413, -0.159551227093, 0.075381636620, -0.220814013481, 0.038408300281, -0.004995152354, 0.010078751296, 0.040657266974, 0.056239426136, 0.085060149431, 0.068754714727, 0.072872400284, 0.106947481632, -0.308546304703, -0.069674599171, -0.112623000145, -0.063631707430, 0.078959625959, -0.228999781609, -0.113809764385, 0.038127812743, -0.046605563164, -0.048587369919, -0.235435414314, -0.217472290993, 0.053750389814, -0.035415196419, -0.067825865746, -0.150451087952, 0.047033441067, 0.091101139784, -0.194262254238, -0.111800551414, -0.285789370537, -0.007608364522, -0.149913394451, -0.096925151348, -0.305913662910, -0.080984199047, -0.036364766955, 0.092257493734, 0.099389094114, -0.225461554527, -0.044632428885, -0.025108575821, -0.014164578915, 0.001609388553, 0.104212951660, 0.016141586006, 0.131583070755, -0.175425446033, -0.006701639295, -0.114346027374, -0.035700270534, 0.021623027325, -0.127881789207, 0.100705778599, 0.045099687576, -0.037036603689, -0.068620997667, 0.104958283901, -0.153554320335, 0.094572162628, -0.042882648110, -0.064524829388, 0.009822543710, 0.113274049759, 0.060883563757, -0.039188215137, 0.073277068138, -0.110787749290, 0.098354798555, 0.109893596172, -0.042616480589, -0.014896343648, -0.040605995059, 0.127049469948, 0.003995794803, -0.061846542358, 0.016790096462, 0.079767954350, 0.026320463419, 0.049973765016, -0.133794248104, -0.014496140182, -0.245779371262, 0.112647521496, -0.046020454168, -0.190287458897, 0.154702842236, -0.087878227234, -0.094459164143, -0.189534711838, -0.055773961544, 0.065852761269, -0.046472328901, 0.110529434681, 0.073642146587, 0.123039674759, 0.047418674827, -0.039671051502, -0.026384806633, 0.050780695677, 0.001590615511, -0.054047483206, -0.081048285961, -0.063029623032, -0.083545958996, 0.075329506397, -0.047838664055, 0.040128618479, -0.104642879963, 0.093437254429, -0.038486540318, -0.082574462891, -0.065856921673, -0.071426254511, 0.019827936590, 0.133355295658, 0.094185638428, 0.077937924862, 0.060769236088, 0.125227236748, 0.128954041004, 0.119129931927, -0.007088107616, 0.067930990458, -0.097152686119, -0.086086273193, 0.029765573144, -0.162787938118, -0.091519236565, -0.078853517771, 0.116651356220, -0.025571110845, -0.151243126392, -0.166459095478, 0.048026204109, -0.046259659529, -0.216182160378, -0.018041458726, 0.014725986123, 0.130805134773, -0.088644373417, -0.039490658045, 0.067798143625}; float fftfilt_rrrf_data_h4x256_y[] = { 0.006212127638, 0.014402629871, 0.019138824386, 0.007337460817, 0.002990547175, 0.007070076667, 0.000464349934, -0.007115853714, -0.026683285355, -0.025489364937, -0.004694499360, 0.000704816717, -0.005713266142, -0.014781907855, -0.019125815998, 0.008430239467, 0.039782821314, 0.020154501439, 0.003990141650, -0.007488755965, -0.015344438902, -0.004719450259, -0.013576348764, -0.012803601954, -0.016395058243, -0.011232627125, -0.012239715093, -0.023478145421, -0.013807285781, -0.011382649065, 0.008897756697, 0.008661723023, -0.019191481858, -0.005643557602, -0.007540062613, -0.016938930639, 0.006777922483, 0.017930194135, 0.004753295233, 0.008976717035, 0.034530632258, 0.014846123076, -0.018021547028, -0.009171918769, 0.007609260636, 0.010276125260, 0.000754459077, -0.007898019473, -0.011486286587, -0.003371297493, -0.015114727435, -0.001407692146, 0.008929118567, -0.012757146890, -0.005466396146, 0.002499060105, -0.002868533164, -0.007424468314, 0.019859520897, 0.034535023664, -0.007706674216, -0.017327293951, 0.009634239964, 0.006186465510, -0.007733563710, -0.009182844461, 0.024274056965, 0.030918145186, 0.011763964249, 0.007090882408, -0.004001868553, -0.021380192871, -0.022754833149, -0.000660437013, 0.005020336999, -0.013849839551, -0.030294705862, -0.013309506170, 0.015714639418, 0.020686016629, 0.014744994233, 0.006182383795, -0.016190044652, -0.021927128113, -0.010415294145, -0.007477696788, -0.009908390960, -0.000598168905, -0.002275175069, -0.004381364749, 0.001563619326, -0.008529370506, -0.007570139794, 0.015825789161, 0.024291791638, 0.003388535453, -0.014392240260, 0.010143054713, 0.017560162996, 0.001357491276, 0.008998423176, 0.009466994781, -0.000356873396, 0.002729071359, 0.024479354632, 0.026158390848, 0.015704925808, 0.029347970586, 0.018221877386, -0.009277966443, 0.009494776448, 0.034707471003, 0.008793011874, 0.004849946576, 0.019119662287, -0.005744666206, -0.008217061474, -0.004105571223, -0.010960970310, -0.014733014296, -0.015176443566, -0.012379874872, -0.015644666925, 0.022699848187, 0.051028649748, 0.018549762248, 0.007472224160, -0.005109901608, 0.008242283953, 0.039758674555, 0.008920758417, -0.011069992067, 0.007261079530, 0.031149863671, 0.049492477364, 0.015284004318, -0.016490747527, 0.004142934403, 0.025564996273, 0.011351639261, -0.020982038768, 0.003815714690, 0.039701414255, 0.043490014719, 0.027055742092, 0.006582535902, 0.017732605940, 0.040757274537, 0.039227876953, 0.004201243751, -0.018455474336, -0.025802710495, 0.011325024528, 0.038564368478, 0.007642577107, -0.004979021836, -0.000606857515, -0.012286211537, -0.015319298242, -0.013595634758, 0.006017503669, 0.026005288293, 0.014373290385, 0.011183095605, -0.000262218936, 0.005436096272, 0.004680511180, -0.019050348257, -0.004801965020, 0.016586221529, -0.001249242642, -0.000043659144, 0.008916431699, -0.006409851067, 0.008020215359, 0.009924877896, -0.015942421690, -0.022900282471, -0.000983801859, 0.002905926546, 0.003874104947, 0.003653855068, -0.023151268515, -0.011766095752, 0.012889310865, 0.009515094775, -0.010035978512, -0.017792313224, 0.006853203808, 0.011044491421, -0.011468398919, -0.014847133247, -0.006288183493, 0.011221483243, 0.020360164728, 0.026674050122, 0.013775768815, -0.014803599781, 0.018270084125, 0.011342883867, -0.015878125160, 0.016558982776, 0.035859750030, 0.024402777719, -0.007211526384, -0.011903993248, -0.006500113845, -0.019937993274, -0.021687601373, -0.014692296619, 0.003426871553, 0.013438867168, -0.000899212332, -0.008616954586, 0.005394918949, 0.017229501936, 0.015756032882, 0.012932176847, -0.001688896039, -0.008601197014, 0.000100074788, 0.007799442483, 0.002403379977, -0.008272542196, 0.011215225703, 0.020106749108, 0.012601329561, 0.002438821104, -0.020315669734, -0.028961114111, -0.016568981922, -0.009111140762, -0.015486083309, -0.024958681018, -0.023803066262, -0.006876114273, 0.001173115553, 0.006018669947, 0.022245884571, 0.008466878338, 0.007712934138, 0.027264733171, 0.017670238763, -0.010302467061, -0.017131074405, 0.018182248950, 0.040365038360, 0.012003618618, -0.010376624909, 0.022792508105, 0.030050872208, -0.005306666123, -0.024180933161, -0.007668779085, 0.018414117957, 0.001248916742}; liquid-dsp-1.3.1/src/filter/tests/data/fftfilt_rrrf_data_h7x256.c000066400000000000000000000266531317124540100246010ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // fftfilt_rrrf_data_h7x256.c: autotest fftfilt data // float fftfilt_rrrf_data_h7x256_h[] = { 0.140616559982, -0.011992717534, -0.003013938852, -0.011477991939, -0.112187731266, -0.093354654312, 0.074616163969}; float fftfilt_rrrf_data_h7x256_x[] = { -0.198634433746, -0.276704359055, -0.007436756045, -0.029181697965, -0.130730390549, 0.145140337944, 0.093274253607, -0.028276038170, -0.026093566418, 0.183164799213, 0.053475326300, -0.103025162220, 0.062650483847, -0.188771390915, -0.037113583088, 0.002068812773, -0.008017702401, -0.109960675240, -0.077615725994, 0.026018035412, -0.109660518169, -0.170424306393, -0.037413102388, 0.057296097279, -0.017119997740, -0.108221471310, -0.035699757934, 0.091696447134, -0.179859602451, 0.172208881378, 0.047351920605, 0.009508173168, 0.096329414845, 0.048371517658, -0.020774090290, 0.017976391315, -0.049352347851, -0.049652296305, -0.076197183132, -0.059912049770, 0.049865084887, -0.183295714855, 0.092628794909, -0.026747608185, 0.013366179168, -0.097838991880, 0.071832561493, -0.057548421621, 0.150674271584, 0.204948568344, 0.068133813143, 0.134078955650, 0.147824907303, 0.023681402206, 0.074496239424, -0.257152867317, -0.046538749337, 0.077637636662, 0.244811058044, 0.205812954903, 0.076498079300, 0.050237774849, 0.058088797331, 0.058162277937, -0.003535797447, 0.002892631851, -0.204548168182, 0.005657804012, 0.103203463554, 0.142777621746, -0.033477127552, 0.199837732315, -0.027476757765, -0.044394394755, -0.060066252947, -0.104752016068, -0.097709661722, -0.130706298351, 0.032775890827, -0.018839289248, 0.050399136543, 0.028471961617, -0.059291934967, 0.089571076632, -0.172548770905, -0.012040051073, 0.020502640307, -0.123626136780, -0.026196390390, -0.020364558697, -0.019754604995, -0.057270252705, -0.317011761665, -0.067777991295, -0.081966227293, 0.051007336378, 0.005001089722, -0.059572064877, -0.246018052101, 0.084007954597, 0.111875116825, -0.105674767494, -0.093867790699, 0.124696004391, -0.114728307724, 0.145655667782, 0.087596571445, 0.031920900941, -0.048701521754, -0.036635088921, 0.078258597851, -0.174296259880, 0.001777398773, -0.011556741595, 0.016063742340, -0.122294688225, -0.062106817961, -0.083234494925, -0.093048858643, -0.132832098007, -0.130951321125, -0.075790464878, 0.107826757431, 0.065403455496, -0.021866463125, 0.076470321417, -0.115176773071, -0.177813613415, 0.007404306531, 0.034460625052, 0.091559529305, 0.025584965944, -0.233118081093, 0.016783872247, 0.118527340889, 0.002443835139, -0.066102498770, 0.099924069643, 0.110413837433, 0.012530249357, 0.039682874084, -0.102561068535, -0.070982843637, -0.224049115181, -0.046074494720, -0.053951752186, -0.024024085701, -0.020918877423, -0.049386295676, -0.124434947968, 0.201082754135, -0.082364642620, -0.069723898172, -0.077210056782, -0.078793448210, 0.021326577663, -0.029980614781, 0.095146137476, 0.002052852511, 0.121688973904, 0.231916475296, 0.069326949120, -0.106731951237, 0.110438179970, 0.032615479827, -0.039900502563, 0.014169178903, 0.135481488705, 0.150449824333, -0.034293845296, -0.125741934776, 0.137323367596, -0.073314142227, -0.256729173660, -0.066909456253, -0.035936996341, -0.142958796024, -0.140863418579, -0.085215097666, -0.066673463583, 0.035038682818, -0.087599039078, -0.024130514264, 0.142523336411, 0.051653099060, 0.186094677448, -0.169976019859, 0.064971995354, 0.007105557621, -0.083290928602, -0.028115510941, -0.012801435590, -0.001878900640, -0.234911966324, -0.035020393133, 0.021636278927, 0.075562286377, 0.018644069135, -0.081580567360, -0.153186178207, 0.046364918351, -0.053498959541, -0.063731038570, -0.168667137623, -0.226871848106, 0.215677857399, 0.166028416157, -0.072063165903, -0.145152175426, 0.010212332010, -0.216380715370, -0.124420678616, 0.041640162468, -0.019694516063, -0.128491973877, -0.063744425774, 0.036548280716, -0.048697099090, 0.177138936520, 0.101957058907, 0.200418853760, -0.044115161896, -0.081440508366, 0.134256255627, 0.034881916642, -0.016943645477, 0.056465440989, -0.041392689943, 0.020602276921, 0.080228483677, 0.113952696323, 0.142240214348, 0.065034645796, 0.036655876040, -0.010240229964, 0.075093430281, 0.116919255257, -0.045885655284, -0.016456852853, -0.016743476689, 0.059479594231, -0.071723133326, 0.004458283633, 0.177911329269, -0.114906835556, -0.055673146248, -0.121907567978, 0.113892269135, -0.031124478579, 0.026398393512, 0.121518325806, -0.129203355312, 0.013991312683, -0.047266671062, -0.165797197819, 0.099366217852}; float fftfilt_rrrf_data_h7x256_y[] = { -0.027931290767, -0.036527048446, 0.002871378203, -0.000900348620, 0.007449880861, 0.071736541733, 0.023948851395, -0.020710146276, 0.011558567506, 0.018827456694, -0.028042283949, -0.010086450022, 0.020308556524, -0.047821747894, -0.027006769038, 0.020818889038, 0.007705728630, -0.007304606298, 0.016866205381, -0.005839934759, -0.016298973644, -0.008597800781, 0.015189446945, 0.006399836981, 0.003056670822, 0.016542526688, 0.007596592949, -0.001806787749, -0.031260991935, 0.044520387756, 0.016913430809, -0.012715020434, 0.020266125790, 0.009387467377, -0.038709991484, 0.008887802636, -0.015809331270, -0.019915827876, -0.005174084562, -0.003262775658, 0.010838392511, -0.013798289642, 0.025261915119, 0.005237958158, -0.001661751700, -0.003462670878, 0.021981362166, -0.028135663622, 0.030693053673, 0.034093858112, 0.009401595589, 0.008139424059, 0.010449388245, -0.040981872086, -0.007327036366, -0.044931617778, -0.027973650948, 0.004942790683, 0.037047060381, 0.049966777634, 0.041445787750, -0.020836545762, -0.033212295434, -0.033698438557, -0.011475301474, 0.002186574921, -0.034953267018, -0.004918868576, 0.014328874613, 0.025515369387, 0.015618207275, 0.045563709091, -0.035167131438, -0.031361372075, -0.011997409010, -0.022200908255, -0.029863902791, 0.006254205122, 0.016506100233, 0.012520079323, 0.024973348930, 0.019048886905, -0.007380278502, 0.001942907036, -0.026935332102, -0.008518025534, 0.010273786799, -0.018002092298, 0.004447210446, 0.021730271212, -0.015086741356, 0.003602761453, -0.027587176784, -0.009823822714, -0.006937488555, 0.018748089942, 0.040553778014, 0.025275375143, -0.042611521568, 0.011757676443, 0.004710422831, -0.003608358999, 0.020301233199, 0.026791678092, -0.054882770430, 0.030238791621, 0.038228983560, -0.008795472799, -0.014940802385, -0.001995096866, -0.020761276696, -0.025668476061, 0.011544716840, 0.009019018042, -0.004600880195, -0.007860348130, 0.014728952731, -0.022649831750, -0.011085775543, -0.005240739986, 0.003997918140, -0.001607881215, 0.031565581702, 0.027013196139, 0.016834464421, 0.020396729202, -0.032590176622, -0.046660538625, 0.007036097494, 0.004957313420, 0.018631105443, 0.038717489292, -0.026583582426, -0.013797276939, 0.003938127652, -0.007299187180, 0.020722040319, 0.035264671435, -0.017759711601, -0.009191541583, 0.019981890768, -0.021059713833, -0.035662571010, -0.035057540677, 0.000216222158, 0.003192531187, 0.020478284609, 0.022147450700, 0.014786561310, -0.022930234264, 0.034450785115, -0.012487537726, -0.002293520691, 0.004929010876, -0.023625633332, -0.013839752803, 0.027167472950, 0.023604122988, 0.009838224295, 0.016346254731, 0.025546898715, 0.000292790611, -0.029285103586, 0.007194347038, -0.034437467230, -0.025457756182, 0.023911766892, 0.021373937942, -0.001986685444, 0.002474461915, -0.014709692341, -0.000304917342, -0.039652662083, -0.034280490433, 0.020849251951, -0.008861922819, -0.030500204522, 0.028675656081, 0.016552898220, -0.015166145728, 0.022000859239, 0.014908498909, 0.010360380914, 0.025116858815, 0.002567172058, 0.026977540816, -0.014425407319, -0.010252117168, -0.022304314803, -0.025107189270, 0.001828790258, 0.021171226565, -0.018615482629, -0.019119842628, 0.009505383997, 0.002038013339, 0.012475689592, 0.027626671729, 0.013547534561, -0.038171874263, -0.004721419960, -0.014212116960, 0.006348483281, 0.002868666481, -0.026061180698, 0.024531926129, 0.038983308893, 0.010709672428, 0.013920220038, -0.014113848161, -0.084973755410, -0.004587206797, 0.043282508352, 0.006617714415, -0.004038115641, 0.027079484275, -0.002684682004, -0.016580593774, 0.045475009133, 0.029616879939, 0.019247518497, -0.013652480208, -0.025296757973, -0.013920765792, -0.014738586605, -0.008423961018, 0.034706519850, -0.017597737374, -0.019105819963, 0.019173187919, 0.013324282832, 0.016264621044, 0.011940905269, -0.011374704130, -0.022444725917, -0.010784037503, 0.003078174417, -0.007533459622, -0.000398654282, -0.008094217007, -0.011750423046, -0.010723392199, 0.016353940211, 0.024488199896, -0.023819390187, -0.005793482451, -0.007536630407, -0.006763537688, -0.008121110474, 0.035389300910, 0.025857426716, -0.024898575974, -0.013389203604, 0.000622597391, -0.039725817044, 0.021063238241}; liquid-dsp-1.3.1/src/filter/tests/data/firdecim_cccf_data_M2h4x20.c000066400000000000000000000057721317124540100247500ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firdecim_cccf_data_M2h4x20.c: autotest firdecim data // #include float complex firdecim_cccf_data_M2h4x20_h[] = { -0.010020822840 + 0.161896349165*_Complex_I, -0.160666600378 + -0.002813281324*_Complex_I, 0.074990149666 + -0.043630565869*_Complex_I, -0.147489652317 + -0.117556939153*_Complex_I}; float complex firdecim_cccf_data_M2h4x20_x[] = { -0.062219283216 + 0.083707729807*_Complex_I, 0.142772365864 + -0.155087351763*_Complex_I, -0.035707773590 + -0.015572103950*_Complex_I, 0.031591519635 + -0.047093660211*_Complex_I, -0.037688362501 + -0.218679837029*_Complex_I, -0.138226220905 + 0.033491576346*_Complex_I, 0.021866054096 + -0.113640931250*_Complex_I, 0.067925963478 + 0.054442249893*_Complex_I, 0.057780733571 + -0.143139771263*_Complex_I, -0.066200531759 + -0.072426438814*_Complex_I, -0.024130609496 + -0.023984088453*_Complex_I, 0.021066337898 + 0.123433455812*_Complex_I, 0.036017867444 + 0.011208051823*_Complex_I, 0.151336512188 + -0.046531046794*_Complex_I, -0.073914188474 + -0.026770749988*_Complex_I, -0.035715003742 + -0.020256147810*_Complex_I, -0.126178961558 + 0.049437469177*_Complex_I, -0.105599807940 + -0.032488566671*_Complex_I, 0.008377427496 + -0.015424316799*_Complex_I, -0.115074264949 + 0.025508983239*_Complex_I}; float complex firdecim_cccf_data_M2h4x20_y[] = { -0.012928487438 + -0.010911895131*_Complex_I, -0.021509784691 + 0.027882703574*_Complex_I, -0.012073246090 + 0.010047339289*_Complex_I, 0.017918504479 + -0.011835742405*_Complex_I, 0.032840148626 + 0.003684533788*_Complex_I, 0.009026607516 + -0.021113482694*_Complex_I, -0.006819209614 + 0.003546692017*_Complex_I, -0.004777468860 + -0.026060577544*_Complex_I, -0.035559582789 + -0.027278788500*_Complex_I, 0.014869302818 + 0.023426450224*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/firdecim_cccf_data_M3h7x30.c000066400000000000000000000072041317124540100247450ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firdecim_cccf_data_M3h7x30.c: autotest firdecim data // #include float complex firdecim_cccf_data_M3h7x30_h[] = { -0.006640626991 + 0.118904206653*_Complex_I, -0.083146000558 + -0.275130943103*_Complex_I, 0.079550052655 + 0.061532677877*_Complex_I, 0.065868508847 + 0.151901113121*_Complex_I, 0.044201174511 + 0.012455933659*_Complex_I, 0.055782888955 + 0.071073047549*_Complex_I, -0.102933394297 + -0.076862023914*_Complex_I}; float complex firdecim_cccf_data_M3h7x30_x[] = { 0.069053975334 + -0.000060226964*_Complex_I, 0.052934817246 + 0.026246887839*_Complex_I, -0.008314557685 + 0.123860251104*_Complex_I, 0.013641467876 + -0.040765094693*_Complex_I, 0.054181459433 + 0.105277320749*_Complex_I, 0.068589348571 + -0.094171049027*_Complex_I, -0.186652190115 + -0.131382418642*_Complex_I, -0.166555782200 + 0.069458887805*_Complex_I, 0.041855583632 + -0.063553427322*_Complex_I, -0.100690278440 + -0.092501422890*_Complex_I, 0.083259362864 + -0.058212988803*_Complex_I, 0.105969639897 + -0.053978459405*_Complex_I, -0.056835014832 + -0.111112267168*_Complex_I, 0.030289623782 + -0.152387642602*_Complex_I, 0.065445845678 + -0.096149080571*_Complex_I, 0.111690055005 + -0.006676373032*_Complex_I, -0.003193339244 + -0.073652552575*_Complex_I, -0.250738405778 + 0.063945369804*_Complex_I, 0.082690418566 + 0.008257821532*_Complex_I, -0.012580995920 + -0.092904421381*_Complex_I, -0.042140374030 + -0.035352352256*_Complex_I, -0.102518977358 + -0.014894177307*_Complex_I, -0.080456903607 + -0.102303385723*_Complex_I, 0.067967690554 + -0.008961243903*_Complex_I, -0.008051789902 + -0.288191500473*_Complex_I, 0.052113077407 + 0.045119892331*_Complex_I, 0.026292838395 + -0.234398783970*_Complex_I, 0.043314256874 + 0.060501473229*_Complex_I, -0.063513872529 + -0.087941912765*_Complex_I, -0.065933510466 + 0.101592986516*_Complex_I}; float complex firdecim_cccf_data_M3h7x30_y[] = { -0.000451400453 + 0.008211208098*_Complex_I, 0.046679220394 + 0.009712412319*_Complex_I, -0.017763427623 + -0.015970470090*_Complex_I, -0.023951776164 + -0.049756621013*_Complex_I, 0.005079568893 + -0.033963764074*_Complex_I, 0.010470512110 + -0.004032766261*_Complex_I, 0.063479867902 + 0.089940072424*_Complex_I, -0.013695440245 + -0.005147235363*_Complex_I, 0.018210209849 + -0.062011233592*_Complex_I, -0.014235918784 + 0.002032286514*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/firdecim_cccf_data_M4h13x40.c000066400000000000000000000106501317124540100250230ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firdecim_cccf_data_M4h13x40.c: autotest firdecim data // #include float complex firdecim_cccf_data_M4h13x40_h[] = { -0.002562542003 + -0.154124323834*_Complex_I, -0.023583498668 + 0.104733275459*_Complex_I, 0.022367426058 + -0.120923475320*_Complex_I, -0.132621145254 + -0.178735883634*_Complex_I, -0.168112709779 + 0.034712075125*_Complex_I, 0.057724042805 + 0.008285579385*_Complex_I, -0.047739385482 + 0.142477282131*_Complex_I, 0.067869682601 + 0.097364083820*_Complex_I, 0.059426213111 + 0.468175487351*_Complex_I, 0.006482342651 + -0.003418897658*_Complex_I, -0.004209444510 + -0.083952075513*_Complex_I, 0.011361818419 + -0.070937481458*_Complex_I, 0.094086356591 + -0.103332276920*_Complex_I}; float complex firdecim_cccf_data_M4h13x40_x[] = { -0.024194231006 + -0.138925187631*_Complex_I, 0.203856156849 + -0.080078393335*_Complex_I, -0.068961728054 + 0.201298529466*_Complex_I, -0.051809449253 + 0.046347258011*_Complex_I, -0.149903686678 + -0.212870505681*_Complex_I, 0.029836494947 + -0.048639942573*_Complex_I, 0.037533241642 + -0.206079736569*_Complex_I, 0.051371569347 + -0.039092683420*_Complex_I, -0.090350663461 + 0.047672789069*_Complex_I, -0.156001075276 + 0.148239674685*_Complex_I, 0.151211606918 + -0.081137753153*_Complex_I, 0.014410288934 + -0.091766222951*_Complex_I, 0.128650669104 + -0.109361279278*_Complex_I, -0.014454025380 + -0.017884354391*_Complex_I, -0.027777545721 + 0.014889779800*_Complex_I, -0.102482421038 + 0.153280094094*_Complex_I, 0.054231085410 + -0.036048916993*_Complex_I, -0.097774825326 + 0.071640661283*_Complex_I, 0.016069399348 + -0.072264453423*_Complex_I, -0.020335452514 + -0.102705025246*_Complex_I, -0.001428129588 + 0.058319600411*_Complex_I, 0.050490262274 + 0.068382581850*_Complex_I, 0.037146918761 + -0.014078089282*_Complex_I, 0.131825401964 + -0.052212284043*_Complex_I, -0.021358931115 + 0.034076612121*_Complex_I, 0.007883745543 + -0.045225145346*_Complex_I, 0.066077716475 + -0.011748246722*_Complex_I, 0.020987892322 + 0.148992296687*_Complex_I, 0.046814707826 + -0.080934756420*_Complex_I, 0.092525039263 + 0.149989890332*_Complex_I, 0.063112963675 + -0.084774798237*_Complex_I, -0.019463083228 + 0.059819778564*_Complex_I, -0.026299503842 + -0.005553793151*_Complex_I, 0.135276140520 + -0.011249885171*_Complex_I, -0.055971818305 + -0.061539002690*_Complex_I, 0.041589677363 + 0.218745686754*_Complex_I, -0.154541640002 + 0.176344746584*_Complex_I, -0.093756310243 + 0.038311802363*_Complex_I, 0.075234897328 + 0.138257000400*_Complex_I, -0.097930194448 + -0.076486145877*_Complex_I}; float complex firdecim_cccf_data_M4h13x40_y[] = { -0.021349751874 + 0.004084921123*_Complex_I, -0.045716199011 + 0.026670647628*_Complex_I, 0.062793796326 + 0.020298966406*_Complex_I, 0.171764657602 + -0.129296598427*_Complex_I, -0.140510571307 + -0.025391053246*_Complex_I, 0.078880319262 + 0.080737389437*_Complex_I, 0.026829099733 + -0.015427110029*_Complex_I, -0.058971359279 + -0.004947680884*_Complex_I, -0.009091338962 + -0.022653029705*_Complex_I, 0.017223757651 + 0.057653177650*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/firdecim_cccf_data_M5h23x50.c000066400000000000000000000126201317124540100250250ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firdecim_cccf_data_M5h23x50.c: autotest firdecim data // #include float complex firdecim_cccf_data_M5h23x50_h[] = { 0.105720400924 + 0.057437069192*_Complex_I, -0.028209083196 + -0.004313504575*_Complex_I, -0.072874560021 + 0.042888303750*_Complex_I, -0.085512857926 + 0.020535437583*_Complex_I, -0.100456191359 + 0.103253822583*_Complex_I, 0.021202177209 + 0.035197979854*_Complex_I, -0.181412547496 + -0.065280832354*_Complex_I, -0.089735489990 + -0.035169413725*_Complex_I, 0.091350151539 + 0.024388575583*_Complex_I, 0.115625359788 + -0.072145623875*_Complex_I, -0.051852629863 + -0.004567932396*_Complex_I, 0.009526328844 + -0.150554350114*_Complex_I, 0.111472545344 + 0.100620569627*_Complex_I, 0.072732704374 + -0.028216475627*_Complex_I, -0.041864189108 + 0.010588416120*_Complex_I, 0.050598746124 + -0.003896637950*_Complex_I, -0.118777133157 + 0.070610240227*_Complex_I, -0.016104655770 + 0.004328632751*_Complex_I, 0.057125599610 + 0.100422001833*_Complex_I, 0.154824278727 + -0.040505357012*_Complex_I, 0.019585396789 + 0.108879628006*_Complex_I, 0.052374918456 + -0.044109539660*_Complex_I, 0.013011637257 + -0.076892387668*_Complex_I}; float complex firdecim_cccf_data_M5h23x50_x[] = { -0.045706059285 + -0.026925548272*_Complex_I, 0.074640818692 + 0.020008220501*_Complex_I, -0.041286610033 + -0.136882935267*_Complex_I, 0.009816935182 + -0.078646240225*_Complex_I, 0.089010380616 + -0.149190270600*_Complex_I, 0.083497556154 + -0.043557829025*_Complex_I, 0.182551809767 + -0.029983057525*_Complex_I, 0.156019880201 + 0.005770028753*_Complex_I, 0.061786541086 + -0.064921440736*_Complex_I, 0.243601293648 + 0.048234370911*_Complex_I, -0.038392905410 + 0.026874189965*_Complex_I, 0.098986088062 + -0.051036508330*_Complex_I, 0.145073787044 + 0.133408806994*_Complex_I, -0.012274691331 + -0.001003240627*_Complex_I, -0.047977493556 + 0.090394581449*_Complex_I, 0.067234934373 + -0.080081570574*_Complex_I, -0.066259448979 + 0.124203939183*_Complex_I, -0.107414957417 + -0.017911178063*_Complex_I, -0.035170912051 + -0.011180346308*_Complex_I, 0.087106081663 + 0.108450957223*_Complex_I, -0.071732901242 + -0.054445545216*_Complex_I, -0.027106150089 + 0.035717288781*_Complex_I, 0.008967266976 + -0.124029666988*_Complex_I, -0.027842462142 + 0.016454828477*_Complex_I, 0.035515455355 + 0.042131771080*_Complex_I, 0.012844114428 + 0.106011213637*_Complex_I, 0.081631987459 + 0.062426819327*_Complex_I, 0.130657890629 + -0.002602075127*_Complex_I, -0.094246564430 + -0.033523978166*_Complex_I, -0.053733329944 + 0.108359828647*_Complex_I, -0.005664508011 + 0.021469330759*_Complex_I, -0.014929153350 + 0.017941698073*_Complex_I, 0.020461861960 + -0.100937164479*_Complex_I, 0.001605545133 + 0.153966424471*_Complex_I, -0.042286310689 + -0.074770813879*_Complex_I, 0.171684109561 + 0.076554260668*_Complex_I, 0.175238329863 + 0.075856527238*_Complex_I, 0.060276983038 + -0.075910005194*_Complex_I, 0.009291016375 + -0.012009065640*_Complex_I, 0.165631852407 + -0.056358816657*_Complex_I, 0.022403278379 + -0.053838057764*_Complex_I, 0.012578774881 + -0.028070849755*_Complex_I, 0.111896323878 + -0.067413483086*_Complex_I, 0.193577629326 + 0.022715731850*_Complex_I, -0.024575467522 + -0.001589364951*_Complex_I, 0.049219675943 + -0.168094546969*_Complex_I, -0.052368096464 + 0.158302243383*_Complex_I, 0.029964399158 + -0.012022357247*_Complex_I, 0.126368745124 + 0.002307518720*_Complex_I, 0.014850257877 + 0.006988676981*_Complex_I}; float complex firdecim_cccf_data_M5h23x50_y[] = { -0.003285538333 + -0.005471801848*_Complex_I, 0.007588480326 + 0.024542591101*_Complex_I, -0.057029837651 + 0.045181309977*_Complex_I, -0.052759259646 + -0.065315303001*_Complex_I, 0.096950584899 + -0.077249583961*_Complex_I, 0.000722131494 + 0.033051673725*_Complex_I, 0.010653757445 + -0.053755642413*_Complex_I, 0.037166575400 + 0.001442464438*_Complex_I, 0.015685676896 + 0.008079773457*_Complex_I, -0.025642858413 + 0.014281592109*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/firdecim_crcf_data_M2h4x20.c000066400000000000000000000055721317124540100247650ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firdecim_crcf_data_M2h4x20.c: autotest firdecim data // #include float firdecim_crcf_data_M2h4x20_h[] = { 0.031235809409, -0.216021656042, -0.123125426658, 0.014724190886}; float complex firdecim_crcf_data_M2h4x20_x[] = { -0.121360059018 + -0.040946328225*_Complex_I, -0.048183917318 + -0.090893384286*_Complex_I, 0.050431539967 + -0.039477767743*_Complex_I, -0.092873851447 + -0.016290157417*_Complex_I, 0.067927836995 + 0.034766499357*_Complex_I, -0.062738323035 + -0.070124552362*_Complex_I, -0.089685845706 + 0.085063483262*_Complex_I, 0.036320846361 + 0.192249836854*_Complex_I, -0.097540647206 + -0.078675689987*_Complex_I, 0.062450869382 + 0.091837474249*_Complex_I, -0.062450045345 + -0.029363766863*_Complex_I, -0.030191356564 + 0.094898259922*_Complex_I, 0.130002759179 + -0.034950407712*_Complex_I, 0.030652983878 + 0.015398314893*_Complex_I, -0.028490871597 + 0.130293581637*_Complex_I, 0.114396819866 + -0.058213046230*_Complex_I, -0.090569184709 + -0.080687388201*_Complex_I, -0.002440656567 + 0.093805498501*_Complex_I, 0.181551012573 + 0.015635958339*_Complex_I, 0.081568978667 + 0.051967040191*_Complex_I}; float complex firdecim_crcf_data_M2h4x20_y[] = { -0.003790779673 + -0.001278991704*_Complex_I, 0.026926548630 + 0.023443353500*_Complex_I, 0.015265670091 + 0.008127371986*_Complex_I, 0.001020290227 + 0.013284949227*_Complex_I, -0.000774013472 + -0.055493631953*_Complex_I, -0.002896889061 + -0.008238383106*_Complex_I, 0.019191455251 + -0.016624124713*_Complex_I, -0.023962832263 + 0.006444039955*_Complex_I, -0.023581901158 + -0.005760782332*_Complex_I, 0.019033897622 + -0.010698088224*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/firdecim_crcf_data_M3h7x30.c000066400000000000000000000066521317124540100247720ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firdecim_crcf_data_M3h7x30.c: autotest firdecim data // #include float firdecim_crcf_data_M3h7x30_h[] = { -0.067137698321, 0.054412252965, -0.182856503708, -0.054617127674, -0.009870765494, -0.026617010237, 0.011725565067}; float complex firdecim_crcf_data_M3h7x30_x[] = { -0.088297122268 + 0.055665944654*_Complex_I, -0.016432697221 + 0.148455554729*_Complex_I, 0.140757522457 + 0.073543902343*_Complex_I, 0.063460474341 + 0.032803595179*_Complex_I, -0.010344707877 + -0.062988102121*_Complex_I, 0.039529652200 + -0.054529222034*_Complex_I, 0.119571808389 + -0.098769254813*_Complex_I, 0.014024766895 + -0.018877394409*_Complex_I, 0.075151006910 + -0.136112320307*_Complex_I, 0.167466666363 + 0.037009456983*_Complex_I, -0.006066715214 + 0.052827861682*_Complex_I, 0.048336909246 + -0.157938756841*_Complex_I, 0.022542224668 + 0.123894877722*_Complex_I, -0.109162126495 + -0.080322251267*_Complex_I, 0.060401040885 + -0.013549823453*_Complex_I, -0.065450090580 + 0.134084060551*_Complex_I, 0.080552956850 + -0.129409082705*_Complex_I, -0.054479718117 + -0.047011198746*_Complex_I, 0.186369060662 + -0.125658475188*_Complex_I, -0.191665411586 + -0.030921221765*_Complex_I, 0.063129882080 + 0.100182552563*_Complex_I, 0.065520569371 + -0.107290345371*_Complex_I, 0.146258184364 + -0.041133067761*_Complex_I, 0.048045169203 + 0.040835459595*_Complex_I, 0.006679291241 + 0.024648912594*_Complex_I, 0.038593404874 + -0.254488576034*_Complex_I, -0.176346189965 + -0.001937288661*_Complex_I, -0.171141933206 + -0.024023949503*_Complex_I, 0.216869453975 + 0.054039885226*_Complex_I, 0.165978694869 + -0.091956658785*_Complex_I}; float complex firdecim_crcf_data_M3h7x30_y[] = { 0.005928065557 + -0.003737283399*_Complex_I, 0.011225704498 + -0.028387046159*_Complex_I, -0.009438639157 + 0.009365565615*_Complex_I, -0.015620112302 + 0.001554880391*_Complex_I, -0.006633571221 + -0.027905221566*_Complex_I, 0.028058535196 + -0.001231894454*_Complex_I, -0.024058004824 + 0.025942864482*_Complex_I, 0.021530701506 + 0.030652367492*_Complex_I, -0.021493289366 + 0.012309152915*_Complex_I, -0.009126109290 + 0.046129860989*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/firdecim_crcf_data_M4h13x40.c000066400000000000000000000100321317124540100250340ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firdecim_crcf_data_M4h13x40.c: autotest firdecim data // #include float firdecim_crcf_data_M4h13x40_h[] = { -0.017634479811, 0.078644323992, 0.010062975901, 0.002767448419, -0.012666798459, 0.072474187801, 0.138641311321, 0.096895207192, 0.005424669952, -0.095669120702, 0.115011527536, 0.045576979285, -0.032175124851}; float complex firdecim_crcf_data_M4h13x40_x[] = { -0.112962750920 + -0.174396579717*_Complex_I, 0.036553706748 + -0.051072169083*_Complex_I, 0.022797265387 + 0.042572931849*_Complex_I, 0.008765340086 + 0.005707935306*_Complex_I, 0.106501635473 + -0.087740150292*_Complex_I, -0.021475975887 + 0.041386858553*_Complex_I, -0.140639585019 + 0.075707242551*_Complex_I, -0.170100822245 + 0.024811268189*_Complex_I, 0.077084240435 + 0.022103264096*_Complex_I, -0.034031018357 + 0.008016611966*_Complex_I, 0.042615847754 + -0.119291859183*_Complex_I, 0.004089922446 + 0.056510429034*_Complex_I, 0.145879823424 + 0.102239060582*_Complex_I, 0.131816984427 + -0.085645947698*_Complex_I, -0.118561232326 + 0.150671338454*_Complex_I, -0.032855598424 + 0.084885603624*_Complex_I, -0.029028910328 + 0.095508389514*_Complex_I, 0.162474927440 + -0.002144805045*_Complex_I, -0.066178053685 + -0.010931400887*_Complex_I, -0.164098083762 + -0.014709199385*_Complex_I, -0.042421547313 + -0.165166102873*_Complex_I, -0.143613555453 + -0.020483960094*_Complex_I, 0.074273402726 + 0.026166548871*_Complex_I, 0.039546848666 + 0.060817356400*_Complex_I, -0.283154531123 + -0.068141024882*_Complex_I, -0.171382954008 + 0.157655929741*_Complex_I, 0.100887524169 + -0.227019774244*_Complex_I, -0.134270894830 + -0.095892207602*_Complex_I, 0.061905242843 + -0.098697402618*_Complex_I, 0.070002196277 + 0.099716632447*_Complex_I, -0.111631217405 + -0.033672309864*_Complex_I, -0.042616607537 + -0.111931082366*_Complex_I, -0.004433766647 + -0.118350103892*_Complex_I, -0.029922536821 + 0.288101612082*_Complex_I, 0.112347437422 + 0.012061775097*_Complex_I, 0.121008925435 + 0.081465180909*_Complex_I, -0.022480348602 + 0.032724942501*_Complex_I, -0.057932648610 + 0.146711091659*_Complex_I, 0.091043924052 + -0.118961124120*_Complex_I, -0.060921349688 + -0.036527277081*_Complex_I}; float complex firdecim_crcf_data_M4h13x40_y[] = { 0.001992039351 + 0.003075392964*_Complex_I, 0.000572688534 + 0.004492265743*_Complex_I, -0.010835528800 + 0.003970601587*_Complex_I, -0.029138197244 + 0.024645444782*_Complex_I, -0.005729955161 + 0.004471983412*_Complex_I, -0.016781980003 + 0.000255273787*_Complex_I, -0.005670110185 + 0.008026992933*_Complex_I, 0.007921191245 + -0.004652046754*_Complex_I, -0.019294993452 + -0.027474217637*_Complex_I, 0.025318608692 + -0.002964377998*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/firdecim_crcf_data_M5h23x50.c000066400000000000000000000113261317124540100250460ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firdecim_crcf_data_M5h23x50.c: autotest firdecim data // #include float firdecim_crcf_data_M5h23x50_h[] = { 0.002280218687, 0.030259168999, 0.042315352513, 0.023335125905, 0.187877503860, -0.125992843938, 0.011263591538, 0.085275043313, -0.000421564647, -0.061084018425, -0.061455696212, -0.019398732964, 0.054084065833, -0.139019814895, -0.006954271771, 0.066739670458, 0.060380686235, -0.030379569378, 0.062093917175, -0.108597003256, -0.026039280890, -0.061515114912, 0.038253839794}; float complex firdecim_crcf_data_M5h23x50_x[] = { -0.182183709645 + -0.105810548671*_Complex_I, -0.119835664561 + 0.052187599214*_Complex_I, -0.080413311444 + -0.007654126449*_Complex_I, 0.097423911392 + 0.139994199967*_Complex_I, 0.227363312459 + 0.148762801146*_Complex_I, -0.035703226649 + 0.016200983468*_Complex_I, 0.112245547440 + -0.012233367286*_Complex_I, 0.048367738935 + -0.084918284786*_Complex_I, 0.014605478600 + -0.020568647750*_Complex_I, -0.097889245398 + 0.168068267634*_Complex_I, 0.049395920002 + 0.049056756925*_Complex_I, 0.077571659414 + -0.016603490981*_Complex_I, -0.184216448023 + 0.038356590636*_Complex_I, -0.001919304196 + 0.044652884985*_Complex_I, -0.137958101403 + 0.039437297572*_Complex_I, -0.014249713446 + -0.012873748415*_Complex_I, 0.080615138558 + 0.010722054400*_Complex_I, 0.163287071747 + 0.157849778887*_Complex_I, 0.014760203683 + 0.017904920717*_Complex_I, -0.023896962586 + -0.167898683088*_Complex_I, -0.103145190697 + -0.052205104745*_Complex_I, 0.060639622041 + 0.000262344853*_Complex_I, -0.103152379379 + 0.094308639066*_Complex_I, 0.087724817642 + 0.138912843443*_Complex_I, 0.118286611822 + -0.059245080063*_Complex_I, 0.072397607400 + 0.055570352604*_Complex_I, -0.120828136006 + -0.053193491502*_Complex_I, 0.017568748356 + 0.062747031152*_Complex_I, -0.173562312809 + 0.024099395003*_Complex_I, 0.029150371763 + 0.142074561483*_Complex_I, 0.025859464873 + 0.055295550529*_Complex_I, 0.033521057962 + 0.015990392806*_Complex_I, -0.153314777647 + 0.029921210372*_Complex_I, -0.083426782876 + 0.085727794977*_Complex_I, -0.082913880724 + 0.118554053112*_Complex_I, -0.000295266978 + 0.046816730776*_Complex_I, -0.091635622603 + -0.074886539618*_Complex_I, 0.187307078036 + 0.079033670911*_Complex_I, 0.016483267210 + 0.214994027303*_Complex_I, 0.182841584926 + -0.060579741754*_Complex_I, 0.098946994244 + 0.014088074701*_Complex_I, 0.103226498009 + -0.107310190377*_Complex_I, -0.102346312686 + -0.043967864658*_Complex_I, 0.003356469485 + 0.080001448898*_Complex_I, 0.015380876414 + -0.033386312073*_Complex_I, 0.113435756454 + 0.076011600452*_Complex_I, 0.222681717597 + -0.048179807062*_Complex_I, 0.213685265876 + 0.154819154890*_Complex_I, -0.145263809029 + 0.080441672618*_Complex_I, -0.065703128284 + 0.056608305388*_Complex_I}; float complex firdecim_crcf_data_M5h23x50_y[] = { -0.000415418699 + -0.000241271190*_Complex_I, 0.009483904304 + 0.033419922261*_Complex_I, 0.053902979681 + 0.014937609575*_Complex_I, -0.004064163171 + -0.007100167361*_Complex_I, 0.027338357030 + 0.015054094814*_Complex_I, 0.032378938500 + 0.015062971531*_Complex_I, -0.072114751319 + -0.021601257083*_Complex_I, -0.000363929634 + -0.002841410024*_Complex_I, -0.028488318939 + -0.002263371809*_Complex_I, 0.049749343516 + 0.025688357259*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/firdecim_rrrf_data_M2h4x20.c000066400000000000000000000037201317124540100250140ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firdecim_rrrf_data_M2h4x20.c: autotest firdecim data // float firdecim_rrrf_data_M2h4x20_h[] = { 0.070782309250, -0.114245586699, 0.008215220382, -0.116718567037}; float firdecim_rrrf_data_M2h4x20_x[] = { 0.098311328839, -0.051405684088, -0.097846553674, 0.070744555579, -0.092569362020, 0.125743342560, -0.015936561579, 0.092440100110, -0.007046555447, -0.011409188742, 0.065796277764, 0.121624056526, 0.001291608019, -0.103251042400, -0.067174551288, -0.069262060525, 0.038107684731, -0.091432498375, 0.094339814736, 0.004969612518}; float firdecim_rrrf_data_M2h4x20_y[] = { 0.006958702881, -0.000245283250, -0.009438359685, -0.024511329437, -0.025867150062, -0.004886703086, -0.011931393613, -0.007143968697, 0.022109694637, 0.025520580844}; liquid-dsp-1.3.1/src/filter/tests/data/firdecim_rrrf_data_M3h7x30.c000066400000000000000000000043241317124540100250220ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firdecim_rrrf_data_M3h7x30.c: autotest firdecim data // float firdecim_rrrf_data_M3h7x30_h[] = { -0.074705344704, 0.020538592337, -0.020061495576, 0.096703320953, 0.100160540368, 0.097166994081, 0.083888510566}; float firdecim_rrrf_data_M3h7x30_x[] = { -0.077089593357, 0.032375219181, 0.141488397385, 0.034405467968, -0.138389144841, 0.154646756715, 0.086331166522, 0.041332691838, 0.091791117954, -0.065105465675, 0.075745848821, 0.012475523017, -0.107768670583, 0.233864631918, -0.110944430251, -0.060308141718, -0.251948448147, 0.153274083486, -0.114102376762, -0.183548035449, -0.152968693185, 0.049660839590, -0.056844064619, -0.153304122180, 0.018994945270, 0.000201893929, -0.055497296237, 0.101173781919, -0.050453255942, -0.019320758294}; float firdecim_rrrf_data_M3h7x30_y[] = { 0.005759004645, -0.007768614835, 0.013680669269, 0.019197170461, 0.020943849985, -0.009738613503, 0.013465672357, -0.028391740957, -0.041353046024, -0.023577651344}; liquid-dsp-1.3.1/src/filter/tests/data/firdecim_rrrf_data_M4h13x40.c000066400000000000000000000050301317124540100250740ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firdecim_rrrf_data_M4h13x40.c: autotest firdecim data // float firdecim_rrrf_data_M4h13x40_h[] = { -0.050178519704, 0.099634819705, 0.087767256514, 0.031474342328, -0.161835107291, 0.031896126939, -0.240761793751, -0.044460468897, 0.019656280155, 0.150308997913, -0.145260671043, 0.044691633752, -0.228340355042}; float firdecim_rrrf_data_M4h13x40_x[] = { -0.006034368030, -0.171592529075, -0.063780807965, 0.013676314399, 0.116628260211, 0.119863895134, 0.111602959230, 0.130154286756, 0.038035316610, 0.059453633879, -0.109240225614, 0.077742393809, -0.021666946122, 0.067622802572, -0.058137116614, -0.069171140610, 0.067330056503, 0.087258333681, 0.042012179512, -0.025556605587, -0.111286144010, -0.040760608600, 0.127330790275, 0.033399307914, -0.005634951089, 0.043243872564, 0.038979737383, -0.045742865035, -0.193432344744, -0.020574800494, -0.065306698326, -0.101479446471, -0.016230721248, 0.000392179194, -0.065936759641, 0.032965659365, 0.057788436776, -0.268236198963, -0.077821704788, -0.125842807499}; float firdecim_rrrf_data_M4h13x40_y[] = { 0.000302795655, -0.014511652270, 0.029055193091, -0.025764218622, -0.000775391175, 0.028459415706, 0.024044484393, -0.040542156850, 0.012864586577, -0.002482554609}; liquid-dsp-1.3.1/src/filter/tests/data/firdecim_rrrf_data_M5h23x50.c000066400000000000000000000056501317124540100251070ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firdecim_rrrf_data_M5h23x50.c: autotest firdecim data // float firdecim_rrrf_data_M5h23x50_h[] = { -0.067636988306, -0.129830871935, -0.096852198413, -0.101084148415, -0.099274002866, 0.068432593779, -0.123467175510, 0.053608743344, 0.062001100783, -0.186969419240, 0.089108369240, -0.007475824870, 0.163590779858, 0.097601917788, 0.092009543577, -0.041838135753, -0.056136168702, 0.003032887982, 0.009882398914, 0.074984250657, -0.019855593061, -0.060394654408, 0.023157699589}; float firdecim_rrrf_data_M5h23x50_x[] = { -0.053013073944, -0.096057779578, 0.089544324704, -0.000543553496, 0.162822533187, -0.074585191755, 0.104404924404, -0.029558379775, -0.007349400311, -0.194774278732, -0.170758029656, 0.045377876421, 0.080652365875, 0.072939196850, -0.089654082233, -0.103982998990, 0.163030711963, -0.024228077817, 0.131281994357, 0.016327074888, -0.055411828614, 0.043034256150, 0.018076404143, 0.097676360852, 0.137184094723, 0.082482387627, 0.056634950389, 0.027836125209, -0.014908882821, 0.162327107907, -0.153015761693, -0.020845168829, -0.001125342955, -0.044310410921, -0.053090705118, -0.024619825348, 0.039550843685, -0.206275854122, 0.034696692856, -0.153816675012, -0.028473257841, 0.054242064784, 0.197473069156, 0.002233912029, 0.021458220407, 0.122982229244, 0.127458372904, -0.040153514587, -0.055390576800, 0.126488480454}; float firdecim_rrrf_data_M5h23x50_y[] = { 0.003585644662, -0.019185323038, 0.023723637517, -0.016266117610, -0.039970055370, -0.037092249176, 0.027140256398, 0.025837751181, 0.028127341349, -0.054916331965}; liquid-dsp-1.3.1/src/filter/tests/data/firfilt_cccf_data_h13x32.c000066400000000000000000000121271317124540100245010ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firfilt_cccf_data_h13x32.c: autotest firfilt data // #include float complex firfilt_cccf_data_h13x32_h[] = { -0.016900612660 + -0.094711890552*_Complex_I, 0.021604417271 + 0.142776429157*_Complex_I, -0.115236149764 + -0.169153952067*_Complex_I, -0.104650665737 + -0.070706448696*_Complex_I, -0.324134992109 + 0.000276600538*_Complex_I, 0.084579923351 + 0.050862911890*_Complex_I, 0.037182962083 + -0.060208798591*_Complex_I, -0.025070759196 + -0.102300651911*_Complex_I, -0.172106098520 + 0.036477087826*_Complex_I, -0.104230620945 + -0.026070285900*_Complex_I, -0.098231380216 + 0.164187739422*_Complex_I, 0.073260028098 + 0.102435049392*_Complex_I, -0.064585416482 + 0.016491998619*_Complex_I}; float complex firfilt_cccf_data_h13x32_x[] = { -0.230394652772 + -0.084902186709*_Complex_I, 0.116521954181 + -0.075921100646*_Complex_I, -0.037505572140 + 0.050295775262*_Complex_I, 0.011196490896 + -0.111587364031*_Complex_I, -0.136496843877 + 0.079379261628*_Complex_I, 0.119267886716 + -0.106802817114*_Complex_I, -0.019101973377 + -0.012951763335*_Complex_I, 0.013025947353 + -0.027697311008*_Complex_I, -0.019147300547 + 0.101327659435*_Complex_I, 0.099708276687 + -0.005787000260*_Complex_I, 0.068401822498 + 0.064073386055*_Complex_I, -0.037396159261 + -0.075336873450*_Complex_I, -0.100404642212 + -0.010670539381*_Complex_I, 0.158140877685 + -0.091346399746*_Complex_I, -0.014860736865 + -0.063687261938*_Complex_I, 0.080260238653 + -0.095670107832*_Complex_I, -0.039374218095 + -0.044034420137*_Complex_I, -0.064080642555 + -0.070686889846*_Complex_I, 0.001854749241 + 0.115365376524*_Complex_I, 0.010746506918 + -0.241675580817*_Complex_I, 0.000549090314 + -0.105646197984*_Complex_I, 0.076651038231 + 0.139227636964*_Complex_I, 0.142025555338 + -0.030479656574*_Complex_I, 0.052085787214 + 0.049670506263*_Complex_I, 0.072171078854 + 0.026786779778*_Complex_I, -0.025753470644 + 0.135280754343*_Complex_I, -0.021573256842 + -0.151434524956*_Complex_I, 0.075816838810 + -0.117216580293*_Complex_I, 0.072760555750 + -0.032730991216*_Complex_I, -0.066907752810 + -0.020500064860*_Complex_I, -0.166213598571 + 0.030726287248*_Complex_I, -0.276903984324 + -0.003789664941*_Complex_I}; float complex firfilt_cccf_data_h13x32_y[] = { -0.004147435830 + 0.023256012109*_Complex_I, -0.002015434559 + -0.044482089545*_Complex_I, 0.030942859967 + 0.066454518780*_Complex_I, -0.026911288885 + 0.010771317579*_Complex_I, 0.095968947613 + 0.038484837745*_Complex_I, -0.092014317271 + -0.013169924277*_Complex_I, 0.049198135608 + 0.035484075721*_Complex_I, -0.025796455461 + 0.044082591823*_Complex_I, 0.078672781715 + -0.025486364457*_Complex_I, -0.072129355236 + 0.058152098733*_Complex_I, 0.060708464475 + -0.020499489129*_Complex_I, -0.012897457718 + 0.010369404477*_Complex_I, 0.040569721031 + -0.076402320248*_Complex_I, -0.061438066081 + 0.022914256728*_Complex_I, 0.010560216826 + 0.008397165450*_Complex_I, -0.007466249710 + 0.045405657448*_Complex_I, 0.045052264644 + -0.014977016558*_Complex_I, -0.103883227654 + 0.025733650083*_Complex_I, -0.020931229354 + 0.011790200727*_Complex_I, -0.082554523156 + 0.082257052415*_Complex_I, 0.062290900829 + 0.006126149167*_Complex_I, -0.001939383449 + 0.054104380393*_Complex_I, -0.080894136635 + -0.026061525625*_Complex_I, -0.014425095108 + 0.144945090491*_Complex_I, 0.027136649299 + 0.013953073572*_Complex_I, -0.004380661218 + -0.036741472069*_Complex_I, -0.088435984052 + -0.001543185349*_Complex_I, 0.051743211037 + -0.012397485596*_Complex_I, -0.019549545189 + 0.010425517862*_Complex_I, -0.009114204900 + 0.008932656001*_Complex_I, -0.003773949758 + 0.033245440352*_Complex_I, -0.062498938791 + 0.037655501652*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/firfilt_cccf_data_h23x64.c000066400000000000000000000213131317124540100245040ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firfilt_cccf_data_h23x64.c: autotest firfilt data // #include float complex firfilt_cccf_data_h23x64_h[] = { 0.007386483162 + -0.009424072453*_Complex_I, 0.050423187035 + 0.150124405632*_Complex_I, 0.243542351374 + 0.080326589069*_Complex_I, -0.024338280301 + -0.114090910866*_Complex_I, 0.196460953569 + -0.124970764904*_Complex_I, -0.105561981596 + 0.041404720111*_Complex_I, -0.101639566392 + -0.046297689433*_Complex_I, -0.163657198362 + 0.005526168199*_Complex_I, -0.112922732770 + 0.063835893419*_Complex_I, 0.101174309677 + -0.014946487353*_Complex_I, 0.022730956655 + -0.120281555357*_Complex_I, 0.098219187560 + -0.193182817593*_Complex_I, -0.104212145985 + 0.050487269587*_Complex_I, -0.111765574417 + 0.198335922799*_Complex_I, -0.176342404298 + 0.020342954856*_Complex_I, -0.008161867550 + 0.131912314088*_Complex_I, 0.002095296558 + 0.017356532465*_Complex_I, -0.048192202598 + -0.033184854044*_Complex_I, -0.116973286896 + 0.160940600018*_Complex_I, -0.117776822786 + 0.154916853064*_Complex_I, -0.054689494037 + -0.147596255159*_Complex_I, -0.061473756719 + -0.101802249138*_Complex_I, -0.069996222196 + 0.068670445429*_Complex_I}; float complex firfilt_cccf_data_h23x64_x[] = { -0.078781393877 + 0.110995541416*_Complex_I, -0.047869391092 + -0.021406341819*_Complex_I, 0.037075730398 + 0.142733143372*_Complex_I, 0.030132814646 + -0.067132734894*_Complex_I, 0.061282796666 + 0.010485822100*_Complex_I, 0.102675878253 + -0.033081022766*_Complex_I, 0.033541370777 + 0.079278562425*_Complex_I, -0.054593695346 + -0.027854211664*_Complex_I, 0.145123800751 + -0.056723330167*_Complex_I, 0.011046150157 + 0.040345229995*_Complex_I, -0.035136035623 + 0.087660836105*_Complex_I, 0.016994675402 + 0.012775882535*_Complex_I, 0.044321746934 + -0.049948987747*_Complex_I, -0.028623515736 + 0.009984465451*_Complex_I, -0.047556759717 + 0.018286483908*_Complex_I, -0.006226807241 + 0.024241509652*_Complex_I, 0.064579293390 + -0.055779520425*_Complex_I, 0.006724710050 + -0.045321225291*_Complex_I, -0.014197864403 + -0.074364241862*_Complex_I, -0.189692736681 + 0.036236471869*_Complex_I, -0.043006387932 + 0.015254723104*_Complex_I, 0.183456865086 + -0.046633999430*_Complex_I, -0.096745178650 + -0.157866894203*_Complex_I, 0.049851534577 + -0.011841563370*_Complex_I, -0.128605225270 + -0.121500740667*_Complex_I, 0.208521246393 + 0.074928493344*_Complex_I, 0.015993704716 + -0.142778722944*_Complex_I, 0.099274527811 + 0.252094407113*_Complex_I, 0.095595074594 + -0.110420978049*_Complex_I, -0.160033363989 + 0.021797330986*_Complex_I, -0.033832678704 + 0.074483735094*_Complex_I, 0.063099121768 + 0.029430379768*_Complex_I, 0.073790479995 + 0.116859113625*_Complex_I, 0.029697732194 + -0.064419571602*_Complex_I, -0.121376933005 + -0.068190026772*_Complex_I, 0.157696201880 + 0.013694270490*_Complex_I, 0.192086239328 + 0.177711736014*_Complex_I, 0.050443921971 + 0.194189638728*_Complex_I, 0.104425685379 + 0.145809752108*_Complex_I, 0.052724394018 + -0.077432998652*_Complex_I, -0.138821609433 + 0.064732623753*_Complex_I, -0.091470669189 + 0.063059053083*_Complex_I, 0.126212251998 + 0.047314249385*_Complex_I, -0.096047066646 + 0.177236809567*_Complex_I, 0.052301840404 + -0.008778675600*_Complex_I, -0.121968378742 + -0.054938313986*_Complex_I, -0.052829966951 + -0.030310428105*_Complex_I, 0.018028043678 + -0.025287719529*_Complex_I, -0.027374857808 + 0.073286356627*_Complex_I, 0.097021248414 + 0.117164045551*_Complex_I, 0.041807049929 + -0.087406811774*_Complex_I, -0.016480216738 + 0.009889058359*_Complex_I, 0.025179492882 + 0.203064743411*_Complex_I, 0.157077633956 + -0.037868143998*_Complex_I, 0.186492422521 + 0.007792322512*_Complex_I, -0.058684153831 + 0.005148456049*_Complex_I, 0.043091823396 + 0.043031309641*_Complex_I, 0.070177096613 + -0.053637529243*_Complex_I, -0.026547396369 + -0.080476576072*_Complex_I, -0.001571308583 + -0.035758437403*_Complex_I, -0.015191595806 + -0.121248560074*_Complex_I, -0.150343511708 + -0.218457418741*_Complex_I, 0.214202412315 + -0.062090364159*_Complex_I, 0.051648310107 + 0.008540965007*_Complex_I}; float complex firfilt_cccf_data_h23x64_y[] = { 0.000464112585 + 0.001562308262*_Complex_I, -0.021190870009 + -0.005937253959*_Complex_I, -0.025683625328 + 0.013143026224*_Complex_I, -0.015326079628 + 0.009211447989*_Complex_I, 0.006829901541 + 0.076012393531*_Complex_I, 0.021716854352 + -0.026318353103*_Complex_I, 0.061035502538 + 0.035739634892*_Complex_I, 0.020352690891 + -0.042409807844*_Complex_I, 0.023045428223 + -0.028106571621*_Complex_I, 0.010032616072 + -0.021662309111*_Complex_I, 0.022940764323 + 0.032595296512*_Complex_I, -0.051515604616 + 0.041000933031*_Complex_I, 0.005746042283 + -0.027665280631*_Complex_I, 0.029717785937 + 0.005867034288*_Complex_I, 0.009507729239 + -0.065470886864*_Complex_I, -0.055592736641 + -0.039847345306*_Complex_I, -0.019477634830 + -0.054757658494*_Complex_I, -0.001079490064 + 0.040551530555*_Complex_I, -0.023105026049 + -0.021489136993*_Complex_I, -0.013772576463 + -0.059289523063*_Complex_I, 0.010368064793 + -0.051492201632*_Complex_I, -0.052573934313 + 0.036913855369*_Complex_I, -0.029463371581 + 0.017335195435*_Complex_I, -0.002016229441 + 0.029445890489*_Complex_I, -0.064174313079 + -0.021020171587*_Complex_I, 0.046007178326 + -0.038216963612*_Complex_I, -0.047237084003 + -0.018439493080*_Complex_I, 0.077901945535 + 0.026803231226*_Complex_I, -0.160590610173 + -0.048895121067*_Complex_I, 0.033009384953 + 0.122366292068*_Complex_I, 0.047500812021 + 0.030446168988*_Complex_I, 0.027755264333 + 0.023740335853*_Complex_I, -0.029958186540 + -0.099197879754*_Complex_I, -0.093565182221 + 0.037118606810*_Complex_I, 0.037892348897 + 0.081665210582*_Complex_I, 0.017203419707 + -0.049660120581*_Complex_I, 0.123469958964 + 0.075552201157*_Complex_I, 0.075598725500 + -0.068066054148*_Complex_I, -0.019888756884 + 0.076027214270*_Complex_I, -0.016956893179 + 0.064628354823*_Complex_I, 0.054092135963 + 0.231143717249*_Complex_I, 0.107916203047 + -0.024623113347*_Complex_I, -0.067826976867 + -0.080607084998*_Complex_I, -0.084406829425 + 0.006461650420*_Complex_I, -0.097403134020 + 0.026083051061*_Complex_I, -0.174546809897 + 0.011876261770*_Complex_I, 0.073748943090 + -0.055147402729*_Complex_I, 0.097549181238 + -0.004423842043*_Complex_I, 0.077466051940 + -0.102440912522*_Complex_I, -0.159166842272 + -0.050231066222*_Complex_I, -0.169079556837 + 0.020999784115*_Complex_I, -0.011606027825 + 0.070186046595*_Complex_I, 0.059157126631 + -0.011799023310*_Complex_I, 0.026862671786 + -0.020855448914*_Complex_I, -0.068295073554 + 0.079282428595*_Complex_I, -0.048389220558 + -0.036671891516*_Complex_I, -0.104950395650 + -0.102233724778*_Complex_I, -0.028973062537 + -0.073361406548*_Complex_I, 0.093580906591 + -0.063967765018*_Complex_I, 0.024718362523 + -0.132740996962*_Complex_I, -0.024359580020 + -0.079781595584*_Complex_I, -0.073363097948 + -0.031874352056*_Complex_I, 0.007512286472 + -0.110602957303*_Complex_I, 0.074317818667 + -0.076288705193*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/firfilt_cccf_data_h4x8.c000066400000000000000000000044551317124540100243510ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firfilt_cccf_data_h4x8.c: autotest firfilt data // #include float complex firfilt_cccf_data_h4x8_h[] = { -0.031084031859 + -0.013523088141*_Complex_I, -0.129175459526 + 0.067705781544*_Complex_I, 0.221460930668 + -0.057515301525*_Complex_I, -0.023734659272 + 0.094741117144*_Complex_I}; float complex firfilt_cccf_data_h4x8_x[] = { 0.035529355081 + -0.025645176804*_Complex_I, 0.010053327033 + 0.058182925297*_Complex_I, -0.051911580279 + -0.038455783791*_Complex_I, 0.087876912441 + -0.008273223193*_Complex_I, -0.195891631367 + 0.043381908184*_Complex_I, -0.018068686759 + 0.096890714727*_Complex_I, 0.072440149482 + 0.119581756000*_Complex_I, -0.070807340362 + 0.027693599784*_Complex_I}; float complex firfilt_cccf_data_h4x8_y[] = { -0.001451197592 + 0.000316688892*_Complex_I, -0.002378879142 + 0.003773758321*_Complex_I, 0.002248990658 + -0.012660658356*_Complex_I, 0.013625136077 + 0.016803422304*_Complex_I, -0.023574746940 + 0.002359815677*_Complex_I, 0.048100008285 + -0.032526172551*_Complex_I, -0.047049781567 + 0.010960128197*_Complex_I, -0.012767824065 + -0.007537619160*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/firfilt_cccf_data_h7x16.c000066400000000000000000000063471317124540100244350ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firfilt_cccf_data_h7x16.c: autotest firfilt data // #include float complex firfilt_cccf_data_h7x16_h[] = { 0.059672454354 + -0.020066091352*_Complex_I, -0.074492656514 + -0.047414131969*_Complex_I, 0.035667494507 + -0.071294810193*_Complex_I, 0.039143057258 + 0.079656472813*_Complex_I, -0.014290705994 + -0.119186857470*_Complex_I, 0.072724115403 + 0.012655052298*_Complex_I, -0.195972668164 + -0.009791166658*_Complex_I}; float complex firfilt_cccf_data_h7x16_x[] = { -0.078420841238 + 0.087748743839*_Complex_I, -0.108100101013 + 0.135812982907*_Complex_I, -0.084609799993 + -0.122999836505*_Complex_I, 0.004784051237 + -0.110951409765*_Complex_I, -0.051782714777 + -0.055641082544*_Complex_I, -0.152740278646 + 0.078038723137*_Complex_I, -0.069927868237 + -0.029365176615*_Complex_I, -0.014589069109 + -0.028292391657*_Complex_I, -0.001773824861 + 0.092262042610*_Complex_I, 0.013547386638 + 0.007206123368*_Complex_I, 0.024099272780 + -0.029680768546*_Complex_I, -0.084253318229 + -0.003754881467*_Complex_I, -0.074747526125 + 0.016818234473*_Complex_I, -0.018741410126 + 0.035601500906*_Complex_I, -0.022799538279 + 0.052284827296*_Complex_I, -0.019334058586 + 0.032106298627*_Complex_I}; float complex firfilt_cccf_data_h7x16_y[] = { -0.002918789759 + 0.006809782675*_Complex_I, 0.006276944689 + 0.007455059607*_Complex_I, 0.010434073117 + -0.001912734754*_Complex_I, -0.005702292584 + 0.016196656152*_Complex_I, -0.025081177186 + 0.012200218722*_Complex_I, 0.003335423652 + 0.014801280201*_Complex_I, 0.006724005065 + 0.002747460191*_Complex_I, 0.009525148495 + -0.023079851588*_Complex_I, -0.004054704111 + 0.027058137376*_Complex_I, 0.008922503980 + 0.020765026017*_Complex_I, 0.003379220673 + 0.021621450005*_Complex_I, 0.008092396331 + -0.009379092265*_Complex_I, 0.024410342880 + 0.008452609790*_Complex_I, 0.007947112966 + 0.022079470097*_Complex_I, -0.003430027671 + -0.018931432282*_Complex_I, 0.001572545942 + 0.003497349824*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/firfilt_crcf_data_h13x32.c000066400000000000000000000113111317124540100245120ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firfilt_crcf_data_h13x32.c: autotest firfilt data // #include float firfilt_crcf_data_h13x32_h[] = { 0.005113901796, 0.005286268339, -0.119811540901, -0.004501609093, -0.065007372397, 0.048866593324, 0.013172470077, -0.002661385800, 0.103490232103, -0.080549511664, 0.044381828692, 0.059428974785, 0.036011050317}; float complex firfilt_crcf_data_h13x32_x[] = { -0.150478051517 + 0.011369787230*_Complex_I, -0.011682362019 + -0.131898855698*_Complex_I, 0.002241423344 + 0.056583759593*_Complex_I, -0.059449335305 + 0.187622651747*_Complex_I, -0.180436000741 + 0.005303426369*_Complex_I, 0.011260126047 + 0.058406411239*_Complex_I, 0.104607282644 + 0.079267822272*_Complex_I, 0.085374933204 + 0.051946754389*_Complex_I, -0.022910313299 + 0.030414137098*_Complex_I, 0.088237668857 + -0.149226301695*_Complex_I, -0.077336181799 + 0.011213633150*_Complex_I, -0.041671694767 + -0.010591371244*_Complex_I, -0.072827057153 + 0.029626684791*_Complex_I, -0.031258311706 + -0.032641520688*_Complex_I, -0.008154356734 + 0.089595819254*_Complex_I, 0.008874945980 + 0.055052307581*_Complex_I, 0.021540988384 + 0.002343360972*_Complex_I, 0.031406241630 + -0.041565525378*_Complex_I, -0.186621079183 + -0.055706611874*_Complex_I, -0.204887932486 + 0.107546397697*_Complex_I, -0.001299342939 + -0.091725815207*_Complex_I, 0.098883395599 + -0.042781095000*_Complex_I, -0.148848628287 + 0.075959712533*_Complex_I, 0.168232372928 + 0.044377154144*_Complex_I, 0.162761143249 + -0.111406681457*_Complex_I, -0.069728838323 + 0.030195226651*_Complex_I, -0.015037533839 + 0.032270195219*_Complex_I, 0.047319395233 + -0.049920188058*_Complex_I, -0.275633692987 + -0.077201329969*_Complex_I, 0.260550021883 + -0.026872750426*_Complex_I, 0.154250187563 + -0.051859524539*_Complex_I, 0.085702710731 + -0.034956856551*_Complex_I}; float complex firfilt_crcf_data_h13x32_y[] = { -0.000769529978 + 0.000058143975*_Complex_I, -0.000855209812 + -0.000614414049*_Complex_I, 0.017978713542 + -0.001770120683*_Complex_I, 0.001784905863 + 0.017010423559*_Complex_I, 0.008329226648 + -0.005905805446*_Complex_I, -0.000377533572 + -0.013277356194*_Complex_I, 0.019781654463 + -0.010739936790*_Complex_I, 0.004673510867 + -0.017536447645*_Complex_I, -0.018937503016 + 0.001766778181*_Complex_I, -0.009796095237 + -0.022965903194*_Complex_I, -0.011542534189 + 0.009647205778*_Complex_I, -0.026694559597 + 0.028680204257*_Complex_I, -0.004613286077 + -0.018608161470*_Complex_I, 0.011559988327 + 0.025425767569*_Complex_I, 0.015974924004 + 0.005946996608*_Complex_I, -0.007726490650 + 0.012377335870*_Complex_I, -0.007714581040 + -0.006039979551*_Complex_I, 0.018766419009 + -0.012572800123*_Complex_I, -0.012542031545 + 0.012437887461*_Complex_I, 0.000458385988 + 0.000571447349*_Complex_I, 0.016943660061 + 0.007409564688*_Complex_I, 0.024399758745 + -0.020976831445*_Complex_I, 0.007946403220 + 0.025133322345*_Complex_I, -0.012852674380 + -0.005689128468*_Complex_I, 0.003313037804 + 0.000263249514*_Complex_I, -0.027377402722 + -0.004127607511*_Complex_I, -0.026320368186 + 0.009134835527*_Complex_I, -0.012297987932 + 0.013200852928*_Complex_I, 0.007101262388 + -0.017149417134*_Complex_I, 0.000657385901 + 0.001192381502*_Complex_I, -0.008080139857 + 0.018480645475*_Complex_I, -0.007551765865 + 0.003627711775*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/firfilt_crcf_data_h23x64.c000066400000000000000000000200211317124540100245160ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firfilt_crcf_data_h23x64.c: autotest firfilt data // #include float firfilt_crcf_data_h23x64_h[] = { 0.158654410967, -0.020397216842, -0.054283334982, 0.077922310650, -0.072938526203, -0.018649195029, 0.037699516688, 0.039617662775, -0.201106990060, -0.045133363773, -0.083275831491, -0.080588772189, -0.009860694810, 0.086105167459, 0.145475786114, -0.015729607185, -0.064199255334, -0.041339777246, 0.031333251672, -0.178929283974, -0.144469434532, -0.088642880661, 0.061210119166}; float complex firfilt_crcf_data_h23x64_x[] = { -0.061754655621 + 0.035123551291*_Complex_I, -0.042987945529 + 0.204710494551*_Complex_I, -0.115448103025 + -0.048546960311*_Complex_I, -0.107929842580 + -0.067280385493*_Complex_I, -0.138103588190 + 0.010448310166*_Complex_I, -0.001556297552 + 0.087792883061*_Complex_I, 0.046355639811 + 0.064514990229*_Complex_I, -0.073718979418 + 0.103212389197*_Complex_I, -0.167000830993 + -0.051389222147*_Complex_I, -0.014426416714 + 0.176317900074*_Complex_I, -0.107373342455 + -0.005804161965*_Complex_I, 0.080493073150 + -0.061646586042*_Complex_I, 0.027796421084 + -0.154117176222*_Complex_I, 0.146227243025 + -0.085442723323*_Complex_I, -0.069720789489 + 0.186876621048*_Complex_I, 0.062823376713 + 0.065977046975*_Complex_I, 0.090031816754 + 0.114581114467*_Complex_I, 0.086442323768 + 0.125045380084*_Complex_I, 0.019615700330 + -0.022164049481*_Complex_I, 0.002010913947 + 0.016348332723*_Complex_I, 0.115492888651 + -0.140112679132*_Complex_I, -0.000370552599 + 0.115418598778*_Complex_I, 0.171462023973 + 0.045787506437*_Complex_I, -0.044111687463 + -0.011704116119*_Complex_I, -0.267816339997 + 0.084734013406*_Complex_I, 0.013814245144 + 0.002740227971*_Complex_I, 0.090220778414 + 0.134830380675*_Complex_I, -0.106145737111 + -0.024658098491*_Complex_I, -0.112807070004 + 0.044997920710*_Complex_I, -0.192053613103 + -0.062114377970*_Complex_I, -0.079637314543 + 0.045259089396*_Complex_I, 0.012470128523 + -0.117498759881*_Complex_I, -0.029098880159 + 0.100511335166*_Complex_I, 0.076820185739 + -0.000579442122*_Complex_I, -0.146557365265 + 0.068919305920*_Complex_I, 0.046650052137 + 0.086754950098*_Complex_I, 0.049312254431 + 0.100155311839*_Complex_I, -0.018181427657 + -0.155695073922*_Complex_I, -0.020818721382 + 0.050839229113*_Complex_I, 0.075624933038 + -0.140809485613*_Complex_I, 0.024131064286 + -0.061085135867*_Complex_I, -0.031646019927 + -0.020171616314*_Complex_I, 0.029466323016 + -0.143095954720*_Complex_I, -0.000140873686 + 0.104732973661*_Complex_I, 0.124462359562 + -0.105079943629*_Complex_I, -0.058374142846 + 0.033466529094*_Complex_I, 0.026595988216 + 0.220281782376*_Complex_I, -0.007221829817 + 0.141135026450*_Complex_I, -0.021218003577 + -0.050066565886*_Complex_I, 0.035694484054 + 0.231602026762*_Complex_I, 0.102466686268 + -0.099286054817*_Complex_I, -0.054792214672 + 0.060392934122*_Complex_I, -0.001852582407 + 0.025794064903*_Complex_I, 0.071274514129 + 0.142237231718*_Complex_I, 0.029476880291 + 0.023165981190*_Complex_I, -0.027797892310 + -0.051616914281*_Complex_I, 0.061786844168 + 0.001190554171*_Complex_I, 0.041304624689 + -0.028506531399*_Complex_I, -0.075701492591 + -0.019189579127*_Complex_I, -0.043195431393 + -0.100084431779*_Complex_I, 0.039964361882 + 0.004559897250*_Complex_I, -0.252729884604 + -0.091698894534*_Complex_I, -0.056671384848 + 0.100393269844*_Complex_I, 0.047875493425 + -0.053453060952*_Complex_I}; float complex firfilt_crcf_data_h23x64_y[] = { -0.009797648512 + 0.005572506341*_Complex_I, -0.005560604075 + 0.031761800240*_Complex_I, -0.014087267678 + -0.013784337240*_Complex_I, -0.017247262021 + -0.018059567129*_Complex_I, -0.012287793463 + 0.019054948700*_Complex_I, 0.003719976223 + -0.002001383647*_Complex_I, 0.013367035883 + 0.003682443788*_Complex_I, -0.017360179024 + 0.026029334165*_Complex_I, -0.009179615321 + -0.007210433367*_Complex_I, 0.014210107693 + -0.025365792504*_Complex_I, 0.004045839585 + -0.004700697501*_Complex_I, 0.037185762921 + -0.032401586998*_Complex_I, 0.069046316115 + -0.013271584282*_Complex_I, 0.033064747039 + -0.020579633062*_Complex_I, -0.010997016057 + 0.045070901497*_Complex_I, 0.004422576554 + 0.002390243257*_Complex_I, 0.033125238067 + -0.006016697456*_Complex_I, -0.016975087630 + -0.035483520861*_Complex_I, 0.038314599881 + -0.033008052971*_Complex_I, 0.036960796853 + 0.013280585218*_Complex_I, 0.048652304550 + -0.021208466846*_Complex_I, -0.029006820125 + 0.022587827802*_Complex_I, 0.028022156827 + 0.005836099363*_Complex_I, 0.022094506847 + 0.031041275846*_Complex_I, -0.052928165220 + -0.021052052066*_Complex_I, 0.018511503181 + -0.110568047514*_Complex_I, 0.013151749885 + -0.084455750067*_Complex_I, -0.002103151576 + -0.014246866235*_Complex_I, -0.004981810769 + 0.036099080474*_Complex_I, 0.027562144328 + -0.004142628424*_Complex_I, -0.062965485082 + -0.000721660223*_Complex_I, 0.001355528130 + 0.039494603193*_Complex_I, -0.013676340973 + 0.019821560124*_Complex_I, 0.017190322837 + -0.023603201848*_Complex_I, -0.013639010839 + -0.090413596530*_Complex_I, 0.035568646535 + -0.005785803158*_Complex_I, 0.009541669638 + -0.037656127703*_Complex_I, -0.037436737172 + -0.045380997215*_Complex_I, -0.001373976193 + -0.005853270514*_Complex_I, 0.037863401295 + 0.058080181959*_Complex_I, 0.036122757372 + -0.031465040781*_Complex_I, -0.080256218002 + 0.010144726857*_Complex_I, -0.012130289685 + -0.064577476905*_Complex_I, 0.001740193468 + -0.024376309816*_Complex_I, 0.062877940058 + -0.049615721082*_Complex_I, 0.020116976889 + -0.036592663265*_Complex_I, -0.000380054511 + 0.039223753313*_Complex_I, 0.017068821785 + 0.021526831643*_Complex_I, 0.021954695055 + 0.037691348334*_Complex_I, 0.067990755649 + 0.068783656132*_Complex_I, 0.037145711035 + 0.043650952232*_Complex_I, -0.014003385917 + -0.065891325372*_Complex_I, -0.048189055475 + 0.056129109261*_Complex_I, 0.057414520047 + -0.036184434048*_Complex_I, -0.016064913162 + -0.054756587631*_Complex_I, -0.016229690128 + -0.092689300019*_Complex_I, 0.009080345865 + 0.006957646952*_Complex_I, 0.017213929524 + -0.068928651567*_Complex_I, -0.036862824002 + 0.024446597685*_Complex_I, -0.018313177259 + 0.012846228600*_Complex_I, -0.002556177228 + 0.060786016298*_Complex_I, -0.069716561264 + 0.004791194532*_Complex_I, -0.004221111697 + -0.015828369005*_Complex_I, 0.018252044788 + 0.020184229477*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/firfilt_crcf_data_h4x8.c000066400000000000000000000042551317124540100243660ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firfilt_crcf_data_h4x8.c: autotest firfilt data // #include float firfilt_crcf_data_h4x8_h[] = { 0.081125556518, -0.048097526791, 0.083945750272, 0.016820374297}; float complex firfilt_crcf_data_h4x8_x[] = { 0.212556497097 + -0.062593316778*_Complex_I, 0.074632428892 + -0.155168218555*_Complex_I, -0.139928836211 + -0.151937330426*_Complex_I, 0.057785165005 + 0.027214057011*_Complex_I, 0.047104310251 + -0.016114794312*_Complex_I, 0.140236563713 + 0.296500956218*_Complex_I, -0.134588116658 + -0.011633439603*_Complex_I, 0.035369414992 + -0.047878728319*_Complex_I}; float complex firfilt_crcf_data_h4x8_y[] = { 0.017243764119 + -0.005077917658*_Complex_I, -0.004168844485 + -0.009577524353*_Complex_I, 0.002901774665 + -0.010117235877*_Complex_I, 0.021258439696 + -0.004562990201*_Complex_I, -0.009449045890 + -0.017980731205*_Complex_I, 0.011608332082 + 0.024557748499*_Complex_I, -0.012737392976 + -0.016099749821*_Complex_I, 0.021907294708 + 0.021294289547*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/firfilt_crcf_data_h7x16.c000066400000000000000000000060151317124540100244440ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firfilt_crcf_data_h7x16.c: autotest firfilt data // #include float firfilt_crcf_data_h7x16_h[] = { 0.027835212534, -0.040645664069, -0.095885554580, 0.200974194416, 0.142773900141, -0.084839081860, 0.026675441534}; float complex firfilt_crcf_data_h7x16_x[] = { -0.050554619430 + -0.051932459243*_Complex_I, 0.033654160787 + 0.041969310283*_Complex_I, 0.083110727700 + 0.078162488859*_Complex_I, -0.077891200631 + -0.098321707426*_Complex_I, -0.187861386260 + -0.107086777579*_Complex_I, -0.151977015997 + 0.027468572824*_Complex_I, 0.081513596724 + 0.062785557274*_Complex_I, 0.031782625481 + -0.013462505188*_Complex_I, -0.007610286404 + 0.087544934055*_Complex_I, 0.155881117469 + 0.110195135092*_Complex_I, -0.104429397916 + 0.137400420010*_Complex_I, -0.116176549274 + 0.071085593565*_Complex_I, -0.164136953851 + 0.202903767828*_Complex_I, 0.084667802512 + 0.059492856539*_Complex_I, 0.026416620904 + 0.138990393077*_Complex_I, -0.116423582608 + -0.028759261678*_Complex_I}; float complex firfilt_crcf_data_h7x16_y[] = { -0.001407198576 + -0.001445551040*_Complex_I, 0.002991596797 + 0.003279053964*_Complex_I, 0.005792966776 + 0.005449371658*_Complex_I, -0.018933330628 + -0.020375106640*_Complex_I, -0.010486602589 + -0.005458937140*_Complex_I, 0.036671134061 + 0.040651505702*_Complex_I, 0.018467514775 + -0.002647275592*_Complex_I, -0.042885517171 + -0.046631668104*_Complex_I, -0.057859564144 + -0.002378383977*_Complex_I, 0.010144797998 + 0.023802283800*_Complex_I, 0.017394817258 + -0.007977151925*_Complex_I, -0.021897278604 + -0.003093924849*_Complex_I, 0.039886090889 + 0.027046322091*_Complex_I, 0.022929460881 + 0.022153334200*_Complex_I, -0.038653803420 + 0.008885169596*_Complex_I, -0.048989194709 + 0.030055784593*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/firfilt_rrrf_data_h13x32.c000066400000000000000000000054431317124540100245610ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firfilt_rrrf_data_h13x32.c: autotest firfilt data // float firfilt_rrrf_data_h13x32_h[] = { 0.061701400663, -0.003256845257, 0.085737504490, -0.119088464421, -0.094195167190, -0.035614627393, -0.075640421976, -0.178180567927, 0.062656377018, 0.024575001277, 0.158593583928, 0.002228379520, 0.112351904789}; float firfilt_rrrf_data_h13x32_x[] = { -0.020470493148, 0.102018118476, -0.054985718021, 0.006308577753, -0.136776277914, -0.097553343057, 0.015106021667, -0.115276028482, -0.139555063727, -0.008140535272, 0.149942052537, -0.011892278070, 0.065230575705, 0.142075094351, -0.164907789585, -0.032484693281, -0.096276951150, 0.147981941286, -0.058167278365, 0.122586631059, -0.085249376452, -0.044902927900, 0.078432553797, 0.057861317911, -0.063852807160, -0.049949958624, -0.041909155283, -0.022591033341, 0.048035976026, 0.022495836486, -0.073843897589, 0.112675367305}; float firfilt_rrrf_data_h13x32_y[] = { -0.001263058100, 0.006361330031, -0.005480042042, 0.011752906544, -0.023395131780, -0.007365237036, -0.008133908376, -0.001942584790, 0.002035200118, 0.017539310799, 0.018129651215, 0.071947442682, 0.032171241395, 0.004309016586, -0.015673178031, 0.002288611018, -0.077270639492, -0.048373764758, -0.012295934305, 0.006856074159, -0.019007594657, 0.044313034038, 0.016681139459, 0.021356291565, -0.035698344648, 0.018453059195, -0.069848287101, 0.038262898124, -0.010626132241, 0.023942333214, -0.013545270316, 0.034191460826}; liquid-dsp-1.3.1/src/filter/tests/data/firfilt_rrrf_data_h23x64.c000066400000000000000000000103531317124540100245630ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firfilt_rrrf_data_h23x64.c: autotest firfilt data // float firfilt_rrrf_data_h23x64_h[] = { 0.023507854506, 0.027103933172, 0.106752895472, 0.074063587060, 0.012575431714, -0.014208904360, -0.189995720602, 0.034113160679, 0.175609922460, 0.105200934542, -0.005136522642, -0.005531746670, 0.139731146359, -0.079842377920, -0.233214917226, 0.035638281722, -0.163205439104, -0.032478500610, 0.199430113992, 0.220129425730, -0.036005167889, 0.056409106456, -0.004421322176}; float firfilt_rrrf_data_h23x64_x[] = { -0.013049061997, 0.119281727724, -0.119365267096, 0.039835879910, -0.009513587246, 0.082243762515, 0.027956820983, -0.069085027701, 0.052848019057, 0.146020985374, 0.037417929487, -0.084232021180, -0.009683296201, -0.090624445719, -0.006075254980, 0.165633370941, -0.073874907410, 0.017988275377, 0.070181770610, -0.244164921762, -0.038716233769, 0.076498331411, -0.013031514838, -0.213155932917, -0.027341233086, -0.146873071789, -0.026995500788, -0.072655809839, 0.156894258163, 0.124930378658, 0.056420922814, 0.134062816355, -0.086478418152, 0.065523216564, -0.081200039055, 0.011086704550, 0.085758668011, 0.132499850065, 0.054287271241, 0.057554900510, -0.022403923256, 0.244428874813, 0.084740945011, 0.112048571173, -0.245511705590, 0.030473857673, -0.089496518267, 0.112146468923, -0.038155919073, -0.079948318739, 0.081965047586, 0.060785574587, -0.015596830096, 0.062834032397, -0.138572554778, 0.183714729747, 0.046778584717, -0.046081790098, -0.074463177805, -0.206183023427, 0.125672790474, 0.071969502765, 0.088478692161, -0.118547492713}; float firfilt_rrrf_data_h23x64_y[] = { -0.000306755451, 0.002450376596, -0.000966042507, 0.009468397319, -0.003216187841, -0.001227073462, 0.004104453009, -0.013702311097, 0.032216367463, 0.008663721625, -0.000634352930, -0.004782446546, 0.012088802412, 0.038158275560, -0.033642624259, -0.056941408268, 0.025461989933, 0.042996863950, 0.042722153417, -0.013343258900, -0.002992404220, -0.070410666038, -0.020716833687, -0.012052257283, 0.015366009966, -0.010804920764, -0.018064798938, 0.027733552912, -0.024577324228, 0.020395693321, 0.044679445466, -0.071992656961, -0.028274328337, 0.109882255190, -0.054423216252, -0.062518613459, 0.073109299563, -0.001030697779, 0.000264209985, 0.117080616804, 0.074883914872, 0.008816712343, -0.093804636161, -0.024674797173, -0.069634193023, -0.015132328421, 0.010801011890, -0.019904446976, 0.054767171785, 0.070007069212, 0.098407344602, -0.023208041689, -0.034398540605, -0.056178855164, 0.015638332591, 0.011048505195, -0.032658159097, -0.031311550317, 0.061445928366, 0.033547250971, 0.134751463913, -0.058463369920, 0.012179813382, -0.001597271199}; liquid-dsp-1.3.1/src/filter/tests/data/firfilt_rrrf_data_h4x8.c000066400000000000000000000032471317124540100244240ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firfilt_rrrf_data_h4x8.c: autotest firfilt data // float firfilt_rrrf_data_h4x8_h[] = { -0.121887159208, -0.231303112477, -0.011081038093, 0.002940945390}; float firfilt_rrrf_data_h4x8_x[] = { 0.087523073427, 0.091626543082, 0.069905988906, -0.025530671018, -0.085926435885, 0.016121796124, 0.067241716218, 0.036151454364}; float firfilt_rrrf_data_h4x8_y[] = { -0.010667938785, -0.031412458342, -0.030683993510, -0.013815528486, 0.015873490575, 0.018398508167, -0.011047853592, -0.020390967516}; liquid-dsp-1.3.1/src/filter/tests/data/firfilt_rrrf_data_h7x16.c000066400000000000000000000040471317124540100245050ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firfilt_rrrf_data_h7x16.c: autotest firfilt data // float firfilt_rrrf_data_h7x16_h[] = { 0.167653994833, 0.011522192990, 0.015882599202, -0.093561396312, 0.074301353348, -0.124295601121, 0.032095823166}; float firfilt_rrrf_data_h7x16_x[] = { 0.096678620741, 0.015023630036, 0.051530016668, -0.094237043292, 0.007423744308, 0.024664429619, -0.199548815687, 0.003258035222, 0.082829872734, 0.142277057992, -0.149671886106, -0.058687993370, 0.018936199920, -0.026660942281, 0.016612364911, 0.178689105006}; float firfilt_rrrf_data_h7x16_y[] = { 0.016208556982, 0.003632721318, 0.010347826097, -0.024012250428, 0.006754954149, -0.012997772766, -0.019171751321, -0.014980556455, 0.022366048926, 0.041414757082, -0.040097174540, 0.008782967641, -0.013845574916, 0.009200324306, -0.017877119698, 0.046763669812}; liquid-dsp-1.3.1/src/filter/tests/data/gen_firfilt_data.m000066400000000000000000000120021317124540100233460ustar00rootroot00000000000000% % generate firfilt data for autotests % clear all; close all; % % function to generate data % function gen_firfilt_datafile(type,h_len,x_len); % determine type x_complex = 0; h_complex = 0; y_complex = 0; if strcmp(type,'rrr'), x_complex = 0; h_complex = 0; y_complex = 0; elseif strcmp(type,'crc'), x_complex = 1; h_complex = 0; y_complex = 1; elseif strcmp(type,'ccc'), x_complex = 1; h_complex = 1; y_complex = 1; else, error(['invalid/unsupported type (' type ')']); end; % generate filter coefficients if h_complex, h = 0.1*[randn(1,h_len) + 1i*randn(1,h_len)]; else, h = 0.1*[randn(1,h_len)]; end; % generate input data if x_complex, x = 0.1*[randn(1,x_len) + 1i*randn(1,x_len)]; else, x = 0.1*[randn(1,x_len)]; end; % filter input y = filter(h,1,x); y_len = length(y); % print results % filename example: firfilt_crcf_data_h12x44.c filename = ['firfilt_' type 'f_data_h' num2str(h_len) 'x' num2str(x_len) '.c']; fid = fopen(filename,'w'); fprintf(fid,'/* Copyright (c) 2007 - 2015 Joseph Gaeddert\n'); fprintf(fid,' *\n'); fprintf(fid,' * Permission is hereby granted, free of charge, to any person obtaining a copy\n'); fprintf(fid,' * of this software and associated documentation files (the "Software"), to deal\n'); fprintf(fid,' * in the Software without restriction, including without limitation the rights\n'); fprintf(fid,' * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n'); fprintf(fid,' * copies of the Software, and to permit persons to whom the Software is\n'); fprintf(fid,' * furnished to do so, subject to the following conditions:\n'); fprintf(fid,' * \n'); fprintf(fid,' * The above copyright notice and this permission notice shall be included in\n'); fprintf(fid,' * all copies or substantial portions of the Software.\n'); fprintf(fid,' *\n'); fprintf(fid,' * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n'); fprintf(fid,' * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n'); fprintf(fid,' * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n'); fprintf(fid,' * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n'); fprintf(fid,' * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n'); fprintf(fid,' * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n'); fprintf(fid,' * THE SOFTWARE.\n'); fprintf(fid,' */\n'); fprintf(fid,'\n'); fprintf(fid,'//\n'); fprintf(fid,'// %s: autotest firfilt data\n', filename); fprintf(fid,'//\n'); fprintf(fid,'\n'); if h_complex || x_complex || y_complex, fprintf(fid,'#include \n\n'); end; % construct base name, e.g. 'firfilt_crcf_test_h12x44' basename = ['firfilt_' type 'f_data_h' num2str(h_len) 'x' num2str(x_len)]; % save coefficients array if h_complex, fprintf(fid,'float complex '); else, fprintf(fid,'float '); end; fprintf(fid,'%s_h[] = {\n', basename); for i=1:h_len, if h_complex, fprintf(fid,' %16.12f + %16.12f*_Complex_I', real(h(i)), imag(h(i))); else, fprintf(fid,' %16.12f', h(i)); end; if i==h_len, fprintf(fid,'};\n\n'); else, fprintf(fid,',\n'); end; end; % save input array if x_complex, fprintf(fid,'float complex '); else, fprintf(fid,'float '); end; fprintf(fid,'%s_x[] = {\n', basename); for i=1:x_len, if x_complex, fprintf(fid,' %16.12f + %16.12f*_Complex_I', real(x(i)), imag(x(i))); else, fprintf(fid,' %16.12f', x(i)); end; if i==x_len, fprintf(fid,'};\n\n'); else, fprintf(fid,',\n'); end; end; % save output array if y_complex, fprintf(fid,'float complex '); else, fprintf(fid,'float '); end; fprintf(fid,'%s_y[] = {\n', basename); for i=1:y_len, if y_complex, fprintf(fid,' %16.12f + %16.12f*_Complex_I', real(y(i)), imag(y(i))); else, fprintf(fid,' %16.12f', y(i)); end; if i==y_len, fprintf(fid,'};\n\n'); else, fprintf(fid,',\n'); end; end; fclose(fid); printf('results written to %s\n', filename); endfunction; % % generate firfilt data for autotests % % rrrf data gen_firfilt_datafile('rrr', 4, 8); gen_firfilt_datafile('rrr', 7, 16); gen_firfilt_datafile('rrr', 13, 32); gen_firfilt_datafile('rrr', 23, 64); % crcf data gen_firfilt_datafile('crc', 4, 8); gen_firfilt_datafile('crc', 7, 16); gen_firfilt_datafile('crc', 13, 32); gen_firfilt_datafile('crc', 23, 64); % cccf data gen_firfilt_datafile('ccc', 4, 8); gen_firfilt_datafile('ccc', 7, 16); gen_firfilt_datafile('ccc', 13, 32); gen_firfilt_datafile('ccc', 23, 64); liquid-dsp-1.3.1/src/filter/tests/data/gen_iirfilt_data.m000066400000000000000000000146461317124540100233710ustar00rootroot00000000000000% % generate iirfilt data for autotests % clear all; close all; % % function to generate data % function gen_iirfilt_datafile(type,h_len,x_len); % determine type x_complex = 0; h_complex = 0; y_complex = 0; if strcmp(type,'rrr'), x_complex = 0; h_complex = 0; y_complex = 0; elseif strcmp(type,'crc'), x_complex = 1; h_complex = 0; y_complex = 1; elseif strcmp(type,'ccc'), x_complex = 1; h_complex = 1; y_complex = 1; else, error(['invalid/unsupported type (' type ')']); end; % % generate low-pass butterworth filter coefficients % % generate complex roots n = h_len - 1; % filter order r = mod(n, 2); % odd/even order L = (n-r)/2; % filter semi-length pa = zeros(1,n); % analog poles (roots of a) for i=0:(L-1), theta = (2*(i+1) + n - 1)*pi / (2*n); pa(2*i+1) = exp( j*theta ); pa(2*i+2) = exp(-j*theta ); end; if r, pa(end) = -1; end; % convert analog poles/zeros/gain to digital fc = 0.1; m = abs(tan(pi*fc)); p = zeros(1,n); z = zeros(1,n); k = 1; for i=1:n, % compute digital zeros... z(i) = -1; % compute digital pols pm = pa(i)*m; p(i) = (1 + pm)/(1 - pm); % compute digital gain k = k*(1 - p(i)) / (1 - z(i)); end; % expand roots b = [1]; a = [1]; k = 1; % gain for i=1:n, b = conv(b, [1, -z(i)]); a = conv(a, [1, -p(i)]); k = k*(1 - p(i))/(1 - z(i)); end; k = real(k); a = real(a); b = real(b) * k; % modulate coefficients for complex type if h_complex, for i=1:h_len, a(i) = a(i) * exp(j*2*pi*0.1*i); b(i) = b(i) * exp(j*2*pi*0.1*i); end; end; % generate input data if x_complex, x = 0.1*[randn(1,x_len) + 1i*randn(1,x_len)]; else, x = 0.1*[randn(1,x_len)]; end; % filter input y = filter(b,a,x); y_len = length(y); % print results % filename example: iirfilt_crcf_data_h12x44.c filename = ['iirfilt_' type 'f_data_h' num2str(h_len) 'x' num2str(x_len) '.c']; fid = fopen(filename,'w'); fprintf(fid,'/* Copyright (c) 2007 - 2015 Joseph Gaeddert\n'); fprintf(fid,' *\n'); fprintf(fid,' * Permission is hereby granted, free of charge, to any person obtaining a copy\n'); fprintf(fid,' * of this software and associated documentation files (the "Software"), to deal\n'); fprintf(fid,' * in the Software without restriction, including without limitation the rights\n'); fprintf(fid,' * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n'); fprintf(fid,' * copies of the Software, and to permit persons to whom the Software is\n'); fprintf(fid,' * furnished to do so, subject to the following conditions:\n'); fprintf(fid,' * \n'); fprintf(fid,' * The above copyright notice and this permission notice shall be included in\n'); fprintf(fid,' * all copies or substantial portions of the Software.\n'); fprintf(fid,' *\n'); fprintf(fid,' * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n'); fprintf(fid,' * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n'); fprintf(fid,' * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n'); fprintf(fid,' * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n'); fprintf(fid,' * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n'); fprintf(fid,' * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n'); fprintf(fid,' * THE SOFTWARE.\n'); fprintf(fid,' */\n'); fprintf(fid,'\n'); fprintf(fid,'//\n'); fprintf(fid,'// %s: autotest iirfilt data\n', filename); fprintf(fid,'//\n'); fprintf(fid,'\n'); if h_complex || x_complex || y_complex, fprintf(fid,'#include \n\n'); end; % construct base name, e.g. 'iirfilt_crcf_test_h12x44' basename = ['iirfilt_' type 'f_data_h' num2str(h_len) 'x' num2str(x_len)]; % save coefficients arrays if h_complex, fprintf(fid,'float complex '); else, fprintf(fid,'float '); end; fprintf(fid,'%s_b[] = {\n', basename); for i=1:h_len, if h_complex, fprintf(fid,' %16.12f + %16.12f*_Complex_I', real(b(i)), imag(b(i))); else, fprintf(fid,' %16.12f', b(i)); end; if i==h_len, fprintf(fid,'};\n\n'); else, fprintf(fid,',\n'); end; end; % save coefficients arrays if h_complex, fprintf(fid,'float complex '); else, fprintf(fid,'float '); end; fprintf(fid,'%s_a[] = {\n', basename); for i=1:h_len, if h_complex, fprintf(fid,' %16.12f + %16.12f*_Complex_I', real(a(i)), imag(a(i))); else, fprintf(fid,' %16.12f', a(i)); end; if i==h_len, fprintf(fid,'};\n\n'); else, fprintf(fid,',\n'); end; end; % save input array if x_complex, fprintf(fid,'float complex '); else, fprintf(fid,'float '); end; fprintf(fid,'%s_x[] = {\n', basename); for i=1:x_len, if x_complex, fprintf(fid,' %16.12f + %16.12f*_Complex_I', real(x(i)), imag(x(i))); else, fprintf(fid,' %16.12f', x(i)); end; if i==x_len, fprintf(fid,'};\n\n'); else, fprintf(fid,',\n'); end; end; % save output array if y_complex, fprintf(fid,'float complex '); else, fprintf(fid,'float '); end; fprintf(fid,'%s_y[] = {\n', basename); for i=1:y_len, if y_complex, fprintf(fid,' %16.12f + %16.12f*_Complex_I', real(y(i)), imag(y(i))); else, fprintf(fid,' %16.12f', y(i)); end; if i==y_len, fprintf(fid,'};\n\n'); else, fprintf(fid,',\n'); end; end; fclose(fid); printf('results written to %s\n', filename); endfunction; % % generate test data % % rrrf data gen_iirfilt_datafile('rrr', 3, 64); gen_iirfilt_datafile('rrr', 5, 64); gen_iirfilt_datafile('rrr', 7, 64); % crcf data gen_iirfilt_datafile('crc', 3, 64); gen_iirfilt_datafile('crc', 5, 64); gen_iirfilt_datafile('crc', 7, 64); % cccf data gen_iirfilt_datafile('ccc', 3, 64); gen_iirfilt_datafile('ccc', 5, 64); gen_iirfilt_datafile('ccc', 7, 64); liquid-dsp-1.3.1/src/filter/tests/data/iirfilt_cccf_data_h3x64.c000066400000000000000000000176451317124540100244420ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // iirfilt_cccf_data_h3x64.c: autotest iirfilt data // #include float complex iirfilt_cccf_data_h3x64_b[] = { 0.054572462936 + 0.039649215181*_Complex_I, 0.041689651984 + 0.128307555581*_Complex_I, -0.020844825992 + 0.064153777791*_Complex_I}; float complex iirfilt_cccf_data_h3x64_a[] = { 0.809016994375 + 0.587785252292*_Complex_I, -0.353200399524 + -1.087039054939*_Complex_I, -0.127562709117 + 0.392597649806*_Complex_I}; float complex iirfilt_cccf_data_h3x64_x[] = { -0.024833213118 + -0.034917156419*_Complex_I, -0.203303753453 + -0.146194321825*_Complex_I, 0.046955837790 + -0.018522626941*_Complex_I, -0.009310945228 + -0.145839543251*_Complex_I, 0.050014713286 + 0.074118954232*_Complex_I, 0.053029015111 + 0.038309174053*_Complex_I, 0.024855918446 + -0.013616668881*_Complex_I, -0.075445314910 + -0.100119258919*_Complex_I, 0.160017817197 + 0.023949186601*_Complex_I, 0.146076212120 + -0.000269193014*_Complex_I, 0.015195370146 + 0.275825448022*_Complex_I, 0.071299735570 + 0.054576601750*_Complex_I, -0.143098150747 + 0.029176300561*_Complex_I, -0.029456081088 + -0.072086611744*_Complex_I, 0.068475191123 + -0.216689722106*_Complex_I, 0.076757256920 + 0.097275143829*_Complex_I, -0.043846185419 + 0.306249972124*_Complex_I, 0.070413973865 + 0.090585247522*_Complex_I, 0.132485779791 + -0.159268673808*_Complex_I, 0.026917161537 + -0.100640356329*_Complex_I, 0.007473659993 + 0.080379816333*_Complex_I, 0.190359743048 + 0.112433411463*_Complex_I, -0.120301668631 + 0.050439886600*_Complex_I, -0.046297800762 + -0.003443247054*_Complex_I, -0.124614723514 + 0.115573697342*_Complex_I, 0.145848137742 + -0.028451577663*_Complex_I, 0.150217608922 + 0.041411226796*_Complex_I, 0.065634804159 + -0.047306957256*_Complex_I, -0.082921695322 + -0.079112928494*_Complex_I, -0.145226550689 + -0.188234399475*_Complex_I, -0.034483517482 + 0.115199412906*_Complex_I, 0.011933371178 + -0.013196555096*_Complex_I, -0.135183164034 + -0.016707765823*_Complex_I, -0.023217606041 + 0.034147466698*_Complex_I, 0.048294051851 + -0.023691893478*_Complex_I, 0.032010168738 + -0.060275616633*_Complex_I, -0.145436488960 + -0.187315942943*_Complex_I, -0.087977813311 + 0.136955551173*_Complex_I, -0.124764798898 + 0.030020090717*_Complex_I, -0.085914119584 + 0.066553144151*_Complex_I, 0.080940796771 + 0.007884486399*_Complex_I, -0.073277212995 + 0.029723354716*_Complex_I, 0.218025609607 + -0.011507652078*_Complex_I, -0.050453154704 + 0.168205457912*_Complex_I, 0.065308138197 + 0.010673521587*_Complex_I, 0.164945191560 + 0.069669644982*_Complex_I, -0.019014062556 + -0.020454796529*_Complex_I, 0.064918556283 + -0.050548033336*_Complex_I, 0.028164657959 + -0.173995204773*_Complex_I, 0.122134013651 + 0.005095487421*_Complex_I, 0.234213744496 + -0.143695630868*_Complex_I, 0.084679105788 + -0.021311700717*_Complex_I, 0.054268742828 + 0.007308179887*_Complex_I, -0.029620954263 + 0.054909993996*_Complex_I, 0.019992503058 + -0.115385511675*_Complex_I, -0.064206101272 + -0.057135496497*_Complex_I, 0.102760385313 + 0.007278409932*_Complex_I, 0.177210934528 + 0.054290451135*_Complex_I, 0.128563865148 + 0.003219961582*_Complex_I, -0.083833350402 + 0.040801324808*_Complex_I, -0.080842077428 + 0.120550027178*_Complex_I, -0.019021541271 + 0.041759686472*_Complex_I, -0.115073955933 + -0.091807014377*_Complex_I, 0.153344859386 + -0.062742865142*_Complex_I}; float complex iirfilt_cccf_data_h3x64_y[] = { -0.001675131192 + -0.002355346350*_Complex_I, -0.013622046565 + -0.018945208542*_Complex_I, -0.006286044544 + -0.061360482408*_Complex_I, 0.040817629094 + -0.077423785655*_Complex_I, 0.082560403156 + -0.042905448043*_Complex_I, 0.081885166095 + 0.020646150389*_Complex_I, 0.035185788192 + 0.059385572466*_Complex_I, -0.012349534229 + 0.041702279147*_Complex_I, -0.008719427172 + -0.005108227398*_Complex_I, 0.043586624569 + -0.002694870087*_Complex_I, 0.060010371171 + 0.071790678150*_Complex_I, -0.011700201664 + 0.134289646346*_Complex_I, -0.104085781588 + 0.103901309521*_Complex_I, -0.133770658357 + 0.006298194510*_Complex_I, -0.071593140378 + -0.089829654416*_Complex_I, 0.047530468946 + -0.094499459711*_Complex_I, 0.094339040540 + 0.021353778886*_Complex_I, 0.000763487486 + 0.119530519765*_Complex_I, -0.094370685059 + 0.079578408854*_Complex_I, -0.069334619720 + -0.012623371571*_Complex_I, 0.012050086613 + -0.029603434811*_Complex_I, 0.049219627613 + 0.026131367418*_Complex_I, 0.013542931769 + 0.089200137012*_Complex_I, -0.066921684818 + 0.079213353516*_Complex_I, -0.100736964307 + 0.008675016473*_Complex_I, -0.073014776026 + -0.045716119068*_Complex_I, -0.002251024625 + -0.047215888024*_Complex_I, 0.043409846071 + 0.011329094890*_Complex_I, 0.020075927067 + 0.051751627220*_Complex_I, -0.025464006128 + 0.018170901171*_Complex_I, -0.017900643236 + -0.046047380472*_Complex_I, 0.021720291461 + -0.051218319397*_Complex_I, 0.023820600962 + -0.021299144521*_Complex_I, -0.000443310781 + -0.015435045664*_Complex_I, -0.005171097244 + -0.029938427283*_Complex_I, 0.015962947694 + -0.032614702790*_Complex_I, 0.026567768778 + -0.027656459980*_Complex_I, 0.025886386590 + -0.031773276552*_Complex_I, 0.011142820861 + -0.022130140814*_Complex_I, -0.023018410554 + -0.024004380806*_Complex_I, -0.028989134806 + -0.045608118967*_Complex_I, -0.005447370179 + -0.044390449128*_Complex_I, 0.016111369022 + -0.025494020513*_Complex_I, 0.033164181168 + 0.018349162452*_Complex_I, -0.002881749460 + 0.064999887863*_Complex_I, -0.037794707920 + 0.054120734400*_Complex_I, -0.033549552744 + 0.041209685622*_Complex_I, -0.029745345484 + 0.028385093658*_Complex_I, -0.012206946909 + 0.000426141907*_Complex_I, 0.033070597342 + -0.013052292197*_Complex_I, 0.081548142195 + 0.013614572710*_Complex_I, 0.101806391304 + 0.065450185198*_Complex_I, 0.073804512902 + 0.112077362053*_Complex_I, 0.012136514124 + 0.118696097982*_Complex_I, -0.039510405075 + 0.074133214086*_Complex_I, -0.038427157781 + 0.006482000625*_Complex_I, 0.006530434509 + -0.025726623154*_Complex_I, 0.055688677705 + 0.002152977720*_Complex_I, 0.064499041530 + 0.067061388496*_Complex_I, 0.016662206642 + 0.109004403882*_Complex_I, -0.055089624558 + 0.092364887087*_Complex_I, -0.096355781376 + 0.032987760948*_Complex_I, -0.090540548264 + -0.030202075604*_Complex_I, -0.036200313340 + -0.078861745571*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/iirfilt_cccf_data_h5x64.c000066400000000000000000000201551317124540100244320ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // iirfilt_cccf_data_h5x64.c: autotest iirfilt data // #include float complex iirfilt_cccf_data_h5x64_b[] = { 0.003902975763 + 0.002835677878*_Complex_I, 0.005963216337 + 0.018352892749*_Complex_I, -0.008944824505 + 0.027529339123*_Complex_I, -0.015611903052 + 0.011342711511*_Complex_I, -0.004824343358 + 0.000000000000*_Complex_I}; float complex iirfilt_cccf_data_h5x64_a[] = { 0.809016994375 + 0.587785252292*_Complex_I, -0.732219787612 + -2.253540785927*_Complex_I, -0.715061744841 + 2.200733760162*_Complex_I, 0.853242236735 + -0.619916771678*_Complex_I, -0.187379492368 + 0.000000000000*_Complex_I}; float complex iirfilt_cccf_data_h5x64_x[] = { -0.139691779780 + -0.008483106386*_Complex_I, -0.016364784445 + -0.044182994598*_Complex_I, -0.027693468539 + -0.032794063650*_Complex_I, -0.104737698912 + 0.045751273952*_Complex_I, 0.142328368973 + -0.016207638981*_Complex_I, -0.036733974222 + -0.069688017846*_Complex_I, 0.060203955630 + 0.133175392895*_Complex_I, -0.001765141276 + 0.015191859044*_Complex_I, -0.001821699218 + -0.185914660662*_Complex_I, -0.117231114471 + -0.018976758319*_Complex_I, 0.056506370766 + 0.169868105876*_Complex_I, 0.053136860955 + -0.057576775991*_Complex_I, -0.033555900108 + 0.043991132807*_Complex_I, 0.174322859539 + -0.016411750716*_Complex_I, 0.048756047942 + -0.098065494186*_Complex_I, 0.097489588055 + -0.128464359980*_Complex_I, 0.013198059974 + 0.124985844357*_Complex_I, 0.041433063500 + -0.091281097108*_Complex_I, -0.065717968668 + -0.070462413308*_Complex_I, -0.229581678727 + 0.016392994937*_Complex_I, 0.136389898546 + -0.044643438493*_Complex_I, 0.170063648104 + -0.138204335760*_Complex_I, -0.261885373085 + -0.036055969744*_Complex_I, 0.049405811588 + -0.051424162851*_Complex_I, 0.083569523085 + -0.051487491473*_Complex_I, 0.071788757486 + -0.084369347265*_Complex_I, 0.003003764878 + 0.132223891359*_Complex_I, -0.024192470852 + 0.070159890098*_Complex_I, 0.038349724977 + 0.034974242507*_Complex_I, -0.116330185087 + 0.073501409708*_Complex_I, 0.024045897003 + 0.055819960513*_Complex_I, 0.017889237527 + -0.004469182117*_Complex_I, -0.024106461932 + -0.117012466455*_Complex_I, 0.071738300668 + 0.045036393627*_Complex_I, 0.028843052996 + -0.078769113102*_Complex_I, 0.063621483394 + -0.058568970562*_Complex_I, -0.068750316567 + 0.039728781772*_Complex_I, 0.100842588600 + 0.110482009478*_Complex_I, -0.125927976752 + 0.054480687277*_Complex_I, -0.020084532983 + -0.082864071477*_Complex_I, 0.031724080774 + -0.219039642975*_Complex_I, -0.048991766271 + -0.080798818403*_Complex_I, -0.051508440449 + 0.079624596487*_Complex_I, 0.079700844111 + 0.120292888480*_Complex_I, -0.042922860897 + -0.142995288222*_Complex_I, -0.066949342662 + 0.135970774477*_Complex_I, 0.019060475689 + 0.089390846898*_Complex_I, -0.050687616475 + 0.060447837252*_Complex_I, 0.032012337624 + -0.039188802723*_Complex_I, -0.076316420307 + -0.055316484097*_Complex_I, 0.066550049652 + 0.021107378195*_Complex_I, -0.136321433622 + 0.150816889613*_Complex_I, -0.111846218504 + -0.006277547874*_Complex_I, -0.162278498147 + 0.091756441800*_Complex_I, -0.169150340863 + 0.165920997781*_Complex_I, 0.031684008666 + -0.124705259988*_Complex_I, 0.142337877021 + -0.055397634380*_Complex_I, 0.008471585352 + 0.093647831898*_Complex_I, 0.056572323420 + 0.087500434149*_Complex_I, 0.028450731692 + -0.096199543245*_Complex_I, 0.239170762991 + 0.094782640689*_Complex_I, 0.004312922000 + -0.031035272406*_Complex_I, 0.020341098638 + -0.131272589643*_Complex_I, -0.037882757496 + 0.067034671078*_Complex_I}; float complex iirfilt_cccf_data_h5x64_y[] = { -0.000673921110 + -0.000040925418*_Complex_I, -0.003398473742 + -0.002947141586*_Complex_I, -0.002922206681 + -0.013825603768*_Complex_I, 0.011351930937 + -0.025613672702*_Complex_I, 0.033720704702 + -0.021360914845*_Complex_I, 0.044875076203 + -0.000783873348*_Complex_I, 0.038233094284 + 0.020787564602*_Complex_I, 0.020600577348 + 0.033987306418*_Complex_I, -0.002864320304 + 0.035531578366*_Complex_I, -0.022888054681 + 0.018549029265*_Complex_I, -0.019307396550 + -0.009888096688*_Complex_I, 0.008180046532 + -0.019679894883*_Complex_I, 0.026199927267 + 0.001599932018*_Complex_I, 0.012556168826 + 0.025757319931*_Complex_I, -0.012290310862 + 0.024840701409*_Complex_I, -0.017818483865 + 0.008876391685*_Complex_I, -0.003397754549 + 0.006239299921*_Complex_I, 0.005174089802 + 0.027426334643*_Complex_I, -0.014436018353 + 0.050414195091*_Complex_I, -0.048944405480 + 0.042237569566*_Complex_I, -0.061143399567 + 0.001943733440*_Complex_I, -0.031290087686 + -0.037546290383*_Complex_I, 0.024191792032 + -0.037281132537*_Complex_I, 0.055994057347 + 0.009484372596*_Complex_I, 0.035113320604 + 0.053950125645*_Complex_I, -0.000319184066 + 0.053553543859*_Complex_I, -0.003748044735 + 0.033707721402*_Complex_I, 0.009722926629 + 0.040553199336*_Complex_I, -0.006989849521 + 0.066477615272*_Complex_I, -0.055424307952 + 0.061810233374*_Complex_I, -0.086421338855 + 0.011297407459*_Complex_I, -0.068414816046 + -0.045801400009*_Complex_I, -0.020384923008 + -0.067735377613*_Complex_I, 0.019283433521 + -0.051755804853*_Complex_I, 0.034417002461 + -0.021893955948*_Complex_I, 0.031236415488 + 0.004272156915*_Complex_I, 0.019138535253 + 0.021319083228*_Complex_I, 0.004038232283 + 0.030041100664*_Complex_I, -0.013714706258 + 0.032179049891*_Complex_I, -0.035521139667 + 0.023369946120*_Complex_I, -0.050537187534 + -0.006832451226*_Complex_I, -0.030529075574 + -0.049682114778*_Complex_I, 0.029567916254 + -0.061475046317*_Complex_I, 0.079914850669 + -0.013639694885*_Complex_I, 0.066420597833 + 0.056057061117*_Complex_I, 0.001313278909 + 0.079337579523*_Complex_I, -0.048412140007 + 0.039309365767*_Complex_I, -0.044229246054 + -0.013111052841*_Complex_I, -0.014299116501 + -0.031757251195*_Complex_I, 0.001458230817 + -0.025843774220*_Complex_I, 0.003668689756 + -0.024816091795*_Complex_I, 0.013579943623 + -0.028642603348*_Complex_I, 0.025561989594 + -0.017704337809*_Complex_I, 0.013826559239 + -0.002285027652*_Complex_I, -0.012918803263 + -0.015966285682*_Complex_I, -0.016572881084 + -0.058389357048*_Complex_I, 0.019617042366 + -0.094896571757*_Complex_I, 0.080139425197 + -0.089945804958*_Complex_I, 0.120711490363 + -0.029113736905*_Complex_I, 0.094470811623 + 0.049975768139*_Complex_I, 0.016348380400 + 0.077528800177*_Complex_I, -0.038765003010 + 0.039996085676*_Complex_I, -0.035736567857 + -0.000694897676*_Complex_I, -0.015553151187 + -0.003464831303*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/iirfilt_cccf_data_h7x64.c000066400000000000000000000204651317124540100244400ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // iirfilt_cccf_data_h7x64.c: autotest iirfilt data // #include float complex iirfilt_cccf_data_h7x64_b[] = { 0.000275500748 + 0.000200163010*_Complex_I, 0.000631391531 + 0.001943223322*_Complex_I, -0.001578478829 + 0.004858058305*_Complex_I, -0.005510014966 + 0.004003260202*_Complex_I, -0.005108064791 + 0.000000000000*_Complex_I, -0.001653004490 + -0.001200978061*_Complex_I, -0.000105231922 + -0.000323870554*_Complex_I}; float complex iirfilt_cccf_data_h7x64_a[] = { 0.809016994375 + 0.587785252292*_Complex_I, -1.106106182941 + -3.404244789607*_Complex_I, -1.748624319785 + 5.381712281707*_Complex_I, 4.017105304210 + -2.918597842985*_Complex_I, -2.529494905841 + 0.000000000000*_Complex_I, 0.570578744331 + 0.414549723333*_Complex_I, -0.025882175591 + -0.079657145723*_Complex_I}; float complex iirfilt_cccf_data_h7x64_x[] = { -0.098550426609 + -0.003621212634*_Complex_I, -0.016756220318 + 0.048451159934*_Complex_I, 0.128559901552 + -0.175906398240*_Complex_I, 0.042354962510 + 0.175294582513*_Complex_I, 0.044042909613 + -0.033981151417*_Complex_I, 0.096167707817 + 0.043304738718*_Complex_I, 0.008843481666 + 0.157764101243*_Complex_I, 0.047946611970 + 0.072647112324*_Complex_I, -0.005116789209 + 0.027119998834*_Complex_I, 0.056600964002 + 0.277180066672*_Complex_I, -0.038103339311 + -0.158209538469*_Complex_I, -0.190286655252 + -0.175199843166*_Complex_I, 0.046655418918 + 0.117071622909*_Complex_I, -0.040116383719 + 0.003741131243*_Complex_I, 0.106707347270 + -0.131096478967*_Complex_I, 0.156218986693 + -0.053370165924*_Complex_I, 0.049386533650 + 0.102352649704*_Complex_I, -0.035443738919 + -0.092876336588*_Complex_I, -0.061253027039 + -0.061242620775*_Complex_I, -0.225771811818 + -0.034350311320*_Complex_I, -0.010532720169 + 0.007358131605*_Complex_I, 0.030330062576 + 0.124193458018*_Complex_I, 0.141406666457 + -0.078752149635*_Complex_I, -0.145791273156 + 0.023246728519*_Complex_I, -0.011541061424 + -0.152743782535*_Complex_I, -0.068198003148 + -0.062679366340*_Complex_I, 0.073619746128 + 0.013331230908*_Complex_I, 0.092211502182 + 0.096482943911*_Complex_I, -0.038021973216 + -0.031446557366*_Complex_I, -0.008559170319 + -0.023697838529*_Complex_I, 0.004944119278 + -0.073417141786*_Complex_I, 0.110759757286 + 0.145622092402*_Complex_I, 0.087582530761 + -0.051117071597*_Complex_I, -0.104346081702 + -0.129040232033*_Complex_I, 0.013296100000 + 0.043301334280*_Complex_I, 0.106655262054 + -0.084832308563*_Complex_I, 0.036672357213 + -0.108439057934*_Complex_I, -0.072605878689 + -0.074457714998*_Complex_I, -0.070446103747 + -0.090753818960*_Complex_I, -0.043844178551 + -0.001965788736*_Complex_I, 0.074808520578 + -0.029341850412*_Complex_I, -0.029417618007 + -0.105379562333*_Complex_I, -0.084718140076 + 0.065078236549*_Complex_I, 0.006736811174 + 0.057115610089*_Complex_I, 0.128294037265 + 0.016598548472*_Complex_I, 0.056536504992 + 0.095386541532*_Complex_I, -0.180675222360 + 0.073501707373*_Complex_I, 0.075621856422 + -0.019260447414*_Complex_I, -0.123616785095 + 0.040307567607*_Complex_I, 0.231558123335 + -0.162832384201*_Complex_I, -0.215960867581 + -0.007986024628*_Complex_I, 0.128200674463 + -0.048905384561*_Complex_I, -0.024701418483 + -0.022333678059*_Complex_I, 0.168095436407 + 0.021880796886*_Complex_I, -0.053661700721 + 0.138981768476*_Complex_I, -0.085052752996 + 0.061710282625*_Complex_I, -0.070265421254 + 0.003218384541*_Complex_I, 0.078160292681 + -0.023479825626*_Complex_I, -0.039515617329 + 0.098596493423*_Complex_I, 0.024455660290 + 0.059965817173*_Complex_I, -0.054708570486 + -0.041259730433*_Complex_I, 0.014136360877 + -0.049081577540*_Complex_I, 0.076788203575 + 0.031140443013*_Complex_I, 0.140726220651 + -0.116220629853*_Complex_I}; float complex iirfilt_cccf_data_h7x64_y[] = { -0.000033560131 + -0.000001233159*_Complex_I, -0.000258851151 + -0.000182022816*_Complex_I, -0.000494649917 + -0.001373362038*_Complex_I, 0.001394642558 + -0.004175303248*_Complex_I, 0.008554931816 + -0.004804359573*_Complex_I, 0.016796138686 + 0.005120290566*_Complex_I, 0.010932000560 + 0.024911804007*_Complex_I, -0.017061529751 + 0.034832808964*_Complex_I, -0.049761088897 + 0.015264433783*_Complex_I, -0.059020207327 + -0.027171699378*_Complex_I, -0.036205994556 + -0.064624947209*_Complex_I, 0.000601917126 + -0.076588962383*_Complex_I, 0.028262998034 + -0.068260421645*_Complex_I, 0.044537214577 + -0.058361858676*_Complex_I, 0.064596876978 + -0.048925217761*_Complex_I, 0.088128996753 + -0.021843906515*_Complex_I, 0.089856452956 + 0.026332726109*_Complex_I, 0.054471127041 + 0.068223976540*_Complex_I, -0.000290875094 + 0.076123105710*_Complex_I, -0.044282578145 + 0.048889124487*_Complex_I, -0.059353580762 + 0.004067442508*_Complex_I, -0.041761212642 + -0.036859569919*_Complex_I, -0.000561785939 + -0.053116743086*_Complex_I, 0.040104448371 + -0.032897900323*_Complex_I, 0.050619601896 + 0.011940322017*_Complex_I, 0.021768243925 + 0.046287205351*_Complex_I, -0.019213577363 + 0.040918226497*_Complex_I, -0.030599821708 + 0.006207948813*_Complex_I, -0.002845413304 + -0.013157003063*_Complex_I, 0.024556915659 + 0.011232088898*_Complex_I, 0.007350619475 + 0.051864253016*_Complex_I, -0.044765635147 + 0.053713175283*_Complex_I, -0.073600260113 + 0.004656138635*_Complex_I, -0.044922245023 + -0.043553047795*_Complex_I, 0.005045527096 + -0.039432366427*_Complex_I, 0.016567161506 + 0.001409186000*_Complex_I, -0.014892968732 + 0.020249556494*_Complex_I, -0.038020558990 + -0.003690764330*_Complex_I, -0.020379281032 + -0.029896511388*_Complex_I, 0.009911763020 + -0.018485013558*_Complex_I, 0.009213285286 + 0.015408996809*_Complex_I, -0.020607967078 + 0.028064347058*_Complex_I, -0.040072285887 + 0.009103845685*_Complex_I, -0.029633824328 + -0.009491108934*_Complex_I, -0.012674711398 + -0.002412590925*_Complex_I, -0.017757155057 + 0.015724298695*_Complex_I, -0.039259428540 + 0.015648709858*_Complex_I, -0.050519151856 + -0.005459876230*_Complex_I, -0.042568847598 + -0.027243436178*_Complex_I, -0.027047977959 + -0.039658949321*_Complex_I, -0.008598155325 + -0.047768931278*_Complex_I, 0.018620409918 + -0.047826408941*_Complex_I, 0.046696907915 + -0.025513963561*_Complex_I, 0.051035872527 + 0.016271017736*_Complex_I, 0.021627412575 + 0.048969234788*_Complex_I, -0.020027138727 + 0.049506949727*_Complex_I, -0.046847717023 + 0.024846966173*_Complex_I, -0.053679844164 + -0.005914224145*_Complex_I, -0.045675563357 + -0.036479785730*_Complex_I, -0.018483743745 + -0.062516165506*_Complex_I, 0.025991231714 + -0.064521736503*_Complex_I, 0.058934016585 + -0.030613923443*_Complex_I, 0.051235943856 + 0.012914473925*_Complex_I, 0.016853513686 + 0.024980258409*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/iirfilt_crcf_data_h3x64.c000066400000000000000000000173411317124540100244520ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // iirfilt_crcf_data_h3x64.c: autotest iirfilt data // #include float iirfilt_crcf_data_h3x64_b[] = { 0.067455273889, 0.134910547778, 0.067455273889}; float iirfilt_crcf_data_h3x64_a[] = { 1.000000000000, -1.142980502540, 0.412801598096}; float complex iirfilt_crcf_data_h3x64_x[] = { 0.157714921372 + 0.096933651372*_Complex_I, 0.112931825396 + 0.063629523666*_Complex_I, 0.036350589338 + 0.126527528681*_Complex_I, -0.131639758916 + 0.002850582881*_Complex_I, 0.124813993717 + -0.161564813627*_Complex_I, 0.055810697081 + -0.079984015750*_Complex_I, -0.113597866433 + 0.059629208365*_Complex_I, -0.081276130300 + -0.032884892886*_Complex_I, 0.189206432747 + 0.151230084280*_Complex_I, 0.046653973791 + 0.039106242827*_Complex_I, 0.062707370238 + 0.114770667926*_Complex_I, -0.005370634420 + -0.115131667770*_Complex_I, -0.042638922558 + -0.133249195976*_Complex_I, -0.036786574989 + -0.119823837652*_Complex_I, 0.086588872188 + 0.012335566540*_Complex_I, 0.162897246678 + 0.076457627729*_Complex_I, -0.046976140791 + 0.024454556465*_Complex_I, 0.037224871206 + 0.005544202178*_Complex_I, -0.106866213474 + -0.004556655371*_Complex_I, 0.112442348190 + -0.043675611175*_Complex_I, -0.139836308260 + -0.165558641382*_Complex_I, -0.124475577909 + 0.044150412760*_Complex_I, -0.112036331740 + 0.092938383030*_Complex_I, 0.004665562144 + 0.077748113050*_Complex_I, -0.016082143750 + -0.159087937039*_Complex_I, -0.122649745886 + 0.169674782967*_Complex_I, -0.059903644318 + -0.028174007533*_Complex_I, -0.135926561418 + 0.161939672399*_Complex_I, 0.058515792150 + -0.092207684338*_Complex_I, -0.001328847093 + -0.044399214544*_Complex_I, 0.148659720963 + -0.189463417484*_Complex_I, -0.026581782415 + 0.095051513873*_Complex_I, 0.031890698003 + -0.042421129272*_Complex_I, -0.122306862234 + 0.005962301978*_Complex_I, -0.061265177784 + 0.106033789898*_Complex_I, 0.261292757319 + -0.214947283935*_Complex_I, 0.103799428426 + 0.080318756697*_Complex_I, -0.049679368664 + 0.150833170036*_Complex_I, 0.042691894941 + 0.069350178325*_Complex_I, -0.046630189152 + -0.062689469185*_Complex_I, -0.012129146913 + 0.031853481774*_Complex_I, 0.020440626886 + 0.011527708526*_Complex_I, 0.048482096955 + 0.129990980549*_Complex_I, 0.042635428860 + -0.223911417035*_Complex_I, -0.010964205149 + -0.143631009428*_Complex_I, 0.065181991532 + -0.058004538996*_Complex_I, -0.000090077953 + -0.081470015783*_Complex_I, 0.011047855650 + 0.146709286197*_Complex_I, -0.114534249385 + 0.131496385737*_Complex_I, 0.071234677078 + 0.077433138944*_Complex_I, 0.200723551597 + 0.001379408486*_Complex_I, -0.026760201597 + 0.140751935283*_Complex_I, 0.047450662078 + -0.024838330640*_Complex_I, 0.013847228689 + -0.209058524164*_Complex_I, 0.093422613814 + 0.012081621105*_Complex_I, 0.136809870406 + -0.145382142602*_Complex_I, 0.009187149051 + 0.116724633427*_Complex_I, 0.136993412455 + 0.031913868005*_Complex_I, 0.000837449944 + -0.080964662247*_Complex_I, -0.060279791907 + -0.040256932738*_Complex_I, 0.037791227194 + -0.030926237571*_Complex_I, -0.041416454010 + -0.072873679453*_Complex_I, -0.022768793380 + -0.030601437534*_Complex_I, 0.108180951121 + 0.069467116791*_Complex_I}; float complex iirfilt_crcf_data_h3x64_y[] = { 0.010638703218 + 0.006538686002*_Complex_I, 0.041055083998 + 0.024843109564*_Complex_I, 0.070859923453 + 0.049353938820*_Complex_I, 0.067686035774 + 0.067709646463*_Complex_I, 0.041224538648 + 0.055038544970*_Complex_I, 0.030901594293 + 0.007957479174*_Complex_I, 0.026588402992 + -0.031291537326*_Complex_I, 0.000590470547 + -0.038619471159*_Complex_I, -0.016165649635 + -0.021437053514*_Complex_I, 0.004469726906 + 0.012262241589*_Complex_I, 0.035069044446 + 0.046083751239*_Complex_I, 0.049482788267 + 0.057966414042*_Complex_I, 0.042710472013 + 0.030452084359*_Complex_I, 0.019794496184 + -0.022948199659*_Complex_I, 0.002995531001 + -0.063121775432*_Complex_I, 0.015441215948 + -0.063934986641*_Complex_I, 0.041061093206 + -0.034223045125*_Complex_I, 0.047719585714 + -0.003893175152*_Complex_I, 0.032237020788 + 0.011767694149*_Complex_I, 0.012826028856 + 0.011870448387*_Complex_I, -0.000119320177 + -0.008657506452*_Complex_I, -0.025108083598 + -0.037099080266*_Complex_I, -0.062432000766 + -0.037771955955*_Complex_I, -0.084190602890 + -0.007096982968*_Complex_I, -0.078469021221 + 0.013507514859*_Complex_I, -0.065062852144 + 0.013595810519*_Complex_I, -0.063645820627 + 0.020222934773*_Complex_I, -0.071411851802 + 0.036070220963*_Complex_I, -0.073780802600 + 0.046606489405*_Complex_I, -0.056215295888 + 0.033869398399*_Complex_I, -0.020000348431 + -0.005517294981*_Complex_I, 0.018518800909 + -0.042431351088*_Complex_I, 0.038015719300 + -0.049039042613*_Complex_I, 0.030065702572 + -0.037444083204*_Complex_I, 0.000189612796 + -0.017459075006*_Complex_I, -0.011084433416 + -0.004290467457*_Complex_I, 0.025372744806 + -0.014124980335*_Complex_I, 0.061854301275 + -0.007862452949*_Complex_I, 0.063403692253 + 0.027289128630*_Complex_I, 0.046198628950 + 0.049738403126*_Complex_I, 0.022401700824 + 0.043954279075*_Complex_I, 0.003130865455 + 0.030553031785*_Complex_I, -0.000459085357 + 0.029249594984*_Complex_I, 0.008978406999 + 0.024030129591*_Complex_I, 0.018734404042 + -0.015736413767*_Complex_I, 0.023500424489 + -0.066300146201*_Complex_I, 0.027175003553 + -0.092293433110*_Complex_I, 0.026489439187 + -0.083128349690*_Complex_I, 0.012817484482 + -0.033748033571*_Complex_I, -0.006186235518 + 0.028602009338*_Complex_I, 0.003062407634 + 0.066032501481*_Complex_I, 0.036133722347 + 0.078570737258*_Complex_I, 0.053166399461 + 0.079952991289*_Complex_I, 0.051382646333 + 0.050991991806*_Complex_I, 0.048152970882 + -0.003786577505*_Complex_I, 0.056593380224 + -0.047656514100*_Complex_I, 0.070186171051 + -0.063832284508*_Complex_I, 0.076568506010 + -0.045193020750*_Complex_I, 0.077701414291 + -0.018586956449*_Complex_I, 0.062491319025 + -0.014074548285*_Complex_I, 0.033824419480 + -0.021392925087*_Complex_I, 0.011102622655 + -0.030445232324*_Complex_I, -0.005846867304 + -0.039949067467*_Complex_I, -0.009834168653 + -0.037451411970*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/iirfilt_crcf_data_h5x64.c000066400000000000000000000174611317124540100244570ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // iirfilt_crcf_data_h5x64.c: autotest iirfilt data // #include float iirfilt_crcf_data_h5x64_b[] = { 0.004824343358, 0.019297373431, 0.028946060146, 0.019297373431, 0.004824343358}; float iirfilt_crcf_data_h5x64_a[] = { 1.000000000000, -2.369513007182, 2.313988414416, -1.054665405879, 0.187379492368}; float complex iirfilt_crcf_data_h5x64_x[] = { 0.034816486087 + -0.057435933225*_Complex_I, -0.138922686034 + 0.002487157060*_Complex_I, 0.002168200782 + 0.075752631688*_Complex_I, 0.110645778286 + 0.097973148283*_Complex_I, -0.062999498912 + 0.034473236147*_Complex_I, 0.030513585484 + 0.108486942526*_Complex_I, 0.130905798224 + -0.206952317034*_Complex_I, 0.104557822758 + -0.049326363722*_Complex_I, 0.175995475228 + -0.040903480637*_Complex_I, 0.263382017202 + 0.007386489593*_Complex_I, 0.075401623113 + 0.034346157974*_Complex_I, -0.004787311774 + 0.050323428781*_Complex_I, 0.039595621673 + -0.013034423002*_Complex_I, 0.289435339135 + 0.004887226549*_Complex_I, 0.000109192613 + -0.098143317718*_Complex_I, 0.218628727322 + 0.045783638022*_Complex_I, 0.011357280346 + 0.060469524704*_Complex_I, -0.005462153874 + 0.011440185961*_Complex_I, 0.086903581383 + 0.054667638583*_Complex_I, 0.009197661173 + -0.006158688411*_Complex_I, 0.082244960567 + -0.138538495472*_Complex_I, 0.078074527675 + -0.110054617600*_Complex_I, -0.071517687777 + -0.053281282254*_Complex_I, 0.050695873651 + 0.049035186418*_Complex_I, -0.064011859850 + 0.057026886508*_Complex_I, 0.002187309591 + 0.247199024244*_Complex_I, 0.177910643270 + 0.036260952778*_Complex_I, -0.133404966159 + 0.007272659425*_Complex_I, 0.104545832232 + 0.100374198245*_Complex_I, 0.152937259249 + -0.006345268825*_Complex_I, -0.089893987831 + -0.066730853350*_Complex_I, -0.031614665144 + -0.108199665873*_Complex_I, -0.019945023665 + -0.036637064501*_Complex_I, 0.035423077805 + -0.084251698103*_Complex_I, -0.045559909198 + -0.065683835690*_Complex_I, 0.082043588708 + -0.073113783286*_Complex_I, 0.146363247845 + -0.313133192986*_Complex_I, 0.163657926540 + 0.035668446628*_Complex_I, -0.133126328934 + -0.033221937410*_Complex_I, -0.041582597083 + 0.060780541288*_Complex_I, -0.102136662865 + 0.064174466409*_Complex_I, 0.129371455827 + -0.122309646349*_Complex_I, 0.081072163867 + 0.121012321373*_Complex_I, 0.035429837296 + 0.040975877524*_Complex_I, 0.047403447509 + 0.014166128441*_Complex_I, 0.081667476778 + 0.117576764934*_Complex_I, 0.142529344063 + -0.015788307193*_Complex_I, 0.107269994778 + 0.039678416397*_Complex_I, -0.189638285144 + -0.025105560583*_Complex_I, 0.127449393546 + -0.026105377201*_Complex_I, 0.051057729361 + -0.029706326528*_Complex_I, 0.095342091161 + -0.221870514334*_Complex_I, 0.033077914989 + -0.078421433242*_Complex_I, 0.139326073519 + 0.176520418207*_Complex_I, 0.180222947875 + -0.140485235948*_Complex_I, -0.092080231794 + 0.044423535254*_Complex_I, -0.116184788790 + -0.081712392283*_Complex_I, -0.015159814021 + -0.253655296232*_Complex_I, -0.165572835614 + 0.032968825997*_Complex_I, -0.018186027637 + 0.146030996176*_Complex_I, -0.081743534837 + 0.046764387177*_Complex_I, -0.163907916201 + 0.000894565796*_Complex_I, 0.066507006426 + 0.153027239112*_Complex_I, -0.093381553000 + 0.004333390574*_Complex_I}; float complex iirfilt_crcf_data_h5x64_y[] = { 0.000167966683 + -0.000277090663*_Complex_I, 0.000399655237 + -0.001752933682*_Complex_I, -0.001104267382 + -0.004761506250*_Complex_I, -0.006137988749 + -0.006620307024*_Complex_I, -0.012217626919 + -0.002445090386*_Complex_I, -0.014480238497 + 0.010330691717*_Complex_I, -0.010763861323 + 0.028395668560*_Complex_I, -0.000501503170 + 0.042087127701*_Complex_I, 0.017677520131 + 0.040492499282*_Complex_I, 0.044775392784 + 0.020918790830*_Complex_I, 0.079868253591 + -0.007890790986*_Complex_I, 0.117333468546 + -0.032191317082*_Complex_I, 0.145332483454 + -0.041696063730*_Complex_I, 0.153450768495 + -0.034623789141*_Complex_I, 0.143091173002 + -0.017649460381*_Complex_I, 0.125440207813 + -0.001185301267*_Complex_I, 0.110781054574 + 0.007694330137*_Complex_I, 0.102309442381 + 0.009525121208*_Complex_I, 0.096424656974 + 0.009467240886*_Complex_I, 0.087905819414 + 0.011472932774*_Complex_I, 0.075351746332 + 0.015189934128*_Complex_I, 0.061539619627 + 0.015371965161*_Complex_I, 0.050238103007 + 0.005354811389*_Complex_I, 0.042392909138 + -0.015692162843*_Complex_I, 0.035487235197 + -0.039320795693*_Complex_I, 0.026683183579 + -0.051939223046*_Complex_I, 0.016086735480 + -0.042351028087*_Complex_I, 0.007718993110 + -0.009467148500*_Complex_I, 0.005371191435 + 0.034876269506*_Complex_I, 0.009169183447 + 0.073622002790*_Complex_I, 0.018251989832 + 0.094472386300*_Complex_I, 0.030162933688 + 0.092028482193*_Complex_I, 0.038047814129 + 0.066731638129*_Complex_I, 0.035763727219 + 0.025446392854*_Complex_I, 0.023934856252 + -0.020176728351*_Complex_I, 0.008437472733 + -0.058844376262*_Complex_I, -0.003244989715 + -0.085035950076*_Complex_I, -0.003390870214 + -0.101037326348*_Complex_I, 0.012003956420 + -0.111181202859*_Complex_I, 0.036474465180 + -0.114015132267*_Complex_I, 0.054397129333 + -0.103816397690*_Complex_I, 0.053458816959 + -0.078552582252*_Complex_I, 0.035502609681 + -0.044222383504*_Complex_I, 0.014265637465 + -0.010619069148*_Complex_I, 0.003101144454 + 0.016085677224*_Complex_I, 0.006286890891 + 0.034538795527*_Complex_I, 0.020824414839 + 0.045682197348*_Complex_I, 0.042111099700 + 0.051038175528*_Complex_I, 0.064730289486 + 0.051165119231*_Complex_I, 0.079924238054 + 0.045642918872*_Complex_I, 0.080081550492 + 0.034340023196*_Complex_I, 0.067180942535 + 0.017458189468*_Complex_I, 0.051064446907 + -0.005688909571*_Complex_I, 0.040695417558 + -0.033996511064*_Complex_I, 0.040715290376 + -0.059379363759*_Complex_I, 0.051739083738 + -0.071274663107*_Complex_I, 0.067460869459 + -0.066847437344*_Complex_I, 0.074610717895 + -0.053096308826*_Complex_I, 0.062263741557 + -0.042094216632*_Complex_I, 0.029932249437 + -0.041388946019*_Complex_I, -0.013495205238 + -0.045430267433*_Complex_I, -0.055715901366 + -0.041773963667*_Complex_I, -0.087248260391 + -0.024536503294*_Complex_I, -0.103228307102 + 0.002973369704*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/iirfilt_crcf_data_h7x64.c000066400000000000000000000176011317124540100244550ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // iirfilt_crcf_data_h7x64.c: autotest iirfilt data // #include float iirfilt_crcf_data_h7x64_b[] = { 0.000340537653, 0.002043225916, 0.005108064791, 0.006810753054, 0.005108064791, 0.002043225916, 0.000340537653}; float iirfilt_crcf_data_h7x64_a[] = { 1.000000000000, -3.579434798331, 5.658667165934, -4.965415228779, 2.529494905841, -0.705274114510, 0.083756479619}; float complex iirfilt_crcf_data_h7x64_x[] = { 0.004233635522 + 0.032166672422*_Complex_I, -0.157552590267 + 0.250368602921*_Complex_I, 0.054267060665 + -0.005044027264*_Complex_I, 0.051025281222 + 0.067245838231*_Complex_I, -0.027078112717 + -0.126549310903*_Complex_I, 0.035527067912 + 0.084082095013*_Complex_I, -0.045166037588 + 0.117512061237*_Complex_I, -0.170543036494 + -0.210138171552*_Complex_I, 0.122017191616 + 0.083315021977*_Complex_I, 0.087665380573 + -0.113419352152*_Complex_I, -0.020592340496 + 0.051461184327*_Complex_I, 0.005438907415 + -0.034203108407*_Complex_I, -0.004238610906 + -0.010875374856*_Complex_I, 0.014448167389 + 0.140297619530*_Complex_I, 0.023037852846 + 0.147634578106*_Complex_I, 0.039831512515 + 0.117367316573*_Complex_I, -0.049079756276 + -0.134214287084*_Complex_I, -0.081369646592 + -0.123999271543*_Complex_I, -0.060778482772 + -0.005943225227*_Complex_I, 0.060096536726 + 0.110619062414*_Complex_I, -0.029590602066 + 0.069542558264*_Complex_I, 0.276694153680 + 0.033847635389*_Complex_I, -0.069801585631 + -0.024433292968*_Complex_I, 0.103527771239 + 0.043047059964*_Complex_I, 0.052392266919 + 0.106611921459*_Complex_I, 0.047921013690 + 0.144591771640*_Complex_I, -0.100885260679 + 0.085422512163*_Complex_I, 0.023817071089 + 0.007631681829*_Complex_I, -0.103520290629 + 0.065084699549*_Complex_I, 0.141218652175 + 0.181817618913*_Complex_I, 0.091918916526 + 0.090132723783*_Complex_I, 0.073412476081 + -0.185654057154*_Complex_I, 0.064690355167 + -0.154617720920*_Complex_I, -0.141562424619 + -0.078498890176*_Complex_I, -0.089061791163 + -0.089972135569*_Complex_I, 0.061285035005 + -0.042181313189*_Complex_I, 0.011648008082 + 0.030075451872*_Complex_I, -0.050030705016 + 0.044231269056*_Complex_I, 0.055904020426 + -0.100086776348*_Complex_I, 0.067035512200 + 0.110427319881*_Complex_I, 0.112195729535 + -0.159140605014*_Complex_I, -0.008321783937 + -0.074224475191*_Complex_I, 0.124554695470 + -0.000035276105*_Complex_I, 0.178233609860 + -0.241786527172*_Complex_I, 0.013428861272 + 0.019929110617*_Complex_I, 0.106814998943 + 0.061446999514*_Complex_I, -0.087662510082 + -0.142756477357*_Complex_I, 0.005116389200 + 0.004875226134*_Complex_I, -0.082163710392 + -0.003854447463*_Complex_I, 0.055960629067 + 0.147529880141*_Complex_I, 0.104198321794 + 0.047973142904*_Complex_I, -0.092852806707 + -0.088517198490*_Complex_I, 0.008453380604 + 0.016712253059*_Complex_I, -0.168237622832 + 0.182661482388*_Complex_I, -0.003676740087 + 0.067558336540*_Complex_I, 0.083397702670 + 0.084971378309*_Complex_I, 0.105858021404 + 0.040735314366*_Complex_I, -0.117228290082 + -0.024601874801*_Complex_I, -0.158931397897 + -0.101660731802*_Complex_I, -0.079872460607 + -0.030609694665*_Complex_I, -0.070191072161 + 0.183132157615*_Complex_I, -0.187191287439 + -0.013144361324*_Complex_I, -0.097352654114 + -0.073775329625*_Complex_I, -0.160782253378 + 0.108482062513*_Complex_I}; float complex iirfilt_crcf_data_h7x64_y[] = { 0.000001441712 + 0.000010953963*_Complex_I, -0.000039841800 + 0.000190192712*_Complex_I, -0.000432579170 + 0.001292948964*_Complex_I, -0.001963477446 + 0.005116752194*_Complex_I, -0.005460987213 + 0.013853437396*_Complex_I, -0.010691848048 + 0.028003970363*_Complex_I, -0.015829219307 + 0.044636043744*_Complex_I, -0.018444702482 + 0.058202478955*_Complex_I, -0.017385042715 + 0.063522217409*_Complex_I, -0.013852978602 + 0.058220061227*_Complex_I, -0.010372120290 + 0.043135943082*_Complex_I, -0.008386259332 + 0.021557712213*_Complex_I, -0.007057894617 + -0.001756678543*_Complex_I, -0.004462600311 + -0.021708921739*_Complex_I, 0.000413860784 + -0.033985730231*_Complex_I, 0.006867599715 + -0.035636537512*_Complex_I, 0.013151792937 + -0.025207996188*_Complex_I, 0.017581663360 + -0.003488920494*_Complex_I, 0.018987594562 + 0.024903700370*_Complex_I, 0.016476110032 + 0.051134067764*_Complex_I, 0.009459018773 + 0.065241189212*_Complex_I, -0.001441469538 + 0.061675106678*_Complex_I, -0.013298737003 + 0.042982674038*_Complex_I, -0.020975009992 + 0.018439112600*_Complex_I, -0.019171489571 + -0.001220893708*_Complex_I, -0.005478667970 + -0.008887635676*_Complex_I, 0.017790116314 + -0.002906881750*_Complex_I, 0.044167796652 + 0.014155489246*_Complex_I, 0.065318293362 + 0.037562815973*_Complex_I, 0.073959143834 + 0.061781091547*_Complex_I, 0.066724360261 + 0.081615483562*_Complex_I, 0.046102292983 + 0.093697367755*_Complex_I, 0.020214021152 + 0.097173425139*_Complex_I, -0.000316969804 + 0.092297203234*_Complex_I, -0.007456572181 + 0.078335403968*_Complex_I, -0.000109513959 + 0.053648935265*_Complex_I, 0.015245116502 + 0.018291043433*_Complex_I, 0.028507759029 + -0.023453077073*_Complex_I, 0.031847159216 + -0.063005523552*_Complex_I, 0.023465571027 + -0.090337797990*_Complex_I, 0.007593101686 + -0.098277994324*_Complex_I, -0.008080860379 + -0.085900545160*_Complex_I, -0.015861382531 + -0.059241419647*_Complex_I, -0.011151330660 + -0.029092859925*_Complex_I, 0.006066947770 + -0.006896796239*_Complex_I, 0.031921995818 + -0.000519982404*_Complex_I, 0.060475303064 + -0.011467885217*_Complex_I, 0.085275600399 + -0.034448894253*_Complex_I, 0.100389600600 + -0.059802028892*_Complex_I, 0.101457128362 + -0.077810326455*_Complex_I, 0.087090251053 + -0.082216982388*_Complex_I, 0.060162530535 + -0.071286280151*_Complex_I, 0.027739822472 + -0.047336780803*_Complex_I, -0.001368012589 + -0.016047415915*_Complex_I, -0.020598333225 + 0.014978961236*_Complex_I, -0.028528780470 + 0.039136270897*_Complex_I, -0.028450797573 + 0.053688158765*_Complex_I, -0.024993006862 + 0.060174099568*_Complex_I, -0.020853885213 + 0.062097322569*_Complex_I, -0.016606097058 + 0.061833377745*_Complex_I, -0.013052589087 + 0.058990818175*_Complex_I, -0.012808887831 + 0.051482609352*_Complex_I, -0.019272140076 + 0.038484586328*_Complex_I, -0.034383553960 + 0.022386350903*_Complex_I}; liquid-dsp-1.3.1/src/filter/tests/data/iirfilt_rrrf_data_h3x64.c000066400000000000000000000076731317124540100245170ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // iirfilt_rrrf_data_h3x64.c: autotest iirfilt data // float iirfilt_rrrf_data_h3x64_b[] = { 0.067455273889, 0.134910547778, 0.067455273889}; float iirfilt_rrrf_data_h3x64_a[] = { 1.000000000000, -1.142980502540, 0.412801598096}; float iirfilt_rrrf_data_h3x64_x[] = { -0.028895214542, -0.069021825021, 0.030604896335, -0.028355924919, 0.116559552929, 0.143033796152, 0.034240066758, 0.245754661028, -0.085048302237, 0.037276632441, -0.027971098990, 0.028792388017, 0.061299546415, 0.019217231932, -0.068210516011, -0.030965552175, -0.104543256906, -0.219154025020, -0.060076982615, 0.175962646540, 0.111681770625, 0.038846767797, -0.074493060382, -0.068437932045, -0.210154533613, -0.059543914700, -0.003275225407, 0.027794772921, 0.001988917543, -0.065169452924, 0.076196405886, -0.110895781816, -0.193987624818, -0.048983036631, -0.057777317818, -0.273728284279, 0.139583588189, -0.048520445612, 0.038028122617, 0.142317597668, 0.006158624121, 0.094921369690, 0.106674550704, -0.007693480844, 0.009150091523, -0.124420550406, -0.048419736980, 0.074400545011, -0.007592916601, -0.023547687981, 0.086672380799, 0.052067890613, 0.134684497125, 0.051380348106, -0.007288328205, -0.053065747221, -0.029240930355, -0.010101089710, -0.143148550970, -0.025032159897, -0.067586830823, 0.279800929422, 0.176230712305, -0.021010061898}; float iirfilt_rrrf_data_h3x64_y[] = { -0.001949134611, -0.010781978190, -0.020715430137, -0.021666234384, -0.010111215930, 0.020847673860, 0.057471408279, 0.087927924056, 0.106503226141, 0.093052363747, 0.059797591762, 0.030618424605, 0.016444297289, 0.017664634020, 0.015528526008, 0.000462009068, -0.021712865669, -0.055983972836, -0.095696176666, -0.097287095541, -0.044473486551, 0.018885017236, 0.047693346170, 0.034670819807, -0.008493798786, -0.061005530002, -0.088651942626, -0.078727771165, -0.049725604069, -0.026589239497, -0.013382207683, -0.005916351681, -0.024144727506, -0.062110319563, -0.084615103632, -0.100637524633, -0.111508046878, -0.088814270452, -0.050047352820, -0.009082968266, 0.032458745755, 0.057683060225, 0.072948677736, 0.079842760097, 0.067920438561, 0.036995173732, -0.005187492618, -0.031107316161, -0.027154581221, -0.015790078206, -0.004680801567, 0.014784961041, 0.040787361040, 0.065664391433, 0.073741325675, 0.056081570347, 0.024036384207, -0.003883289580, -0.027352105314, -0.051342067332, -0.064984304437, -0.045014384740, 0.020451760070, 0.083190163742}; liquid-dsp-1.3.1/src/filter/tests/data/iirfilt_rrrf_data_h5x64.c000066400000000000000000000100131317124540100244770ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // iirfilt_rrrf_data_h5x64.c: autotest iirfilt data // float iirfilt_rrrf_data_h5x64_b[] = { 0.004824343358, 0.019297373431, 0.028946060146, 0.019297373431, 0.004824343358}; float iirfilt_rrrf_data_h5x64_a[] = { 1.000000000000, -2.369513007182, 2.313988414416, -1.054665405879, 0.187379492368}; float iirfilt_rrrf_data_h5x64_x[] = { -0.071435037288, -0.013824638625, 0.000604766808, -0.157245338765, -0.148499909731, 0.036854467235, -0.092170127241, -0.030750688358, -0.256687046040, -0.011293794477, -0.152735111898, -0.039350864050, -0.026481755383, 0.026344708916, -0.165804900216, 0.075110855166, 0.169733039664, 0.112960857425, 0.102855045747, -0.058065586616, -0.019482689014, -0.069631526814, 0.080391768879, -0.148962611101, -0.063224959929, 0.177207853044, 0.064119106525, 0.182006292285, 0.032851335390, 0.025859709218, 0.012249245529, 0.020538703403, -0.010050632447, 0.157918073531, 0.155799289392, 0.161618591338, -0.061931920946, -0.002480403144, -0.080860681406, -0.119527652190, 0.041981586004, 0.049388453948, -0.119534817516, -0.004446996769, -0.010415835934, 0.070065217532, 0.016956615378, 0.196554086088, -0.089159910224, 0.005262040310, 0.025380561695, -0.190719045717, -0.137704432243, -0.012169688901, -0.072683558269, 0.115787622162, -0.013755488460, 0.060139162368, 0.002047451288, 0.123978241358, 0.006962698789, -0.019071948553, -0.062140245356, -0.111724700578}; float iirfilt_rrrf_data_h5x64_y[] = { -0.000344627148, -0.002261801903, -0.006893530299, -0.013989605147, -0.023862607597, -0.038312044528, -0.056089194368, -0.071280615399, -0.079550560246, -0.083028835474, -0.086748998983, -0.092533693567, -0.097949600919, -0.098429082259, -0.090466124573, -0.075337575372, -0.056782281433, -0.034261954387, -0.004056342067, 0.032512857031, 0.065692345386, 0.082703529450, 0.076861903089, 0.052102523397, 0.018224928933, -0.015275405731, -0.038407046800, -0.040894489472, -0.018910631091, 0.020295410235, 0.061246521124, 0.088475490616, 0.094228350367, 0.080859234115, 0.059352937798, 0.044593577702, 0.046274753880, 0.061145236873, 0.075354763624, 0.074888924042, 0.054105775368, 0.018945116326, -0.016551695165, -0.040692464489, -0.050718972892, -0.049083944974, -0.038287527306, -0.019928604327, 0.004267855964, 0.029703630925, 0.048181600553, 0.052618134862, 0.039776735477, 0.010021908144, -0.029959006998, -0.066860943714, -0.086821708742, -0.082569377253, -0.056991021236, -0.020344296462, 0.016435506907, 0.045346639362, 0.060576452509, 0.058193434336}; liquid-dsp-1.3.1/src/filter/tests/data/iirfilt_rrrf_data_h7x64.c000066400000000000000000000101331317124540100245040ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // iirfilt_rrrf_data_h7x64.c: autotest iirfilt data // float iirfilt_rrrf_data_h7x64_b[] = { 0.000340537653, 0.002043225916, 0.005108064791, 0.006810753054, 0.005108064791, 0.002043225916, 0.000340537653}; float iirfilt_rrrf_data_h7x64_a[] = { 1.000000000000, -3.579434798331, 5.658667165934, -4.965415228779, 2.529494905841, -0.705274114510, 0.083756479619}; float iirfilt_rrrf_data_h7x64_x[] = { 0.014320460019, -0.048569878607, -0.028557745674, -0.034174525472, 0.041246019674, 0.176001687252, 0.069536678145, 0.085964825944, -0.085126074719, -0.107634084553, 0.014274481662, -0.086938201253, 0.041217197713, -0.012812412897, 0.112987870327, -0.147787754865, 0.049941237222, 0.088160959037, 0.142541502659, -0.024664403921, 0.087433714309, -0.131271281366, -0.101343790061, -0.095899142873, 0.077515723928, -0.128215021128, -0.085076363355, 0.019632244375, -0.024601764309, 0.135464981990, -0.096554438720, -0.055332193061, 0.107799859774, 0.016856032152, -0.133717866605, 0.107909223614, -0.000321585843, -0.040614549926, -0.065576753282, 0.080916136192, -0.062112903973, 0.097792565904, 0.053573189262, 0.101970184507, 0.007522028461, -0.110691703882, 0.182044058589, -0.040926270512, -0.092754193263, -0.034827070696, -0.046124677770, 0.127874701414, 0.085875818987, -0.157133769105, -0.116516897741, -0.217687959211, 0.111806530552, -0.053629641350, -0.117298829882, 0.008546053824, -0.015153030008, -0.012695501670, -0.154176199014, -0.055346850979}; float iirfilt_rrrf_data_h7x64_y[] = { 0.000004876656, 0.000030175734, 0.000044602316, -0.000207441342, -0.001316715725, -0.003834371001, -0.007275018208, -0.009225570706, -0.005882384450, 0.005486878229, 0.023590162522, 0.042219969073, 0.052802355644, 0.049012293557, 0.030431004460, 0.003094166085, -0.023276941451, -0.039861135430, -0.042388322400, -0.031669690474, -0.011613377381, 0.012796864675, 0.036227386395, 0.053027192148, 0.057804353706, 0.047254362471, 0.022407095078, -0.010858715211, -0.043986796642, -0.068957103048, -0.080449888307, -0.076669122221, -0.059625824351, -0.034801293799, -0.009374291628, 0.010427870419, 0.021114523610, 0.022335161439, 0.016423814986, 0.007136897293, -0.002051012043, -0.008952563583, -0.012527673359, -0.012220519177, -0.007483592886, 0.002024488272, 0.015481250523, 0.030132672907, 0.041993092794, 0.047610337377, 0.045176156453, 0.034600601261, 0.017674973347, -0.001466118954, -0.017059538441, -0.024634672249, -0.024401342427, -0.021654066688, -0.023062032857, -0.031927019266, -0.046389502559, -0.061179016193, -0.070675753063, -0.071539050622}; liquid-dsp-1.3.1/src/filter/tests/fftfilt_autotest.h000066400000000000000000000102241317124540100225410ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest fftfilt data definitions // #ifndef __LIQUID_FFTFILT_AUTOTEST_H__ #define __LIQUID_FFTFILT_AUTOTEST_H__ // autotest helper functions: // _h : filter coefficients // _h_len : filter coefficients length // _x : input array // _x_len : input array length // _y : output array // _y_len : output array length void fftfilt_rrrf_test(float * _h, unsigned int _h_len, float * _x, unsigned int _x_len, float * _y, unsigned int _y_len); void fftfilt_crcf_test(float * _h, unsigned int _h_len, float complex * _x, unsigned int _x_len, float complex * _y, unsigned int _y_len); void fftfilt_cccf_test(float complex * _h, unsigned int _h_len, float complex * _x, unsigned int _x_len, float complex * _y, unsigned int _y_len); // // autotest datasets // // rrrf extern float fftfilt_rrrf_data_h4x256_h[]; extern float fftfilt_rrrf_data_h4x256_x[]; extern float fftfilt_rrrf_data_h4x256_y[]; extern float fftfilt_rrrf_data_h7x256_h[]; extern float fftfilt_rrrf_data_h7x256_x[]; extern float fftfilt_rrrf_data_h7x256_y[]; extern float fftfilt_rrrf_data_h13x256_h[]; extern float fftfilt_rrrf_data_h13x256_x[]; extern float fftfilt_rrrf_data_h13x256_y[]; extern float fftfilt_rrrf_data_h23x256_h[]; extern float fftfilt_rrrf_data_h23x256_x[]; extern float fftfilt_rrrf_data_h23x256_y[]; // crcf extern float fftfilt_crcf_data_h4x256_h[]; extern float complex fftfilt_crcf_data_h4x256_x[]; extern float complex fftfilt_crcf_data_h4x256_y[]; extern float fftfilt_crcf_data_h7x256_h[]; extern float complex fftfilt_crcf_data_h7x256_x[]; extern float complex fftfilt_crcf_data_h7x256_y[]; extern float fftfilt_crcf_data_h13x256_h[]; extern float complex fftfilt_crcf_data_h13x256_x[]; extern float complex fftfilt_crcf_data_h13x256_y[]; extern float fftfilt_crcf_data_h23x256_h[]; extern float complex fftfilt_crcf_data_h23x256_x[]; extern float complex fftfilt_crcf_data_h23x256_y[]; // cccf extern float complex fftfilt_cccf_data_h4x256_h[]; extern float complex fftfilt_cccf_data_h4x256_x[]; extern float complex fftfilt_cccf_data_h4x256_y[]; extern float complex fftfilt_cccf_data_h7x256_h[]; extern float complex fftfilt_cccf_data_h7x256_x[]; extern float complex fftfilt_cccf_data_h7x256_y[]; extern float complex fftfilt_cccf_data_h13x256_h[]; extern float complex fftfilt_cccf_data_h13x256_x[]; extern float complex fftfilt_cccf_data_h13x256_y[]; extern float complex fftfilt_cccf_data_h23x256_h[]; extern float complex fftfilt_cccf_data_h23x256_x[]; extern float complex fftfilt_cccf_data_h23x256_y[]; #endif // __LIQUID_FFTFILT_AUTOTEST_H__ liquid-dsp-1.3.1/src/filter/tests/fftfilt_runtest.c000066400000000000000000000133641317124540100224000ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "autotest/autotest.h" #include "liquid.h" // autotest helper function // _h : filter coefficients // _h_len : filter coefficients length // _x : input array // _x_len : input array length // _y : output array // _y_len : output array length void fftfilt_rrrf_test(float * _h, unsigned int _h_len, float * _x, unsigned int _x_len, float * _y, unsigned int _y_len) { float tol = 0.001f; // determine appropriate block size // NOTE: this number can be anything at least _h_len-1 unsigned int n = 1 << liquid_nextpow2(_h_len-1); // determine number of blocks div_t d = div(_x_len, n); unsigned int num_blocks = d.quot + (d.rem ? 1 : 0); if (liquid_autotest_verbose) { printf("fftfilt_rrrf_test(), h_len: %3u, x_len: %3u (%3u blocks @ %3u samples, %3u remaining)\n", _h_len, _x_len, n, d.quot, d.rem); } // load filter coefficients externally fftfilt_rrrf q = fftfilt_rrrf_create(_h, _h_len, n); // allocate memory for output float y_test[n*num_blocks]; unsigned int i; // compute output in blocks of size 'n' for (i=0; i Ypeak || i==0) { Ypeak = Ymag; fpeak = f; } // find peak side-lobe value, ignoring frequencies // within a certain range of signal frequency if ( fabsf(f-fy) > main_lobe_width ) max_sidelobe = Ymag > max_sidelobe ? Ymag : max_sidelobe; } if (liquid_autotest_verbose) { // print results printf(" desired resampling rate : %12.8f\n", r); printf(" measured resampling rate : %12.8f (%u/%u)\n", r_actual, ny, nx); printf(" peak spectrum : %12.8f dB (expected 0.0 dB)\n", Ypeak); printf(" peak frequency : %12.8f (expected %-12.8f)\n", fpeak, fy); printf(" max sidelobe : %12.8f dB (expected at least %.2f dB)\n", max_sidelobe, -As); } CONTEND_DELTA( r_actual, r, 0.01f ); // check actual output sample rate CONTEND_DELTA( Ypeak, 0.0f, 0.25f ); // peak should be about 0 dB CONTEND_DELTA( fpeak, fy, 0.01f ); // peak frequency should be nearly 0.2 CONTEND_LESS_THAN( max_sidelobe, -As ); // maximum side-lobe should be sufficiently low #if 0 // export results for debugging char filename[] = "msresamp_crcf_autotest.m"; FILE*fid = fopen(filename,"w"); fprintf(fid,"%% %s: auto-generated file\n",filename); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"r = %12.8f;\n", r); fprintf(fid,"nx = %u;\n", nx); fprintf(fid,"ny = %u;\n", ny); fprintf(fid,"nfft = %u;\n", nfft); fprintf(fid,"Y = zeros(1,nfft);\n"); for (i=0; i Ypeak || i==0) { Ypeak = Ymag; fpeak = f; } // find peak side-lobe value, ignoring frequencies // within a certain range of signal frequency if ( fabsf(f-fy) > main_lobe_width ) max_sidelobe = Ymag > max_sidelobe ? Ymag : max_sidelobe; } if (liquid_autotest_verbose) { // print results printf(" desired resampling rate : %12.8f\n", r); printf(" measured resampling rate : %12.8f (%u/%u)\n", r_actual, ny, nx); printf(" peak spectrum : %12.8f dB (expected 0.0 dB)\n", Ypeak); printf(" peak frequency : %12.8f (expected %-12.8f)\n", fpeak, fy); printf(" max sidelobe : %12.8f dB (expected at least %.2f dB)\n", max_sidelobe, -As); } CONTEND_DELTA( r_actual, r, 0.01f ); // check actual output sample rate CONTEND_DELTA( Ypeak, 0.0f, 0.25f ); // peak should be about 0 dB CONTEND_DELTA( fpeak, fy, 0.01f ); // peak frequency should be nearly 0.2 CONTEND_LESS_THAN( max_sidelobe, -As ); // maximum side-lobe should be sufficiently low #if 0 // export results for debugging char filename[] = "resamp_crcf_autotest.m"; FILE*fid = fopen(filename,"w"); fprintf(fid,"%% %s: auto-generated file\n",filename); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n"); fprintf(fid,"r = %12.8f;\n", r); fprintf(fid,"nx = %u;\n", nx); fprintf(fid,"ny = %u;\n", ny); fprintf(fid,"nfft = %u;\n", nfft); fprintf(fid,"Y = zeros(1,nfft);\n"); for (i=0; i 0.5f) { // force dt to be in [0.5,0.5] dt -= 1.0f; ds++; } unsigned int i; // allocate arrays float complex s[num_symbols]; // data symbols float complex x[num_samples]; // interpolated samples float complex y[num_samples_resamp];// resampled data (resamp_crcf) float complex z[num_symbols + 64]; // synchronized symbols // generate pseudo-random QPSK symbols // NOTE: by using an m-sequence generator this sequence will be identical // each time this test is run msequence ms = msequence_create_default(10); for (i=0; i 0.5f) { // force dt to be in [0.5,0.5] dt -= 1.0f; ds++; } unsigned int i; // allocate arrays float s[num_symbols]; // data symbols float x[num_samples]; // interpolated samples float y[num_samples_resamp]; // resampled data (resamp_rrrf) float z[num_symbols + 64]; // synchronized symbols // generate pseudo-random BPSK symbols // NOTE: by using an m-sequence generator this sequence will be identical // each time this test is run msequence ms = msequence_create_default(10); for (i=0; i #include #include #include #include "liquid.internal.h" // callback function static int bpacketsync_benchmark_callback(unsigned char * _payload, int _payload_valid, unsigned int _payload_len, framesyncstats_s _stats, void * _userdata) { if (!_payload_valid) return 0; // increment number of packets found and return unsigned int * num_packets_found = (unsigned int *) _userdata; *num_packets_found += 1; return 0; } void benchmark_bpacketsync(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { // adjust number of iterations *_num_iterations *= 4; // options unsigned int dec_msg_len = 64; // original data message length crc_scheme check = LIQUID_CRC_NONE; // data integrity check fec_scheme fec0 = LIQUID_FEC_NONE; // inner code fec_scheme fec1 = LIQUID_FEC_NONE; // outer code // create packet generator bpacketgen pg = bpacketgen_create(0, dec_msg_len, check, fec0, fec1); // compute packet length unsigned int enc_msg_len = bpacketgen_get_packet_len(pg); // initialize arrays unsigned char msg_org[dec_msg_len]; // original message unsigned char msg_enc[enc_msg_len]; // encoded message unsigned int num_packets_found=0; // create packet synchronizer bpacketsync ps = bpacketsync_create(0, bpacketsync_benchmark_callback, (void*)&num_packets_found); unsigned long int i; // initialize original data message for (i=0; i #include #include #include #include "liquid.internal.h" // Helper function to keep code base small void bpresync_cccf_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _n, unsigned int _m) { // adjust number of iterations *_num_iterations *= 4; *_num_iterations /= _n; *_num_iterations /= _m; // generate sequence (random) float complex h[_n]; unsigned long int i; for (i=0; i<_n; i++) { h[i] = (rand() % 2 ? 1.0f : -1.0f) + (rand() % 2 ? 1.0f : -1.0f)*_Complex_I; } // generate synchronizer bpresync_cccf q = bpresync_cccf_create(h, _n, 0.1f, _m); // input sequence (random) float complex x[7]; for (i=0; i<7; i++) { x[i] = (rand() % 2 ? 1.0f : -1.0f) + (rand() % 2 ? 1.0f : -1.0f)*_Complex_I; } float complex rxy; float dphi_hat; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { // push input sequence through synchronizer bpresync_cccf_push(q, x[0]); bpresync_cccf_correlate(q, &rxy, &dphi_hat); bpresync_cccf_push(q, x[1]); bpresync_cccf_correlate(q, &rxy, &dphi_hat); bpresync_cccf_push(q, x[2]); bpresync_cccf_correlate(q, &rxy, &dphi_hat); bpresync_cccf_push(q, x[3]); bpresync_cccf_correlate(q, &rxy, &dphi_hat); bpresync_cccf_push(q, x[4]); bpresync_cccf_correlate(q, &rxy, &dphi_hat); bpresync_cccf_push(q, x[5]); bpresync_cccf_correlate(q, &rxy, &dphi_hat); bpresync_cccf_push(q, x[6]); bpresync_cccf_correlate(q, &rxy, &dphi_hat); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 7; // clean up allocated objects bpresync_cccf_destroy(q); } #define BPRESYNC_CCCF_BENCHMARK_API(N,M) \ ( struct rusage * _start, \ struct rusage * _finish, \ unsigned long int * _num_iterations) \ { bpresync_cccf_bench(_start, _finish, _num_iterations, N, M); } void benchmark_bpresync_cccf_16 BPRESYNC_CCCF_BENCHMARK_API(16, 6); void benchmark_bpresync_cccf_32 BPRESYNC_CCCF_BENCHMARK_API(32, 6); void benchmark_bpresync_cccf_64 BPRESYNC_CCCF_BENCHMARK_API(64, 6); void benchmark_bpresync_cccf_128 BPRESYNC_CCCF_BENCHMARK_API(128, 6); void benchmark_bpresync_cccf_256 BPRESYNC_CCCF_BENCHMARK_API(256, 6); liquid-dsp-1.3.1/src/framing/bench/bsync_benchmark.c000066400000000000000000000062461317124540100223620ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "liquid.internal.h" // Helper function to keep code base small void bsync_cccf_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _n) { // adjust number of iterations *_num_iterations *= 4; *_num_iterations /= _n; // generate sequence (random) float complex h[_n]; unsigned long int i; for (i=0; i<_n; i++) { h[i] = (rand() % 2 ? 1.0f : -1.0f) + (rand() % 2 ? 1.0f : -1.0f)*_Complex_I; } // generate synchronizer bsync_cccf q = bsync_cccf_create(_n,h); // input sequence (random) float complex x[7]; for (i=0; i<7; i++) { x[i] = (rand() % 2 ? 1.0f : -1.0f) + (rand() % 2 ? 1.0f : -1.0f)*_Complex_I; } float complex rxy; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { // push input sequence through synchronizer bsync_cccf_correlate(q, x[0], &rxy); bsync_cccf_correlate(q, x[1], &rxy); bsync_cccf_correlate(q, x[2], &rxy); bsync_cccf_correlate(q, x[3], &rxy); bsync_cccf_correlate(q, x[4], &rxy); bsync_cccf_correlate(q, x[5], &rxy); bsync_cccf_correlate(q, x[6], &rxy); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 7; // clean up allocated objects bsync_cccf_destroy(q); } #define BSYNC_CCCF_BENCHMARK_API(N) \ ( struct rusage * _start, \ struct rusage * _finish, \ unsigned long int * _num_iterations) \ { bsync_cccf_bench(_start, _finish, _num_iterations, N); } void benchmark_bsync_cccf_16 BSYNC_CCCF_BENCHMARK_API(16) void benchmark_bsync_cccf_32 BSYNC_CCCF_BENCHMARK_API(32) void benchmark_bsync_cccf_64 BSYNC_CCCF_BENCHMARK_API(64) void benchmark_bsync_cccf_128 BSYNC_CCCF_BENCHMARK_API(128) void benchmark_bsync_cccf_256 BSYNC_CCCF_BENCHMARK_API(256) liquid-dsp-1.3.1/src/framing/bench/detector_benchmark.c000066400000000000000000000072301317124540100230470ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "liquid.internal.h" // Helper function to keep code base small void detector_cccf_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _n) { // adjust number of iterations *_num_iterations *= 4; *_num_iterations /= _n; // generate sequence (random) float complex h[_n]; unsigned long int i; for (i=0; i<_n; i++) { h[i] = (rand() % 2 ? 1.0f : -1.0f) + (rand() % 2 ? 1.0f : -1.0f)*_Complex_I; } // generate synchronizer float threshold = 0.5f; float dphi_max = 0.07f; detector_cccf q = detector_cccf_create(h, _n, threshold, dphi_max); // input sequence (random) float complex x[7]; for (i=0; i<7; i++) { x[i] = (rand() % 2 ? 1.0f : -1.0f) + (rand() % 2 ? 1.0f : -1.0f)*_Complex_I; } float tau_hat; float dphi_hat; float gamma_hat; // start trials getrusage(RUSAGE_SELF, _start); int detected = 0; for (i=0; i<(*_num_iterations); i++) { // push input sequence through synchronizer detected ^= detector_cccf_correlate(q, x[0], &tau_hat, & dphi_hat, &gamma_hat); detected ^= detector_cccf_correlate(q, x[1], &tau_hat, & dphi_hat, &gamma_hat); detected ^= detector_cccf_correlate(q, x[2], &tau_hat, & dphi_hat, &gamma_hat); detected ^= detector_cccf_correlate(q, x[3], &tau_hat, & dphi_hat, &gamma_hat); detected ^= detector_cccf_correlate(q, x[4], &tau_hat, & dphi_hat, &gamma_hat); detected ^= detector_cccf_correlate(q, x[5], &tau_hat, & dphi_hat, &gamma_hat); detected ^= detector_cccf_correlate(q, x[6], &tau_hat, & dphi_hat, &gamma_hat); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 7; // clean up allocated objects detector_cccf_destroy(q); } #define DETECTOR_CCCF_BENCHMARK_API(N) \ ( struct rusage * _start, \ struct rusage * _finish, \ unsigned long int * _num_iterations) \ { detector_cccf_bench(_start, _finish, _num_iterations, N); } void benchmark_detector_cccf_16 DETECTOR_CCCF_BENCHMARK_API(16); void benchmark_detector_cccf_32 DETECTOR_CCCF_BENCHMARK_API(32); void benchmark_detector_cccf_64 DETECTOR_CCCF_BENCHMARK_API(64); void benchmark_detector_cccf_128 DETECTOR_CCCF_BENCHMARK_API(128); void benchmark_detector_cccf_256 DETECTOR_CCCF_BENCHMARK_API(256); liquid-dsp-1.3.1/src/framing/bench/flexframesync_benchmark.c000066400000000000000000000102031317124540100240760ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "liquid.h" typedef struct { unsigned char * header; unsigned char * payload; unsigned int num_frames_tx; unsigned int num_frames_detected; unsigned int num_headers_valid; unsigned int num_payloads_valid; } framedata; static int callback(unsigned char * _header, int _header_valid, unsigned char * _payload, unsigned int _payload_len, int _payload_valid, framesyncstats_s _stats, void * _userdata) { //printf("callback invoked\n"); framedata * fd = (framedata*) _userdata; // increment number of frames detected fd->num_frames_detected++; // check if header is valid if (_header_valid) fd->num_headers_valid++; // check if payload is valid if (_payload_valid) fd->num_payloads_valid++; return 0; } // Helper function to keep code base small void benchmark_flexframesync( struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { *_num_iterations /= 128; unsigned long int i; // create flexframegen object flexframegenprops_s fgprops; flexframegenprops_init_default(&fgprops); fgprops.check = LIQUID_CRC_32; fgprops.fec0 = LIQUID_FEC_NONE; fgprops.fec1 = LIQUID_FEC_NONE; fgprops.mod_scheme = LIQUID_MODEM_QPSK; flexframegen fg = flexframegen_create(&fgprops); flexframegen_print(fg); // frame data unsigned int payload_len = 8; unsigned char header[14]; unsigned char payload[payload_len]; // initialize header, payload for (i=0; i<14; i++) header[i] = i; for (i=0; i #include #include #include #include "liquid.h" typedef struct { unsigned int num_frames_tx; // number of transmitted frames unsigned int num_frames_detected; // number of received frames (detected) unsigned int num_frames_valid; // number of valid payloads } framedata; static int callback(unsigned char * _header, int _header_valid, unsigned char * _payload, unsigned int _payload_len, int _payload_valid, framesyncstats_s _stats, void * _userdata) { //printf("callback invoked, payload valid: %s\n", _payload_valid ? "yes" : "no"); framedata * fd = (framedata*) _userdata; fd->num_frames_detected += 1; fd->num_frames_valid += _payload_valid ? 1 : 0; return 0; } // Helper function to keep code base small void benchmark_framesync64( struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { *_num_iterations /= 128; unsigned long int i; framegen64 fg = framegen64_create(); framegen64_print(fg); // frame data unsigned char header[8] = {0, 1, 2, 3, 4, 5, 6, 7}; unsigned char payload[64]; // initialize payload for (i=0; i<64; i++) payload[i] = rand() & 0xff; framedata fd = {0, 0, 0}; // create framesync64 object framesync64 fs = framesync64_create(callback,(void*)&fd); framesync64_print(fs); // generate the frame //unsigned int frame_len = framegen64_getframelen(fg); unsigned int frame_len = LIQUID_FRAME64_LEN; float complex frame[frame_len]; framegen64_execute(fg, header, payload, frame); // add some noise for (i=0; i #include #include #include #include #include "liquid.h" typedef struct { unsigned char * header; unsigned char * payload; unsigned int num_frames_tx; unsigned int num_frames_detected; unsigned int num_headers_valid; unsigned int num_payloads_valid; } framedata; static int callback(unsigned char * _header, int _header_valid, unsigned char * _payload, unsigned int _payload_len, int _payload_valid, framesyncstats_s _stats, void * _userdata) { //printf("callback invoked\n"); framedata * fd = (framedata*) _userdata; // increment number of frames detected fd->num_frames_detected++; // check if header is valid if (_header_valid) fd->num_headers_valid++; // check if payload is valid if (_payload_valid) fd->num_payloads_valid++; return 0; } // benchmark regular frame synchronizer with short frames; effectively // test acquisition complexity void benchmark_gmskframesync(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations) { *_num_iterations /= 128; unsigned long int i; // options unsigned int payload_len = 8; // length of payload (bytes) crc_scheme check = LIQUID_CRC_32; // data validity check fec_scheme fec0 = LIQUID_FEC_NONE; // inner forward error correction fec_scheme fec1 = LIQUID_FEC_NONE; // outer forward error correction float SNRdB = 30.0f; // SNR // derived values float nstd = powf(10.0f, -SNRdB/20.0f); // create gmskframegen object gmskframegen fg = gmskframegen_create(); // frame data unsigned char header[14]; unsigned char payload[payload_len]; // initialize header, payload for (i=0; i<14; i++) header[i] = i; for (i=0; i #include #include #include #include "liquid.internal.h" // Helper function to keep code base small void presync_cccf_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _n, unsigned int _m) { // adjust number of iterations *_num_iterations *= 4; *_num_iterations /= _n; *_num_iterations /= _m; // generate sequence (random) float complex h[_n]; unsigned long int i; for (i=0; i<_n; i++) { h[i] = (rand() % 2 ? 1.0f : -1.0f) + (rand() % 2 ? 1.0f : -1.0f)*_Complex_I; } // generate synchronizer presync_cccf q = presync_cccf_create(h, _n, 0.1f, _m); // input sequence (random) float complex x[7]; for (i=0; i<7; i++) { x[i] = (rand() % 2 ? 1.0f : -1.0f) + (rand() % 2 ? 1.0f : -1.0f)*_Complex_I; } float complex rxy; float dphi_hat; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { // push input sequence through synchronizer presync_cccf_push(q, x[0]); presync_cccf_correlate(q, &rxy, &dphi_hat); presync_cccf_push(q, x[1]); presync_cccf_correlate(q, &rxy, &dphi_hat); presync_cccf_push(q, x[2]); presync_cccf_correlate(q, &rxy, &dphi_hat); presync_cccf_push(q, x[3]); presync_cccf_correlate(q, &rxy, &dphi_hat); presync_cccf_push(q, x[4]); presync_cccf_correlate(q, &rxy, &dphi_hat); presync_cccf_push(q, x[5]); presync_cccf_correlate(q, &rxy, &dphi_hat); presync_cccf_push(q, x[6]); presync_cccf_correlate(q, &rxy, &dphi_hat); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 7; // clean up allocated objects presync_cccf_destroy(q); } #define PRESYNC_CCCF_BENCHMARK_API(N,M) \ ( struct rusage * _start, \ struct rusage * _finish, \ unsigned long int * _num_iterations) \ { presync_cccf_bench(_start, _finish, _num_iterations, N, M); } void benchmark_presync_cccf_16 PRESYNC_CCCF_BENCHMARK_API(16, 6); void benchmark_presync_cccf_32 PRESYNC_CCCF_BENCHMARK_API(32, 6); void benchmark_presync_cccf_64 PRESYNC_CCCF_BENCHMARK_API(64, 6); void benchmark_presync_cccf_128 PRESYNC_CCCF_BENCHMARK_API(128, 6); void benchmark_presync_cccf_256 PRESYNC_CCCF_BENCHMARK_API(256, 6); liquid-dsp-1.3.1/src/framing/bench/qdetector_benchmark.c000066400000000000000000000075531317124540100232400ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2017 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "liquid.internal.h" // Helper function to keep code base small void qdetector_cccf_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _n) { // adjust number of iterations *_num_iterations *= 4; *_num_iterations /= _n; // generate sequence (random) float complex h[_n]; unsigned long int i; for (i=0; i<_n; i++) { h[i] = (rand() % 2 ? 1.0f : -1.0f) + (rand() % 2 ? 1.0f : -1.0f)*_Complex_I; } // generate synchronizer int ftype = LIQUID_FIRFILT_ARKAISER; unsigned int k = 2; // samples/symbol unsigned int m = 7; // filter delay [symbols] float beta = 0.3f; // excess bandwidth factor float threshold = 0.5f; // threshold for detection float range = 0.05f; // carrier offset search range [radians/sample] qdetector_cccf q = qdetector_cccf_create_linear(h, _n, ftype, k, m, beta); qdetector_cccf_set_threshold(q,threshold); qdetector_cccf_set_range (q, range); // input sequence (random) float complex x[7]; for (i=0; i<7; i++) { x[i] = (rand() % 2 ? 1.0f : -1.0f) + (rand() % 2 ? 1.0f : -1.0f)*_Complex_I; } // start trials getrusage(RUSAGE_SELF, _start); int detected = 0; for (i=0; i<(*_num_iterations); i++) { // push input sequence through synchronizer detected ^= qdetector_cccf_execute(q, x[0]) != NULL; detected ^= qdetector_cccf_execute(q, x[1]) != NULL; detected ^= qdetector_cccf_execute(q, x[2]) != NULL; detected ^= qdetector_cccf_execute(q, x[3]) != NULL; detected ^= qdetector_cccf_execute(q, x[4]) != NULL; detected ^= qdetector_cccf_execute(q, x[5]) != NULL; detected ^= qdetector_cccf_execute(q, x[6]) != NULL; } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 7; // clean up allocated objects qdetector_cccf_destroy(q); } #define QDETECTOR_CCCF_BENCHMARK_API(N) \ ( struct rusage * _start, \ struct rusage * _finish, \ unsigned long int * _num_iterations) \ { qdetector_cccf_bench(_start, _finish, _num_iterations, N); } void benchmark_qdetector_cccf_16 QDETECTOR_CCCF_BENCHMARK_API(16); void benchmark_qdetector_cccf_32 QDETECTOR_CCCF_BENCHMARK_API(32); void benchmark_qdetector_cccf_64 QDETECTOR_CCCF_BENCHMARK_API(64); void benchmark_qdetector_cccf_128 QDETECTOR_CCCF_BENCHMARK_API(128); void benchmark_qdetector_cccf_256 QDETECTOR_CCCF_BENCHMARK_API(256); liquid-dsp-1.3.1/src/framing/packetizer.readme.txt000066400000000000000000000044111317124540100221350ustar00rootroot00000000000000====================================== packetizer ====================================== The liquid packetizer is a structure for abstracting multi-level forward error-correction from the user. The packetizer accepts a buffer of uncoded data bytes and adds a cyclic redundancy check (crc) before applying two levels of forward error- correction and bit-level interleaving. The user may choose any two supported FEC schemes (including none) and the packetizer object will handle buffering and data management internally, providing a truly abstract interface. The same is true for the packet decoder which accepts an array of possibly corrupt data and attempts to recover the original message using the FEC schemes provided. The packet decoder returns the validity of the resulting CRC as well as its best effort of decoding the message. The packetizer also allows for re-structuring if the user wishes to change error-correction schemes or data lengths. This is accomplished with the packetier_recreate() method. Here is a minimal example demonstrating the packetizer's most basic functionality: #include ... { // set up the options unsigned int n=16; // uncoded data length crc_scheme check = LIQUID_CRC_32; // data integrity check fec_scheme fec0 = LIQUID_FEC_HAMMING74; // inner code fec_scheme fec1 = LIQUID_FEC_REP3; // outer code // compute resulting packet length unsigned int k = packetizer_compute_enc_msg_len(n,fec0,fec1); // set up the arrays unsigned char msg[n]; // original message unsigned char packet[k]; // encoded message unsigned char msg_dec[n]; // decoded message int crc_pass; // decoder validity check // create the packetizer object packetizer p = packetizer_create(n,check,fec0,fec1); // initialize msg here unsigned int i; for (i=0; i time new header options: header check fec1 bytes bpsk syms 1% FER SNR [[14 + 5 + crc16] + h128 ] > 32 > 256 3.0 dB / 2.9 dB soft [[14 + 5 + crc24] + g2412] > 45 > 360 - dB / - [[14 + 5 + crc24] + v27 ] > 46 > 368 - dB / -0.3 dB soft [[14 + 5 + crc24] + v39 ] > 69 > 552 - dB / -1.1 dB soft concatenated code: 14 + 6 + 4 = 24 + secded7264 > 27 + h84 > 54 [[[14 + 6 + crc32] + secded7264] + h84] > 54 > 432 - dB / 0.2 dB soft section # syms Description ramp up (r/u) 0+ phasing (1010...) with ramp up phasing pattern 0+ 10101010... p/n sequence 64 BPSK P/N sequence (m-sequence, g=0x005b) header 256 # bytes crc 2 cyclic redundancy check packet fec 2 payload fec (inner/outer), check mod scheme/bps 1 modulation scheme, depth payload_len 2 # bytes in payload (up to 65535) user data 14 space for user-defined data total 19 encoded 32 Hamming(12,8) payload [variable] data payload using arbitrary linear modulation ramp down (r\d) 0+ phasing (1010...) with ramp down The header includes a mandatory 32-bit crc with 1/2 rate forward error- correction code totaling 256 bits (32 bytes) of encoded data. liquid-dsp-1.3.1/src/framing/readme.framesync64.md000066400000000000000000000031231317124540100217150ustar00rootroot00000000000000 frame64 description ------------------- ## Structure ## signal ^ | .+-------+---------------------------+. | / | | | \ | r/u | p/n | header/payload | r\d |__/ | | | \__ +--------------------------------------------------> time section length Description ramp-up 3 symbols filter ramp/up p/n sequence 64 symbols BPSK p/n sequence (m-sequence, g=0x0043) header/payload 600 symbols 64-byte packet payload with 8-byte header, 24-bit crc, encoded with the Golay(24,12) FEC, (150 bytes encoded) modulated with QPSK ramp-dn 3 symbols filter ramp\down total: 670 symbols interpolated: 1340 samples interpolated using half-rate square- root Nyquist pulse-shaping filter at 2 samples/symbol ## Description ## The frame structure is simply a 64-bit pseudo-random p/n sequence modulated with BPSK followed by a QPSK payload. The payload has a fixed length of 64 bytes (with an 8-byte 'header'), a 24-bit cyclic redudancy check, and encoded with a half-rate Golay(24,12) block code. The entire frame uses a square-root Nyquist pulse shape with an excess bandwidth of 0.5 and interpolated at two samples per symbol. The resulting frame length is exactly 1340 samples. liquid-dsp-1.3.1/src/framing/readme.gmskframe.txt000066400000000000000000000044371317124540100217600ustar00rootroot00000000000000 GMSK frame structure ==================== The gmskframegen and gmskframesync object facilite sending packets over the air with Gauss minimum-shift keying (GMSK). This modulation scheme is a special case of binary frequency-shift keying (BFSK) which uses the minimum frequency separation between tones and uses Gauss pulse shaping to reduce its occupied bandwidth. Its spectral efficiency is nominally 1 b/s/Hz, and the framing structure allows any length payload up to 65,535 bytes with two levels of forward error-correction coding. signal ^ | .+---------+-----+--------+----//---+. | / | | | | | \ | r/u | phasing | p/n | header | payload | r\d |__/ | | | | | \__ +-------------------------------------------------> time section # bits Description ramp up (r/u) 8 phasing (1010...) with ramp up phasing pattern 40 10101010... p/n sequence 64 BPSK P/N sequence (m-sequence, g=0x005b) header 208 includes payload length, fec schemes, crc, and 8 bytes of user-defined data, all encoded with the Hamming(12,8) block code payload [variable] data payload using arbitrary forward error correction ramp down (r\d) 8 phasing (1010...) with ramp down The approximate spectral efficiency of the frame is determined by the following equation: payload*8/rate 1 ---------------------- * -------- bits/second/Hertz 328 + payload*8/rate 1 + BT where 'payload' is the length of the payload (in bytes), 'rate' is the rate of the pair of forward error-correction codes, and 'BT' is the bandwidth-time constant of the GMSK signaling. Note that 328 is the number of bits of overhead associated with the frame (e.g. sending the header, etc.) For example, if the payload is 1024 bytes encoded with a half-rate convolutional code, and modulated with a bandwdith-time constant of BT=0.5, the approximate spectral efficiency is 1024*8/(1/2) 1 ------------------ * --------- = 0.654 b/s/Hz 328 + 1024*8/(1/2) 1 + 0.5 liquid-dsp-1.3.1/src/framing/readme.ofdm.txt000066400000000000000000000117161317124540100207270ustar00rootroot00000000000000========================================================================= OFDM flexible framing structure ========================================================================= signal ^ | +----+----+----+----+----+-//-+----+----+-//-+----+ | | | | | | | | | | S0 | S0 | .. | S1 | ..header.. | ..payload.. | |___| | | | | | |__ +---------------------------------------------------------> time spectral null ^ pilot subcarrier / | / *----*----* *----*----+----*----*----*----*----* | | | | | | | | | ... | ___/ \____/ | \___ +---------------------------+----------------------------+ freq -Fs/2 0 +Fs/2 Overview: The ofdmflexframe family of objects (generator and synchronizer) realize a simple way to load data onto an OFDM physical layer system. OFDM has several benefits over traditional 'narrowband' communications systems. These objects allow the user to abstractly specify the number of subcarriers, their assignment (null/pilot/data), forward error-correction and modulation scheme. Furthermore, the framing structure includes a provision for a brief user-defined header which can be used for source/destination address, packet identifier, etc. Operational description: The structure of the frame consists of three main components: the preamble, the header, and the payload. Preamble The preamble consists of two types of phasing symbols: the S0 and S1 sequences. The S0 symbols are necessary for coarse carrier frequency and timing offsets while the S1 sequence is used for fine timing acquisition and equalizer gain estimation. The transmitter generates multiple S0 symbols (minimally 2, but usually 3 or more) and just a single S1 symbol. This aligns the receiver's timing to that of the transmitter, signalling the start of the header. Header The header consists of one or more OFDM symbols; the exact number of OFDM symbols depends on the number of subcarriers allocated and the assignment of these subcarriers (null/pilot/data). The header carries exactly 14 bytes of information, 6 of which are used internally and the remaining 8 are user-defined. The internal data signal the receiver of the modulation, forward error-correction, and data validation schemes of the payload as well as its length in bytes. These data are encoded with a forward error-correction scheme and modulated onto the first several OFDM symbols. Payload The payload consists of zero or more OFDM symbols. Like the header, the exact number of OFDM symbols depends on the number of subcarriers allocated and the assignment of these subcarriers. OFDM frame gen/sync parameters (must match on both TX and RX side): M : Total number of subcarriers p* : subcarrier allocation cplen : cyclic prefix length (samples) M0 : number of null subcarriers Mp : number of pilot subcarriers Md : number of data subcarriers num_S0 : number of S0 symbols num_S1 : number of S1 symbols (must be 1, non-negotiable) Notes: * The length of each data symbol is equal to the number of subcarriers plus the cyclic prefix length (e.g. if N=64 and cplen=16, each data symbol is 80 samples long) with the exception of the S0 training symbols which are simply the number of subcarriers. * The S0 symbols do NOT have a cyclic prefix; this is necessary to preserve continuity between symbols. Unlike 802.11a (and derivative protocols) in which a fixed cyclic prefix has been designed into the system, the flexibility of liquid-dsp's OFDM framing structure requires that no prefix is added to maintain temporal continuity. Details: section num samples Description/purpose S0 M*num_S0 Initial preamble for coarse carrier frequency, phase, and timing offset estimates S1 M+cplen Secondary preamble for timing disambiguation and equalization header [variable] Framing descriptor user-defined: 8 bytes internal : 6 bytes encoded with Hamming(12,8), 16-bit CRC: 24 bytes modulated with QPSK : 96 modem symbols ... payload [variable] user-defined length... TODO: * Iteratively improve initial carrier frequency, phase, timing offset by averaging over S0 symbols (until S1 symbol is found) * Make cyclic prefix length discoverable on the receiver by observing phase slope of S1 liquid-dsp-1.3.1/src/framing/src/000077500000000000000000000000001317124540100165665ustar00rootroot00000000000000liquid-dsp-1.3.1/src/framing/src/bpacketgen.c000066400000000000000000000226651317124540100210500ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // bpacketgen // // binary packet generator/encoder // #include #include #include #include #include "liquid.internal.h" // bpacketgen object structure struct bpacketgen_s { // options unsigned int g; // p/n sequence genpoly unsigned int pnsequence_len; // p/n sequence length (bytes) unsigned int dec_msg_len; // payload length crc_scheme crc; // payload check fec_scheme fec0; // payload fec (inner) fec_scheme fec1; // payload fec (outer) // derived values unsigned int enc_msg_len; // encoded mesage length unsigned int header_len; // header length (12 bytes encoded) unsigned int packet_len; // total packet length // arrays unsigned char * pnsequence; // p/n sequence // bpacket header // 0 : version number // 1 : crc // 2 : fec0 // 3 : fec1 // 4:5 : payload length unsigned char header_dec[6]; // uncoded bytes unsigned char header_enc[12]; // 12 = 6 + crc16 at hamming(12,8) // objects msequence ms; packetizer p_header; packetizer p_payload; }; // create bpacketgen object // _m : p/n sequence length (ignored) // _dec_msg_len : decoded message length (original uncoded data) // _crc : data validity check (e.g. cyclic redundancy check) // _fec0 : inner forward error-correction code scheme // _fec1 : outer forward error-correction code scheme bpacketgen bpacketgen_create(unsigned int _m, unsigned int _dec_msg_len, int _crc, int _fec0, int _fec1) { // validate input // create bpacketgen object bpacketgen q = (bpacketgen) malloc(sizeof(struct bpacketgen_s)); q->dec_msg_len = _dec_msg_len; q->crc = _crc; q->fec0 = _fec0; q->fec1 = _fec1; // implied values q->g = 0; q->pnsequence_len = 8; // derived values q->enc_msg_len = packetizer_compute_enc_msg_len(q->dec_msg_len, q->crc, q->fec0, q->fec1); q->header_len = packetizer_compute_enc_msg_len(6, LIQUID_CRC_16, LIQUID_FEC_NONE, LIQUID_FEC_HAMMING128); bpacketgen_compute_packet_len(q); // arrays q->pnsequence = (unsigned char*) malloc((q->pnsequence_len)*sizeof(unsigned char)); // create m-sequence generator // TODO : configure sequence from generator polynomial q->ms = msequence_create_default(6); // create header packet encoder q->p_header = packetizer_create(6, LIQUID_CRC_16, LIQUID_FEC_NONE, LIQUID_FEC_HAMMING128); assert(q->header_len == packetizer_get_enc_msg_len(q->p_header)); // create payload packet encoder q->p_payload = packetizer_create(q->dec_msg_len, q->crc, q->fec0, q->fec1); // assemble semi-static framing structures bpacketgen_assemble_header(q); bpacketgen_assemble_pnsequence(q); return q; } // re-create bpacketgen object from old object // _q : old bpacketgen object // _m : p/n sequence length (ignored) // _dec_msg_len : decoded message length (original uncoded data) // _crc : data validity check (e.g. cyclic redundancy check) // _fec0 : inner forward error-correction code scheme // _fec1 : outer forward error-correction code scheme bpacketgen bpacketgen_recreate(bpacketgen _q, unsigned int _m, unsigned int _dec_msg_len, int _crc, int _fec0, int _fec1) { // validate input // re-create internal packetizer object _q->dec_msg_len = _dec_msg_len; _q->crc = _crc; _q->fec0 = _fec0; _q->fec1 = _fec1; // derived values _q->enc_msg_len = packetizer_compute_enc_msg_len(_q->dec_msg_len, _q->crc, _q->fec0, _q->fec1); _q->header_len = packetizer_compute_enc_msg_len(6, LIQUID_CRC_16, LIQUID_FEC_NONE, LIQUID_FEC_HAMMING128); bpacketgen_compute_packet_len(_q); // arrays _q->g = 0; _q->pnsequence_len = 8; _q->pnsequence = (unsigned char*) realloc(_q->pnsequence, (_q->pnsequence_len)*sizeof(unsigned char)); // re-create m-sequence generator // TODO : configure sequence from generator polynomial msequence_destroy(_q->ms); _q->ms = msequence_create_default(6); // re-create payload packet encoder _q->p_payload = packetizer_recreate(_q->p_payload, _q->dec_msg_len, _q->crc, _q->fec0, _q->fec1); // assemble semi-static framing structures bpacketgen_assemble_header(_q); bpacketgen_assemble_pnsequence(_q); return _q; } // destroy bpacketgen object, freeing all internally-allocated memory void bpacketgen_destroy(bpacketgen _q) { // free arrays free(_q->pnsequence); // destroy internal objects msequence_destroy(_q->ms); packetizer_destroy(_q->p_header); packetizer_destroy(_q->p_payload); // free main object memory free(_q); } // print bpacketgen internals void bpacketgen_print(bpacketgen _q) { printf("bpacketgen:\n"); printf(" p/n poly : 0x%.4x\n", _q->g); printf(" p/n len : %u bytes\n", _q->pnsequence_len); printf(" header len : %u bytes\n", _q->header_len); printf(" payload len : %u bytes\n", _q->dec_msg_len); printf(" crc : %s\n", crc_scheme_str[_q->crc][1]); printf(" fec (inner) : %s\n", fec_scheme_str[_q->fec0][1]); printf(" fec (outer) : %s\n", fec_scheme_str[_q->fec1][1]); printf(" packet len : %u bytes\n", _q->packet_len); printf(" efficiency : %8.2f %%\n", 100.0f*(float)_q->dec_msg_len/(float)_q->packet_len); } // return length of full packet unsigned int bpacketgen_get_packet_len(bpacketgen _q) { return _q->packet_len; } // encode packet void bpacketgen_encode(bpacketgen _q, unsigned char * _msg_dec, unsigned char * _packet) { // output byte index counter unsigned int n=0; // copy p/n sequence memmove(&_packet[n], _q->pnsequence, _q->pnsequence_len*sizeof(unsigned char)); n += _q->pnsequence_len; // copy header memmove(&_packet[n], _q->header_enc, _q->header_len*sizeof(unsigned char)); n += _q->header_len; // encode payload packetizer_encode(_q->p_payload, _msg_dec, &_packet[n]); n += _q->enc_msg_len; // verify length is correct assert(n == _q->packet_len); } // // internal methods // // compute packet length void bpacketgen_compute_packet_len(bpacketgen _q) { _q->packet_len = _q->pnsequence_len + _q->header_len + _q->enc_msg_len; } // generate p/n sequence void bpacketgen_assemble_pnsequence(bpacketgen _q) { // reset m-sequence generator msequence_reset(_q->ms); unsigned int i; unsigned int j; for (i=0; i<_q->pnsequence_len; i++) { unsigned char byte = 0; for (j=0; j<8; j++) { byte <<= 1; byte |= msequence_advance(_q->ms); } _q->pnsequence[i] = byte; } } // assemble packet header void bpacketgen_assemble_header(bpacketgen _q) { _q->header_dec[0] = BPACKET_VERSION; _q->header_dec[1] = (unsigned char) _q->crc; _q->header_dec[2] = (unsigned char) _q->fec0; _q->header_dec[3] = (unsigned char) _q->fec1; _q->header_dec[4] = (unsigned char) (_q->dec_msg_len >> 8) & 0xff; _q->header_dec[5] = (unsigned char) (_q->dec_msg_len ) & 0xff; // encode header packetizer_encode(_q->p_header, _q->header_dec, _q->header_enc); } liquid-dsp-1.3.1/src/framing/src/bpacketsync.c000066400000000000000000000335431317124540100212500ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // bpacketsync // // binary packet synchronizer/decoder // #include #include #include #include #include #include "liquid.internal.h" #define DEBUG_BPACKETSYNC 0 // bpacketsync object structure struct bpacketsync_s { // options unsigned int g; // p/n sequence genpoly unsigned int pnsequence_len; // p/n sequence length (bytes) unsigned int dec_msg_len; // payload length crc_scheme crc; // payload check fec_scheme fec0; // payload fec (inner) fec_scheme fec1; // payload fec (outer) // derived values unsigned int enc_msg_len; // encoded mesage length unsigned int header_len; // header length (12 bytes encoded) unsigned int packet_len; // total packet length // arrays unsigned char * pnsequence; // p/n sequence unsigned char * payload_enc; // payload (encoded) unsigned char * payload_dec; // payload (decoded) // bpacket header // 0 : version number // 1 : crc // 2 : fec0 // 3 : fec1 // 4:5 : payload length unsigned char header_dec[6]; // uncoded bytes unsigned char header_enc[12]; // 12 = 6 + crc16 at hamming(12,8) // objects msequence ms; packetizer p_header; packetizer p_payload; bsequence bpn; // binary p/n sequence bsequence brx; // binary received sequence // status variables enum { BPACKETSYNC_STATE_SEEKPN=0, // seek p/n sequence BPACKETSYNC_STATE_RXHEADER, // receive header data BPACKETSYNC_STATE_RXPAYLOAD // receive payload data } state; // counters unsigned int num_bytes_received; unsigned int num_bits_received; unsigned char byte_rx; unsigned char byte_mask; // flags int header_valid; int payload_valid; // user-defined parameters bpacketsync_callback callback; void * userdata; framesyncstats_s framestats; }; bpacketsync bpacketsync_create(unsigned int _m, bpacketsync_callback _callback, void * _userdata) { // create bpacketsync object bpacketsync q = (bpacketsync) malloc(sizeof(struct bpacketsync_s)); q->callback = _callback; q->userdata = _userdata; // default values q->dec_msg_len = 1; q->crc = LIQUID_CRC_NONE; q->fec0 = LIQUID_FEC_NONE; q->fec1 = LIQUID_FEC_NONE; // implied values q->g = 0; q->pnsequence_len = 8; // derived values q->enc_msg_len = packetizer_compute_enc_msg_len(q->dec_msg_len, q->crc, q->fec0, q->fec1); q->header_len = packetizer_compute_enc_msg_len(6, LIQUID_CRC_16, LIQUID_FEC_NONE, LIQUID_FEC_HAMMING128); // arrays q->pnsequence = (unsigned char*) malloc((q->pnsequence_len)*sizeof(unsigned char)); q->payload_enc = (unsigned char*) malloc((q->enc_msg_len)*sizeof(unsigned char)); q->payload_dec = (unsigned char*) malloc((q->dec_msg_len)*sizeof(unsigned char)); // create m-sequence generator // TODO : configure sequence from generator polynomial q->ms = msequence_create_default(6); // create header packet encoder q->p_header = packetizer_create(6, LIQUID_CRC_16, LIQUID_FEC_NONE, LIQUID_FEC_HAMMING128); assert(q->header_len == packetizer_get_enc_msg_len(q->p_header)); // create payload packet encoder q->p_payload = packetizer_create(q->dec_msg_len, q->crc, q->fec0, q->fec1); // create binary sequence objects q->bpn = bsequence_create(q->pnsequence_len*8); q->brx = bsequence_create(q->pnsequence_len*8); // assemble semi-static framing structures bpacketsync_assemble_pnsequence(q); // reset synchronizer bpacketsync_reset(q); return q; } void bpacketsync_destroy(bpacketsync _q) { // free arrays free(_q->pnsequence); free(_q->payload_enc); free(_q->payload_dec); // destroy internal objects msequence_destroy(_q->ms); packetizer_destroy(_q->p_header); packetizer_destroy(_q->p_payload); bsequence_destroy(_q->bpn); bsequence_destroy(_q->brx); // free main object memory free(_q); } void bpacketsync_print(bpacketsync _q) { printf("bpacketsync:\n"); printf(" p/n poly : 0x%.4x\n", _q->g); printf(" p/n len : %u bytes\n", _q->pnsequence_len); printf(" header len : %u bytes\n", _q->header_len); printf(" payload len : %u bytes\n", _q->dec_msg_len); printf(" crc : %s\n", crc_scheme_str[_q->crc][1]); printf(" fec (inner) : %s\n", fec_scheme_str[_q->fec0][1]); printf(" fec (outer) : %s\n", fec_scheme_str[_q->fec1][1]); printf(" packet len : %u bytes\n", _q->packet_len); printf(" efficiency : %8.2f %%\n", 100.0f*(float)_q->dec_msg_len/(float)_q->packet_len); } void bpacketsync_reset(bpacketsync _q) { // clear received sequence buffer bsequence_reset(_q->brx); // reset counters _q->num_bytes_received = 0; _q->num_bits_received = 0; _q->byte_rx = 0; _q->byte_mask = 0x00; // reset state _q->state = BPACKETSYNC_STATE_SEEKPN; } // run synchronizer on array of input bytes // _q : bpacketsync object // _bytes : input data array [size: _n x 1] // _n : input array size void bpacketsync_execute(bpacketsync _q, unsigned char * _bytes, unsigned int _n) { unsigned int i; for (i=0; i<_n; i++) bpacketsync_execute_byte(_q, _bytes[i]); } // run synchronizer on input byte // _q : bpacketsync object // _byte : input byte void bpacketsync_execute_byte(bpacketsync _q, unsigned char _byte) { unsigned int j; for (j=0; j<8; j++) { // strip bit from byte unsigned char bit = (_byte >> (8-j-1)) & 1; // run synchronizer on bit bpacketsync_execute_bit(_q, bit); } } // run synchronizer on input symbol // _q : bpacketsync object // _sym : input symbol with _bps significant bits // _bps : number of bits in input symbol void bpacketsync_execute_sym(bpacketsync _q, unsigned char _sym, unsigned int _bps) { // validate input if (_bps > 8) { fprintf(stderr,"error: bpacketsync_execute_sym(), bits per symbol must be in [0,8]\n"); exit(1); } unsigned int j; for (j=0; j<_bps; j++) { // strip bit from byte unsigned char bit = (_sym >> (_bps-j-1)) & 1; // run synchronizer on bit bpacketsync_execute_bit(_q, bit); } } // execute one bit at a time void bpacketsync_execute_bit(bpacketsync _q, unsigned char _bit) { // mask input to ensure one bit of resolution _bit = _bit & 0x01; // execute state-specific methods switch (_q->state) { case BPACKETSYNC_STATE_SEEKPN: bpacketsync_execute_seekpn(_q, _bit); break; case BPACKETSYNC_STATE_RXHEADER: bpacketsync_execute_rxheader(_q, _bit); break; case BPACKETSYNC_STATE_RXPAYLOAD: bpacketsync_execute_rxpayload(_q, _bit); break; default: fprintf(stderr,"error: bpacketsync_execute(), invalid state\n"); exit(1); } } // // internal methods // void bpacketsync_assemble_pnsequence(bpacketsync _q) { // reset m-sequence generator msequence_reset(_q->ms); unsigned int i; for (i=0; i<8*_q->pnsequence_len; i++) bsequence_push(_q->bpn, msequence_advance(_q->ms)); } void bpacketsync_execute_seekpn(bpacketsync _q, unsigned char _bit) { // push bit into correlator bsequence_push(_q->brx, _bit); // compute p/n sequence correlation int rxy = bsequence_correlate(_q->bpn, _q->brx); float r = 2.0f*(float)rxy / (float)(_q->pnsequence_len*8) - 1.0f; // check threshold if ( fabsf(r) > 0.8f ) { #if DEBUG_BPACKETSYNC printf("p/n sequence found!, rxy = %8.4f\n", r); #endif // flip polarity of bits if correlation is negative _q->byte_mask = r > 0 ? 0x00 : 0xff; // switch operational mode _q->state = BPACKETSYNC_STATE_RXHEADER; } } void bpacketsync_execute_rxheader(bpacketsync _q, unsigned char _bit) { // push bit into accumulated byte _q->byte_rx <<= 1; _q->byte_rx |= (_bit & 1); _q->num_bits_received++; if (_q->num_bits_received == 8) { // append byte to encoded header array _q->header_enc[_q->num_bytes_received] = _q->byte_rx ^ _q->byte_mask; _q->num_bits_received=0; _q->num_bytes_received++; if (_q->num_bytes_received == _q->header_len) { _q->num_bits_received = 0; _q->num_bytes_received = 0; // decode header bpacketsync_decode_header(_q); // TODO : invoke header callback now if (_q->header_valid) { // re-allocate memory for arrays bpacketsync_reconfig(_q); // switch operational mode _q->state = BPACKETSYNC_STATE_RXPAYLOAD; } else { // reset synchronizer bpacketsync_reset(_q); } } } } void bpacketsync_execute_rxpayload(bpacketsync _q, unsigned char _bit) { // push bit into accumulated byte _q->byte_rx <<= 1; _q->byte_rx |= (_bit & 1); _q->num_bits_received++; if (_q->num_bits_received == 8) { // append byte to encoded payload array _q->payload_enc[_q->num_bytes_received] = _q->byte_rx ^ _q->byte_mask; _q->num_bits_received=0; _q->num_bytes_received++; if (_q->num_bytes_received == _q->enc_msg_len) { _q->num_bits_received = 0; _q->num_bytes_received = 0; // decode payload data bpacketsync_decode_payload(_q); // invoke callback if (_q->callback != NULL) { // set frame stats framesyncstats_init_default(&_q->framestats); _q->framestats.check = _q->crc; _q->framestats.fec0 = _q->fec0; _q->framestats.fec1 = _q->fec1; _q->callback(_q->payload_dec, _q->payload_valid, _q->dec_msg_len, _q->framestats, _q->userdata); } // reset synchronizer bpacketsync_reset(_q); } } } void bpacketsync_decode_header(bpacketsync _q) { // decode header array _q->header_valid = packetizer_decode(_q->p_header, _q->header_enc, _q->header_dec); // return unconditionally if header failed if (!_q->header_valid) return; // strip header info int version = _q->header_dec[0]; _q->crc = (crc_scheme) _q->header_dec[1]; _q->fec0 = (fec_scheme) _q->header_dec[2]; _q->fec1 = (fec_scheme) _q->header_dec[3]; _q->dec_msg_len = (_q->header_dec[4] << 8) | (_q->header_dec[5] ); // check version number if (version != BPACKET_VERSION) fprintf(stderr,"warning: bpacketsync, version mismatch!\n"); // TODO : check crc, fec0, fec1 schemes } void bpacketsync_decode_payload(bpacketsync _q) { // decode payload _q->payload_valid = packetizer_decode(_q->p_payload, _q->payload_enc, _q->payload_dec); } void bpacketsync_reconfig(bpacketsync _q) { // reconfigure packetizer _q->p_payload = packetizer_recreate(_q->p_payload, _q->dec_msg_len, _q->crc, _q->fec0, _q->fec1); // re-compute encoded message (packet) length _q->enc_msg_len = packetizer_get_enc_msg_len(_q->p_payload); // re-allocate memory for encoded packet _q->payload_enc = (unsigned char*) realloc(_q->payload_enc, _q->enc_msg_len*sizeof(unsigned char)); // re-allocate memory for decoded packet _q->payload_dec = (unsigned char*) realloc(_q->payload_dec, _q->dec_msg_len*sizeof(unsigned char)); } liquid-dsp-1.3.1/src/framing/src/bpresync.c000066400000000000000000000163671317124540100205740ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Binary pre-demod synchronizer // #include #include #include #include #include "liquid.internal.h" struct BPRESYNC(_s) { unsigned int n; // sequence length unsigned int m; // number of binary synchronizers bsequence rx_i; // received pattern (in-phase) bsequence rx_q; // received pattern (quadrature) float * dphi; // array of frequency offsets [size: m x 1] bsequence * sync_i; // synchronization pattern (in-phase) bsequence * sync_q; // synchronization pattern (quadrature) float * rxy; // output correlation [size: m x 1] float n_inv; // 1/n (pre-computed for speed) }; /* create binary pre-demod synchronizer */ /* _v : baseband sequence */ /* _n : baseband sequence length */ /* _dphi_max : maximum absolute frequency deviation */ /* _m : number of correlators */ BPRESYNC() BPRESYNC(_create)(TC * _v, unsigned int _n, float _dphi_max, unsigned int _m) { // validate input if (_n < 1) { fprintf(stderr, "error: bpresync_%s_create(), invalid input length\n", EXTENSION_FULL); exit(1); } else if (_m == 0) { fprintf(stderr, "error: bpresync_%s_create(), number of correlators must be at least 1\n", EXTENSION_FULL); exit(1); } // allocate main object memory and initialize BPRESYNC() _q = (BPRESYNC()) malloc(sizeof(struct BPRESYNC(_s))); _q->n = _n; _q->m = _m; _q->n_inv = 1.0f / (float)(_q->n); unsigned int i; // create internal receive buffers _q->rx_i = bsequence_create(_q->n); _q->rx_q = bsequence_create(_q->n); // create internal array of frequency offsets _q->dphi = (float*) malloc( _q->m*sizeof(float) ); // create internal synchronizers _q->sync_i = (bsequence*) malloc( _q->m*sizeof(bsequence) ); _q->sync_q = (bsequence*) malloc( _q->m*sizeof(bsequence) ); for (i=0; i<_q->m; i++) { _q->sync_i[i] = bsequence_create(_q->n); _q->sync_q[i] = bsequence_create(_q->n); // generate signal with frequency offset _q->dphi[i] = (float)i / (float)(_q->m-1)*_dphi_max; unsigned int k; for (k=0; k<_q->n; k++) { TC v_prime = _v[k] * cexpf(-_Complex_I*k*_q->dphi[i]); bsequence_push(_q->sync_i[i], crealf(v_prime)>0); bsequence_push(_q->sync_q[i], cimagf(v_prime)>0); } } // allocate memory for cross-correlation _q->rxy = (float*) malloc( _q->m*sizeof(float) ); // reset object BPRESYNC(_reset)(_q); return _q; } void BPRESYNC(_destroy)(BPRESYNC() _q) { unsigned int i; // free received symbol buffers free(_q->rx_i); free(_q->rx_q); // free internal syncrhonizer objects for (i=0; i<_q->m; i++) { bsequence_destroy(_q->sync_i[i]); bsequence_destroy(_q->sync_q[i]); } free(_q->sync_i); free(_q->sync_q); // free internal frequency offset array free(_q->dphi); // free internal cross-correlation array free(_q->rxy); // free main object memory free(_q); } void BPRESYNC(_print)(BPRESYNC() _q) { printf("bpresync_%s: %u samples\n", EXTENSION_FULL, _q->n); } void BPRESYNC(_reset)(BPRESYNC() _q) { unsigned int i; for (i=0; i<_q->n; i++) { bsequence_push(_q->rx_i, (i+0) % 2); bsequence_push(_q->rx_q, (i+1) % 2); } } // correlate input sequence with particular // _q : pre-demod synchronizer object // _id : ... void BPRESYNC(_correlatex)(BPRESYNC() _q, unsigned int _id, float complex * _rxy0, float complex * _rxy1) { // validate input... if (_id >= _q->m) { fprintf(stderr,"error: bpresync_%s_correlatex(), invalid id\n", EXTENSION_FULL); exit(1); } // compute correlations int rxy_ii = 2*bsequence_correlate(_q->sync_i[_id], _q->rx_i) - (int)(_q->n); int rxy_qq = 2*bsequence_correlate(_q->sync_q[_id], _q->rx_q) - (int)(_q->n); int rxy_iq = 2*bsequence_correlate(_q->sync_i[_id], _q->rx_q) - (int)(_q->n); int rxy_qi = 2*bsequence_correlate(_q->sync_q[_id], _q->rx_i) - (int)(_q->n); // non-conjugated int rxy_i0 = rxy_ii - rxy_qq; int rxy_q0 = rxy_iq + rxy_qi; *_rxy0 = (rxy_i0 + rxy_q0 * _Complex_I) * _q->n_inv; // conjugated int rxy_i1 = rxy_ii + rxy_qq; int rxy_q1 = rxy_iq - rxy_qi; *_rxy1 = (rxy_i1 + rxy_q1 * _Complex_I) * _q->n_inv; } /* push input sample into pre-demod synchronizer */ /* _q : pre-demod synchronizer object */ /* _x : input sample */ void BPRESYNC(_push)(BPRESYNC() _q, TI _x) { // push symbol into buffers bsequence_push(_q->rx_i, REAL(_x)>0); bsequence_push(_q->rx_q, IMAG(_x)>0); } /* correlate input sequence */ /* _q : pre-demod synchronizer object */ /* _rxy : output cross correlation */ /* _dphi_hat : output frequency offset estimate */ void BPRESYNC(_correlate)(BPRESYNC() _q, TO * _rxy, float * _dphi_hat) { unsigned int i; float complex rxy_max = 0; // maximum cross-correlation float abs_rxy_max = 0; // absolute value of rxy_max float complex rxy0; float complex rxy1; float dphi_hat = 0.0f; for (i=0; i<_q->m; i++) { BPRESYNC(_correlatex)(_q, i, &rxy0, &rxy1); // check non-conjugated value if ( ABS(rxy0) > abs_rxy_max ) { rxy_max = rxy0; abs_rxy_max = ABS(rxy0); dphi_hat = _q->dphi[i]; } // check conjugated value if ( ABS(rxy1) > abs_rxy_max ) { rxy_max = rxy1; abs_rxy_max = ABS(rxy1); dphi_hat = -_q->dphi[i]; } } *_rxy = rxy_max; *_dphi_hat = dphi_hat; } liquid-dsp-1.3.1/src/framing/src/bpresync_cccf.c000066400000000000000000000034571317124540100215460ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Binary pre-demod synchronizer // #include "liquid.internal.h" // #define BPRESYNC(name) LIQUID_CONCAT(bpresync_cccf,name) // print and naming extensions #define PRINTVAL(x) printf("%12.4e + j%12.4e", crealf(x), cimagf(x)) #define EXTENSION_SHORT "f" #define EXTENSION_FULL "cccf" #define TO float complex #define TC float complex #define TI float complex #define ABS(X) cabsf(X) #define REAL(X) crealf(X) #define IMAG(X) cimagf(X) #define BSYNC(name) LIQUID_CONCAT(bsync_cccf,name) #define TO_COMPLEX #define TC_COMPLEX #define TI_COMPLEX // source files #include "bpresync.c" liquid-dsp-1.3.1/src/framing/src/bsync.c000066400000000000000000000115441317124540100200550ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // P/N synchronizer // #include #include #include #include #include "liquid.internal.h" struct BSYNC(_s) { unsigned int n; // sequence length bsequence sync_i; // synchronization pattern (in-phase) bsequence sym_i; // received symbols (in-phase) //#if defined TC_COMPLEX bsequence sync_q; // synchronization pattern (quadrature) //#endif //#if defined TI_COMPLEX bsequence sym_q; // received symbols (quadrature) //#endif TO rxy; // cross correlation }; BSYNC() BSYNC(_create)(unsigned int _n, TC * _v) { BSYNC() fs = (BSYNC()) malloc(sizeof(struct BSYNC(_s))); fs->n = _n; fs->sync_i = bsequence_create(fs->n); #ifdef TC_COMPLEX fs->sync_q = bsequence_create(fs->n); #endif fs->sym_i = bsequence_create(fs->n); #ifdef TI_COMPLEX fs->sym_q = bsequence_create(fs->n); #endif unsigned int i; for (i=0; in; i++) { bsequence_push(fs->sync_i, crealf(_v[i])>0); #ifdef TC_COMPLEX bsequence_push(fs->sync_q, cimagf(_v[i])>0); #endif } return fs; } // TODO : test this method BSYNC() BSYNC(_create_msequence)(unsigned int _g, unsigned int _k) { // validate input if (_k == 0) { fprintf(stderr,"bsync_xxxt_create_msequence(), samples/symbol must be greater than zero\n"); exit(1); } unsigned int m = liquid_msb_index(_g) - 1; // create/initialize msequence msequence ms = msequence_create(m, _g, 1); BSYNC() fs = (BSYNC()) malloc(sizeof(struct BSYNC(_s))); unsigned int n = msequence_get_length(ms); fs->sync_i = bsequence_create(n * _k); #ifdef TC_COMPLEX fs->sync_q = bsequence_create(n * _k); #endif fs->sym_i = bsequence_create(n * _k); #ifdef TI_COMPLEX fs->sym_q = bsequence_create(n * _k); #endif msequence_reset(ms); #if 0 bsequence_init_msequence(fs->sync_i,ms); #ifdef TC_COMPLEX msequence_reset(ms); bsequence_init_msequence(fs->sync_q,ms); #endif #else unsigned int i; unsigned int j; for (i=0; isync_i, bit); #ifdef TC_COMPLEX bsequence_push(fs->sync_q, bit); #endif } } #endif msequence_destroy(ms); fs->n = _k*n; return fs; } void BSYNC(_destroy)(BSYNC() _fs) { bsequence_destroy(_fs->sync_i); #ifdef TC_COMPLEX bsequence_destroy(_fs->sync_q); #endif bsequence_destroy(_fs->sym_i); #ifdef TI_COMPLEX bsequence_destroy(_fs->sym_q); #endif free(_fs); } void BSYNC(_print)(BSYNC() _fs) { } void BSYNC(_correlate)(BSYNC() _fs, TI _sym, TO *_y) { // push symbol into buffers bsequence_push(_fs->sym_i, crealf(_sym)>0.0 ? 1 : 0); #ifdef TI_COMPLEX bsequence_push(_fs->sym_q, cimagf(_sym)>0.0 ? 1 : 0); #endif // compute dotprod #if defined TC_COMPLEX && defined TI_COMPLEX // cccx TO rxy_ii = 2.*bsequence_correlate(_fs->sync_i, _fs->sym_i) - (float)(_fs->n); TO rxy_qq = 2.*bsequence_correlate(_fs->sync_q, _fs->sym_q) - (float)(_fs->n); TO rxy_iq = 2.*bsequence_correlate(_fs->sync_i, _fs->sym_q) - (float)(_fs->n); TO rxy_qi = 2.*bsequence_correlate(_fs->sync_q, _fs->sym_i) - (float)(_fs->n); _fs->rxy = (rxy_ii - rxy_qq) + _Complex_I*(rxy_iq + rxy_qi); #elif defined TI_COMPLEX // crcx float rxy_ii = 2.*bsequence_correlate(_fs->sync_i, _fs->sym_i) - (float)(_fs->n); float rxy_iq = 2.*bsequence_correlate(_fs->sync_i, _fs->sym_q) - (float)(_fs->n); _fs->rxy = rxy_ii + _Complex_I * rxy_iq; #else // rrrx _fs->rxy = 2.*bsequence_correlate(_fs->sync_i, _fs->sym_i) - (float)(_fs->n); #endif // divide by sequence length *_y = _fs->rxy / (float)(_fs->n); } liquid-dsp-1.3.1/src/framing/src/bsync_cccf.c000066400000000000000000000032621317124540100210310ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Framing API: floating-point // #include "liquid.internal.h" // #define BSYNC(name) LIQUID_CONCAT(bsync_cccf,name) #define PRINTVAL(x) printf("%12.4e + j%12.4e", crealf(x), cimagf(x)) #define TO float complex #define TC float complex #define TI float complex #define ABS(X) cabsf(X) #define WINDOW(name) LIQUID_CONCAT(windowcf,name) #define DOTPROD(name) LIQUID_CONCAT(dotprod_cccf,name) #define TO_COMPLEX #define TC_COMPLEX #define TI_COMPLEX // source files #include "bsync.c" liquid-dsp-1.3.1/src/framing/src/bsync_crcf.c000066400000000000000000000032521317124540100210470ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Framing API: floating-point // #include "liquid.internal.h" // #define BSYNC(name) LIQUID_CONCAT(bsync_crcf,name) #define PRINTVAL(x) printf("%12.4e + j%12.4e", crealf(x), cimagf(x)) #define TO float complex #define TC float #define TI float complex #define ABS(X) cabsf(X) #define WINDOW(name) LIQUID_CONCAT(windowcf,name) #define DOTPROD(name) LIQUID_CONCAT(dotprod_crcf,name) #define TO_COMPLEX #undef TC_COMPLEX #define TI_COMPLEX // source files #include "bsync.c" liquid-dsp-1.3.1/src/framing/src/bsync_rrrf.c000066400000000000000000000031741317124540100211100ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Framing API: floating-point // #include "liquid.internal.h" // #define BSYNC(name) LIQUID_CONCAT(bsync_rrrf,name) #define PRINTVAL(x) printf("%12.4e", x) #define TO float #define TC float #define TI float #define ABS(X) fabsf(X) #define WINDOW(name) LIQUID_CONCAT(windowf,name) #define DOTPROD(name) LIQUID_CONCAT(dotprod_rrrf,name) #undef TO_COMPLEX #undef TC_COMPLEX #undef TI_COMPLEX // source files #include "bsync.c" liquid-dsp-1.3.1/src/framing/src/detector_cccf.c000066400000000000000000000414731317124540100215320ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // detector_cccf.c // // Pre-demodulation detector // #include #include #include #include #include #include #include "liquid.internal.h" #define DEBUG_DETECTOR 0 #define DEBUG_DETECTOR_PRINT 0 #define DEBUG_DETECTOR_BUFFER_LEN (1600) #define DEBUG_DETECTOR_FILENAME "detector_cccf_debug.m" // // internal method declarations // // update sum{ |x|^2 } void detector_cccf_update_sumsq(detector_cccf _q, float complex _x); // compute all dot product outputs void detector_cccf_compute_dotprods(detector_cccf _q); // estimate carrier and timing offsets void detector_cccf_estimate_offsets(detector_cccf _q, float * _tau_hat, float * _dphi_hat); // print debugging information void detector_cccf_debug_print(detector_cccf _q, const char * _filename); struct detector_cccf_s { float complex * s; // sequence unsigned int n; // sequence length float threshold; // detection threshold // derived values float n_inv; // 1/n (pre-computed for speed) windowcf buffer; // input buffer // internal correlators dotprod_cccf * dp; // vector dot products (pre-spun) unsigned int m; // number of correlators float dphi_step; // step size for each correlator float dphi_max; // maximum carrier offset float * dphi; // correlator frequencies [size: m x 1] float * rxy; // correlator outputs [size: m x 1] float * rxy0; // buffered correlator outputs [size: m x 1] float * rxy1; // buffered correlator outputs [size: m x 1] unsigned int imax; // index of maximum unsigned int idetect; // index of detection // estimation of E{|x|^2} wdelayf x2; // buffer of |x|^2 values float x2_sum; // sum{ |x|^2 } float x2_hat; // estimate of E{|x|^2} // counters/states enum { DETECTOR_STATE_SEEK=0, // seek sequence DETECTOR_STATE_FINDMAX, // find maximum } state; unsigned int timer; // sample timer #if DEBUG_DETECTOR windowcf debug_x; windowf debug_x2; windowf debug_rxy; #endif }; // create detector_cccf object // _s : sequence // _n : sequence length // _threshold : detection threshold (default: 0.7) // _dphi_max : maximum carrier offset detector_cccf detector_cccf_create(float complex * _s, unsigned int _n, float _threshold, float _dphi_max) { // validate input if (_n == 0) { fprintf(stderr,"error: detector_cccf_create(), sequence length cannot be zero\n"); exit(1); } else if (_threshold <= 0.0f) { fprintf(stderr,"error: detector_cccf_create(), threshold must be greater than zero (0.6 recommended)\n"); exit(1); } // allocate memory for main object detector_cccf q = (detector_cccf) malloc(sizeof(struct detector_cccf_s)); unsigned int i; // set internal properties q->n = _n; q->threshold = _threshold; q->dphi_max = _dphi_max; // derived values q->n_inv = 1.0f / (float)(q->n); // 1/n for faster processing q->dphi_step = 0.8f * M_PI / (float)(q->n); // compute number of correlators q->m = (int) ceilf( fabsf(_dphi_max / q->dphi_step) ); // ensure at least two correlators if (q->m < 2) q->m = 2; // re-compute maximum carrier offset q->dphi_max = q->m * q->dphi_step; // allocate memory for sequence and copy q->s = (float complex*) malloc((q->n)*sizeof(float complex)); memmove(q->s, _s, q->n*sizeof(float complex)); // create internal buffer q->buffer = windowcf_create(q->n); q->x2 = wdelayf_create(q->n); // create internal correlators (dot products) q->dp = (dotprod_cccf*) malloc((q->m)*sizeof(dotprod_cccf)); q->dphi = (float*) malloc((q->m)*sizeof(float)); q->rxy0 = (float*) malloc((q->m)*sizeof(float)); q->rxy1 = (float*) malloc((q->m)*sizeof(float)); q->rxy = (float*) malloc((q->m)*sizeof(float)); unsigned int k; float complex sconj[q->n]; for (k=0; km; k++) { // pre-spin sequence (slightly over-sampled in frequency) q->dphi[k] = ((float)k - (float)(q->m-1)/2) * q->dphi_step; for (i=0; in; i++) sconj[i] = conjf(q->s[i]) * cexpf(-_Complex_I*q->dphi[k]*i); q->dp[k] = dotprod_cccf_create(sconj, q->n); } // reset state detector_cccf_reset(q); #if DEBUG_DETECTOR q->debug_x = windowcf_create(DEBUG_DETECTOR_BUFFER_LEN); q->debug_x2 = windowf_create(DEBUG_DETECTOR_BUFFER_LEN); q->debug_rxy = windowf_create(DEBUG_DETECTOR_BUFFER_LEN); #endif // return object return q; } void detector_cccf_destroy(detector_cccf _q) { #if DEBUG_DETECTOR detector_cccf_debug_print(_q, DEBUG_DETECTOR_FILENAME); windowcf_destroy(_q->debug_x); windowf_destroy(_q->debug_x2); windowf_destroy(_q->debug_rxy); #endif // destroy input buffer windowcf_destroy(_q->buffer); // destroy internal correlators (dot products) unsigned int k; for (k=0; k<_q->m; k++) dotprod_cccf_destroy(_q->dp[k]); free(_q->dp); free(_q->dphi); free(_q->rxy); free(_q->rxy0); free(_q->rxy1); // destroy |x|^2 buffer wdelayf_destroy(_q->x2); // free internal buffers/arrays free(_q->s); // free main object memory free(_q); } void detector_cccf_print(detector_cccf _q) { printf("detector_cccf:\n"); printf(" sequence length : %-u\n", _q->n); printf(" threshold : %8.4f\n", _q->threshold); printf(" maximum carrier : %8.4f rad/sample\n", _q->dphi_max); printf(" num. correlators : %u\n", _q->m); } void detector_cccf_reset(detector_cccf _q) { // reset internal state windowcf_reset(_q->buffer); wdelayf_reset(_q->x2); // reset internal state _q->timer = _q->n; // reset timer _q->state = DETECTOR_STATE_SEEK; // set state to seek threshold _q->imax = 0; // index of maximum rxy value _q->idetect = 0; // index of detected maximum _q->x2_sum = 0.0f; // sum{ |x|^2 } // clear cross-correlator outputs //memset(_q->rxy, 0x00, sizeof(_q->rxy)); memset(_q->rxy0, 0x00, _q->m*sizeof(float)); memset(_q->rxy1, 0x00, _q->m*sizeof(float)); } // Run sample through pre-demod detector's correlator. // Returns '1' if signal was detected, '0' otherwise // _q : pre-demod detector // _x : input sample // _tau_hat : fractional sample offset estimate (set when detected) // _dphi_hat : carrier frequency offset estimate (set when detected) // _gamma_hat : channel gain estimate (set when detected) int detector_cccf_correlate(detector_cccf _q, float complex _x, float * _tau_hat, float * _dphi_hat, float * _gamma_hat) { // push sample into buffer windowcf_push(_q->buffer, _x); // update sum{|x|^2} detector_cccf_update_sumsq(_q, _x); #if DEBUG_DETECTOR windowcf_push(_q->debug_x, _x); windowf_push(_q->debug_x2, _q->x2_hat); #endif // return if no timeout if (_q->timer) { // hasn't timed out yet //printf("timer = %u\n", _q->timer); _q->timer--; #if DEBUG_DETECTOR windowf_push(_q->debug_rxy, 0.0f); #endif return 0; } // save previous correlator outputs memmove(_q->rxy0, _q->rxy1, _q->m*sizeof(float)); memmove(_q->rxy1, _q->rxy, _q->m*sizeof(float)); // compute vector dot products detector_cccf_compute_dotprods(_q); // find max{rxy} float rxy_abs = _q->rxy[ _q->imax ]; #if DEBUG_DETECTOR windowf_push(_q->debug_rxy, rxy_abs); #endif if (_q->state == DETECTOR_STATE_SEEK) { // check to see if value exceeds threshold if (rxy_abs > _q->threshold) { #if DEBUG_DETECTOR_PRINT printf("threshold exceeded: rxy = %8.4f\n", rxy_abs); #endif _q->idetect = _q->imax; _q->state = DETECTOR_STATE_FINDMAX; } } else if (_q->state == DETECTOR_STATE_FINDMAX) { // see if this new value exceeds maximum if ( _q->rxy[_q->imax] > _q->rxy1[_q->idetect] ) { #if DEBUG_DETECTOR_PRINT printf("maximum not yet reached: rxy = %8.4f\n", rxy_abs); #endif // set new index of maximum _q->idetect = _q->imax; } else { // peak was found last time; run estimates, reset values, // and return #if DEBUG_DETECTOR_PRINT printf("maximum found: rxy = %8.4f\n", rxy_abs); #endif // estimate timing and carrier offsets detector_cccf_estimate_offsets(_q, _tau_hat, _dphi_hat); *_gamma_hat = sqrtf(_q->x2_hat); // soft state reset _q->state = DETECTOR_STATE_SEEK; // set timer to allow signal to settle _q->timer = _q->n/4; return 1; } } else { fprintf(stderr,"error: detector_cccf_correlate(), unknown/unsupported internal state\n"); exit(1); } return 0; } // // internal methods // // compute sum{ |x|^2 } void detector_cccf_update_sumsq(detector_cccf _q, float complex _x) { // update estimate of signal magnitude float x2_n = crealf(_x * conjf(_x)); // |x[n-1]|^2 (input sample) float x2_0; // |x[0] |^2 (oldest sample) wdelayf_read(_q->x2, &x2_0); // read oldest sample wdelayf_push(_q->x2, x2_n); // push newest sample _q->x2_sum = _q->x2_sum + x2_n - x2_0; // update sum( |x|^2 ) of last 'n' input samples if (_q->x2_sum < FLT_EPSILON) { _q->x2_sum = FLT_EPSILON; } #if 0 // filtered estimate of E{ |x|^2 } _q->x2_hat = 0.8f*_q->x2_hat + 0.2f*_q->x2_sum*_q->n_inv; #else // unfiltered estimate of E{ |x|^2 } _q->x2_hat = _q->x2_sum * _q->n_inv; #endif } // compute all dot product outputs void detector_cccf_compute_dotprods(detector_cccf _q) { // read buffer float complex * r; windowcf_read(_q->buffer, &r); // compute dot products // TODO: compute conjugate as well unsigned int k; float complex rxy; #if DEBUG_DETECTOR_PRINT printf(" rxy : "); #endif float rxy_max = 0; // TODO: peridically re-compute scaling factor) for (k=0; k<_q->m; k++) { // execute vector dot product dotprod_cccf_execute(_q->dp[k], r, &rxy); // save scaled magnitude // TODO: compute scaled squared magnitude so as not to have // to compute square root _q->rxy[k] = cabsf(rxy) * _q->n_inv / sqrtf(_q->x2_hat); #if DEBUG_DETECTOR_PRINT printf("%6.4f (%6.4f) ", _q->rxy[k], _q->dphi[k]); #endif // find index of maximum if (_q->rxy[k] > rxy_max) { rxy_max = _q->rxy[k]; _q->imax = k; } } #if DEBUG_DETECTOR_PRINT printf("\n"); #endif } // estimate carrier and timing offsets void detector_cccf_estimate_offsets(detector_cccf _q, float * _tau_hat, float * _dphi_hat) { // check length of... if (_q->m == 1) { // compute carrier offset //*_dphi_hat = _q->dphi[_q->idetect]; *_dphi_hat = 0.0f; // interpolate to find timing offset //*_tau_hat = 0.5f*(_q->rxy2 - _q->rxy0) / (_q->rxy2 + _q->rxy0 - 2*_q->rxy1); *_tau_hat = 0.0f; return; } // _q->rxy0: [rm0] // | // | // | // _q->rxy1: [r0m]---[r00]---[r0p]-->freq // | // | // | // [rp0] // | // _q->rxy V time // float rm0 = _q->rxy0[_q->idetect]; float r0m = _q->idetect==0 ? _q->rxy1[_q->idetect+1] : _q->rxy1[_q->idetect-1]; float r00 = _q->rxy1[_q->idetect]; float r0p = _q->idetect==_q->m-1 ? _q->rxy1[_q->idetect-1] : _q->rxy1[_q->idetect+1]; float rp0 = _q->rxy[_q->idetect]; #if DEBUG_DETECTOR_PRINT // print values for interpolation printf("idetect : %u\n", _q->idetect); printf(" [%8.5f]\n", rm0); printf(" |\n"); printf(" |\n"); printf("[%8.5f]---[%8.5f]----[%8.5f]--> freq\n", r0m, r00, r0p); printf(" %8.5f\n", _q->dphi[_q->idetect]); printf(" |\n"); printf(" [%8.5f]\n", rp0); printf(" |\n"); printf(" V time\n"); #endif // interpolate frequency offset estimate float dphi_detect = _q->dphi[_q->idetect]; // frequency from detection *_dphi_hat = dphi_detect - _q->dphi_step * 0.5f*(r0p - r0m) / (r0p + r0m - 2*r00); // interpolate timing offset estimate *_tau_hat = 0.5f*(rp0 - rm0) / (rp0 + rm0 - 2*r00); // force result to be in proper range if (*_tau_hat < -0.499f) *_tau_hat = -0.499f; if (*_tau_hat > 0.499f) *_tau_hat = 0.499f; } #if 0 float detector_cccf_estimate_dphi(detector_cccf _q) { // read buffer... float complex * r; windowcf_read(_q->buffer, &r); // float complex r0 = 0.0f; float complex r1 = 0.0f; float complex metric = 0.0f; unsigned int i; for (i=0; i<_q->n; i++) { r0 = r1; r1 = r[i] * conjf(_q->s[i]); metric += r1 * conjf(r0); } return cargf(metric); } #endif void detector_cccf_debug_print(detector_cccf _q, const char * _filename) { #if DEBUG_DETECTOR FILE * fid = fopen(_filename,"w"); if (!fid) { fprintf(stderr,"error: detector_cccf_debug_print(), could not open '%s' for writing\n", _filename); return; } fprintf(fid,"%% %s : auto-generated file\n", DEBUG_DETECTOR_FILENAME); fprintf(fid,"close all;\n"); fprintf(fid,"clear all;\n"); fprintf(fid,"N = %u;\n", DEBUG_DETECTOR_BUFFER_LEN); unsigned int i; float complex * rc; float * r; fprintf(fid,"x = zeros(1,N);\n"); windowcf_read(_q->debug_x, &rc); for (i=0; idebug_rxy, &r); for (i=0; idebug_x2, &r); for (i=0; i #include #include #include #include #include #include "liquid.internal.h" #define DEBUG_FLEXFRAMEGEN 1 // reconfigure internal properties void flexframegen_reconfigure (flexframegen _q); float complex flexframegen_generate_symbol (flexframegen _q); float complex flexframegen_generate_preamble(flexframegen _q); float complex flexframegen_generate_header (flexframegen _q); float complex flexframegen_generate_payload (flexframegen _q); float complex flexframegen_generate_tail (flexframegen _q); // default flexframegen properties static flexframegenprops_s flexframegenprops_default = { LIQUID_CRC_16, // check LIQUID_FEC_NONE, // fec0 LIQUID_FEC_NONE, // fec1 LIQUID_MODEM_BPSK, // mod_scheme }; void flexframegenprops_init_default(flexframegenprops_s * _props) { memmove(_props, &flexframegenprops_default, sizeof(flexframegenprops_s)); } struct flexframegen_s { // interpolator unsigned int k; // interp samples/symbol (fixed at 2) unsigned int m; // interp filter delay (symbols) float beta; // excess bandwidth factor firinterp_crcf interp; // interpolator object float complex buf_interp[2]; // output interpolator buffer [size: k x 1] flexframegenprops_s props; // payload properties // preamble float complex * preamble_pn; // p/n sequence // header unsigned char * header; // header data qpacketmodem header_encoder; // header encoder/modulator unsigned int header_mod_len; // header length (encoded/modulated) float complex * header_mod; // header symbols (encoded/modulated) qpilotgen header_pilotgen; // header pilot symbol generator unsigned int header_sym_len; // header length (pilots added) float complex * header_sym; // header symbols (pilots added) // payload unsigned int payload_dec_len; // length of decoded qpacketmodem payload_encoder; // packet encoder/modulator unsigned int payload_sym_len; // length of encoded/modulated payload float complex * payload_sym; // encoded payload symbols // counters/states unsigned int symbol_counter; // output symbol number unsigned int sample_counter; // output sample number int frame_assembled; // frame assembled flag int frame_complete; // frame completed flag enum { STATE_PREAMBLE=0, // write preamble p/n sequence STATE_HEADER, // write header symbols STATE_PAYLOAD, // write payload symbols STATE_TAIL, // tail symbols } state; // write state }; flexframegen flexframegen_create(flexframegenprops_s * _fgprops) { flexframegen q = (flexframegen) malloc(sizeof(struct flexframegen_s)); unsigned int i; // create pulse-shaping filter q->k = 2; q->m = 7; q->beta = 0.25f; q->interp = firinterp_crcf_create_prototype(LIQUID_FIRFILT_ARKAISER,q->k,q->m,q->beta,0); // generate pn sequence q->preamble_pn = (float complex *) malloc(64*sizeof(float complex)); msequence ms = msequence_create(7, 0x0089, 1); for (i=0; i<64; i++) { q->preamble_pn[i] = (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2); q->preamble_pn[i] += (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2) * _Complex_I; } msequence_destroy(ms); // create header encoder/modulator q->header = (unsigned char *) malloc(FLEXFRAME_H_DEC*sizeof(unsigned char)); q->header_encoder = qpacketmodem_create(); qpacketmodem_configure(q->header_encoder, FLEXFRAME_H_DEC, FLEXFRAME_H_CRC, FLEXFRAME_H_FEC0, FLEXFRAME_H_FEC1, LIQUID_MODEM_QPSK); q->header_mod_len = qpacketmodem_get_frame_len(q->header_encoder); q->header_mod = (float complex *) malloc(q->header_mod_len*sizeof(float complex)); // create header pilot sequence generator q->header_pilotgen = qpilotgen_create(q->header_mod_len, 16); q->header_sym_len = qpilotgen_get_frame_len(q->header_pilotgen); q->header_sym = (float complex *) malloc(q->header_sym_len*sizeof(float complex)); //printf("header: %u bytes > %u mod > %u sym\n", 64, q->header_mod_len, q->header_sym_len); // payload encoder/modulator (initialize with default parameters to be reconfigured later) q->payload_encoder = qpacketmodem_create(); q->payload_dec_len = 64; q->payload_sym_len = qpacketmodem_get_frame_len(q->payload_encoder); q->payload_sym = (float complex *) malloc( q->payload_sym_len*sizeof(float complex)); // reset object flexframegen_reset(q); // set payload properties flexframegen_setprops(q, _fgprops); // return pointer to main object return q; } void flexframegen_destroy(flexframegen _q) { // destroy internal objects firinterp_crcf_destroy(_q->interp); qpacketmodem_destroy (_q->header_encoder); qpilotgen_destroy (_q->header_pilotgen); qpacketmodem_destroy (_q->payload_encoder); // free buffers/arrays free(_q->preamble_pn); // preamble symbols free(_q->header); // header bytes free(_q->header_mod); // encoded/modulated header symbols free(_q->payload_sym); // encoded/modulated payload symbols // destroy frame generator free(_q); } // print flexframegen object internals void flexframegen_print(flexframegen _q) { unsigned int num_frame_symbols = 64 + // preamble p/n sequence length _q->header_sym_len + // header symbols _q->payload_sym_len + // number of modulation symbols 2*_q->m; // number of tail symbols unsigned int num_frame_bits = 8*_q->payload_dec_len; float eta = (float)num_frame_bits / (float)num_frame_symbols; printf("flexframegen:\n"); printf(" head : %u symbols\n", _q->m); printf(" preamble : %u\n", 64); printf(" header : %u symbols (%u bytes)\n", _q->header_sym_len, FLEXFRAME_H_DEC); printf(" payload : %u symbols (%u bytes)\n", _q->payload_sym_len, _q->payload_dec_len); printf(" payload crc : %s\n", crc_scheme_str[_q->props.check][1]); printf(" fec (inner) : %s\n", fec_scheme_str[_q->props.fec0][1]); printf(" fec (outer) : %s\n", fec_scheme_str[_q->props.fec1][1]); printf(" mod scheme : %s\n", modulation_types[_q->props.mod_scheme].name); printf(" tail : %u symbols\n", _q->m); printf(" total : %u symbols\n", num_frame_symbols); printf(" efficiency : %.2f bits/second/Hz\n", eta); } // reset flexframegen object internals void flexframegen_reset(flexframegen _q) { // reset internal counters and state _q->symbol_counter = 0; _q->sample_counter = 0; _q->frame_assembled = 0; _q->frame_complete = 0; _q->state = STATE_PREAMBLE; } // is frame assembled? int flexframegen_is_assembled(flexframegen _q) { return _q->frame_assembled; } // get flexframegen properties // _q : frame generator object // _props : frame generator properties structure pointer void flexframegen_getprops(flexframegen _q, flexframegenprops_s * _props) { // copy properties structure to output pointer memmove(_props, &_q->props, sizeof(flexframegenprops_s)); } // set flexframegen properties // _q : frame generator object // _props : frame generator properties structure pointer int flexframegen_setprops(flexframegen _q, flexframegenprops_s * _props) { // if frame is already assembled, give warning if (_q->frame_assembled) { fprintf(stderr, "warning: flexframegen_setprops(), frame is already assembled; must reset() first\n"); return -1; } // if properties object is NULL, initialize with defaults if (_props == NULL) { flexframegen_setprops(_q, &flexframegenprops_default); return 0; } // validate input if (_props->check == LIQUID_CRC_UNKNOWN || _props->check >= LIQUID_CRC_NUM_SCHEMES) { fprintf(stderr, "error: flexframegen_setprops(), invalid/unsupported CRC scheme\n"); exit(1); } else if (_props->fec0 == LIQUID_FEC_UNKNOWN || _props->fec1 == LIQUID_FEC_UNKNOWN) { fprintf(stderr, "error: flexframegen_setprops(), invalid/unsupported FEC scheme\n"); exit(1); } else if (_props->mod_scheme == LIQUID_MODEM_UNKNOWN ) { fprintf(stderr, "error: flexframegen_setprops(), invalid/unsupported modulation scheme\n"); exit(1); } // TODO : determine if re-configuration is necessary // copy properties to internal structure memmove(&_q->props, _props, sizeof(flexframegenprops_s)); // reconfigure payload buffers (reallocate as necessary) flexframegen_reconfigure(_q); return 0; } // get frame length (number of samples) unsigned int flexframegen_getframelen(flexframegen _q) { if (!_q->frame_assembled) { fprintf(stderr,"warning: flexframegen_getframelen(), frame not assembled!\n"); return 0; } unsigned int num_frame_symbols = 64 + // preamble p/n sequence length _q->header_sym_len + // header symbols _q->payload_sym_len + // number of modulation symbols 2*_q->m; // number of tail symbols return num_frame_symbols*_q->k; // k samples/symbol } // exectue frame generator (create the frame) // _q : frame generator object // _header : user-defined header // _payload : variable payload buffer (configured by setprops method) // _payload_dec_len: length of payload void flexframegen_assemble(flexframegen _q, const unsigned char * _header, const unsigned char * _payload, unsigned int _payload_dec_len) { // reset object flexframegen_reset(_q); // set decoded payload length _q->payload_dec_len = _payload_dec_len; // copy user-defined header to internal if (_header == NULL) memset(_q->header, 0x00, FLEXFRAME_H_USER*sizeof(unsigned char)); else memmove(_q->header, _header, FLEXFRAME_H_USER*sizeof(unsigned char)); // first several bytes of header are user-defined unsigned int n = FLEXFRAME_H_USER; // add FLEXFRAME_PROTOCOL _q->header[n+0] = FLEXFRAME_PROTOCOL; // add payload length _q->header[n+1] = (_q->payload_dec_len >> 8) & 0xff; _q->header[n+2] = (_q->payload_dec_len ) & 0xff; // add modulation scheme/depth (pack into single byte) _q->header[n+3] = (unsigned int)(_q->props.mod_scheme); // add CRC, forward error-correction schemes // CRC : most-significant 3 bits of [n+4] // fec0 : least-significant 5 bits of [n+4] // fec1 : least-significant 5 bits of [n+5] _q->header[n+4] = (_q->props.check & 0x07) << 5; _q->header[n+4] |= (_q->props.fec0) & 0x1f; _q->header[n+5] = (_q->props.fec1) & 0x1f; // encode/modulate header qpacketmodem_encode(_q->header_encoder, _q->header, _q->header_mod); // add pilots qpilotgen_execute(_q->header_pilotgen, _q->header_mod, _q->header_sym); // reconfigure payload flexframegen_reconfigure(_q); // encode/modulate payload qpacketmodem_encode(_q->payload_encoder, _payload, _q->payload_sym); // set assembled flag _q->frame_assembled = 1; } // write samples of assembled frame, two samples at a time, returning // '1' when frame is complete, '0' otherwise. Zeros will be written // to the buffer if the frame is not assembled // _q : frame generator object // _buffer : output buffer [size: _buffer_len x 1] // _buffer_len : output buffer length int flexframegen_write_samples(flexframegen _q, float complex * _buffer, unsigned int _buffer_len) { unsigned int i; for (i=0; i<_buffer_len; i++) { // determine if new sample needs to be written if (_q->sample_counter == 0) { // generate new symbol float complex sym = flexframegen_generate_symbol(_q); // interpolate result firinterp_crcf_execute(_q->interp, sym, _q->buf_interp); } // write output sample from interpolator buffer _buffer[i] = _q->buf_interp[_q->sample_counter]; // adjust sample counter _q->sample_counter = (_q->sample_counter + 1) % _q->k; } return _q->frame_complete; } // // internal // // reconfigure internal buffers, objects, etc. void flexframegen_reconfigure(flexframegen _q) { // configure payload encoder/modulator qpacketmodem_configure(_q->payload_encoder, _q->payload_dec_len, _q->props.check, _q->props.fec0, _q->props.fec1, _q->props.mod_scheme); // re-allocate memory for encoded message _q->payload_sym_len = qpacketmodem_get_frame_len(_q->payload_encoder); _q->payload_sym = (float complex*) realloc(_q->payload_sym, _q->payload_sym_len*sizeof(float complex)); // ensure payload was reallocated appropriately if (_q->payload_sym == NULL) { fprintf(stderr,"error: flexframegen_reconfigure(), could not re-allocate payload array\n"); exit(1); } } // fill interpolator buffer float complex flexframegen_generate_symbol(flexframegen _q) { // write zeros to buffer if frame is not assembled if (!_q->frame_assembled) return 0.0f; switch (_q->state) { case STATE_PREAMBLE: return flexframegen_generate_preamble(_q); break; case STATE_HEADER: return flexframegen_generate_header (_q); break; case STATE_PAYLOAD: return flexframegen_generate_payload (_q); break; case STATE_TAIL: return flexframegen_generate_tail (_q); break; default: fprintf(stderr,"error: flexframegen_generate_symbol(), unknown/unsupported internal state\n"); exit(1); } return 0.0f; } // generate preamble float complex flexframegen_generate_preamble(flexframegen _q) { float complex symbol = _q->preamble_pn[_q->symbol_counter++]; // check state if (_q->symbol_counter == 64) { _q->symbol_counter = 0; _q->state = STATE_HEADER; } return symbol; } // generate header float complex flexframegen_generate_header(flexframegen _q) { float complex symbol = _q->header_sym[_q->symbol_counter++]; // check state if (_q->symbol_counter == _q->header_sym_len) { _q->symbol_counter = 0; _q->state = STATE_PAYLOAD; } return symbol; } // generate payload float complex flexframegen_generate_payload(flexframegen _q) { float complex symbol = _q->payload_sym[_q->symbol_counter++]; // check state if (_q->symbol_counter == _q->payload_sym_len) { _q->symbol_counter = 0; _q->state = STATE_TAIL; } return symbol; } // generate tail float complex flexframegen_generate_tail(flexframegen _q) { // increment symbol counter _q->symbol_counter++; // check state if (_q->symbol_counter == 2*_q->m) { _q->symbol_counter = 0; _q->frame_complete = 1; _q->frame_assembled = 0; } return 0.0f; } liquid-dsp-1.3.1/src/framing/src/flexframesync.c000066400000000000000000000771351317124540100216150ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // flexframesync.c // // basic frame synchronizer // #include #include #include #include #include #include #include "liquid.internal.h" #define DEBUG_FLEXFRAMESYNC 1 #define DEBUG_FLEXFRAMESYNC_PRINT 0 #define DEBUG_FILENAME "flexframesync_internal_debug.m" #define DEBUG_BUFFER_LEN (2000) #define FLEXFRAMESYNC_ENABLE_EQ 0 // push samples through detection stage void flexframesync_execute_seekpn(flexframesync _q, float complex _x); // step receiver mixer, matched filter, decimator // _q : frame synchronizer // _x : input sample // _y : output symbol int flexframesync_step(flexframesync _q, float complex _x, float complex * _y); // push samples through synchronizer, saving received p/n symbols void flexframesync_execute_rxpreamble(flexframesync _q, float complex _x); // decode header and reconfigure payload void flexframesync_decode_header(flexframesync _q); // receive header symbols void flexframesync_execute_rxheader(flexframesync _q, float complex _x); // receive payload symbols void flexframesync_execute_rxpayload(flexframesync _q, float complex _x); // flexframesync object structure struct flexframesync_s { // callback framesync_callback callback; // user-defined callback function void * userdata; // user-defined data structure framesyncstats_s framesyncstats; // frame statistic object (synchronizer) framedatastats_s framedatastats; // frame statistic object (synchronizer) // synchronizer objects unsigned int m; // filter delay (symbols) float beta; // filter excess bandwidth factor qdetector_cccf detector; // pre-demod detector float tau_hat; // fractional timing offset estimate float dphi_hat; // carrier frequency offset estimate float phi_hat; // carrier phase offset estimate float gamma_hat; // channel gain estimate nco_crcf mixer; // carrier frequency recovery (coarse) nco_crcf pll; // carrier frequency recovery (fine) // timing recovery objects, states firpfb_crcf mf; // matched filter decimator unsigned int npfb; // number of filters in symsync int mf_counter; // matched filter output timer unsigned int pfb_index; // filterbank index #if FLEXFRAMESYNC_ENABLE_EQ eqlms_cccf equalizer; // equalizer (trained on p/n sequence) #endif // preamble float complex * preamble_pn; // known 64-symbol p/n sequence float complex * preamble_rx; // received p/n symbols // header float complex * header_sym; // header symbols with pilots (received) unsigned int header_sym_len; // header symbols with pilots (length) qpilotsync header_pilotsync; // header demodulator/decoder float complex * header_mod; // header symbols (received) unsigned int header_mod_len; // header symbols (length) qpacketmodem header_decoder; // header demodulator/decoder unsigned char * header_dec; // header bytes (decoded) int header_valid; // header CRC flag // payload modem payload_demod; // payload demod (for phase recovery only) float complex * payload_sym; // payload symbols (received) unsigned int payload_sym_len; // payload symbols (length) qpacketmodem payload_decoder; // payload demodulator/decoder unsigned char * payload_dec; // payload data (bytes) unsigned int payload_dec_len; // payload data (length) int payload_valid; // payload CRC flag // status variables unsigned int preamble_counter; // counter: num of p/n syms received unsigned int symbol_counter; // counter: num of symbols received enum { FLEXFRAMESYNC_STATE_DETECTFRAME=0, // detect frame (seek p/n sequence) FLEXFRAMESYNC_STATE_RXPREAMBLE, // receive p/n sequence FLEXFRAMESYNC_STATE_RXHEADER, // receive header data FLEXFRAMESYNC_STATE_RXPAYLOAD, // receive payload data } state; // receiver state #if DEBUG_FLEXFRAMESYNC int debug_enabled; // debugging enabled? int debug_objects_created; // debugging objects created? int debug_qdetector_flush; // debug: flag to set if we are flushing detector windowcf debug_x; // debug: raw input samples #endif }; // create flexframesync object // _callback : callback function invoked when frame is received // _userdata : user-defined data object passed to callback flexframesync flexframesync_create(framesync_callback _callback, void * _userdata) { flexframesync q = (flexframesync) malloc(sizeof(struct flexframesync_s)); q->callback = _callback; q->userdata = _userdata; q->m = 7; // filter delay (symbols) q->beta = 0.3f; // excess bandwidth factor unsigned int i; // generate p/n sequence q->preamble_pn = (float complex*) malloc(64*sizeof(float complex)); q->preamble_rx = (float complex*) malloc(64*sizeof(float complex)); msequence ms = msequence_create(7, 0x0089, 1); for (i=0; i<64; i++) { q->preamble_pn[i] = (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2); q->preamble_pn[i] += (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2) * _Complex_I; } msequence_destroy(ms); // create frame detector unsigned int k = 2; // samples/symbol q->detector = qdetector_cccf_create_linear(q->preamble_pn, 64, LIQUID_FIRFILT_ARKAISER, k, q->m, q->beta); qdetector_cccf_set_threshold(q->detector, 0.5f); // create symbol timing recovery filters q->npfb = 32; // number of filters in the bank q->mf = firpfb_crcf_create_rnyquist(LIQUID_FIRFILT_ARKAISER, q->npfb,k,q->m,q->beta); #if FLEXFRAMESYNC_ENABLE_EQ // create equalizer unsigned int p = 3; q->equalizer = eqlms_cccf_create_lowpass(2*k*p+1, 0.4f); eqlms_cccf_set_bw(q->equalizer, 0.05f); #endif // create down-coverters for carrier phase tracking q->mixer = nco_crcf_create(LIQUID_NCO); q->pll = nco_crcf_create(LIQUID_NCO); nco_crcf_pll_set_bandwidth(q->pll, 1e-4f); // very low bandwidth // header demodulator/decoder q->header_dec = (unsigned char *) malloc(FLEXFRAME_H_DEC*sizeof(unsigned char)); q->header_decoder = qpacketmodem_create(); qpacketmodem_configure(q->header_decoder, FLEXFRAME_H_DEC, FLEXFRAME_H_CRC, FLEXFRAME_H_FEC0, FLEXFRAME_H_FEC1, LIQUID_MODEM_QPSK); q->header_mod_len = qpacketmodem_get_frame_len(q->header_decoder); q->header_mod = (float complex*) malloc(q->header_mod_len*sizeof(float complex)); // header pilot synchronizer q->header_pilotsync = qpilotsync_create(q->header_mod_len, 16); q->header_sym_len = qpilotsync_get_frame_len(q->header_pilotsync); q->header_sym = (float complex*) malloc(q->header_sym_len*sizeof(float complex)); // payload demodulator for phase recovery q->payload_demod = modem_create(LIQUID_MODEM_QPSK); // create payload demodulator/decoder object q->payload_dec_len = 64; int check = LIQUID_CRC_24; int fec0 = LIQUID_FEC_NONE; int fec1 = LIQUID_FEC_GOLAY2412; int mod_scheme = LIQUID_MODEM_QPSK; q->payload_decoder = qpacketmodem_create(); qpacketmodem_configure(q->payload_decoder, q->payload_dec_len, check, fec0, fec1, mod_scheme); //qpacketmodem_print(q->payload_decoder); //assert( qpacketmodem_get_frame_len(q->payload_decoder)==600 ); q->payload_sym_len = qpacketmodem_get_frame_len(q->payload_decoder); // allocate memory for payload symbols and recovered data bytes q->payload_sym = (float complex*) malloc(q->payload_sym_len*sizeof(float complex)); q->payload_dec = (unsigned char*) malloc(q->payload_dec_len*sizeof(unsigned char)); // reset global data counters flexframesync_reset_framedatastats(q); #if DEBUG_FLEXFRAMESYNC // set debugging flags, objects to NULL q->debug_enabled = 0; q->debug_objects_created = 0; q->debug_qdetector_flush = 0; q->debug_x = NULL; #endif // reset state and return flexframesync_reset(q); return q; } // destroy frame synchronizer object, freeing all internal memory void flexframesync_destroy(flexframesync _q) { #if DEBUG_FLEXFRAMESYNC // clean up debug objects (if created) if (_q->debug_objects_created) windowcf_destroy(_q->debug_x); #endif // free allocated arrays free(_q->preamble_pn); free(_q->preamble_rx); free(_q->header_sym); free(_q->header_mod); free(_q->header_dec); free(_q->payload_sym); free(_q->payload_dec); // destroy synchronization objects qpilotsync_destroy (_q->header_pilotsync); // header demodulator/decoder qpacketmodem_destroy (_q->header_decoder); // header demodulator/decoder modem_destroy (_q->payload_demod); // payload demodulator (for PLL) qpacketmodem_destroy (_q->payload_decoder); // payload demodulator/decoder qdetector_cccf_destroy(_q->detector); // frame detector firpfb_crcf_destroy (_q->mf); // matched filter nco_crcf_destroy (_q->mixer); // oscillator (coarse) nco_crcf_destroy (_q->pll); // oscillator (fine) #if FLEXFRAMESYNC_ENABLE_EQ eqlms_cccf_destroy (_q->equalizer); // LMS equalizer #endif // free main object memory free(_q); } // print frame synchronizer object internals void flexframesync_print(flexframesync _q) { printf("flexframesync:\n"); framedatastats_print(&_q->framedatastats); } // reset frame synchronizer object void flexframesync_reset(flexframesync _q) { // reset binary pre-demod synchronizer qdetector_cccf_reset(_q->detector); // reset carrier recovery objects nco_crcf_reset(_q->mixer); nco_crcf_reset(_q->pll); // reset symbol timing recovery state firpfb_crcf_reset(_q->mf); // reset state _q->state = FLEXFRAMESYNC_STATE_DETECTFRAME; _q->preamble_counter= 0; _q->symbol_counter = 0; // reset frame statistics _q->framesyncstats.evm = 0.0f; } int flexframesync_is_frame_open(flexframesync _q) { return (_q->state == FLEXFRAMESYNC_STATE_DETECTFRAME) ? 0 : 1; } // execute frame synchronizer // _q : frame synchronizer object // _x : input sample array [size: _n x 1] // _n : number of input samples void flexframesync_execute(flexframesync _q, float complex * _x, unsigned int _n) { unsigned int i; for (i=0; i<_n; i++) { #if DEBUG_FLEXFRAMESYNC // write samples to debug buffer // NOTE: the debug_qdetector_flush prevents samples from being written twice if (_q->debug_enabled && !_q->debug_qdetector_flush) windowcf_push(_q->debug_x, _x[i]); #endif switch (_q->state) { case FLEXFRAMESYNC_STATE_DETECTFRAME: // detect frame (look for p/n sequence) flexframesync_execute_seekpn(_q, _x[i]); break; case FLEXFRAMESYNC_STATE_RXPREAMBLE: // receive p/n sequence symbols flexframesync_execute_rxpreamble(_q, _x[i]); break; case FLEXFRAMESYNC_STATE_RXHEADER: // receive header symbols flexframesync_execute_rxheader(_q, _x[i]); break; case FLEXFRAMESYNC_STATE_RXPAYLOAD: // receive payload symbols flexframesync_execute_rxpayload(_q, _x[i]); break; default: fprintf(stderr,"error: flexframesync_exeucte(), unknown/unsupported state\n"); exit(1); } } } // // internal methods // // execute synchronizer, seeking p/n sequence // _q : frame synchronizer object // _x : input sample // _sym : demodulated symbol void flexframesync_execute_seekpn(flexframesync _q, float complex _x) { // push through pre-demod synchronizer float complex * v = qdetector_cccf_execute(_q->detector, _x); // check if frame has been detected if (v == NULL) return; // get estimates _q->tau_hat = qdetector_cccf_get_tau (_q->detector); _q->gamma_hat = qdetector_cccf_get_gamma(_q->detector); _q->dphi_hat = qdetector_cccf_get_dphi (_q->detector); _q->phi_hat = qdetector_cccf_get_phi (_q->detector); #if DEBUG_FLEXFRAMESYNC_PRINT printf("***** frame detected! tau-hat:%8.4f, dphi-hat:%8.4f, gamma:%8.2f dB\n", _q->tau_hat, _q->dphi_hat, 20*log10f(_q->gamma_hat)); #endif // set appropriate filterbank index if (_q->tau_hat > 0) { _q->pfb_index = (unsigned int)( _q->tau_hat * _q->npfb) % _q->npfb; _q->mf_counter = 0; } else { _q->pfb_index = (unsigned int)((1.0f+_q->tau_hat) * _q->npfb) % _q->npfb; _q->mf_counter = 1; } // output filter scale (gain estimate, scaled by 1/2 for k=2 samples/symbol) firpfb_crcf_set_scale(_q->mf, 0.5f / _q->gamma_hat); // set frequency/phase of mixer nco_crcf_set_frequency(_q->mixer, _q->dphi_hat); nco_crcf_set_phase (_q->mixer, _q->phi_hat ); // update state _q->state = FLEXFRAMESYNC_STATE_RXPREAMBLE; #if DEBUG_FLEXFRAMESYNC // the debug_qdetector_flush prevents samples from being written twice _q->debug_qdetector_flush = 1; #endif // run buffered samples through synchronizer unsigned int buf_len = qdetector_cccf_get_buf_len(_q->detector); flexframesync_execute(_q, v, buf_len); #if DEBUG_FLEXFRAMESYNC _q->debug_qdetector_flush = 0; #endif } // step receiver mixer, matched filter, decimator // _q : frame synchronizer // _x : input sample // _y : output symbol int flexframesync_step(flexframesync _q, float complex _x, float complex * _y) { // mix sample down float complex v; nco_crcf_mix_down(_q->mixer, _x, &v); nco_crcf_step (_q->mixer); // push sample into filterbank firpfb_crcf_push (_q->mf, v); firpfb_crcf_execute(_q->mf, _q->pfb_index, &v); #if FLEXFRAMESYNC_ENABLE_EQ // push sample through equalizer eqlms_cccf_push(_q->equalizer, v); #endif // increment counter to determine if sample is available _q->mf_counter++; int sample_available = (_q->mf_counter >= 1) ? 1 : 0; // set output sample if available if (sample_available) { #if FLEXFRAMESYNC_ENABLE_EQ // compute equalizer output eqlms_cccf_execute(_q->equalizer, &v); #endif // set output *_y = v; // decrement counter by k=2 samples/symbol _q->mf_counter -= 2; } // return flag return sample_available; } // execute synchronizer, receiving p/n sequence // _q : frame synchronizer object // _x : input sample // _sym : demodulated symbol void flexframesync_execute_rxpreamble(flexframesync _q, float complex _x) { // step synchronizer float complex mf_out = 0.0f; int sample_available = flexframesync_step(_q, _x, &mf_out); // compute output if timeout if (sample_available) { // save output in p/n symbols buffer #if FLEXFRAMESYNC_ENABLE_EQ unsigned int delay = 2*_q->m + 3; // delay from matched filter and equalizer #else unsigned int delay = 2*_q->m; // delay from matched filter #endif if (_q->preamble_counter >= delay) { unsigned int index = _q->preamble_counter-delay; _q->preamble_rx[index] = mf_out; #if FLEXFRAMESYNC_ENABLE_EQ // train equalizer eqlms_cccf_step(_q->equalizer, _q->preamble_pn[index], mf_out); #endif } // update p/n counter _q->preamble_counter++; // update state if (_q->preamble_counter == 64 + delay) _q->state = FLEXFRAMESYNC_STATE_RXHEADER; } } // execute synchronizer, receiving header // _q : frame synchronizer object // _x : input sample // _sym : demodulated symbol void flexframesync_execute_rxheader(flexframesync _q, float complex _x) { // step synchronizer float complex mf_out = 0.0f; int sample_available = flexframesync_step(_q, _x, &mf_out); // compute output if timeout if (sample_available) { // save payload symbols (modem input/output) _q->header_sym[_q->symbol_counter] = mf_out; // increment counter _q->symbol_counter++; if (_q->symbol_counter == _q->header_sym_len) { // decode header flexframesync_decode_header(_q); if (_q->header_valid) { // continue on to decoding payload _q->symbol_counter = 0; _q->state = FLEXFRAMESYNC_STATE_RXPAYLOAD; return; } // update statistics _q->framedatastats.num_frames_detected++; // header invalid: invoke callback if (_q->callback != NULL) { // set framestats internals _q->framesyncstats.evm = 0.0f; //20*log10f(sqrtf(_q->framesyncstats.evm / 600)); _q->framesyncstats.rssi = 20*log10f(_q->gamma_hat); _q->framesyncstats.cfo = nco_crcf_get_frequency(_q->mixer); _q->framesyncstats.framesyms = NULL; _q->framesyncstats.num_framesyms = 0; _q->framesyncstats.mod_scheme = LIQUID_MODEM_UNKNOWN; _q->framesyncstats.mod_bps = 0; _q->framesyncstats.check = LIQUID_CRC_UNKNOWN; _q->framesyncstats.fec0 = LIQUID_FEC_UNKNOWN; _q->framesyncstats.fec1 = LIQUID_FEC_UNKNOWN; // invoke callback method _q->callback(_q->header_dec, _q->header_valid, NULL, // payload 0, // payload length 0, // payload valid, _q->framesyncstats, _q->userdata); } // reset frame synchronizer flexframesync_reset(_q); return; } } } // decode header void flexframesync_decode_header(flexframesync _q) { // recover data symbols from pilots qpilotsync_execute(_q->header_pilotsync, _q->header_sym, _q->header_mod); // decode payload _q->header_valid = qpacketmodem_decode(_q->header_decoder, _q->header_mod, _q->header_dec); if (!_q->header_valid) return; // set fine carrier frequency and phase float dphi_hat = qpilotsync_get_dphi(_q->header_pilotsync); float phi_hat = qpilotsync_get_phi (_q->header_pilotsync); //printf("residual offset: dphi=%12.8f, phi=%12.8f\n", dphi_hat, phi_hat); nco_crcf_set_frequency(_q->pll, dphi_hat); nco_crcf_set_phase (_q->pll, phi_hat + dphi_hat * _q->header_sym_len); // first several bytes of header are user-defined unsigned int n = FLEXFRAME_H_USER; // first byte is for expansion/version validation unsigned int protocol = _q->header_dec[n+0]; if (protocol != FLEXFRAME_PROTOCOL) { fprintf(stderr,"warning: flexframesync_decode_header(), invalid framing protocol %u (expected %u)\n", protocol, FLEXFRAME_PROTOCOL); _q->header_valid = 0; return; } // strip off payload length unsigned int payload_dec_len = (_q->header_dec[n+1] << 8) | (_q->header_dec[n+2]); _q->payload_dec_len = payload_dec_len; // strip off modulation scheme/depth unsigned int mod_scheme = _q->header_dec[n+3]; // strip off CRC, forward error-correction schemes // CRC : most-significant 3 bits of [n+4] // fec0 : least-significant 5 bits of [n+4] // fec1 : least-significant 5 bits of [n+5] unsigned int check = (_q->header_dec[n+4] >> 5 ) & 0x07; unsigned int fec0 = (_q->header_dec[n+4] ) & 0x1f; unsigned int fec1 = (_q->header_dec[n+5] ) & 0x1f; // validate properties if (mod_scheme == 0 || mod_scheme >= LIQUID_MODEM_NUM_SCHEMES) { fprintf(stderr,"warning: flexframesync_decode_header(), invalid modulation scheme\n"); _q->header_valid = 0; return; } else if (check == LIQUID_CRC_UNKNOWN || check >= LIQUID_CRC_NUM_SCHEMES) { fprintf(stderr,"warning: flexframesync_decode_header(), decoded CRC exceeds available\n"); _q->header_valid = 0; return; } else if (fec0 == LIQUID_FEC_UNKNOWN || fec0 >= LIQUID_FEC_NUM_SCHEMES) { fprintf(stderr,"warning: flexframesync_decode_header(), decoded FEC (inner) exceeds available\n"); _q->header_valid = 0; return; } else if (fec1 == LIQUID_FEC_UNKNOWN || fec1 >= LIQUID_FEC_NUM_SCHEMES) { fprintf(stderr,"warning: flexframesync_decode_header(), decoded FEC (outer) exceeds available\n"); _q->header_valid = 0; return; } // re-create payload demodulator for phase-locked loop _q->payload_demod = modem_recreate(_q->payload_demod, mod_scheme); // reconfigure payload demodulator/decoder qpacketmodem_configure(_q->payload_decoder, payload_dec_len, check, fec0, fec1, mod_scheme); // set length appropriately _q->payload_sym_len = qpacketmodem_get_frame_len(_q->payload_decoder); // re-allocate buffers accordingly _q->payload_sym = (float complex*) realloc(_q->payload_sym, (_q->payload_sym_len)*sizeof(float complex)); _q->payload_dec = (unsigned char*) realloc(_q->payload_dec, (_q->payload_dec_len)*sizeof(unsigned char)); if (_q->payload_sym == NULL || _q->payload_dec == NULL) { fprintf(stderr,"error: flexframesync_decode_header(), could not re-allocate payload arrays\n"); _q->header_valid = 0; return; } #if DEBUG_FLEXFRAMESYNC_PRINT // print results printf("flexframesync_decode_header():\n"); printf(" header crc : %s\n", _q->header_valid ? "pass" : "FAIL"); printf(" check : %s\n", crc_scheme_str[check][1]); printf(" fec (inner) : %s\n", fec_scheme_str[fec0][1]); printf(" fec (outer) : %s\n", fec_scheme_str[fec1][1]); printf(" mod scheme : %s\n", modulation_types[mod_scheme].name); printf(" payload sym len : %u\n", _q->payload_sym_len); printf(" payload dec len : %u\n", _q->payload_dec_len); printf(" user data :"); unsigned int i; for (i=0; iheader_dec[i]); printf("\n"); #endif } // execute synchronizer, receiving payload // _q : frame synchronizer object // _x : input sample // _sym : demodulated symbol void flexframesync_execute_rxpayload(flexframesync _q, float complex _x) { // step synchronizer float complex mf_out = 0.0f; int sample_available = flexframesync_step(_q, _x, &mf_out); // compute output if timeout if (sample_available) { // TODO: clean this up // mix down with fine-tuned oscillator nco_crcf_mix_down(_q->pll, mf_out, &mf_out); // track phase, accumulate error-vector magnitude unsigned int sym; modem_demodulate(_q->payload_demod, mf_out, &sym); float phase_error = modem_get_demodulator_phase_error(_q->payload_demod); float evm = modem_get_demodulator_evm (_q->payload_demod); nco_crcf_pll_step(_q->pll, phase_error); nco_crcf_step(_q->pll); _q->framesyncstats.evm += evm*evm; // save payload symbols (modem input/output) _q->payload_sym[_q->symbol_counter] = mf_out; // increment counter _q->symbol_counter++; if (_q->symbol_counter == _q->payload_sym_len) { // decode payload _q->payload_valid = qpacketmodem_decode(_q->payload_decoder, _q->payload_sym, _q->payload_dec); // update statistics _q->framedatastats.num_frames_detected++; _q->framedatastats.num_headers_valid++; _q->framedatastats.num_payloads_valid += _q->payload_valid; _q->framedatastats.num_bytes_received += _q->payload_dec_len; // invoke callback if (_q->callback != NULL) { // set framestats internals int ms = qpacketmodem_get_modscheme(_q->payload_decoder); _q->framesyncstats.evm = 10*log10f(_q->framesyncstats.evm / (float)_q->payload_sym_len); _q->framesyncstats.rssi = 20*log10f(_q->gamma_hat); _q->framesyncstats.cfo = nco_crcf_get_frequency(_q->mixer); _q->framesyncstats.framesyms = _q->payload_sym; _q->framesyncstats.num_framesyms = _q->payload_sym_len; _q->framesyncstats.mod_scheme = ms; _q->framesyncstats.mod_bps = modulation_types[ms].bps; _q->framesyncstats.check = qpacketmodem_get_crc(_q->payload_decoder); _q->framesyncstats.fec0 = qpacketmodem_get_fec0(_q->payload_decoder); _q->framesyncstats.fec1 = qpacketmodem_get_fec1(_q->payload_decoder); // invoke callback method _q->callback(_q->header_dec, _q->header_valid, _q->payload_dec, _q->payload_dec_len, _q->payload_valid, _q->framesyncstats, _q->userdata); } // reset frame synchronizer flexframesync_reset(_q); return; } } } // reset frame data statistics void flexframesync_reset_framedatastats(flexframesync _q) { framedatastats_reset(&_q->framedatastats); } // retrieve frame data statistics framedatastats_s flexframesync_get_framedatastats(flexframesync _q) { return _q->framedatastats; } // enable debugging void flexframesync_debug_enable(flexframesync _q) { // create debugging objects if necessary #if DEBUG_FLEXFRAMESYNC if (_q->debug_objects_created) return; // create debugging objects _q->debug_x = windowcf_create(DEBUG_BUFFER_LEN); // set debugging flags _q->debug_enabled = 1; _q->debug_objects_created = 1; #else fprintf(stderr,"flexframesync_debug_enable(): compile-time debugging disabled\n"); #endif } // disable debugging void flexframesync_debug_disable(flexframesync _q) { // disable debugging #if DEBUG_FLEXFRAMESYNC _q->debug_enabled = 0; #else fprintf(stderr,"flexframesync_debug_enable(): compile-time debugging disabled\n"); #endif } // print debugging information void flexframesync_debug_print(flexframesync _q, const char * _filename) { #if DEBUG_FLEXFRAMESYNC if (!_q->debug_objects_created) { fprintf(stderr,"error: flexframesync_debug_print(), debugging objects don't exist; enable debugging first\n"); return; } unsigned int i; float complex * rc; FILE* fid = fopen(_filename,"w"); fprintf(fid,"%% %s: auto-generated file", _filename); fprintf(fid,"\n\n"); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n\n"); fprintf(fid,"n = %u;\n", DEBUG_BUFFER_LEN); // main figure fprintf(fid,"figure('Color','white','position',[100 100 800 600]);\n"); // write x fprintf(fid,"x = zeros(1,n);\n"); windowcf_read(_q->debug_x, &rc); for (i=0; ipreamble_pn; for (i=0; i<64; i++) fprintf(fid,"preamble_pn(%4u) = %12.4e + 1i*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i])); // write p/n symbols fprintf(fid,"preamble_rx = zeros(1,64);\n"); rc = _q->preamble_rx; for (i=0; i<64; i++) fprintf(fid,"preamble_rx(%4u) = %12.4e + 1i*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i])); // write recovered header symbols (after qpilotsync) fprintf(fid,"header_mod = zeros(1,%u);\n", _q->header_mod_len); rc = _q->header_mod; for (i=0; i<_q->header_mod_len; i++) fprintf(fid,"header_mod(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i])); // write raw payload symbols fprintf(fid,"payload_sym = zeros(1,%u);\n", _q->payload_sym_len); rc = _q->payload_sym; for (i=0; i<_q->payload_sym_len; i++) fprintf(fid,"payload_sym(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i])); fprintf(fid,"subplot(3,2,[3 5]);\n"); fprintf(fid,"plot(real(header_mod),imag(header_mod),'o');\n"); fprintf(fid,"xlabel('in-phase');\n"); fprintf(fid,"ylabel('quadrature phase');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"axis([-1 1 -1 1]*1.5);\n"); fprintf(fid,"axis square;\n"); fprintf(fid,"title('Received Header Symbols');\n"); fprintf(fid,"subplot(3,2,[4 6]);\n"); fprintf(fid,"plot(real(payload_sym),imag(payload_sym),'+');\n"); fprintf(fid,"xlabel('in-phase');\n"); fprintf(fid,"ylabel('quadrature phase');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"axis([-1 1 -1 1]*1.5);\n"); fprintf(fid,"axis square;\n"); fprintf(fid,"title('Received Payload Symbols');\n"); fprintf(fid,"\n\n"); fclose(fid); printf("flexframesync/debug: results written to %s\n", _filename); #else fprintf(stderr,"flexframesync_debug_print(): compile-time debugging disabled\n"); #endif } liquid-dsp-1.3.1/src/framing/src/framedatastats.c000066400000000000000000000045521317124540100217430ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // framedatastats.c // // Default and generic frame statistics // #include #include #include #include #include #include "liquid.internal.h" // reset framedatastats object void framedatastats_reset(framedatastats_s * _stats) { if (_stats == NULL) return; _stats->num_frames_detected = 0; _stats->num_headers_valid = 0; _stats->num_payloads_valid = 0; _stats->num_bytes_received = 0; } // print framedatastats object void framedatastats_print(framedatastats_s * _stats) { if (_stats == NULL) return; float percent_headers = 0.0f; float percent_payloads = 0.0f; if (_stats->num_frames_detected > 0) { percent_headers = 100.0f*(float)_stats->num_headers_valid / (float)_stats->num_frames_detected; percent_payloads = 100.0f*(float)_stats->num_payloads_valid / (float)_stats->num_frames_detected; } printf(" frames detected : %u\n", _stats->num_frames_detected); printf(" headers valid : %-6u (%8.4f %%)\n", _stats->num_headers_valid, percent_headers); printf(" payloads valid : %-6u (%8.4f %%)\n", _stats->num_payloads_valid, percent_payloads); printf(" bytes received : %lu\n", _stats->num_bytes_received); } liquid-dsp-1.3.1/src/framing/src/framegen64.c000066400000000000000000000140231317124540100206700ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // framegen64.c // // frame64 generator: 8-byte header, 64-byte payload, 1340-sample frame // #include #include #include #include #include #include #include "liquid.internal.h" struct framegen64_s { qpacketmodem enc; // packet encoder/modulator qpilotgen pilotgen; // pilot symbol generator float complex pn_sequence[64]; // 64-symbol p/n sequence unsigned char payload_dec[150]; // 600 = 150 bytes * 8 bits/bytes / 2 bits/symbol float complex payload_sym[600]; // modulated payload symbols float complex payload_tx[630]; // modulated payload symbols with pilots unsigned int m; // filter delay (symbols) float beta; // filter excess bandwidth factor firinterp_crcf interp; // pulse-shaping filter }; // create framegen64 object framegen64 framegen64_create() { framegen64 q = (framegen64) malloc(sizeof(struct framegen64_s)); q->m = 7; q->beta = 0.3f; unsigned int i; // generate pn sequence msequence ms = msequence_create(7, 0x0089, 1); for (i=0; i<64; i++) { q->pn_sequence[i] = (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2); q->pn_sequence[i] += (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2)*_Complex_I; } msequence_destroy(ms); // create payload encoder/modulator object int check = LIQUID_CRC_24; int fec0 = LIQUID_FEC_NONE; int fec1 = LIQUID_FEC_GOLAY2412; int mod_scheme = LIQUID_MODEM_QPSK; q->enc = qpacketmodem_create(); qpacketmodem_configure(q->enc, 72, check, fec0, fec1, mod_scheme); //qpacketmodem_print(q->enc); assert( qpacketmodem_get_frame_len(q->enc)==600 ); // create pilot generator q->pilotgen = qpilotgen_create(600, 21); assert( qpilotgen_get_frame_len(q->pilotgen)==630 ); // create pulse-shaping filter (k=2) q->interp = firinterp_crcf_create_prototype(LIQUID_FIRFILT_ARKAISER,2,q->m,q->beta,0); // return main object return q; } // destroy framegen64 object void framegen64_destroy(framegen64 _q) { // destroy internal objects qpacketmodem_destroy(_q->enc); qpilotgen_destroy(_q->pilotgen); // free main object memory free(_q); } // print framegen64 object internals void framegen64_print(framegen64 _q) { float eta = (float) (8*(64 + 8)) / (float) (LIQUID_FRAME64_LEN/2); printf("framegen64 [m=%u, beta=%4.2f]:\n", _q->m, _q->beta); printf(" preamble/etc.\n"); printf(" * ramp/up symbols : %3u\n", _q->m); printf(" * p/n symbols : %3u\n", 64); printf(" * ramp\\down symbols : %3u\n", _q->m); printf(" * zero padding : %3u\n", 12); printf(" payload\n"); #if 0 printf(" * payload crc : %s\n", crc_scheme_str[_q->check][1]); printf(" * fec (inner) : %s\n", fec_scheme_str[_q->fec0][1]); printf(" * fec (outer) : %s\n", fec_scheme_str[_q->fec1][1]); #endif printf(" * payload len, uncoded : %3u bytes\n", 64); printf(" * payload len, coded : %3u bytes\n", 150); printf(" * modulation scheme : %s\n", modulation_types[LIQUID_MODEM_QPSK].name); printf(" * payload symbols : %3u\n", 600); printf(" * pilot symbols : %3u\n", 30); printf(" summary\n"); printf(" * total symbols : %3u\n", LIQUID_FRAME64_LEN/2); printf(" * spectral efficiency : %6.4f b/s/Hz\n", eta); } // execute frame generator (creates a frame) // _q : frame generator object // _header : 8-byte header data // _payload : 64-byte payload data // _frame : output frame samples [size: LIQUID_FRAME64_LEN x 1] void framegen64_execute(framegen64 _q, unsigned char * _header, unsigned char * _payload, float complex * _frame) { unsigned int i; // concatenate header and payload memmove(&_q->payload_dec[0], _header, 8*sizeof(unsigned char)); memmove(&_q->payload_dec[8], _payload, 64*sizeof(unsigned char)); // run packet encoder and modulator qpacketmodem_encode(_q->enc, _q->payload_dec, _q->payload_sym); // add pilot symbols qpilotgen_execute(_q->pilotgen, _q->payload_sym, _q->payload_tx); unsigned int n=0; // reset interpolator firinterp_crcf_reset(_q->interp); // p/n sequence for (i=0; i<64; i++) { firinterp_crcf_execute(_q->interp, _q->pn_sequence[i], &_frame[n]); n+=2; } // frame payload for (i=0; i<630; i++) { firinterp_crcf_execute(_q->interp, _q->payload_tx[i], &_frame[n]); n+=2; } // interpolator settling for (i=0; i<2*_q->m + 2 + 10; i++) { firinterp_crcf_execute(_q->interp, 0.0f, &_frame[n]); n+=2; } assert(n==LIQUID_FRAME64_LEN); } liquid-dsp-1.3.1/src/framing/src/framesync64.c000066400000000000000000000456311317124540100211040ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // framesync64.c // // basic frame synchronizer // #include #include #include #include #include #include #include "liquid.internal.h" #define DEBUG_FRAMESYNC64 1 #define DEBUG_FRAMESYNC64_PRINT 0 #define DEBUG_FILENAME "framesync64_internal_debug.m" #define DEBUG_BUFFER_LEN (1600) #define FRAMESYNC64_ENABLE_EQ 0 // push samples through detection stage void framesync64_execute_seekpn(framesync64 _q, float complex _x); // step receiver mixer, matched filter, decimator // _q : frame synchronizer // _x : input sample // _y : output symbol int framesync64_step(framesync64 _q, float complex _x, float complex * _y); // push samples through synchronizer, saving received p/n symbols void framesync64_execute_rxpreamble(framesync64 _q, float complex _x); // receive payload symbols void framesync64_execute_rxpayload(framesync64 _q, float complex _x); // framesync64 object structure struct framesync64_s { // callback framesync_callback callback; // user-defined callback function void * userdata; // user-defined data structure framesyncstats_s framestats; // frame statistic object // synchronizer objects unsigned int m; // filter delay (symbols) float beta; // filter excess bandwidth factor qdetector_cccf detector; // pre-demod detector float tau_hat; // fractional timing offset estimate float dphi_hat; // carrier frequency offset estimate float phi_hat; // carrier phase offset estimate float gamma_hat; // channel gain estimate nco_crcf mixer; // coarse carrier frequency recovery // timing recovery objects, states firpfb_crcf mf; // matched filter decimator unsigned int npfb; // number of filters in symsync int mf_counter; // matched filter output timer unsigned int pfb_index; // filterbank index #if FRAMESYNC64_ENABLE_EQ eqlms_cccf equalizer; // equalizer (trained on p/n sequence) #endif // preamble float complex preamble_pn[64]; // known 64-symbol p/n sequence float complex preamble_rx[64]; // received p/n symbols // payload decoder float complex payload_rx [630]; // received payload symbols with pilots float complex payload_sym[600]; // received payload symbols unsigned char payload_dec[ 72]; // decoded payload bytes qpacketmodem dec; // packet demodulator/decoder qpilotsync pilotsync; // pilot extraction, carrier recovery int payload_valid; // did payload pass crc? // status variables enum { FRAMESYNC64_STATE_DETECTFRAME=0, // detect frame (seek p/n sequence) FRAMESYNC64_STATE_RXPREAMBLE, // receive p/n sequence FRAMESYNC64_STATE_RXPAYLOAD, // receive payload data } state; unsigned int preamble_counter; // counter: num of p/n syms received unsigned int payload_counter; // counter: num of payload syms received #if DEBUG_FRAMESYNC64 int debug_enabled; // debugging enabled? int debug_objects_created; // debugging objects created? windowcf debug_x; // debug: raw input samples #endif }; // create framesync64 object // _callback : callback function invoked when frame is received // _userdata : user-defined data object passed to callback framesync64 framesync64_create(framesync_callback _callback, void * _userdata) { framesync64 q = (framesync64) malloc(sizeof(struct framesync64_s)); q->callback = _callback; q->userdata = _userdata; q->m = 7; // filter delay (symbols) q->beta = 0.3f; // excess bandwidth factor unsigned int i; // generate p/n sequence msequence ms = msequence_create(7, 0x0089, 1); for (i=0; i<64; i++) { q->preamble_pn[i] = (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2); q->preamble_pn[i] += (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2)*_Complex_I; } msequence_destroy(ms); // create frame detector unsigned int k = 2; // samples/symbol q->detector = qdetector_cccf_create_linear(q->preamble_pn, 64, LIQUID_FIRFILT_ARKAISER, k, q->m, q->beta); qdetector_cccf_set_threshold(q->detector, 0.5f); // create symbol timing recovery filters q->npfb = 32; // number of filters in the bank q->mf = firpfb_crcf_create_rnyquist(LIQUID_FIRFILT_ARKAISER, q->npfb,k,q->m,q->beta); #if FRAMESYNC64_ENABLE_EQ // create equalizer unsigned int p = 3; q->equalizer = eqlms_cccf_create_lowpass(2*k*p+1, 0.4f); eqlms_cccf_set_bw(q->equalizer, 0.05f); #endif // create down-coverters for carrier phase tracking q->mixer = nco_crcf_create(LIQUID_NCO); // create payload demodulator/decoder object int check = LIQUID_CRC_24; int fec0 = LIQUID_FEC_NONE; int fec1 = LIQUID_FEC_GOLAY2412; int mod_scheme = LIQUID_MODEM_QPSK; q->dec = qpacketmodem_create(); qpacketmodem_configure(q->dec, 72, check, fec0, fec1, mod_scheme); //qpacketmodem_print(q->dec); assert( qpacketmodem_get_frame_len(q->dec)==600 ); // create pilot synchronizer q->pilotsync = qpilotsync_create(600, 21); assert( qpilotsync_get_frame_len(q->pilotsync)==630 ); #if DEBUG_FRAMESYNC64 // set debugging flags, objects to NULL q->debug_enabled = 0; q->debug_objects_created = 0; q->debug_x = NULL; #endif // reset state and return framesync64_reset(q); return q; } // destroy frame synchronizer object, freeing all internal memory void framesync64_destroy(framesync64 _q) { #if DEBUG_FRAMESYNC64 // clean up debug objects (if created) if (_q->debug_objects_created) { windowcf_destroy(_q->debug_x); } #endif // destroy synchronization objects qdetector_cccf_destroy(_q->detector); // frame detector firpfb_crcf_destroy (_q->mf); // matched filter nco_crcf_destroy (_q->mixer); // coarse NCO qpacketmodem_destroy (_q->dec); // payload demodulator qpilotsync_destroy (_q->pilotsync); // pilot synchronizer #if FRAMESYNC64_ENABLE_EQ eqlms_cccf_destroy (_q->equalizer); // LMS equalizer #endif // free main object memory free(_q); } // print frame synchronizer object internals void framesync64_print(framesync64 _q) { printf("framesync64:\n"); } // reset frame synchronizer object void framesync64_reset(framesync64 _q) { // reset binary pre-demod synchronizer qdetector_cccf_reset(_q->detector); // reset carrier recovery objects nco_crcf_reset(_q->mixer); // reset symbol timing recovery state firpfb_crcf_reset(_q->mf); // reset state _q->state = FRAMESYNC64_STATE_DETECTFRAME; _q->preamble_counter= 0; _q->payload_counter = 0; // reset frame statistics _q->framestats.evm = 0.0f; } // execute frame synchronizer // _q : frame synchronizer object // _x : input sample array [size: _n x 1] // _n : number of input samples void framesync64_execute(framesync64 _q, float complex * _x, unsigned int _n) { unsigned int i; for (i=0; i<_n; i++) { #if DEBUG_FRAMESYNC64 if (_q->debug_enabled) windowcf_push(_q->debug_x, _x[i]); #endif switch (_q->state) { case FRAMESYNC64_STATE_DETECTFRAME: // detect frame (look for p/n sequence) framesync64_execute_seekpn(_q, _x[i]); break; case FRAMESYNC64_STATE_RXPREAMBLE: // receive p/n sequence symbols framesync64_execute_rxpreamble(_q, _x[i]); break; case FRAMESYNC64_STATE_RXPAYLOAD: // receive payload symbols framesync64_execute_rxpayload(_q, _x[i]); break; default: fprintf(stderr,"error: framesync64_exeucte(), unknown/unsupported state\n"); exit(1); } } } // // internal methods // // execute synchronizer, seeking p/n sequence // _q : frame synchronizer object // _x : input sample // _sym : demodulated symbol void framesync64_execute_seekpn(framesync64 _q, float complex _x) { // push through pre-demod synchronizer float complex * v = qdetector_cccf_execute(_q->detector, _x); // check if frame has been detected if (v != NULL) { // get estimates _q->tau_hat = qdetector_cccf_get_tau (_q->detector); _q->gamma_hat = qdetector_cccf_get_gamma(_q->detector); _q->dphi_hat = qdetector_cccf_get_dphi (_q->detector); _q->phi_hat = qdetector_cccf_get_phi (_q->detector); #if DEBUG_FRAMESYNC64_PRINT printf("***** frame detected! tau-hat:%8.4f, dphi-hat:%8.4f, gamma:%8.2f dB\n", _q->tau_hat, _q->dphi_hat, 20*log10f(_q->gamma_hat)); #endif // set appropriate filterbank index if (_q->tau_hat > 0) { _q->pfb_index = (unsigned int)( _q->tau_hat * _q->npfb) % _q->npfb; _q->mf_counter = 0; } else { _q->pfb_index = (unsigned int)((1.0f+_q->tau_hat) * _q->npfb) % _q->npfb; _q->mf_counter = 1; } // output filter scale firpfb_crcf_set_scale(_q->mf, 0.5f / _q->gamma_hat); // set frequency/phase of mixer nco_crcf_set_frequency(_q->mixer, _q->dphi_hat); nco_crcf_set_phase (_q->mixer, _q->phi_hat ); // update state _q->state = FRAMESYNC64_STATE_RXPREAMBLE; // run buffered samples through synchronizer unsigned int buf_len = qdetector_cccf_get_buf_len(_q->detector); framesync64_execute(_q, v, buf_len); } } // step receiver mixer, matched filter, decimator // _q : frame synchronizer // _x : input sample // _y : output symbol int framesync64_step(framesync64 _q, float complex _x, float complex * _y) { // mix sample down float complex v; nco_crcf_mix_down(_q->mixer, _x, &v); nco_crcf_step (_q->mixer); // push sample into filterbank firpfb_crcf_push (_q->mf, v); firpfb_crcf_execute(_q->mf, _q->pfb_index, &v); #if FRAMESYNC64_ENABLE_EQ // push sample through equalizer eqlms_cccf_push(_q->equalizer, v); #endif // increment counter to determine if sample is available _q->mf_counter++; int sample_available = (_q->mf_counter >= 1) ? 1 : 0; // set output sample if available if (sample_available) { #if FRAMESYNC64_ENABLE_EQ // compute equalizer output eqlms_cccf_execute(_q->equalizer, &v); #endif // set output *_y = v; // decrement counter by k=2 samples/symbol _q->mf_counter -= 2; } // return flag return sample_available; } // execute synchronizer, receiving p/n sequence // _q : frame synchronizer object // _x : input sample // _sym : demodulated symbol void framesync64_execute_rxpreamble(framesync64 _q, float complex _x) { // step synchronizer float complex mf_out = 0.0f; int sample_available = framesync64_step(_q, _x, &mf_out); // compute output if timeout if (sample_available) { // save output in p/n symbols buffer #if FRAMESYNC64_ENABLE_EQ unsigned int delay = 2*_q->m + 3; // delay from matched filter and equalizer #else unsigned int delay = 2*_q->m; // delay from matched filter #endif if (_q->preamble_counter >= delay) { unsigned int index = _q->preamble_counter-delay; _q->preamble_rx[index] = mf_out; #if FRAMESYNC64_ENABLE_EQ // train equalizer eqlms_cccf_step(_q->equalizer, _q->preamble_pn[index], mf_out); #endif } // update p/n counter _q->preamble_counter++; // update state if (_q->preamble_counter == 64 + delay) _q->state = FRAMESYNC64_STATE_RXPAYLOAD; } } // execute synchronizer, receiving payload // _q : frame synchronizer object // _x : input sample // _sym : demodulated symbol void framesync64_execute_rxpayload(framesync64 _q, float complex _x) { // step synchronizer float complex mf_out = 0.0f; int sample_available = framesync64_step(_q, _x, &mf_out); // compute output if timeout if (sample_available) { // save payload symbols (modem input/output) _q->payload_rx[_q->payload_counter] = mf_out; // increment counter _q->payload_counter++; if (_q->payload_counter == 630) { // recover data symbols from pilots qpilotsync_execute(_q->pilotsync, _q->payload_rx, _q->payload_sym); // decode payload _q->payload_valid = qpacketmodem_decode(_q->dec, _q->payload_sym, _q->payload_dec); // invoke callback if (_q->callback != NULL) { // set framestats internals _q->framestats.evm = 0.0f; //20*log10f(sqrtf(_q->framestats.evm / 600)); _q->framestats.rssi = 20*log10f(_q->gamma_hat); _q->framestats.cfo = nco_crcf_get_frequency(_q->mixer); _q->framestats.framesyms = _q->payload_sym; _q->framestats.num_framesyms = 600; _q->framestats.mod_scheme = LIQUID_MODEM_QPSK; _q->framestats.mod_bps = 2; _q->framestats.check = LIQUID_CRC_24; _q->framestats.fec0 = LIQUID_FEC_NONE; _q->framestats.fec1 = LIQUID_FEC_GOLAY2412; // invoke callback method _q->callback(&_q->payload_dec[0], // header is first 8 bytes _q->payload_valid, &_q->payload_dec[8], // payload is last 64 bytes 64, _q->payload_valid, _q->framestats, _q->userdata); } // reset frame synchronizer framesync64_reset(_q); return; } } } // enable debugging void framesync64_debug_enable(framesync64 _q) { // create debugging objects if necessary #if DEBUG_FRAMESYNC64 if (_q->debug_objects_created) return; // create debugging objects _q->debug_x = windowcf_create(DEBUG_BUFFER_LEN); // set debugging flags _q->debug_enabled = 1; _q->debug_objects_created = 1; #else fprintf(stderr,"framesync64_debug_enable(): compile-time debugging disabled\n"); #endif } // disable debugging void framesync64_debug_disable(framesync64 _q) { // disable debugging #if DEBUG_FRAMESYNC64 _q->debug_enabled = 0; #else fprintf(stderr,"framesync64_debug_enable(): compile-time debugging disabled\n"); #endif } // print debugging information void framesync64_debug_print(framesync64 _q, const char * _filename) { #if DEBUG_FRAMESYNC64 if (!_q->debug_objects_created) { fprintf(stderr,"error: framesync64_debug_print(), debugging objects don't exist; enable debugging first\n"); return; } unsigned int i; float complex * rc; FILE* fid = fopen(_filename,"w"); fprintf(fid,"%% %s: auto-generated file", _filename); fprintf(fid,"\n\n"); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n\n"); fprintf(fid,"n = %u;\n", DEBUG_BUFFER_LEN); // write x fprintf(fid,"x = zeros(1,n);\n"); windowcf_read(_q->debug_x, &rc); for (i=0; ipreamble_pn; for (i=0; i<64; i++) fprintf(fid,"preamble_pn(%4u) = %12.4e + 1i*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i])); // write p/n symbols fprintf(fid,"preamble_rx = zeros(1,64);\n"); rc = _q->preamble_rx; for (i=0; i<64; i++) fprintf(fid,"preamble_rx(%4u) = %12.4e + 1i*%12.4e;\n", i+1, crealf(rc[i]), cimagf(rc[i])); // write raw payload symbols unsigned int payload_sym_len = 600; fprintf(fid,"payload_rx = zeros(1,%u);\n", payload_sym_len); rc = _q->payload_rx; for (i=0; ipayload_sym; for (i=0; i #include #include #include #include #include "liquid.internal.h" framesyncstats_s framesyncstats_default = { // signal quality 0.0f, // error vector magnitude 0.0f, // rssi 0.0f, // carrier frequency offset // demodulated frame symbols NULL, // framesyms 0, // num_framesyms // modulation/coding scheme, etc. LIQUID_MODEM_UNKNOWN, // mod_scheme 0, // mod_bps LIQUID_CRC_UNKNOWN, // check LIQUID_FEC_UNKNOWN, // fec0 LIQUID_FEC_UNKNOWN // fec1 }; // initialize framesyncstats object on default void framesyncstats_init_default(framesyncstats_s * _stats) { memmove(_stats, &framesyncstats_default, sizeof(framesyncstats_s)); } // print framesyncstats object void framesyncstats_print(framesyncstats_s * _stats) { // validate statistics object if (_stats->mod_scheme >= LIQUID_MODEM_NUM_SCHEMES) { fprintf(stderr,"error: framesyncstats_print(), invalid modulation scheme\n"); exit(1); } else if (_stats->check >= LIQUID_CRC_NUM_SCHEMES) { fprintf(stderr,"error: framesyncstats_print(), invalid CRC scheme\n"); exit(1); } else if (_stats->fec0 >= LIQUID_FEC_NUM_SCHEMES) { fprintf(stderr,"error: framesyncstats_print(), invalid FEC scheme (inner)\n"); exit(1); } else if (_stats->fec1 >= LIQUID_FEC_NUM_SCHEMES) { fprintf(stderr,"error: framesyncstats_print(), invalid FEC scheme (outer)\n"); exit(1); } printf(" EVM : %12.8f dB\n", _stats->evm); printf(" rssi : %12.8f dB\n", _stats->rssi); printf(" carrier offset : %12.8f Fs\n", _stats->cfo); printf(" num symbols : %u\n", _stats->num_framesyms); printf(" mod scheme : %s (%u bits/symbol)\n", modulation_types[_stats->mod_scheme].name, _stats->mod_bps); printf(" validity check : %s\n", crc_scheme_str[_stats->check][0]); printf(" fec (inner) : %s\n", fec_scheme_str[_stats->fec0][0]); printf(" fec (outer) : %s\n", fec_scheme_str[_stats->fec1][0]); } liquid-dsp-1.3.1/src/framing/src/gmskframegen.c000066400000000000000000000330701317124540100214030ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // gmskframegen.c // #include #include #include #include #include #include #include "liquid.internal.h" #define DEBUG_GMSKFRAMEGEN 0 // gmskframegen void gmskframegen_encode_header( gmskframegen _q, const unsigned char * _header); void gmskframegen_write_preamble(gmskframegen _q, float complex * _y); void gmskframegen_write_header( gmskframegen _q, float complex * _y); void gmskframegen_write_payload( gmskframegen _q, float complex * _y); void gmskframegen_write_tail( gmskframegen _q, float complex * _y); // gmskframe object structure struct gmskframegen_s { gmskmod mod; // GMSK modulator unsigned int k; // filter samples/symbol unsigned int m; // filter semi-length (symbols) float BT; // filter bandwidth-time product // framing lengths (symbols) unsigned int preamble_len; // unsigned int header_len; // length of header (encoded) unsigned int payload_len; // unsigned int tail_len; // // preamble //unsigned int genpoly_header;// generator polynomial msequence ms_preamble; // preamble p/n sequence // header unsigned char * header_dec; // uncoded header [GMSKFRAME_H_DEC] unsigned char * header_enc; // encoded header [GMSKFRAME_H_ENC] packetizer p_header; // header packetizer // payload packetizer p_payload; // payload packetizer crc_scheme check; // CRC fec_scheme fec0; // inner forward error correction fec_scheme fec1; // outer forward error correction unsigned int dec_msg_len; // unsigned int enc_msg_len; // unsigned char * payload_enc;// encoded payload // framing state enum { STATE_PREAMBLE, // preamble STATE_HEADER, // header STATE_PAYLOAD, // payload (frame) STATE_TAIL, // tail symbols } state; int frame_assembled; // frame assembled flag int frame_complete; // frame completed flag unsigned int symbol_counter;// }; // create gmskframegen object gmskframegen gmskframegen_create() { gmskframegen q = (gmskframegen) malloc(sizeof(struct gmskframegen_s)); // set internal properties q->k = 2; // samples/symbol q->m = 3; // filter delay (symbols) q->BT = 0.5f; // filter bandwidth-time product // internal/derived values q->preamble_len = 63; // number of preamble symbols q->payload_len = 0; // number of payload symbols q->tail_len = 2*q->m; // number of tail symbols (flush interp) // create modulator q->mod = gmskmod_create(q->k, q->m, q->BT); // preamble objects/arrays q->ms_preamble = msequence_create(6, 0x6d, 1); // header objects/arrays q->header_dec = (unsigned char*)malloc(GMSKFRAME_H_DEC*sizeof(unsigned char)); q->header_enc = (unsigned char*)malloc(GMSKFRAME_H_ENC*sizeof(unsigned char)); q->header_len = GMSKFRAME_H_ENC * 8; q->p_header = packetizer_create(GMSKFRAME_H_DEC, GMSKFRAME_H_CRC, GMSKFRAME_H_FEC, LIQUID_FEC_NONE); // payload objects/arrays q->dec_msg_len = 0; q->check = LIQUID_CRC_32; q->fec0 = LIQUID_FEC_NONE; q->fec1 = LIQUID_FEC_NONE; q->p_payload = packetizer_create(q->dec_msg_len, q->check, q->fec0, q->fec1); q->enc_msg_len = packetizer_get_enc_msg_len(q->p_payload); q->payload_len = 8*q->enc_msg_len; // allocate memory for encoded packet q->payload_enc = (unsigned char*) malloc(q->enc_msg_len*sizeof(unsigned char)); // reset framing object gmskframegen_reset(q); // return object return q; } // destroy gmskframegen object void gmskframegen_destroy(gmskframegen _q) { // destroy gmsk modulator gmskmod_destroy(_q->mod); // destroy/free preamble objects/arrays msequence_destroy(_q->ms_preamble); // destroy/free header objects/arrays free(_q->header_dec); free(_q->header_enc); packetizer_destroy(_q->p_header); // destroy/free payload objects/arrays free(_q->payload_enc); packetizer_destroy(_q->p_payload); // free main object memory free(_q); } // reset frame generator object void gmskframegen_reset(gmskframegen _q) { // reset GMSK modulator gmskmod_reset(_q->mod); // reset states _q->state = STATE_PREAMBLE; msequence_reset(_q->ms_preamble); _q->frame_assembled = 0; _q->frame_complete = 0; _q->symbol_counter = 0; } // is frame assembled? int gmskframegen_is_assembled(gmskframegen _q) { return _q->frame_assembled; } // print gmskframegen object internals void gmskframegen_print(gmskframegen _q) { // plot printf("gmskframegen:\n"); printf(" physical properties\n"); printf(" samples/symbol : %u\n", _q->k); printf(" filter delay : %u symbols\n", _q->m); printf(" bandwidth-time : %-8.3f\n", _q->BT); printf(" framing properties\n"); printf(" preamble : %-4u symbols\n", _q->preamble_len); printf(" header : %-4u symbols\n", _q->header_len); printf(" payload : %-4u symbols\n", _q->payload_len); printf(" tail : %-4u symbols\n", _q->tail_len); printf(" packet properties\n"); printf(" crc : %s\n", crc_scheme_str[_q->check][1]); printf(" fec (inner) : %s\n", fec_scheme_str[_q->fec0][1]); printf(" fec (outer) : %s\n", fec_scheme_str[_q->fec1][1]); printf(" total samples : %-4u sampels\n", gmskframegen_getframelen(_q)); } // assemble frame // _q : frame generator object // _header : raw header // _payload : raw payload [size: _payload_len x 1] // _payload_len : raw payload length (bytes) // _check : data validity check // _fec0 : inner forward error correction // _fec1 : outer forward error correction void gmskframegen_assemble(gmskframegen _q, const unsigned char * _header, const unsigned char * _payload, unsigned int _payload_len, crc_scheme _check, fec_scheme _fec0, fec_scheme _fec1) { // re-create frame generator if properties don't match if (_q->dec_msg_len != _payload_len || _q->check != _check || _q->fec0 != _fec0 || _q->fec1 != _fec1) { // set properties _q->dec_msg_len = _payload_len; _q->check = _check; _q->fec0 = _fec0; _q->fec1 = _fec1; // re-create payload packetizer _q->p_payload = packetizer_recreate(_q->p_payload, _q->dec_msg_len, _q->check, _q->fec0, _q->fec1); // get packet length _q->enc_msg_len = packetizer_get_enc_msg_len(_q->p_payload); _q->payload_len = 8*_q->enc_msg_len; // re-allocate memory _q->payload_enc = (unsigned char*) realloc(_q->payload_enc, _q->enc_msg_len*sizeof(unsigned char)); } // set assembled flag _q->frame_assembled = 1; // encode header gmskframegen_encode_header(_q, _header); // encode payload packetizer_encode(_q->p_payload, _payload, _q->payload_enc); } // get frame length (number of samples) unsigned int gmskframegen_getframelen(gmskframegen _q) { if (!_q->frame_assembled) { fprintf(stderr,"warning: gmskframegen_getframelen(), frame not assembled!\n"); return 0; } unsigned int num_frame_symbols = _q->preamble_len + // number of preamble p/n symbols GMSKFRAME_H_SYM + // number of header symbols _q->payload_len + // number of payload symbols 2*_q->m; // number of tail symbols return num_frame_symbols*_q->k; // k samples/symbol } // write sample to output buffer int gmskframegen_write_samples(gmskframegen _q, float complex * _y) { switch (_q->state) { case STATE_PREAMBLE: // write preamble gmskframegen_write_preamble(_q, _y); break; case STATE_HEADER: // write header gmskframegen_write_header(_q, _y); break; case STATE_PAYLOAD: // write payload symbols gmskframegen_write_payload(_q, _y); break; case STATE_TAIL: // write tail symbols gmskframegen_write_tail(_q, _y); break; default: fprintf(stderr,"error: gmskframegen_writesymbol(), unknown/unsupported internal state\n"); exit(1); } if (_q->frame_complete) { // reset framing object #if DEBUG_GMSKFRAMEGEN printf(" ...resetting...\n"); #endif gmskframegen_reset(_q); return 1; } return 0; } // // internal methods // void gmskframegen_encode_header(gmskframegen _q, const unsigned char * _header) { // first 'n' bytes user data memmove(_q->header_dec, _header, GMSKFRAME_H_USER); unsigned int n = GMSKFRAME_H_USER; // first byte is for expansion/version validation _q->header_dec[n+0] = GMSKFRAME_VERSION; // add payload length _q->header_dec[n+1] = (_q->dec_msg_len >> 8) & 0xff; _q->header_dec[n+2] = (_q->dec_msg_len ) & 0xff; // add CRC, forward error-correction schemes // CRC : most-significant 3 bits of [n+4] // fec0 : least-significant 5 bits of [n+4] // fec1 : least-significant 5 bits of [n+5] _q->header_dec[n+3] = (_q->check & 0x07) << 5; _q->header_dec[n+3] |= (_q->fec0) & 0x1f; _q->header_dec[n+4] = (_q->fec1) & 0x1f; // run packet encoder packetizer_encode(_q->p_header, _q->header_dec, _q->header_enc); // scramble header scramble_data(_q->header_enc, GMSKFRAME_H_ENC); #if 0 printf(" header_enc :"); unsigned int i; for (i=0; iheader_enc[i]); printf("\n"); #endif } void gmskframegen_write_preamble(gmskframegen _q, float complex * _y) { unsigned char bit = msequence_advance(_q->ms_preamble); gmskmod_modulate(_q->mod, bit, _y); // apply ramping window to first 'm' symbols if (_q->symbol_counter < _q->m) { unsigned int i; for (i=0; i<_q->k; i++) _y[i] *= hamming(_q->symbol_counter*_q->k + i, 2*_q->m*_q->k); } _q->symbol_counter++; if (_q->symbol_counter == _q->preamble_len) { msequence_reset(_q->ms_preamble); _q->symbol_counter = 0; _q->state = STATE_HEADER; } } void gmskframegen_write_header(gmskframegen _q, float complex * _y) { div_t d = div(_q->symbol_counter, 8); unsigned int byte_index = d.quot; unsigned int bit_index = d.rem; unsigned char byte = _q->header_enc[byte_index]; unsigned char bit = (byte >> (8-bit_index-1)) & 0x01; gmskmod_modulate(_q->mod, bit, _y); _q->symbol_counter++; if (_q->symbol_counter == _q->header_len) { _q->symbol_counter = 0; _q->state = STATE_PAYLOAD; } } void gmskframegen_write_payload(gmskframegen _q, float complex * _y) { div_t d = div(_q->symbol_counter, 8); unsigned int byte_index = d.quot; unsigned int bit_index = d.rem; unsigned char byte = _q->payload_enc[byte_index]; unsigned char bit = (byte >> (8-bit_index-1)) & 0x01; gmskmod_modulate(_q->mod, bit, _y); _q->symbol_counter++; if (_q->symbol_counter == _q->payload_len) { _q->symbol_counter = 0; _q->state = STATE_TAIL; } } void gmskframegen_write_tail(gmskframegen _q, float complex * _y) { unsigned char bit = rand() % 2; gmskmod_modulate(_q->mod, bit, _y); // apply ramping window to last 'm' symbols if (_q->symbol_counter >= _q->m) { unsigned int i; for (i=0; i<_q->k; i++) _y[i] *= hamming(_q->m*_q->k + (_q->symbol_counter-_q->m)*_q->k + i, 2*_q->m*_q->k); } _q->symbol_counter++; if (_q->symbol_counter == _q->tail_len) { _q->symbol_counter = 0; _q->frame_complete = 1; } } liquid-dsp-1.3.1/src/framing/src/gmskframesync.c000066400000000000000000000772461317124540100216230ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // gmskframesync.c // #include #include #include #include #include #include #include "liquid.internal.h" #define DEBUG_GMSKFRAMESYNC 1 #define DEBUG_GMSKFRAMESYNC_PRINT 0 #define DEBUG_GMSKFRAMESYNC_FILENAME "gmskframesync_debug.m" #define DEBUG_GMSKFRAMESYNC_BUFFER_LEN (2000) // enable pre-demodulation filter (remove out-of-band noise) #define GMSKFRAMESYNC_PREFILTER 1 // execute a single, post-filtered sample void gmskframesync_execute_sample(gmskframesync _q, float complex _x); // push buffered p/n sequence through synchronizer void gmskframesync_pushpn(gmskframesync _q); // ... void gmskframesync_syncpn(gmskframesync _q); // update instantaneous frequency estimate void gmskframesync_update_fi(gmskframesync _q, float complex _x); // update symbol synchronizer internal state (filtered error, index, etc.) // _q : frame synchronizer // _x : input sample // _y : output symbol int gmskframesync_update_symsync(gmskframesync _q, float _x, float * _y); // execute stages void gmskframesync_execute_detectframe(gmskframesync _q, float complex _x); void gmskframesync_execute_rxpreamble( gmskframesync _q, float complex _x); void gmskframesync_execute_rxheader( gmskframesync _q, float complex _x); void gmskframesync_execute_rxpayload( gmskframesync _q, float complex _x); // decode header void gmskframesync_decode_header(gmskframesync _q); // gmskframesync object structure struct gmskframesync_s { #if GMSKFRAMESYNC_PREFILTER iirfilt_crcf prefilter; // pre-demodulation filter #endif unsigned int k; // filter samples/symbol unsigned int m; // filter semi-length (symbols) float BT; // filter bandwidth-time product framesync_callback callback; // user-defined callback function void * userdata; // user-defined data structure framesyncstats_s framestats; // frame statistic object // float complex x_prime; // received sample state float fi_hat; // instantaneous frequency estimate // timing recovery objects, states firpfb_rrrf mf; // matched filter decimator firpfb_rrrf dmf; // derivative matched filter decimator unsigned int npfb; // number of filters in symsync float pfb_q; // filtered timing error float pfb_soft; // soft filterbank index int pfb_index; // hard filterbank index int pfb_timer; // filterbank output flag float symsync_out; // symbol synchronizer output // synchronizer objects detector_cccf frame_detector; // pre-demod detector float tau_hat; // fractional timing offset estimate float dphi_hat; // carrier frequency offset estimate float gamma_hat; // channel gain estimate windowcf buffer; // pre-demod buffered samples, size: k*(pn_len+m) nco_crcf nco_coarse; // coarse carrier frequency recovery // preamble unsigned int preamble_len; // number of symbols in preamble float * preamble_pn; // preamble p/n sequence (known) float * preamble_rx; // preamble p/n sequence (received) // header unsigned char * header_mod; unsigned char * header_enc; unsigned char * header_dec; packetizer p_header; int header_valid; // payload char payload_byte; // received byte crc_scheme check; // payload validity check fec_scheme fec0; // payload FEC (inner) fec_scheme fec1; // payload FEC (outer) unsigned int payload_enc_len; // length of encoded payload unsigned int payload_dec_len; // payload length (num un-encoded bytes) unsigned char * payload_enc; // payload data (encoded bytes) unsigned char * payload_dec; // payload data (encoded bytes) packetizer p_payload; // payload packetizer int payload_valid; // did payload pass crc? // status variables enum { STATE_DETECTFRAME=0, // detect frame (seek p/n sequence) STATE_RXPREAMBLE, // receive p/n sequence STATE_RXHEADER, // receive header data STATE_RXPAYLOAD, // receive payload data } state; unsigned int preamble_counter; // counter: num of p/n syms received unsigned int header_counter; // counter: num of header syms received unsigned int payload_counter; // counter: num of payload syms received // debugging structures #if DEBUG_GMSKFRAMESYNC int debug_enabled; // debugging enabled? int debug_objects_created; // debugging objects created? windowcf debug_x; // received samples buffer windowf debug_fi; // instantaneous frequency windowf debug_mf; // matched filter output windowf debug_framesyms; // GMSK output symbols #endif }; // create GMSK frame synchronizer // _callback : callback function // _userdata : user data pointer passed to callback function gmskframesync gmskframesync_create(framesync_callback _callback, void * _userdata) { gmskframesync q = (gmskframesync) malloc(sizeof(struct gmskframesync_s)); q->callback = _callback; q->userdata = _userdata; q->k = 2; // samples/symbol q->m = 3; // filter delay (symbols) q->BT = 0.5f; // filter bandwidth-time product #if GMSKFRAMESYNC_PREFILTER // create default low-pass Butterworth filter q->prefilter = iirfilt_crcf_create_lowpass(3, 0.5f*(1 + q->BT) / (float)(q->k)); #endif unsigned int i; // frame detector q->preamble_len = 63; q->preamble_pn = (float*)malloc(q->preamble_len*sizeof(float)); q->preamble_rx = (float*)malloc(q->preamble_len*sizeof(float)); float complex preamble_samples[q->preamble_len*q->k]; msequence ms = msequence_create(6, 0x6d, 1); gmskmod mod = gmskmod_create(q->k, q->m, q->BT); for (i=0; ipreamble_len + q->m; i++) { unsigned char bit = msequence_advance(ms); // save p/n sequence if (i < q->preamble_len) q->preamble_pn[i] = bit ? 1.0f : -1.0f; // modulate/interpolate if (i < q->m) gmskmod_modulate(mod, bit, &preamble_samples[0]); else gmskmod_modulate(mod, bit, &preamble_samples[(i-q->m)*q->k]); } gmskmod_destroy(mod); msequence_destroy(ms); #if 0 // print sequence for (i=0; ipreamble_len*q->k; i++) printf("preamble(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(preamble_samples[i]), cimagf(preamble_samples[i])); #endif // create frame detector float threshold = 0.5f; // detection threshold float dphi_max = 0.05f; // maximum carrier offset allowable q->frame_detector = detector_cccf_create(preamble_samples, q->preamble_len*q->k, threshold, dphi_max); q->buffer = windowcf_create(q->k*(q->preamble_len+q->m)); // create symbol timing recovery filters q->npfb = 32; // number of filters in the bank q->mf = firpfb_rrrf_create_rnyquist( LIQUID_FIRFILT_GMSKRX,q->npfb,q->k,q->m,q->BT); q->dmf = firpfb_rrrf_create_drnyquist(LIQUID_FIRFILT_GMSKRX,q->npfb,q->k,q->m,q->BT); // create down-coverters for carrier phase tracking q->nco_coarse = nco_crcf_create(LIQUID_NCO); // create/allocate header objects/arrays q->header_mod = (unsigned char*)malloc(GMSKFRAME_H_SYM*sizeof(unsigned char)); q->header_enc = (unsigned char*)malloc(GMSKFRAME_H_ENC*sizeof(unsigned char)); q->header_dec = (unsigned char*)malloc(GMSKFRAME_H_DEC*sizeof(unsigned char)); q->p_header = packetizer_create(GMSKFRAME_H_DEC, GMSKFRAME_H_CRC, GMSKFRAME_H_FEC, LIQUID_FEC_NONE); // create/allocate payload objects/arrays q->payload_dec_len = 1; q->check = LIQUID_CRC_32; q->fec0 = LIQUID_FEC_NONE; q->fec1 = LIQUID_FEC_NONE; q->p_payload = packetizer_create(q->payload_dec_len, q->check, q->fec0, q->fec1); q->payload_enc_len = packetizer_get_enc_msg_len(q->p_payload); q->payload_dec = (unsigned char*) malloc(q->payload_dec_len*sizeof(unsigned char)); q->payload_enc = (unsigned char*) malloc(q->payload_enc_len*sizeof(unsigned char)); #if DEBUG_GMSKFRAMESYNC // debugging structures q->debug_enabled = 0; q->debug_objects_created = 0; q->debug_x = NULL; q->debug_fi = NULL; q->debug_mf = NULL; q->debug_framesyms = NULL; #endif // reset synchronizer gmskframesync_reset(q); // return synchronizer object return q; } // destroy frame synchronizer object, freeing all internal memory void gmskframesync_destroy(gmskframesync _q) { #if DEBUG_GMSKFRAMESYNC // destroy debugging objects if (_q->debug_objects_created) { windowcf_destroy(_q->debug_x); windowf_destroy(_q->debug_fi); windowf_destroy(_q->debug_mf); windowf_destroy( _q->debug_framesyms); } #endif // destroy synchronizer objects #if GMSKFRAMESYNC_PREFILTER iirfilt_crcf_destroy(_q->prefilter);// pre-demodulator filter #endif firpfb_rrrf_destroy(_q->mf); // matched filter firpfb_rrrf_destroy(_q->dmf); // derivative matched filter nco_crcf_destroy(_q->nco_coarse); // coarse NCO // preamble detector_cccf_destroy(_q->frame_detector); windowcf_destroy(_q->buffer); free(_q->preamble_pn); free(_q->preamble_rx); // header packetizer_destroy(_q->p_header); free(_q->header_mod); free(_q->header_enc); free(_q->header_dec); // payload packetizer_destroy(_q->p_payload); free(_q->payload_enc); free(_q->payload_dec); // free main object memory free(_q); } // print frame synchronizer object internals void gmskframesync_print(gmskframesync _q) { printf("gmskframesync:\n"); } // reset frame synchronizer object void gmskframesync_reset(gmskframesync _q) { // reset state and counters _q->state = STATE_DETECTFRAME; _q->preamble_counter = 0; _q->header_counter = 0; _q->payload_counter = 0; // clear pre-demod buffer windowcf_reset(_q->buffer); // reset internal objects detector_cccf_reset(_q->frame_detector); // reset carrier recovery objects nco_crcf_reset(_q->nco_coarse); // reset sample state _q->x_prime = 0.0f; _q->fi_hat = 0.0f; // reset symbol timing recovery state firpfb_rrrf_reset(_q->mf); firpfb_rrrf_reset(_q->dmf); _q->pfb_q = 0.0f; // filtered error signal } int gmskframesync_is_frame_open(gmskframesync _q) { return (_q->state == STATE_DETECTFRAME) ? 0 : 1; } void gmskframesync_execute_sample(gmskframesync _q, float complex _x) { switch (_q->state) { case STATE_DETECTFRAME: // look for p/n sequence gmskframesync_execute_detectframe(_q, _x); break; case STATE_RXPREAMBLE: // receive p/n sequence symbols gmskframesync_execute_rxpreamble(_q, _x); break; case STATE_RXHEADER: // receive header gmskframesync_execute_rxheader(_q, _x); break; case STATE_RXPAYLOAD: // receive payload gmskframesync_execute_rxpayload(_q, _x); break; } } // execute frame synchronizer // _q : frame synchronizer object // _x : input sample array [size: _n x 1] // _n : number of input samples void gmskframesync_execute(gmskframesync _q, float complex * _x, unsigned int _n) { // push through synchronizer unsigned int i; for (i=0; i<_n; i++) { float complex xf; // input sample #if GMSKFRAMESYNC_PREFILTER iirfilt_crcf_execute(_q->prefilter, _x[i], &xf); #else xf = _x[i]; #endif #if DEBUG_GMSKFRAMESYNC if (_q->debug_enabled) windowcf_push(_q->debug_x, xf); #endif gmskframesync_execute_sample(_q, xf); } } // // internal methods // // update symbol synchronizer internal state (filtered error, index, etc.) // _q : frame synchronizer // _x : input sample // _y : output symbol int gmskframesync_update_symsync(gmskframesync _q, float _x, float * _y) { // push sample into filterbanks firpfb_rrrf_push(_q->mf, _x); firpfb_rrrf_push(_q->dmf, _x); // float mf_out = 0.0f; // matched-filter output float dmf_out = 0.0f; // derivatived matched-filter output #if DEBUG_GMSKFRAMESYNC if (_q->debug_enabled) { windowf_push(_q->debug_fi, _q->fi_hat); firpfb_rrrf_execute(_q->mf, _q->pfb_index, &mf_out); windowf_push(_q->debug_mf, mf_out); } #endif int sample_available = 0; // compute output if timeout if (_q->pfb_timer <= 0) { sample_available = 1; // reset timer _q->pfb_timer = 2; // k samples/symbol firpfb_rrrf_execute(_q->mf, _q->pfb_index, &mf_out); firpfb_rrrf_execute(_q->dmf, _q->pfb_index, &dmf_out); // update filtered timing error // lo bandwidth parameters: {0.92, 1.20}, about 100 symbols settling time // med bandwidth parameters: {0.98, 0.20}, about 200 symbols settling time // hi bandwidth parameters: {0.99, 0.05}, about 500 symbols settling time _q->pfb_q = 0.99f*_q->pfb_q + 0.05f*crealf( conjf(mf_out)*dmf_out ); // accumulate error into soft filterbank value _q->pfb_soft += _q->pfb_q; // compute actual filterbank index _q->pfb_index = roundf(_q->pfb_soft); // contrain index to be in [0, npfb-1] while (_q->pfb_index < 0) { _q->pfb_index += _q->npfb; _q->pfb_soft += _q->npfb; // adjust pfb output timer _q->pfb_timer--; } while (_q->pfb_index > _q->npfb-1) { _q->pfb_index -= _q->npfb; _q->pfb_soft -= _q->npfb; // adjust pfb output timer _q->pfb_timer++; } //printf(" b/soft : %12.8f\n", _q->pfb_soft); } // decrement symbol timer _q->pfb_timer--; // set output and return *_y = mf_out / (float)(_q->k); return sample_available; } // push buffered p/n sequence through synchronizer void gmskframesync_pushpn(gmskframesync _q) { unsigned int i; // reset filterbanks firpfb_rrrf_reset(_q->mf); firpfb_rrrf_reset(_q->dmf); // read buffer float complex * rc; windowcf_read(_q->buffer, &rc); // compute delay and filterbank index // tau_hat < 0 : delay = 2*k*m-1, index = round( tau_hat *npfb), flag = 0 // tau_hat > 0 : delay = 2*k*m-2, index = round((1-tau_hat)*npfb), flag = 0 assert(_q->tau_hat < 0.5f && _q->tau_hat > -0.5f); unsigned int delay = 2*_q->k*_q->m - 1; // samples to buffer before computing output _q->pfb_soft = -_q->tau_hat*_q->npfb; _q->pfb_index = (int) roundf(_q->pfb_soft); while (_q->pfb_index < 0) { delay -= 1; _q->pfb_index += _q->npfb; _q->pfb_soft += _q->npfb; } _q->pfb_timer = 0; // set coarse carrier frequency offset nco_crcf_set_frequency(_q->nco_coarse, _q->dphi_hat); unsigned int buffer_len = (_q->preamble_len + _q->m) * _q->k; for (i=0; inco_coarse, rc[i], &y); nco_crcf_step(_q->nco_coarse); // update instantanenous frequency estimate gmskframesync_update_fi(_q, y); // push initial samples into filterbanks firpfb_rrrf_push(_q->mf, _q->fi_hat); firpfb_rrrf_push(_q->dmf, _q->fi_hat); } // set state (still need a few more samples before entire p/n // sequence has been received) _q->state = STATE_RXPREAMBLE; for (i=delay; ipreamble_len; i++) printf(" %3u : %12.8f : %12.8f\n", i, _q->preamble_pn[i], _q->preamble_rx[i]); #endif } // update instantaneous frequency estimate void gmskframesync_update_fi(gmskframesync _q, float complex _x) { // compute differential phase _q->fi_hat = cargf(conjf(_q->x_prime)*_x) * _q->k; // update internal state _q->x_prime = _x; } void gmskframesync_execute_detectframe(gmskframesync _q, float complex _x) { // push sample into pre-demod p/n sequence buffer windowcf_push(_q->buffer, _x); // push through pre-demod synchronizer int detected = detector_cccf_correlate(_q->frame_detector, _x, &_q->tau_hat, &_q->dphi_hat, &_q->gamma_hat); // check if frame has been detected if (detected) { //printf("***** frame detected! tau-hat:%8.4f, dphi-hat:%8.4f, gamma:%8.2f dB\n", // _q->tau_hat, _q->dphi_hat, 20*log10f(_q->gamma_hat)); // push buffered samples through synchronizer // NOTE: state will be updated to STATE_RXPREAMBLE internally gmskframesync_pushpn(_q); } } void gmskframesync_execute_rxpreamble(gmskframesync _q, float complex _x) { // validate input if (_q->preamble_counter == _q->preamble_len) { fprintf(stderr,"warning: gmskframesync_execute_rxpn(), p/n buffer already full!\n"); return; } // mix signal down float complex y; nco_crcf_mix_down(_q->nco_coarse, _x, &y); nco_crcf_step(_q->nco_coarse); // update instantanenous frequency estimate gmskframesync_update_fi(_q, y); // update symbol synchronizer float mf_out = 0.0f; int sample_available = gmskframesync_update_symsync(_q, _q->fi_hat, &mf_out); // compute output if timeout if (sample_available) { // save output in p/n symbols buffer _q->preamble_rx[ _q->preamble_counter ] = mf_out / (float)(_q->k); // update counter _q->preamble_counter++; if (_q->preamble_counter == _q->preamble_len) { gmskframesync_syncpn(_q); _q->state = STATE_RXHEADER; } } } void gmskframesync_execute_rxheader(gmskframesync _q, float complex _x) { // mix signal down float complex y; nco_crcf_mix_down(_q->nco_coarse, _x, &y); nco_crcf_step(_q->nco_coarse); // update instantanenous frequency estimate gmskframesync_update_fi(_q, y); // update symbol synchronizer float mf_out = 0.0f; int sample_available = gmskframesync_update_symsync(_q, _q->fi_hat, &mf_out); // compute output if timeout if (sample_available) { // demodulate unsigned char s = mf_out > 0.0f ? 1 : 0; // TODO: update evm // save bit in buffer _q->header_mod[_q->header_counter] = s; // increment header counter _q->header_counter++; if (_q->header_counter == GMSKFRAME_H_SYM) { // decode header gmskframesync_decode_header(_q); // invoke callback if header is invalid if (!_q->header_valid && _q->callback != NULL) { // set framestats internals _q->framestats.rssi = 20*log10f(_q->gamma_hat); _q->framestats.evm = 0.0f; _q->framestats.framesyms = NULL; _q->framestats.num_framesyms = 0; _q->framestats.mod_scheme = LIQUID_MODEM_UNKNOWN; _q->framestats.mod_bps = 1; _q->framestats.check = LIQUID_CRC_UNKNOWN; _q->framestats.fec0 = LIQUID_FEC_UNKNOWN; _q->framestats.fec1 = LIQUID_FEC_UNKNOWN; // invoke callback method _q->callback(_q->header_dec, _q->header_valid, NULL, 0, 0, _q->framestats, _q->userdata); gmskframesync_reset(_q); } // reset if invalid if (!_q->header_valid) { gmskframesync_reset(_q); return; } // update state _q->state = STATE_RXPAYLOAD; } } } void gmskframesync_execute_rxpayload(gmskframesync _q, float complex _x) { // mix signal down float complex y; nco_crcf_mix_down(_q->nco_coarse, _x, &y); nco_crcf_step(_q->nco_coarse); // update instantanenous frequency estimate gmskframesync_update_fi(_q, y); // update symbol synchronizer float mf_out = 0.0f; int sample_available = gmskframesync_update_symsync(_q, _q->fi_hat, &mf_out); // compute output if timeout if (sample_available) { // demodulate unsigned char s = mf_out > 0.0f ? 1 : 0; // TODO: update evm // save payload _q->payload_byte <<= 1; _q->payload_byte |= s ? 0x01 : 0x00; _q->payload_enc[_q->payload_counter/8] = _q->payload_byte; // increment counter _q->payload_counter++; if (_q->payload_counter == 8*_q->payload_enc_len) { // decode payload _q->payload_valid = packetizer_decode(_q->p_payload, _q->payload_enc, _q->payload_dec); // invoke callback if (_q->callback != NULL) { // set framestats internals _q->framestats.rssi = 20*log10f(_q->gamma_hat); _q->framestats.evm = 0.0f; _q->framestats.framesyms = NULL; _q->framestats.num_framesyms = 0; _q->framestats.mod_scheme = LIQUID_MODEM_UNKNOWN; _q->framestats.mod_bps = 1; _q->framestats.check = _q->check; _q->framestats.fec0 = _q->fec0; _q->framestats.fec1 = _q->fec1; // invoke callback method _q->callback(_q->header_dec, _q->header_valid, _q->payload_dec, _q->payload_dec_len, _q->payload_valid, _q->framestats, _q->userdata); } // reset frame synchronizer gmskframesync_reset(_q); } } } // decode header and re-configure payload decoder void gmskframesync_decode_header(gmskframesync _q) { // pack each 1-bit header symbols into 8-bit bytes unsigned int num_written; liquid_pack_bytes(_q->header_mod, GMSKFRAME_H_SYM, _q->header_enc, GMSKFRAME_H_ENC, &num_written); assert(num_written==GMSKFRAME_H_ENC); // unscramble data unscramble_data(_q->header_enc, GMSKFRAME_H_ENC); // run packet decoder _q->header_valid = packetizer_decode(_q->p_header, _q->header_enc, _q->header_dec); #if DEBUG_GMSKFRAMESYNC_PRINT printf("****** header extracted [%s]\n", _q->header_valid ? "valid" : "INVALID!"); #endif if (!_q->header_valid) return; unsigned int n = GMSKFRAME_H_USER; // first byte is for expansion/version validation if (_q->header_dec[n+0] != GMSKFRAME_VERSION) { fprintf(stderr,"warning: gmskframesync_decode_header(), invalid framing version\n"); _q->header_valid = 0; return; } // strip off payload length unsigned int payload_dec_len = (_q->header_dec[n+1] << 8) | (_q->header_dec[n+2]); // strip off CRC, forward error-correction schemes // CRC : most-significant 3 bits of [n+3] // fec0 : least-significant 5 bits of [n+3] // fec1 : least-significant 5 bits of [n+4] unsigned int check = (_q->header_dec[n+3] >> 5 ) & 0x07; unsigned int fec0 = (_q->header_dec[n+3] ) & 0x1f; unsigned int fec1 = (_q->header_dec[n+4] ) & 0x1f; // validate properties if (check >= LIQUID_CRC_NUM_SCHEMES) { fprintf(stderr,"warning: gmskframesync_decode_header(), decoded CRC exceeds available\n"); check = LIQUID_CRC_UNKNOWN; _q->header_valid = 0; } if (fec0 >= LIQUID_FEC_NUM_SCHEMES) { fprintf(stderr,"warning: gmskframesync_decode_header(), decoded FEC (inner) exceeds available\n"); fec0 = LIQUID_FEC_UNKNOWN; _q->header_valid = 0; } if (fec1 >= LIQUID_FEC_NUM_SCHEMES) { fprintf(stderr,"warning: gmskframesync_decode_header(), decoded FEC (outer) exceeds available\n"); fec1 = LIQUID_FEC_UNKNOWN; _q->header_valid = 0; } // print results #if DEBUG_GMSKFRAMESYNC_PRINT printf(" properties:\n"); printf(" * fec (inner) : %s\n", fec_scheme_str[fec0][1]); printf(" * fec (outer) : %s\n", fec_scheme_str[fec1][1]); printf(" * CRC scheme : %s\n", crc_scheme_str[check][1]); printf(" * payload length : %u bytes\n", payload_dec_len); #endif // configure payload receiver if (_q->header_valid) { // set new packetizer properties _q->payload_dec_len = payload_dec_len; _q->check = check; _q->fec0 = fec0; _q->fec1 = fec1; // recreate packetizer object _q->p_payload = packetizer_recreate(_q->p_payload, _q->payload_dec_len, _q->check, _q->fec0, _q->fec1); // re-compute payload encoded message length _q->payload_enc_len = packetizer_get_enc_msg_len(_q->p_payload); #if DEBUG_GMSKFRAMESYNC_PRINT printf(" * payload encoded : %u bytes\n", _q->payload_enc_len); #endif // re-allocate buffers accordingly _q->payload_enc = (unsigned char*) realloc(_q->payload_enc, _q->payload_enc_len*sizeof(unsigned char)); _q->payload_dec = (unsigned char*) realloc(_q->payload_dec, _q->payload_dec_len*sizeof(unsigned char)); } // } void gmskframesync_debug_enable(gmskframesync _q) { // create debugging objects if necessary #if DEBUG_GMSKFRAMESYNC if (!_q->debug_objects_created) { _q->debug_x = windowcf_create(DEBUG_GMSKFRAMESYNC_BUFFER_LEN); _q->debug_fi = windowf_create(DEBUG_GMSKFRAMESYNC_BUFFER_LEN); _q->debug_mf = windowf_create(DEBUG_GMSKFRAMESYNC_BUFFER_LEN); _q->debug_framesyms = windowf_create(DEBUG_GMSKFRAMESYNC_BUFFER_LEN); } // set debugging flags _q->debug_enabled = 1; _q->debug_objects_created = 1; #else fprintf(stderr,"gmskframesync_debug_enable(): compile-time debugging disabled\n"); #endif } void gmskframesync_debug_disable(gmskframesync _q) { #if DEBUG_GMSKFRAMESYNC _q->debug_enabled = 0; #else fprintf(stderr,"gmskframesync_debug_disable(): compile-time debugging disabled\n"); #endif } void gmskframesync_debug_print(gmskframesync _q, const char * _filename) { #if DEBUG_GMSKFRAMESYNC if (!_q->debug_objects_created) { fprintf(stderr,"error: gmskframe_debug_print(), debugging objects don't exist; enable debugging first\n"); return; } FILE* fid = fopen(_filename,"w"); if (!fid) { fprintf(stderr, "error: gmskframesync_debug_print(), could not open '%s' for writing\n", _filename); return; } fprintf(fid,"%% %s: auto-generated file", _filename); fprintf(fid,"\n\n"); fprintf(fid,"clear all;\n"); fprintf(fid,"close all;\n\n"); fprintf(fid,"num_samples = %u;\n", DEBUG_GMSKFRAMESYNC_BUFFER_LEN); fprintf(fid,"t = 0:(num_samples-1);\n"); unsigned int i; float complex * rc; // write x fprintf(fid,"x = zeros(1,num_samples);\n"); windowcf_read(_q->debug_x, &rc); for (i=0; idebug_fi, &r); for (i=0; idebug_mf, &r); for (i=0; idebug_framesyms, &r); for (i=0; i #include #include #include // forward declaration of internal single source object and methods typedef struct QSOURCE(_s) * QSOURCE(); // internal structure (single source) struct QSOURCE(_s) { int id; // unique id union { // tone struct { int x; } tone; // wide-band noise struct { IIRFILT() filter; } noise; // linear modulation struct { SYMSTREAM() symstream; } linmod; } source; enum { QSOURCE_TONE, QSOURCE_NOISE, QSOURCE_MODEM, } type; nco_crcf mixer; float gain; int enabled; }; QSOURCE() QSOURCE(_create_tone)(int _id); QSOURCE() QSOURCE(_create_noise)(int _id, float _bandwidth); QSOURCE() QSOURCE(_create_modem)(int _id, int _ms, unsigned int _k, unsigned int _m, float _beta); void QSOURCE(_destroy)(QSOURCE() _q); void QSOURCE(_print)(QSOURCE() _q); void QSOURCE(_reset)(QSOURCE() _q); void QSOURCE(_enable)(QSOURCE() _q); void QSOURCE(_disable)(QSOURCE() _q); void QSOURCE(_set_gain)(QSOURCE() _q, float _gain_dB); void QSOURCE(_set_frequency)(QSOURCE() _q, float _dphi); void QSOURCE(_gen_sample)(QSOURCE() _q, TO * _v); // internal structure struct MSOURCE(_s) { QSOURCE() * sources; unsigned int num_sources; int id_counter; }; // // internal methods // // add source to list int MSOURCE(_add_source)(MSOURCE() _q, QSOURCE() _s); // create msource object with linear modulation MSOURCE() MSOURCE(_create)(void) { // allocate memory for main object MSOURCE() q = (MSOURCE()) malloc( sizeof(struct MSOURCE(_s)) ); // q->sources = NULL; q->num_sources = 0; q->id_counter = 0; // reset and return main object MSOURCE(_reset)(q); return q; } // destroy msource object, freeing all internal memory void MSOURCE(_destroy)(MSOURCE() _q) { // destroy internal objects unsigned int i; for (i=0; i<_q->num_sources; i++) QSOURCE(_destroy)(_q->sources[i]); // free list of sources free(_q->sources); // free main object free(_q); } // reset msource internal state void MSOURCE(_reset)(MSOURCE() _q) { } // print void MSOURCE(_print)(MSOURCE() _q) { printf("msource%s:\n", EXTENSION); unsigned int i; for (i=0; i<_q->num_sources; i++) QSOURCE(_print)(_q->sources[i]); } // add tone source int MSOURCE(_add_tone)(MSOURCE() _q) { int id = _q->id_counter; _q->id_counter++; QSOURCE() s = QSOURCE(_create_tone)(id); return MSOURCE(_add_source)(_q, s); } // add noise source int MSOURCE(_add_noise)(MSOURCE() _q, float _bandwidth) { // validate input if (_bandwidth <= 0.0f || _bandwidth > 1.0f) { fprintf(stderr,"error: msource%s_add_noise(), noise bandwidth must be in (0,1.0]\n", EXTENSION); exit(1); } else if (_bandwidth >= 0.9995f) { _bandwidth = 0.9995f; } int id = _q->id_counter; _q->id_counter++; QSOURCE() s = QSOURCE(_create_noise)(id, _bandwidth); return MSOURCE(_add_source)(_q, s); } // add modem source int MSOURCE(_add_modem)(MSOURCE() _q, int _ms, unsigned int _k, unsigned int _m, float _beta) { // validate input if (_k < 2) { fprintf(stderr,"error: msource%s_create(), samples/symbol must be at least 2\n", EXTENSION); exit(1); } else if (_m == 0) { fprintf(stderr,"error: msource%s_create(), filter delay must be greater than zero\n", EXTENSION); exit(1); } else if (_beta <= 0.0f || _beta > 1.0f) { fprintf(stderr,"error: msource%s_create(), filter excess bandwidth must be in (0,1]\n", EXTENSION); exit(1); } else if (_ms == LIQUID_MODEM_UNKNOWN || _ms >= LIQUID_MODEM_NUM_SCHEMES) { fprintf(stderr,"error: msource%s_create(), invalid modulation scheme\n", EXTENSION); exit(1); } int id = _q->id_counter; _q->id_counter++; QSOURCE() s = QSOURCE(_create_modem)(id, _ms, _k, _m, _beta); return MSOURCE(_add_source)(_q, s); } // remove signal void MSOURCE(_remove)(MSOURCE() _q, int _id) { // find source object matching id unsigned int i; int id_found = 0; for (i=0; i<_q->num_sources; i++) { if (_q->sources[i]->id == _id) { id_found = 1; break; } } // check to see if id was found if (!id_found) { fprintf(stderr,"error: qsource%s_remove(), signal id (%d) not found\n", EXTENSION, _id); exit(1); } // delete source //printf("deleting source with id %d (requested %d)\n", _q->sources[i]->id, _id); QSOURCE(_destroy)(_q->sources[i]); // _q->num_sources--; // shift sources down for (; i<_q->num_sources; i++) _q->sources[i] = _q->sources[i+1]; } // enable/disable signal void MSOURCE(_enable)(MSOURCE() _q, int _id) { // validate input if (_id > _q->num_sources) { fprintf(stderr,"error: qsource%s_enable(), signal id (%d) out of range (%u)\n", EXTENSION, _id, _q->num_sources); exit(1); } // set source gain QSOURCE(_enable)(_q->sources[_id]); } void MSOURCE(_disable)(MSOURCE() _q, int _id) { // validate input if (_id > _q->num_sources) { fprintf(stderr,"error: qsource%s_disable(), signal id (%d) out of range (%u)\n", EXTENSION, _id, _q->num_sources); exit(1); } // set source gain QSOURCE(_disable)(_q->sources[_id]); } // set signal gain // _q : msource object // _id : source id // _gain_dB: signal gain in dB void MSOURCE(_set_gain)(MSOURCE() _q, int _id, float _gain_dB) { // validate input if (_id > _q->num_sources) { fprintf(stderr,"error: qsource%s_set_gain(), signal id (%d) out of range (%u)\n", EXTENSION, _id, _q->num_sources); exit(1); } // set source gain QSOURCE(_set_gain)(_q->sources[_id], _gain_dB); } // set carrier offset to signal // _q : msource object // _id : source id // _fc : carrier offset, fc in [-0.5,0.5] void MSOURCE(_set_frequency)(MSOURCE() _q, int _id, float _dphi) { // validate input if (_id > _q->num_sources) { fprintf(stderr,"error: qsource%s_set_frequency(), signal id (%d) out of range (%u)\n", EXTENSION, _id, _q->num_sources); exit(1); } // set source frequency QSOURCE(_set_frequency)(_q->sources[_id], _dphi); } // write block of samples to output buffer // _q : synchronizer object // _buf : output buffer [size: _buf_len x 1] // _buf_len: output buffer size void MSOURCE(_write_samples)(MSOURCE() _q, TO * _buf, unsigned int _buf_len) { TO sample; TO accumulation; unsigned int i; unsigned int j; for (i=0; i<_buf_len; i++) { accumulation = 0; for (j=0; j<_q->num_sources; j++) { QSOURCE(_gen_sample)(_q->sources[j], &sample); accumulation += sample; } _buf[i] = accumulation; } } // // internal msource methods // // add source to list int MSOURCE(_add_source)(MSOURCE() _q, QSOURCE() _s) { if (_s == NULL) return -1; // reallocate if (_q->num_sources == 0) { _q->sources = (QSOURCE()*) malloc(sizeof(QSOURCE())); } else { _q->sources = (QSOURCE()*) realloc(_q->sources, (_q->num_sources+1)*sizeof(QSOURCE())); } // append new object to end of list _q->sources[_q->num_sources] = _s; // _q->num_sources++; // return _q->num_sources-1; } // get source by id QSOURCE() MSOURCE(_get_source)(MSOURCE() _q, int _id) { unsigned int i; for (i=0; i<_q->num_sources; i++) { if (_q->sources[i]->id == _id) return _q->sources[i]; } return NULL; } // // internal qsource // QSOURCE() QSOURCE(_create_tone)(int _id) { // allocate memory for main object QSOURCE() q = (QSOURCE()) malloc( sizeof(struct QSOURCE(_s)) ); q->id = _id; q->type = QSOURCE_TONE; q->mixer = NCO(_create)(LIQUID_VCO); q->gain = 1; q->enabled = 1; // reset and return main object QSOURCE(_reset)(q); return q; } QSOURCE() QSOURCE(_create_noise)(int _id, float _bandwidth) { // TODO: validate input // allocate memory for main object QSOURCE() q = (QSOURCE()) malloc( sizeof(struct QSOURCE(_s)) ); q->id = _id; q->type = QSOURCE_NOISE; unsigned int order = 7; q->source.noise.filter = IIRFILT(_create_prototype)(LIQUID_IIRDES_ELLIP, LIQUID_IIRDES_LOWPASS, LIQUID_IIRDES_SOS, order, 0.5*_bandwidth, 0.0f, 0.1f, 80.0f); q->mixer = NCO(_create)(LIQUID_VCO); q->gain = 1; q->enabled = 1; // reset and return main object QSOURCE(_reset)(q); return q; } QSOURCE() QSOURCE(_create_modem)(int _id, int _ms, unsigned int _k, unsigned int _m, float _beta) { // allocate memory for main object QSOURCE() q = (QSOURCE()) malloc( sizeof(struct QSOURCE(_s)) ); q->id = _id; q->type = QSOURCE_MODEM; q->source.linmod.symstream=SYMSTREAM(_create_linear)(LIQUID_FIRFILT_ARKAISER,_k,_m,_beta,_ms); q->mixer = NCO(_create)(LIQUID_VCO); q->gain = 1; q->enabled = 1; // reset and return main object QSOURCE(_reset)(q); return q; } void QSOURCE(_print)(QSOURCE() _q) { printf(" qsource%s[%3d] : ", EXTENSION, _q->id); // print type-specific parameters switch (_q->type) { case QSOURCE_TONE: printf("tone\n"); break; case QSOURCE_NOISE: printf("noise\n"); break; case QSOURCE_MODEM: printf("modem\n"); break; default: fprintf(stderr,"error: qsource%s_print(), internal logic error\n", EXTENSION); exit(1); } } void QSOURCE(_destroy)(QSOURCE() _q) { // free internal type-specific objects switch (_q->type) { case QSOURCE_TONE: break; case QSOURCE_NOISE: IIRFILT(_destroy)(_q->source.noise.filter); break; case QSOURCE_MODEM: SYMSTREAM(_destroy)(_q->source.linmod.symstream); break; default: fprintf(stderr,"error: qsource%s_destroy(), internal logic error\n", EXTENSION); exit(1); } // destroy mixer object NCO(_destroy)(_q->mixer); // free main object memory free(_q); } void QSOURCE(_reset)(QSOURCE() _q) { } void QSOURCE(_enable)(QSOURCE() _q) { _q->enabled = 1; } void QSOURCE(_disable)(QSOURCE() _q) { _q->enabled = 0; } void QSOURCE(_set_gain)(QSOURCE() _q, float _gain_dB) { // convert from dB _q->gain = powf(10.0f, _gain_dB/20.0f); } void QSOURCE(_set_frequency)(QSOURCE() _q, float _dphi) { NCO(_set_frequency)(_q->mixer, _dphi); } void QSOURCE(_gen_sample)(QSOURCE() _q, TO * _v) { TO sample; // free internal type-specific objects switch (_q->type) { case QSOURCE_TONE: sample = 1.0f; break; case QSOURCE_NOISE: IIRFILT(_execute)(_q->source.noise.filter, (randnf() + _Complex_I*randnf())*M_SQRT1_2, &sample); break; case QSOURCE_MODEM: SYMSTREAM(_write_samples)(_q->source.linmod.symstream, &sample, 1); break; default: fprintf(stderr,"error: qsource%s_gen_sample(), internal logic error\n", EXTENSION); exit(1); } if (!_q->enabled) sample = 0.0f; // apply gain sample *= _q->gain; // mix sample up NCO(_mix_up)(_q->mixer, sample, _v); // step mixer NCO(_step)(_q->mixer); } liquid-dsp-1.3.1/src/framing/src/msourcecf.c000066400000000000000000000034231317124540100207220ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // API: floating-point // #include "liquid.internal.h" // naming extensions (useful for print statements) #define EXTENSION "cf" #define TO float complex // output type #define T float // primitive type #define TO_COMPLEX 1 #define T_COMPLEX 0 // object references #define QSOURCE(name) LIQUID_CONCAT(qsourcecf,name) #define MSOURCE(name) LIQUID_CONCAT(msourcecf,name) #define IIRFILT(name) LIQUID_CONCAT(iirfilt_crcf,name) #define NCO(name) LIQUID_CONCAT(nco_crcf,name) #define SYMSTREAM(name) LIQUID_CONCAT(symstreamcf,name) // source files #include "msource.c" liquid-dsp-1.3.1/src/framing/src/ofdmflexframegen.c000066400000000000000000000620151317124540100222470ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2016 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // ofdmflexframegen.c // // OFDM flexible frame generator // #include #include #include #include #include #include "liquid.internal.h" #define DEBUG_OFDMFLEXFRAMEGEN 0 // reconfigure internal buffers, objects, etc. void ofdmflexframegen_reconfigure(ofdmflexframegen _q); // encode header void ofdmflexframegen_encode_header(ofdmflexframegen _q); // modulate header void ofdmflexframegen_modulate_header(ofdmflexframegen _q); // generate samples of assembled frame (internally) void ofdmflexframegen_gen_symbol (ofdmflexframegen _q); // (generic) void ofdmflexframegen_gen_S0a (ofdmflexframegen _q); // generate S0 symbol (first) void ofdmflexframegen_gen_S0b (ofdmflexframegen _q); // generate S0 symbol (second) void ofdmflexframegen_gen_S1 (ofdmflexframegen _q); // generate S1 symbol void ofdmflexframegen_gen_header (ofdmflexframegen _q); // generate header symbol void ofdmflexframegen_gen_payload(ofdmflexframegen _q); // generate payload symbol void ofdmflexframegen_gen_tail (ofdmflexframegen _q); // generate tail symbol void ofdmflexframegen_gen_zeros (ofdmflexframegen _q); // generate zeros // default ofdmflexframegen properties static ofdmflexframegenprops_s ofdmflexframegenprops_default = { LIQUID_CRC_32, // check LIQUID_FEC_NONE, // fec0 LIQUID_FEC_NONE, // fec1 LIQUID_MODEM_QPSK, // mod_scheme //64 // block_size }; void ofdmflexframegenprops_init_default(ofdmflexframegenprops_s * _props) { memmove(_props, &ofdmflexframegenprops_default, sizeof(ofdmflexframegenprops_s)); } struct ofdmflexframegen_s { unsigned int M; // number of subcarriers unsigned int cp_len; // cyclic prefix length unsigned int taper_len; // taper length unsigned char * p; // subcarrier allocation (null, pilot, data) // constants unsigned int M_null; // number of null subcarriers unsigned int M_pilot; // number of pilot subcarriers unsigned int M_data; // number of data subcarriers unsigned int M_S0; // number of enabled subcarriers in S0 unsigned int M_S1; // number of enabled subcarriers in S1 unsigned int frame_len; // frame length (M + cp_len) // buffers float complex * X; // frequency-domain buffer float complex * buf_tx; // transmit buffer unsigned int buf_index; // buffer index // internal low-level objects ofdmframegen fg; // frame generator object // options/derived lengths unsigned int num_symbols_header; // number of header OFDM symbols unsigned int num_symbols_payload; // number of payload OFDM symbols // header modem mod_header; // header modulator packetizer p_header; // header packetizer unsigned char header[OFDMFLEXFRAME_H_DEC]; // header data (uncoded) unsigned char header_enc[OFDMFLEXFRAME_H_ENC]; // header data (encoded) unsigned char header_mod[OFDMFLEXFRAME_H_SYM]; // header symbols // payload packetizer p_payload; // payload packetizer unsigned int payload_dec_len; // payload length (num un-encoded bytes) modem mod_payload; // payload modulator unsigned char * payload_enc; // payload data (encoded bytes) unsigned char * payload_mod; // payload data (modulated symbols) unsigned int payload_enc_len; // length of encoded payload unsigned int payload_mod_len; // number of modulated symbols in payload // counters/states unsigned int symbol_number; // output symbol number enum { OFDMFLEXFRAMEGEN_STATE_S0a=0, // write S0 symbol (first) OFDMFLEXFRAMEGEN_STATE_S0b, // write S0 symbol (second) OFDMFLEXFRAMEGEN_STATE_S1, // write S1 symbol OFDMFLEXFRAMEGEN_STATE_HEADER, // write header symbols OFDMFLEXFRAMEGEN_STATE_PAYLOAD, // write payload symbols OFDMFLEXFRAMEGEN_STATE_TAIL, // write tail of last symbol OFDMFLEXFRAMEGEN_STATE_ZEROS // write zeros } state; int frame_assembled; // frame assembled flag int frame_complete; // frame completed flag unsigned int header_symbol_index; // unsigned int payload_symbol_index; // // properties ofdmflexframegenprops_s props; }; // create OFDM flexible framing generator object // _M : number of subcarriers, >10 typical // _cp_len : cyclic prefix length // _taper_len : taper length (OFDM symbol overlap) // _p : subcarrier allocation (null, pilot, data), [size: _M x 1] // _fgprops : frame properties (modulation scheme, etc.) ofdmflexframegen ofdmflexframegen_create(unsigned int _M, unsigned int _cp_len, unsigned int _taper_len, unsigned char * _p, ofdmflexframegenprops_s * _fgprops) { // validate input if (_M < 2) { fprintf(stderr,"error: ofdmflexframegen_create(), number of subcarriers must be at least 2\n"); exit(1); } else if (_M % 2) { fprintf(stderr,"error: ofdmflexframegen_create(), number of subcarriers must be even\n"); exit(1); } ofdmflexframegen q = (ofdmflexframegen) malloc(sizeof(struct ofdmflexframegen_s)); q->M = _M; // number of subcarriers q->cp_len = _cp_len; // cyclic prefix length q->taper_len = _taper_len; // taper length // allocate memory for transform buffers q->frame_len = q->M + q->cp_len; // frame length q->X = (float complex*) malloc((q->M )*sizeof(float complex)); q->buf_tx = (float complex*) malloc((q->frame_len)*sizeof(float complex)); q->buf_index = q->frame_len; // allocate memory for subcarrier allocation IDs q->p = (unsigned char*) malloc((q->M)*sizeof(unsigned char)); if (_p == NULL) { // initialize default subcarrier allocation ofdmframe_init_default_sctype(q->M, q->p); } else { // copy user-defined subcarrier allocation memmove(q->p, _p, q->M*sizeof(unsigned char)); } // validate and count subcarrier allocation ofdmframe_validate_sctype(q->p, q->M, &q->M_null, &q->M_pilot, &q->M_data); // create internal OFDM frame generator object q->fg = ofdmframegen_create(q->M, q->cp_len, q->taper_len, q->p); // create header objects q->mod_header = modem_create(OFDMFLEXFRAME_H_MOD); q->p_header = packetizer_create(OFDMFLEXFRAME_H_DEC, OFDMFLEXFRAME_H_CRC, OFDMFLEXFRAME_H_FEC, LIQUID_FEC_NONE); assert(packetizer_get_enc_msg_len(q->p_header)==OFDMFLEXFRAME_H_ENC); // compute number of header symbols div_t d = div(OFDMFLEXFRAME_H_SYM, q->M_data); q->num_symbols_header = d.quot + (d.rem ? 1 : 0); // initial memory allocation for payload q->payload_dec_len = 1; q->p_payload = packetizer_create(q->payload_dec_len, LIQUID_CRC_NONE, LIQUID_FEC_NONE, LIQUID_FEC_NONE); q->payload_enc_len = packetizer_get_enc_msg_len(q->p_payload); q->payload_enc = (unsigned char*) malloc(q->payload_enc_len*sizeof(unsigned char)); q->payload_mod_len = 1; q->payload_mod = (unsigned char*) malloc(q->payload_mod_len*sizeof(unsigned char)); // create payload modem (initially QPSK, overridden by properties) q->mod_payload = modem_create(LIQUID_MODEM_QPSK); // initialize properties ofdmflexframegen_setprops(q, _fgprops); // reset ofdmflexframegen_reset(q); // return pointer to main object return q; } void ofdmflexframegen_destroy(ofdmflexframegen _q) { // destroy internal objects ofdmframegen_destroy(_q->fg); // OFDM frame generator packetizer_destroy(_q->p_header); // header packetizer modem_destroy(_q->mod_header); // header modulator packetizer_destroy(_q->p_payload); // payload packetizer modem_destroy(_q->mod_payload); // payload modulator // free buffers/arrays free(_q->payload_enc); // encoded payload bytes free(_q->payload_mod); // modulated payload symbols free(_q->X); // frequency-domain buffer free(_q->buf_tx); // transmit buffer free(_q->p); // subcarrier allocation // free main object memory free(_q); } void ofdmflexframegen_reset(ofdmflexframegen _q) { // reset symbol counter and state _q->symbol_number = 0; _q->state = OFDMFLEXFRAMEGEN_STATE_S0a; _q->frame_assembled = 0; _q->frame_complete = 0; _q->header_symbol_index = 0; _q->payload_symbol_index = 0; _q->buf_index = _q->frame_len; // reset internal OFDM frame generator object // NOTE: this is important for appropriately setting the pilot phases ofdmframegen_reset(_q->fg); } // is frame assembled? int ofdmflexframegen_is_assembled(ofdmflexframegen _q) { return _q->frame_assembled; } void ofdmflexframegen_print(ofdmflexframegen _q) { printf("ofdmflexframegen:\n"); printf(" num subcarriers : %-u\n", _q->M); printf(" * NULL : %-u\n", _q->M_null); printf(" * pilot : %-u\n", _q->M_pilot); printf(" * data : %-u\n", _q->M_data); printf(" cyclic prefix len : %-u\n", _q->cp_len); printf(" taper len : %-u\n", _q->taper_len); printf(" properties:\n"); printf(" * mod scheme : %s\n", modulation_types[_q->props.mod_scheme].fullname); printf(" * fec (inner) : %s\n", fec_scheme_str[_q->props.fec0][1]); printf(" * fec (outer) : %s\n", fec_scheme_str[_q->props.fec1][1]); printf(" * CRC scheme : %s\n", crc_scheme_str[_q->props.check][1]); printf(" frame assembled : %s\n", _q->frame_assembled ? "yes" : "no"); if (_q->frame_assembled) { printf(" payload:\n"); printf(" * decoded bytes : %-u\n", _q->payload_dec_len); printf(" * encoded bytes : %-u\n", _q->payload_enc_len); printf(" * modulated syms : %-u\n", _q->payload_mod_len); printf(" total OFDM symbols : %-u\n", ofdmflexframegen_getframelen(_q)); printf(" * S0 symbols : %-u @ %u\n", 2, _q->M+_q->cp_len); printf(" * S1 symbols : %-u @ %u\n", 1, _q->M+_q->cp_len); printf(" * header symbols : %-u @ %u\n", _q->num_symbols_header, _q->M+_q->cp_len); printf(" * payload symbols : %-u @ %u\n", _q->num_symbols_payload, _q->M+_q->cp_len); // compute asymptotic spectral efficiency unsigned int num_bits = 8*_q->payload_dec_len; unsigned int num_samples = (_q->M+_q->cp_len)*(3 + _q->num_symbols_header + _q->num_symbols_payload); printf(" spectral efficiency : %-6.4f b/s/Hz\n", (float)num_bits / (float)num_samples); } } // get ofdmflexframegen properties // _q : frame generator object // _props : frame generator properties structure pointer void ofdmflexframegen_getprops(ofdmflexframegen _q, ofdmflexframegenprops_s * _props) { // copy properties structure to output pointer memmove(_props, &_q->props, sizeof(ofdmflexframegenprops_s)); } void ofdmflexframegen_setprops(ofdmflexframegen _q, ofdmflexframegenprops_s * _props) { // if properties object is NULL, initialize with defaults if (_props == NULL) { ofdmflexframegen_setprops(_q, &ofdmflexframegenprops_default); return; } // validate input if (_props->check == LIQUID_CRC_UNKNOWN || _props->check >= LIQUID_CRC_NUM_SCHEMES) { fprintf(stderr, "error: ofdmflexframegen_setprops(), invalid/unsupported CRC scheme\n"); exit(1); } else if (_props->fec0 == LIQUID_FEC_UNKNOWN || _props->fec1 == LIQUID_FEC_UNKNOWN) { fprintf(stderr, "error: ofdmflexframegen_setprops(), invalid/unsupported FEC scheme\n"); exit(1); } else if (_props->mod_scheme == LIQUID_MODEM_UNKNOWN ) { fprintf(stderr, "error: ofdmflexframegen_setprops(), invalid/unsupported modulation scheme\n"); exit(1); } // TODO : determine if re-configuration is necessary // copy properties to internal structure memmove(&_q->props, _props, sizeof(ofdmflexframegenprops_s)); // reconfigure internal buffers, objects, etc. ofdmflexframegen_reconfigure(_q); } // get length of frame (symbols) // _q : OFDM frame generator object unsigned int ofdmflexframegen_getframelen(ofdmflexframegen _q) { // number of S0 symbols (2) // number of S1 symbols (1) // number of header symbols // number of payload symbols return 2 + // S0 symbols 1 + // S1 symbol _q->num_symbols_header + _q->num_symbols_payload; } // assemble a frame from an array of data (NULL pointers will use random data) // _q : OFDM frame generator object // _header : frame header // _payload : payload data [size: _payload_len x 1] // _payload_len : payload data length void ofdmflexframegen_assemble(ofdmflexframegen _q, const unsigned char * _header, const unsigned char * _payload, unsigned int _payload_len) { // reset state ofdmflexframegen_reset(_q); // check payload length and reconfigure if necessary if (_payload_len != _q->payload_dec_len) { _q->payload_dec_len = _payload_len; ofdmflexframegen_reconfigure(_q); } // set assembled flag _q->frame_assembled = 1; // copy user-defined header data if (_header == NULL) memset(_q->header, 0x00, OFDMFLEXFRAME_H_USER*sizeof(unsigned char)); else memmove(_q->header, _header, OFDMFLEXFRAME_H_USER*sizeof(unsigned char)); // encode full header ofdmflexframegen_encode_header(_q); // modulate header ofdmflexframegen_modulate_header(_q); // encode payload packetizer_encode(_q->p_payload, _payload, _q->payload_enc); // // pack modem symbols // // clear payload memset(_q->payload_mod, 0x00, _q->payload_mod_len); // repack 8-bit payload bytes into 'bps'-bit payload symbols unsigned int bps = modulation_types[_q->props.mod_scheme].bps; unsigned int num_written; liquid_repack_bytes(_q->payload_enc, 8, _q->payload_enc_len, _q->payload_mod, bps, _q->payload_mod_len, &num_written); #if DEBUG_OFDMFLEXFRAMEGEN printf("wrote %u symbols (expected %u)\n", num_written, _q->payload_mod_len); #endif } // write samples of assembled frame // _q : OFDM frame generator object // _buf : output buffer [size: _buf_len x 1] // _buf_len : output buffer length int ofdmflexframegen_write(ofdmflexframegen _q, float complex * _buf, unsigned int _buf_len) { unsigned int i; for (i=0; i<_buf_len; i++) { if (_q->buf_index >= _q->frame_len) { ofdmflexframegen_gen_symbol(_q); _q->buf_index = 0; } // TODO: write samples appropriately _buf[i] = _q->buf_tx[_q->buf_index++]; } return _q->frame_complete; } // // internal // // reconfigure internal buffers, objects, etc. void ofdmflexframegen_reconfigure(ofdmflexframegen _q) { // re-create payload packetizer _q->p_payload = packetizer_recreate(_q->p_payload, _q->payload_dec_len, _q->props.check, _q->props.fec0, _q->props.fec1); // re-allocate memory for encoded message _q->payload_enc_len = packetizer_get_enc_msg_len(_q->p_payload); _q->payload_enc = (unsigned char*) realloc(_q->payload_enc, _q->payload_enc_len*sizeof(unsigned char)); #if DEBUG_OFDMFLEXFRAMEGEN //printf(">>>> payload : %u (%u encoded)\n", _q->props.payload_len, _q->payload_enc_len); #endif // re-create modem // TODO : only do this if necessary _q->mod_payload = modem_recreate(_q->mod_payload, _q->props.mod_scheme); // re-allocate memory for payload modem symbols unsigned int bps = modulation_types[_q->props.mod_scheme].bps; div_t d = div(8*_q->payload_enc_len, bps); _q->payload_mod_len = d.quot + (d.rem ? 1 : 0); _q->payload_mod = (unsigned char*)realloc(_q->payload_mod, _q->payload_mod_len*sizeof(unsigned char)); // re-compute number of payload OFDM symbols d = div(_q->payload_mod_len, _q->M_data); _q->num_symbols_payload = d.quot + (d.rem ? 1 : 0); } // encode header void ofdmflexframegen_encode_header(ofdmflexframegen _q) { // first 'n' bytes user data unsigned int n = OFDMFLEXFRAME_H_USER; // first byte is for expansion/version validation _q->header[n+0] = OFDMFLEXFRAME_PROTOCOL; // add payload length _q->header[n+1] = (_q->payload_dec_len >> 8) & 0xff; _q->header[n+2] = (_q->payload_dec_len ) & 0xff; // add modulation scheme/depth (pack into single byte) _q->header[n+3] = _q->props.mod_scheme; // add CRC, forward error-correction schemes // CRC : most-significant 3 bits of [n+4] // fec0 : least-significant 5 bits of [n+4] // fec1 : least-significant 5 bits of [n+5] _q->header[n+4] = (_q->props.check & 0x07) << 5; _q->header[n+4] |= (_q->props.fec0) & 0x1f; _q->header[n+5] = (_q->props.fec1) & 0x1f; // run packet encoder packetizer_encode(_q->p_header, _q->header, _q->header_enc); // scramble header scramble_data(_q->header_enc, OFDMFLEXFRAME_H_ENC); #if 0 // print header (decoded) unsigned int i; printf("header tx (dec) : "); for (i=0; iheader[i]); printf("\n"); // print header (encoded) printf("header tx (enc) : "); for (i=0; iheader_enc[i]); printf("\n"); #endif } // modulate header void ofdmflexframegen_modulate_header(ofdmflexframegen _q) { // repack 8-bit header bytes into 'bps'-bit payload symbols unsigned int bps = modulation_types[OFDMFLEXFRAME_H_MOD].bps; unsigned int num_written; liquid_repack_bytes(_q->header_enc, 8, OFDMFLEXFRAME_H_ENC, _q->header_mod, bps, OFDMFLEXFRAME_H_SYM, &num_written); } // generate transmit samples (fill internal buffer) void ofdmflexframegen_gen_symbol(ofdmflexframegen _q) { // increment symbol counter _q->symbol_number++; switch (_q->state) { case OFDMFLEXFRAMEGEN_STATE_S0a: ofdmflexframegen_gen_S0a (_q); break; case OFDMFLEXFRAMEGEN_STATE_S0b: ofdmflexframegen_gen_S0b (_q); break; case OFDMFLEXFRAMEGEN_STATE_S1: ofdmflexframegen_gen_S1 (_q); break; case OFDMFLEXFRAMEGEN_STATE_HEADER: ofdmflexframegen_gen_header (_q); break; case OFDMFLEXFRAMEGEN_STATE_PAYLOAD: ofdmflexframegen_gen_payload(_q); break; case OFDMFLEXFRAMEGEN_STATE_TAIL: ofdmflexframegen_gen_tail (_q); break; case OFDMFLEXFRAMEGEN_STATE_ZEROS: ofdmflexframegen_gen_zeros (_q); break; default: fprintf(stderr,"error: ofdmflexframegen_writesymbol(), unknown/unsupported internal state\n"); exit(1); } } // write first S0 symbol void ofdmflexframegen_gen_S0a(ofdmflexframegen _q) { #if DEBUG_OFDMFLEXFRAMEGEN printf("writing S0[a] symbol\n"); #endif // write S0 symbol into front of buffer ofdmframegen_write_S0a(_q->fg, _q->buf_tx); // update state _q->state = OFDMFLEXFRAMEGEN_STATE_S0b; } // write second S0 symbol void ofdmflexframegen_gen_S0b(ofdmflexframegen _q) { #if DEBUG_OFDMFLEXFRAMEGEN printf("writing S0[b] symbol\n"); #endif // write S0 symbol into front of buffer ofdmframegen_write_S0b(_q->fg, _q->buf_tx); // update state _q->state = OFDMFLEXFRAMEGEN_STATE_S1; } // write S1 symbol void ofdmflexframegen_gen_S1(ofdmflexframegen _q) { #if DEBUG_OFDMFLEXFRAMEGEN printf("writing S1 symbol\n"); #endif // write S1 symbol into end of buffer ofdmframegen_write_S1(_q->fg, _q->buf_tx); // update state _q->symbol_number = 0; _q->state = OFDMFLEXFRAMEGEN_STATE_HEADER; } // write header symbol void ofdmflexframegen_gen_header(ofdmflexframegen _q) { #if DEBUG_OFDMFLEXFRAMEGEN printf("writing header symbol\n"); #endif // load data onto data subcarriers unsigned int i; int sctype; for (i=0; i<_q->M; i++) { // sctype = _q->p[i]; // if (sctype == OFDMFRAME_SCTYPE_DATA) { // load... if (_q->header_symbol_index < OFDMFLEXFRAME_H_SYM) { // modulate header symbol onto data subcarrier modem_modulate(_q->mod_header, _q->header_mod[_q->header_symbol_index++], &_q->X[i]); //printf(" writing symbol %3u / %3u (x = %8.5f + j%8.5f)\n", _q->header_symbol_index, OFDMFLEXFRAME_H_SYM, crealf(_q->X[i]), cimagf(_q->X[i])); } else { //printf(" random header symbol\n"); // load random symbol unsigned int sym = modem_gen_rand_sym(_q->mod_header); modem_modulate(_q->mod_header, sym, &_q->X[i]); } } else { // ignore subcarrier (ofdmframegen handles nulls and pilots) _q->X[i] = 0.0f; } } // write symbol ofdmframegen_writesymbol(_q->fg, _q->X, _q->buf_tx); // check state if (_q->symbol_number == _q->num_symbols_header) { _q->symbol_number = 0; _q->state = OFDMFLEXFRAMEGEN_STATE_PAYLOAD; } } // write payload symbol void ofdmflexframegen_gen_payload(ofdmflexframegen _q) { #if DEBUG_OFDMFLEXFRAMEGEN printf("writing payload symbol\n"); #endif // load data onto data subcarriers unsigned int i; int sctype; for (i=0; i<_q->M; i++) { // sctype = _q->p[i]; // if (sctype == OFDMFRAME_SCTYPE_DATA) { // load... if (_q->payload_symbol_index < _q->payload_mod_len) { // modulate payload symbol onto data subcarrier modem_modulate(_q->mod_payload, _q->payload_mod[_q->payload_symbol_index++], &_q->X[i]); } else { //printf(" random payload symbol\n"); // load random symbol unsigned int sym = modem_gen_rand_sym(_q->mod_payload); modem_modulate(_q->mod_payload, sym, &_q->X[i]); } } else { // ignore subcarrier (ofdmframegen handles nulls and pilots) _q->X[i] = 0.0f; } } // write symbol ofdmframegen_writesymbol(_q->fg, _q->X, _q->buf_tx); // check to see if this is the last symbol in the payload if (_q->symbol_number == _q->num_symbols_payload) _q->state = OFDMFLEXFRAMEGEN_STATE_TAIL; } // generate buffer of zeros void ofdmflexframegen_gen_tail(ofdmflexframegen _q) { #if DEBUG_OFDMFLEXFRAMEGEN printf("writing tail\n"); #endif // initialize buffer with zeros unsigned int i; for (i=0; i<_q->frame_len; i++) _q->buf_tx[i] = 0.0f; // write taper_len samples to buffer ofdmframegen_writetail(_q->fg, _q->buf_tx); // mark frame as complete _q->frame_complete = 1; _q->frame_assembled = 0; _q->state = OFDMFLEXFRAMEGEN_STATE_ZEROS; } // generate buffer of zeros void ofdmflexframegen_gen_zeros(ofdmflexframegen _q) { #if DEBUG_OFDMFLEXFRAMEGEN printf("writing zeros\n"); #endif unsigned int i; for (i=0; i<_q->frame_len; i++) _q->buf_tx[i] = 0.0f; } liquid-dsp-1.3.1/src/framing/src/ofdmflexframesync.c000066400000000000000000000571701317124540100224600ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // ofdmflexframesync.c // // OFDM frame synchronizer // #include #include #include #include #include #include "liquid.internal.h" #define DEBUG_OFDMFLEXFRAMESYNC 0 #define OFDMFLEXFRAME_H_SOFT (0) // // ofdmflexframesync // // internal callback int ofdmflexframesync_internal_callback(float complex * _X, unsigned char * _p, unsigned int _M, void * _userdata); // receive header data void ofdmflexframesync_rxheader(ofdmflexframesync _q, float complex * _X); // decode header void ofdmflexframesync_decode_header(ofdmflexframesync _q); // receive payload data void ofdmflexframesync_rxpayload(ofdmflexframesync _q, float complex * _X); struct ofdmflexframesync_s { unsigned int M; // number of subcarriers unsigned int cp_len; // cyclic prefix length unsigned int taper_len; // taper length unsigned char * p; // subcarrier allocation (null, pilot, data) // constants unsigned int M_null; // number of null subcarriers unsigned int M_pilot; // number of pilot subcarriers unsigned int M_data; // number of data subcarriers unsigned int M_S0; // number of enabled subcarriers in S0 unsigned int M_S1; // number of enabled subcarriers in S1 // header modem mod_header; // header modulator packetizer p_header; // header packetizer unsigned char header[OFDMFLEXFRAME_H_DEC]; // header data (uncoded) #if OFDMFLEXFRAME_H_SOFT unsigned char header_enc[8*OFDMFLEXFRAME_H_ENC]; // header data (encoded, soft bits) unsigned char header_mod[OFDMFLEXFRAME_H_BPS*OFDMFLEXFRAME_H_SYM]; // header symbols (soft bits) #else unsigned char header_enc[OFDMFLEXFRAME_H_ENC]; // header data (encoded) unsigned char header_mod[OFDMFLEXFRAME_H_SYM]; // header symbols #endif int header_valid; // valid header flag // header properties modulation_scheme ms_payload; // payload modulation scheme unsigned int bps_payload; // payload modulation depth (bits/symbol) unsigned int payload_len; // payload length (number of bytes) crc_scheme check; // payload validity check fec_scheme fec0; // payload FEC (inner) fec_scheme fec1; // payload FEC (outer) // payload packetizer p_payload; // payload packetizer modem mod_payload; // payload demodulator unsigned char * payload_enc; // payload data (encoded bytes) unsigned char * payload_dec; // payload data (decoded bytes) unsigned int payload_enc_len; // length of encoded payload unsigned int payload_mod_len; // number of payload modem symbols int payload_valid; // valid payload flag float complex * payload_syms; // received payload symbols // callback framesync_callback callback; // user-defined callback function void * userdata; // user-defined data structure framesyncstats_s framestats; // frame statistic object float evm_hat; // average error vector magnitude // internal synchronizer objects ofdmframesync fs; // internal OFDM frame synchronizer // counters/states unsigned int symbol_counter; // received symbol number enum { OFDMFLEXFRAMESYNC_STATE_HEADER, // extract header OFDMFLEXFRAMESYNC_STATE_PAYLOAD // extract payload symbols } state; unsigned int header_symbol_index; // number of header symbols received unsigned int payload_symbol_index; // number of payload symbols received unsigned int payload_buffer_index; // bit-level index of payload (pack array) }; // create ofdmflexframesync object // _M : number of subcarriers // _cp_len : length of cyclic prefix [samples] // _taper_len : taper length (OFDM symbol overlap) // _p : subcarrier allocation (PILOT/NULL/DATA) [size: _M x 1] // _callback : user-defined callback function // _userdata : user-defined data structure passed to callback ofdmflexframesync ofdmflexframesync_create(unsigned int _M, unsigned int _cp_len, unsigned int _taper_len, unsigned char * _p, framesync_callback _callback, void * _userdata) { ofdmflexframesync q = (ofdmflexframesync) malloc(sizeof(struct ofdmflexframesync_s)); // validate input if (_M < 8) { fprintf(stderr,"warning: ofdmflexframesync_create(), less than 8 subcarriers\n"); } else if (_M % 2) { fprintf(stderr,"error: ofdmflexframesync_create(), number of subcarriers must be even\n"); exit(1); } else if (_cp_len > _M) { fprintf(stderr,"error: ofdmflexframesync_create(), cyclic prefix length cannot exceed number of subcarriers\n"); exit(1); } // set internal properties q->M = _M; q->cp_len = _cp_len; q->taper_len = _taper_len; q->callback = _callback; q->userdata = _userdata; // allocate memory for subcarrier allocation IDs q->p = (unsigned char*) malloc((q->M)*sizeof(unsigned char)); if (_p == NULL) { // initialize default subcarrier allocation ofdmframe_init_default_sctype(q->M, q->p); } else { // copy user-defined subcarrier allocation memmove(q->p, _p, q->M*sizeof(unsigned char)); } // validate and count subcarrier allocation ofdmframe_validate_sctype(q->p, q->M, &q->M_null, &q->M_pilot, &q->M_data); // create internal framing object q->fs = ofdmframesync_create(_M, _cp_len, _taper_len, _p, ofdmflexframesync_internal_callback, (void*)q); // create header objects q->mod_header = modem_create(OFDMFLEXFRAME_H_MOD); q->p_header = packetizer_create(OFDMFLEXFRAME_H_DEC, OFDMFLEXFRAME_H_CRC, OFDMFLEXFRAME_H_FEC, LIQUID_FEC_NONE); assert(packetizer_get_enc_msg_len(q->p_header)==OFDMFLEXFRAME_H_ENC); // frame properties (default values to be overwritten when frame // header is received and properly decoded) q->ms_payload = LIQUID_MODEM_QPSK; q->bps_payload = 2; q->payload_len = 1; q->check = LIQUID_CRC_NONE; q->fec0 = LIQUID_FEC_NONE; q->fec1 = LIQUID_FEC_NONE; // create payload objects (initally QPSK, etc but overridden by received properties) q->mod_payload = modem_create(q->ms_payload); q->p_payload = packetizer_create(q->payload_len, q->check, q->fec0, q->fec1); q->payload_enc_len = packetizer_get_enc_msg_len(q->p_payload); q->payload_enc = (unsigned char*) malloc(q->payload_enc_len*sizeof(unsigned char)); q->payload_dec = (unsigned char*) malloc(q->payload_len*sizeof(unsigned char)); q->payload_syms = (float complex *) malloc(q->payload_len*sizeof(float complex)); q->payload_mod_len = 0; // reset state ofdmflexframesync_reset(q); // return object return q; } void ofdmflexframesync_destroy(ofdmflexframesync _q) { // destroy internal objects ofdmframesync_destroy(_q->fs); packetizer_destroy(_q->p_header); modem_destroy(_q->mod_header); packetizer_destroy(_q->p_payload); modem_destroy(_q->mod_payload); // free internal buffers/arrays free(_q->p); free(_q->payload_enc); free(_q->payload_dec); free(_q->payload_syms); // free main object memory free(_q); } void ofdmflexframesync_print(ofdmflexframesync _q) { printf("ofdmflexframesync:\n"); printf(" num subcarriers : %-u\n", _q->M); printf(" * NULL : %-u\n", _q->M_null); printf(" * pilot : %-u\n", _q->M_pilot); printf(" * data : %-u\n", _q->M_data); printf(" cyclic prefix len : %-u\n", _q->cp_len); printf(" taper len : %-u\n", _q->taper_len); } void ofdmflexframesync_reset(ofdmflexframesync _q) { // reset internal state _q->state = OFDMFLEXFRAMESYNC_STATE_HEADER; // reset internal counters _q->symbol_counter=0; _q->header_symbol_index=0; _q->payload_symbol_index=0; _q->payload_buffer_index=0; // reset error vector magnitude estimate _q->evm_hat = 1e-12f; // slight offset to ensure no log(0) // reset framestats object framesyncstats_init_default(&_q->framestats); // reset internal OFDM frame synchronizer object ofdmframesync_reset(_q->fs); } int ofdmflexframesync_is_frame_open(ofdmflexframesync _q) { return ofdmframesync_is_frame_open(_q->fs); } // execute synchronizer object on buffer of samples void ofdmflexframesync_execute(ofdmflexframesync _q, float complex * _x, unsigned int _n) { // push samples through ofdmframesync object ofdmframesync_execute(_q->fs, _x, _n); } // // query methods // // received signal strength indication float ofdmflexframesync_get_rssi(ofdmflexframesync _q) { return ofdmframesync_get_rssi(_q->fs); } // received carrier frequency offset float ofdmflexframesync_get_cfo(ofdmflexframesync _q) { return ofdmframesync_get_cfo(_q->fs); } // // debugging methods // // enable debugging for internal ofdm frame synchronizer void ofdmflexframesync_debug_enable(ofdmflexframesync _q) { ofdmframesync_debug_enable(_q->fs); } // disable debugging for internal ofdm frame synchronizer void ofdmflexframesync_debug_disable(ofdmflexframesync _q) { ofdmframesync_debug_disable(_q->fs); } // print debugging file for internal ofdm frame synchronizer void ofdmflexframesync_debug_print(ofdmflexframesync _q, const char * _filename) { ofdmframesync_debug_print(_q->fs, _filename); } // // internal methods // // internal callback // _X : subcarrier symbols // _p : subcarrier allocation // _M : number of subcarriers // _userdata : user-defined data structure int ofdmflexframesync_internal_callback(float complex * _X, unsigned char * _p, unsigned int _M, void * _userdata) { #if DEBUG_OFDMFLEXFRAMESYNC printf("******* ofdmflexframesync callback invoked!\n"); #endif // type-cast userdata as ofdmflexframesync object ofdmflexframesync _q = (ofdmflexframesync) _userdata; _q->symbol_counter++; #if DEBUG_OFDMFLEXFRAMESYNC printf("received symbol %u\n", _q->symbol_counter); #endif // extract symbols switch (_q->state) { case OFDMFLEXFRAMESYNC_STATE_HEADER: ofdmflexframesync_rxheader(_q, _X); break; case OFDMFLEXFRAMESYNC_STATE_PAYLOAD: ofdmflexframesync_rxpayload(_q, _X); break; default: fprintf(stderr,"error: ofdmflexframesync_internal_callback(), unknown/unsupported internal state\n"); exit(1); } // return return 0; } // receive header data void ofdmflexframesync_rxheader(ofdmflexframesync _q, float complex * _X) { #if DEBUG_OFDMFLEXFRAMESYNC printf(" ofdmflexframesync extracting header...\n"); #endif // demodulate header symbols unsigned int i; int sctype; for (i=0; i<_q->M; i++) { // subcarrier type (PILOT/NULL/DATA) sctype = _q->p[i]; // ignore pilot and null subcarriers if (sctype == OFDMFRAME_SCTYPE_DATA) { // unload header symbols // demodulate header symbol unsigned int sym; #if OFDMFLEXFRAME_H_SOFT modem_demodulate_soft(_q->mod_header, _X[i], &sym, &_q->header_mod[OFDMFLEXFRAME_H_BPS*_q->header_symbol_index]); #else modem_demodulate(_q->mod_header, _X[i], &sym); _q->header_mod[_q->header_symbol_index] = sym; #endif _q->header_symbol_index++; //printf(" extracting symbol %3u / %3u (x = %8.5f + j%8.5f)\n", _q->header_symbol_index, OFDMFLEXFRAME_H_SYM, crealf(_X[i]), cimagf(_X[i])); // get demodulator error vector magnitude float evm = modem_get_demodulator_evm(_q->mod_header); _q->evm_hat += evm*evm; // header extracted if (_q->header_symbol_index == OFDMFLEXFRAME_H_SYM) { // decode header ofdmflexframesync_decode_header(_q); // compute error vector magnitude estimate _q->framestats.evm = 10*log10f( _q->evm_hat/OFDMFLEXFRAME_H_SYM ); // invoke callback if header is invalid if (_q->header_valid) _q->state = OFDMFLEXFRAMESYNC_STATE_PAYLOAD; else { //printf("**** header invalid!\n"); // set framestats internals _q->framestats.rssi = ofdmframesync_get_rssi(_q->fs); _q->framestats.cfo = ofdmframesync_get_cfo(_q->fs); _q->framestats.framesyms = NULL; _q->framestats.num_framesyms = 0; _q->framestats.mod_scheme = LIQUID_MODEM_UNKNOWN; _q->framestats.mod_bps = 0; _q->framestats.check = LIQUID_CRC_UNKNOWN; _q->framestats.fec0 = LIQUID_FEC_UNKNOWN; _q->framestats.fec1 = LIQUID_FEC_UNKNOWN; // invoke callback method _q->callback(_q->header, _q->header_valid, NULL, 0, 0, _q->framestats, _q->userdata); ofdmflexframesync_reset(_q); } break; } } } } // decode header void ofdmflexframesync_decode_header(ofdmflexframesync _q) { #if OFDMFLEXFRAME_H_SOFT # if 0 unsigned int i; // copy soft bits for (i=0; i<8*OFDMFLEXFRAME_H_ENC; i++) _q->header_enc[i] = _q->header_mod[i]; # else // TODO: ensure lengths are the same memmove(_q->header_enc, _q->header_mod, 8*OFDMFLEXFRAME_H_ENC); # endif // unscramble header using soft bits unscramble_data_soft(_q->header_enc, OFDMFLEXFRAME_H_ENC); // run packet decoder _q->header_valid = packetizer_decode_soft(_q->p_header, _q->header_enc, _q->header); #else // pack 1-bit header symbols into 8-bit bytes unsigned int num_written; liquid_repack_bytes(_q->header_mod, OFDMFLEXFRAME_H_BPS, OFDMFLEXFRAME_H_SYM, _q->header_enc, 8, OFDMFLEXFRAME_H_ENC, &num_written); assert(num_written==OFDMFLEXFRAME_H_ENC); // unscramble header unscramble_data(_q->header_enc, OFDMFLEXFRAME_H_ENC); // run packet decoder _q->header_valid = packetizer_decode(_q->p_header, _q->header_enc, _q->header); #endif #if 0 // print header printf("header rx (enc) : "); for (i=0; iheader_enc[i]); printf("\n"); // print header printf("header rx (dec) : "); for (i=0; iheader[i]); printf("\n"); #endif #if DEBUG_OFDMFLEXFRAMESYNC printf("****** header extracted [%s]\n", _q->header_valid ? "valid" : "INVALID!"); #endif if (!_q->header_valid) return; unsigned int n = OFDMFLEXFRAME_H_USER; // first byte is for expansion/version validation if (_q->header[n+0] != OFDMFLEXFRAME_PROTOCOL) { fprintf(stderr,"warning: ofdmflexframesync_decode_header(), invalid framing version\n"); _q->header_valid = 0; } // strip off payload length unsigned int payload_len = (_q->header[n+1] << 8) | (_q->header[n+2]); // strip off modulation scheme/depth unsigned int mod_scheme = _q->header[n+3]; if (mod_scheme == 0 || mod_scheme >= LIQUID_MODEM_NUM_SCHEMES) { fprintf(stderr,"warning: ofdmflexframesync_decode_header(), invalid modulation scheme\n"); _q->header_valid = 0; return; } // strip off CRC, forward error-correction schemes // CRC : most-significant 3 bits of [n+4] // fec0 : least-significant 5 bits of [n+4] // fec1 : least-significant 5 bits of [n+5] unsigned int check = (_q->header[n+4] >> 5 ) & 0x07; unsigned int fec0 = (_q->header[n+4] ) & 0x1f; unsigned int fec1 = (_q->header[n+5] ) & 0x1f; // validate properties if (check >= LIQUID_CRC_NUM_SCHEMES) { fprintf(stderr,"warning: ofdmflexframesync_decode_header(), decoded CRC exceeds available\n"); check = LIQUID_CRC_UNKNOWN; _q->header_valid = 0; } if (fec0 >= LIQUID_FEC_NUM_SCHEMES) { fprintf(stderr,"warning: ofdmflexframesync_decode_header(), decoded FEC (inner) exceeds available\n"); fec0 = LIQUID_FEC_UNKNOWN; _q->header_valid = 0; } if (fec1 >= LIQUID_FEC_NUM_SCHEMES) { fprintf(stderr,"warning: ofdmflexframesync_decode_header(), decoded FEC (outer) exceeds available\n"); fec1 = LIQUID_FEC_UNKNOWN; _q->header_valid = 0; } // print results #if DEBUG_OFDMFLEXFRAMESYNC printf(" properties:\n"); printf(" * mod scheme : %s\n", modulation_types[mod_scheme].fullname); printf(" * fec (inner) : %s\n", fec_scheme_str[fec0][1]); printf(" * fec (outer) : %s\n", fec_scheme_str[fec1][1]); printf(" * CRC scheme : %s\n", crc_scheme_str[check][1]); printf(" * payload length : %u bytes\n", payload_len); #endif // configure payload receiver if (_q->header_valid) { // configure modem if (mod_scheme != _q->ms_payload) { // set new properties _q->ms_payload = mod_scheme; _q->bps_payload = modulation_types[mod_scheme].bps; // recreate modem (destroy/create) _q->mod_payload = modem_recreate(_q->mod_payload, _q->ms_payload); } // set new packetizer properties _q->payload_len = payload_len; _q->check = check; _q->fec0 = fec0; _q->fec1 = fec1; // recreate packetizer object _q->p_payload = packetizer_recreate(_q->p_payload, _q->payload_len, _q->check, _q->fec0, _q->fec1); // re-compute payload encoded message length _q->payload_enc_len = packetizer_get_enc_msg_len(_q->p_payload); #if DEBUG_OFDMFLEXFRAMESYNC printf(" * payload encoded : %u bytes\n", _q->payload_enc_len); #endif // re-allocate buffers accordingly _q->payload_enc = (unsigned char*) realloc(_q->payload_enc, _q->payload_enc_len*sizeof(unsigned char)); _q->payload_dec = (unsigned char*) realloc(_q->payload_dec, _q->payload_len*sizeof(unsigned char)); // re-compute number of modulated payload symbols div_t d = div(8*_q->payload_enc_len, _q->bps_payload); _q->payload_mod_len = d.quot + (d.rem ? 1 : 0); _q->payload_syms = (float complex*) realloc(_q->payload_syms, _q->payload_mod_len*sizeof(float complex)); #if DEBUG_OFDMFLEXFRAMESYNC printf(" * payload mod syms: %u symbols\n", _q->payload_mod_len); #endif } } // receive payload data void ofdmflexframesync_rxpayload(ofdmflexframesync _q, float complex * _X) { // demodulate paylod symbols unsigned int i; int sctype; for (i=0; i<_q->M; i++) { // subcarrier type (PILOT/NULL/DATA) sctype = _q->p[i]; // ignore pilot and null subcarriers if (sctype == OFDMFRAME_SCTYPE_DATA) { // unload payload symbols unsigned int sym; modem_demodulate(_q->mod_payload, _X[i], &sym); // store received symbol _q->payload_syms[_q->payload_symbol_index] = _X[i]; // pack decoded symbol into array liquid_pack_array(_q->payload_enc, _q->payload_enc_len, _q->payload_buffer_index, _q->bps_payload, sym); // increment... _q->payload_buffer_index += _q->bps_payload; // increment symbol counter _q->payload_symbol_index++; if (_q->payload_symbol_index == _q->payload_mod_len) { // payload extracted // decode payload _q->payload_valid = packetizer_decode(_q->p_payload, _q->payload_enc, _q->payload_dec); #if DEBUG_OFDMFLEXFRAMESYNC printf("****** payload extracted [%s]\n", _q->payload_valid ? "valid" : "INVALID!"); #endif // ignore callback if set to NULL if (_q->callback == NULL) { ofdmflexframesync_reset(_q); break; } // set framestats internals _q->framestats.rssi = ofdmframesync_get_rssi(_q->fs); _q->framestats.cfo = ofdmframesync_get_cfo(_q->fs); _q->framestats.framesyms = _q->payload_syms; _q->framestats.num_framesyms = _q->payload_mod_len; _q->framestats.mod_scheme = _q->ms_payload; _q->framestats.mod_bps = _q->bps_payload; _q->framestats.check = _q->check; _q->framestats.fec0 = _q->fec0; _q->framestats.fec1 = _q->fec1; // invoke callback method _q->callback(_q->header, _q->header_valid, _q->payload_dec, _q->payload_len, _q->payload_valid, _q->framestats, _q->userdata); // reset object ofdmflexframesync_reset(_q); break; } } } } liquid-dsp-1.3.1/src/framing/src/presync.c000066400000000000000000000163541317124540100204260ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Binary pre-demod synchronizer // #include #include #include #include #include "liquid.internal.h" struct PRESYNC(_s) { unsigned int n; // sequence length unsigned int m; // number of binary synchronizers WINDOW() rx_i; // received pattern (in-phase) WINDOW() rx_q; // received pattern (quadrature) float * dphi; // array of frequency offsets [size: m x 1] DOTPROD() * sync_i; // synchronization pattern (in-phase) DOTPROD() * sync_q; // synchronization pattern (quadrature) float * rxy; // output correlation [size: m x 1] float n_inv; // 1/n (pre-computed for speed) }; /* create binary pre-demod synchronizer */ /* _v : baseband sequence */ /* _n : baseband sequence length */ /* _dphi_max : maximum absolute frequency deviation */ /* _m : number of correlators */ PRESYNC() PRESYNC(_create)(TC * _v, unsigned int _n, float _dphi_max, unsigned int _m) { // validate input if (_n < 1) { fprintf(stderr, "error: bpresync_%s_create(), invalid input length\n", EXTENSION_FULL); exit(1); } else if (_m == 0) { fprintf(stderr, "error: bpresync_%s_create(), number of correlators must be at least 1\n", EXTENSION_FULL); exit(1); } // allocate main object memory and initialize PRESYNC() _q = (PRESYNC()) malloc(sizeof(struct PRESYNC(_s))); _q->n = _n; _q->m = _m; _q->n_inv = 1.0f / (float)(_q->n); unsigned int i; // create internal receive buffers _q->rx_i = WINDOW(_create)(_q->n); _q->rx_q = WINDOW(_create)(_q->n); // create internal array of frequency offsets _q->dphi = (float*) malloc( _q->m*sizeof(float) ); // create internal synchronizers _q->sync_i = (DOTPROD()*) malloc( _q->m*sizeof(DOTPROD()) ); _q->sync_q = (DOTPROD()*) malloc( _q->m*sizeof(DOTPROD()) ); // buffer T vi_prime[_n]; T vq_prime[_n]; for (i=0; i<_q->m; i++) { // generate signal with frequency offset _q->dphi[i] = (float)i / (float)(_q->m-1)*_dphi_max; unsigned int k; for (k=0; k<_q->n; k++) { vi_prime[k] = REAL( _v[k] * cexpf(-_Complex_I*k*_q->dphi[i]) ); vq_prime[k] = IMAG( _v[k] * cexpf(-_Complex_I*k*_q->dphi[i]) ); } _q->sync_i[i] = DOTPROD(_create)(vi_prime, _q->n); _q->sync_q[i] = DOTPROD(_create)(vq_prime, _q->n); } // allocate memory for cross-correlation _q->rxy = (float*) malloc( _q->m*sizeof(float) ); // reset object PRESYNC(_reset)(_q); return _q; } void PRESYNC(_destroy)(PRESYNC() _q) { unsigned int i; // free received symbol buffers WINDOW(_destroy)(_q->rx_i); WINDOW(_destroy)(_q->rx_q); // free internal syncrhonizer objects for (i=0; i<_q->m; i++) { DOTPROD(_destroy)(_q->sync_i[i]); DOTPROD(_destroy)(_q->sync_q[i]); } free(_q->sync_i); free(_q->sync_q); // free internal frequency offset array free(_q->dphi); // free internal cross-correlation array free(_q->rxy); // free main object memory free(_q); } void PRESYNC(_print)(PRESYNC() _q) { printf("bpresync_%s: %u samples\n", EXTENSION_FULL, _q->n); } void PRESYNC(_reset)(PRESYNC() _q) { WINDOW(_reset)(_q->rx_i); WINDOW(_reset)(_q->rx_q); } // correlate input sequence with particular // _q : pre-demod synchronizer object // _id : ... void PRESYNC(_correlatex)(PRESYNC() _q, unsigned int _id, float complex * _rxy0, float complex * _rxy1) { // validate input... if (_id >= _q->m) { fprintf(stderr,"error: bpresync_%s_correlatex(), invalid id\n", EXTENSION_FULL); exit(1); } // get buffer pointers T * ri = NULL; T * rq = NULL; WINDOW(_read)(_q->rx_i, &ri); WINDOW(_read)(_q->rx_q, &rq); // compute correlations T rxy_ii; DOTPROD(_execute)(_q->sync_i[_id], ri, &rxy_ii); T rxy_qq; DOTPROD(_execute)(_q->sync_q[_id], rq, &rxy_qq); T rxy_iq; DOTPROD(_execute)(_q->sync_i[_id], rq, &rxy_iq); T rxy_qi; DOTPROD(_execute)(_q->sync_q[_id], ri, &rxy_qi); // non-conjugated T rxy_i0 = rxy_ii - rxy_qq; T rxy_q0 = rxy_iq + rxy_qi; *_rxy0 = (rxy_i0 + rxy_q0 * _Complex_I) * _q->n_inv; // conjugated T rxy_i1 = rxy_ii + rxy_qq; T rxy_q1 = rxy_iq - rxy_qi; *_rxy1 = (rxy_i1 + rxy_q1 * _Complex_I) * _q->n_inv; } /* push input sample into pre-demod synchronizer */ /* _q : pre-demod synchronizer object */ /* _x : input sample */ void PRESYNC(_push)(PRESYNC() _q, TI _x) { // push symbol into buffers WINDOW(_push)(_q->rx_i, REAL(_x)); WINDOW(_push)(_q->rx_q, REAL(_x)); } /* correlate input sequence */ /* _q : pre-demod synchronizer object */ /* _rxy : output cross correlation */ /* _dphi_hat : output frequency offset estimate */ void PRESYNC(_correlate)(PRESYNC() _q, TO * _rxy, float * _dphi_hat) { unsigned int i; float complex rxy_max = 0; // maximum cross-correlation float abs_rxy_max = 0; // absolute value of rxy_max float complex rxy0; float complex rxy1; float dphi_hat = 0.0f; for (i=0; i<_q->m; i++) { PRESYNC(_correlatex)(_q, i, &rxy0, &rxy1); // check non-conjugated value if ( ABS(rxy0) > abs_rxy_max ) { rxy_max = rxy0; abs_rxy_max = ABS(rxy0); dphi_hat = _q->dphi[i]; } // check conjugated value if ( ABS(rxy1) > abs_rxy_max ) { rxy_max = rxy1; abs_rxy_max = ABS(rxy1); dphi_hat = -_q->dphi[i]; } } *_rxy = rxy_max; *_dphi_hat = dphi_hat; } liquid-dsp-1.3.1/src/framing/src/presync_cccf.c000066400000000000000000000040271317124540100213760ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Binary pre-demod synchronizer // #include "liquid.internal.h" // #define PRESYNC(name) LIQUID_CONCAT(presync_cccf,name) // print and naming extensions #define PRINTVAL(x) printf("%12.4e + j%12.4e", crealf(x), cimagf(x)) #define EXTENSION_SHORT "f" #define EXTENSION_FULL "cccf" #define T float // primitive type #define TO float complex // output type #define TC float complex // coefficient type #define TI float complex // input type #define ABS(X) cabsf(X) #define REAL(X) crealf(X) #define IMAG(X) cimagf(X) #define WINDOW(name) LIQUID_CONCAT(windowf,name) #define DOTPROD(name) LIQUID_CONCAT(dotprod_rrrf,name) #define BSYNC(name) LIQUID_CONCAT(bsync_cccf,name) #define TO_COMPLEX #define TC_COMPLEX #define TI_COMPLEX // source files #include "presync.c" liquid-dsp-1.3.1/src/framing/src/qdetector_cccf.c000066400000000000000000000535551317124540100217170ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // qdetector_cccf.c // #include #include #include #include #include #include "liquid.internal.h" #define DEBUG_QDETECTOR 0 #define DEBUG_QDETECTOR_PRINT 0 #define DEBUG_QDETECTOR_FILENAME "qdetector_cccf_debug.m" // seek signal (initial detection) void qdetector_cccf_execute_seek(qdetector_cccf _q, float complex _x); // align signal in time, compute offset estimates void qdetector_cccf_execute_align(qdetector_cccf _q, float complex _x); // main object definition struct qdetector_cccf_s { unsigned int s_len; // template (time) length: k * (sequence_len + 2*m) float complex * s; // template (time), [size: s_len x 1] float complex * S; // template (freq), [size: nfft x 1] float s2_sum; // sum{ s^2 } float complex * buf_time_0; // time-domain buffer (FFT) float complex * buf_freq_0; // frequence-domain buffer (FFT) float complex * buf_freq_1; // frequence-domain buffer (IFFT) float complex * buf_time_1; // time-domain buffer (IFFT) unsigned int nfft; // fft size fftplan fft; // FFT object: buf_time_0 > buf_freq_0 fftplan ifft; // IFFT object: buf_freq_1 > buf_freq_1 unsigned int counter; // sample counter for determining when to compute FFTs float threshold; // detection threshold int range; // carrier offset search range (subcarriers) unsigned int num_transforms; // number of transforms taken (debugging) float x2_sum_0; // sum{ |x|^2 } of first half of buffer float x2_sum_1; // sum{ |x|^2 } of second half of buffer int offset; // FFT offset index for peak correlation (coarse carrier estimate) float tau_hat; // timing offset estimate float gamma_hat; // signal level estimate (channel gain) float dphi_hat; // carrier frequency offset estimate float phi_hat; // carrier phase offset estimate enum { QDETECTOR_STATE_SEEK, // seek sequence QDETECTOR_STATE_ALIGN, // align sequence } state; // execution state int frame_detected; // frame detected? }; // create detector with generic sequence // _s : sample sequence // _s_len : length of sample sequence qdetector_cccf qdetector_cccf_create(float complex * _s, unsigned int _s_len) { // validate input if (_s_len == 0) { fprintf(stderr,"error: qdetector_cccf_create(), sequence length cannot be zero\n"); exit(1); } // allocate memory for main object and set internal properties qdetector_cccf q = (qdetector_cccf) malloc(sizeof(struct qdetector_cccf_s)); q->s_len = _s_len; // allocate memory and copy sequence q->s = (float complex*) malloc(q->s_len * sizeof(float complex)); memmove(q->s, _s, q->s_len*sizeof(float complex)); q->s2_sum = liquid_sumsqcf(q->s, q->s_len); // compute sum{ s^2 } // prepare transforms q->nfft = 1 << liquid_nextpow2( (unsigned int)( 2 * q->s_len ) ); // NOTE: must be even q->buf_time_0 = (float complex*) malloc(q->nfft * sizeof(float complex)); q->buf_freq_0 = (float complex*) malloc(q->nfft * sizeof(float complex)); q->buf_freq_1 = (float complex*) malloc(q->nfft * sizeof(float complex)); q->buf_time_1 = (float complex*) malloc(q->nfft * sizeof(float complex)); q->fft = fft_create_plan(q->nfft, q->buf_time_0, q->buf_freq_0, LIQUID_FFT_FORWARD, 0); q->ifft = fft_create_plan(q->nfft, q->buf_freq_1, q->buf_time_1, LIQUID_FFT_BACKWARD, 0); // create frequency-domain template by taking nfft-point transform on 's', storing in 'S' q->S = (float complex*) malloc(q->nfft * sizeof(float complex)); memset(q->buf_time_0, 0x00, q->nfft*sizeof(float complex)); memmove(q->buf_time_0, q->s, q->s_len*sizeof(float complex)); fft_execute(q->fft); memmove(q->S, q->buf_freq_0, q->nfft*sizeof(float complex)); // reset state variables q->counter = q->nfft/2; q->num_transforms = 0; q->x2_sum_0 = 0.0f; q->x2_sum_1 = 0.0f; q->state = QDETECTOR_STATE_SEEK; q->frame_detected = 0; memset(q->buf_time_0, 0x00, q->nfft*sizeof(float complex)); // reset estimates q->tau_hat = 0.0f; q->gamma_hat = 0.0f; q->dphi_hat = 0.0f; q->phi_hat = 0.0f; qdetector_cccf_set_threshold(q,0.5f); qdetector_cccf_set_range (q,0.3f); // set initial range for higher detection // return object return q; } // create detector from sequence of symbols using internal linear interpolator // _sequence : symbol sequence // _sequence_len : length of symbol sequence // _ftype : filter prototype (e.g. LIQUID_FIRFILT_RRC) // _k : samples/symbol // _m : filter delay // _beta : excess bandwidth factor qdetector_cccf qdetector_cccf_create_linear(float complex * _sequence, unsigned int _sequence_len, int _ftype, unsigned int _k, unsigned int _m, float _beta) { // validate input if (_sequence_len == 0) { fprintf(stderr,"error: qdetector_cccf_create_linear(), sequence length cannot be zero\n"); exit(1); } else if (_k < 2 || _k > 80) { fprintf(stderr,"error: qdetector_cccf_create_linear(), samples per symbol must be in [2,80]\n"); exit(1); } else if (_m < 1 || _m > 100) { fprintf(stderr,"error: qdetector_cccf_create_linear(), filter delay must be in [1,100]\n"); exit(1); } else if (_beta < 0.0f || _beta > 1.0f) { fprintf(stderr,"error: qdetector_cccf_create_linear(), excess bandwidth factor must be in [0,1]\n"); exit(1); } // create time-domain template unsigned int s_len = _k * (_sequence_len + 2*_m); float complex * s = (float complex*) malloc(s_len * sizeof(float complex)); firinterp_crcf interp = firinterp_crcf_create_prototype(_ftype, _k, _m, _beta, 0); unsigned int i; for (i=0; i<_sequence_len + 2*_m; i++) firinterp_crcf_execute(interp, i < _sequence_len ? _sequence[i] : 0, &s[_k*i]); firinterp_crcf_destroy(interp); // create main object qdetector_cccf q = qdetector_cccf_create(s, s_len); // free allocated temporary array free(s); // return object return q; } // create detector from sequence of symbols using internal linear interpolator // _sequence : bit sequence // _sequence_len : length of bit sequence // _k : samples/symbol // _m : filter delay // _beta : excess bandwidth factor qdetector_cccf qdetector_cccf_create_gmsk(unsigned char * _sequence, unsigned int _sequence_len, unsigned int _k, unsigned int _m, float _beta) { // validate input if (_sequence_len == 0) { fprintf(stderr,"error: qdetector_cccf_create_gmsk(), sequence length cannot be zero\n"); exit(1); } else if (_k < 2 || _k > 80) { fprintf(stderr,"error: qdetector_cccf_create_gmsk(), samples per symbol must be in [2,80]\n"); exit(1); } else if (_m < 1 || _m > 100) { fprintf(stderr,"error: qdetector_cccf_create_gmsk(), filter delay must be in [1,100]\n"); exit(1); } else if (_beta < 0.0f || _beta > 1.0f) { fprintf(stderr,"error: qdetector_cccf_create_gmsk(), excess bandwidth factor must be in [0,1]\n"); exit(1); } // create time-domain template using GMSK modem unsigned int s_len = _k * (_sequence_len + 2*_m); float complex * s = (float complex*) malloc(s_len * sizeof(float complex)); gmskmod mod = gmskmod_create(_k, _m, _beta); unsigned int i; for (i=0; i<_sequence_len + 2*_m; i++) gmskmod_modulate(mod, i < _sequence_len ? _sequence[i] : 0, &s[_k*i]); gmskmod_destroy(mod); // create main object qdetector_cccf q = qdetector_cccf_create(s, s_len); // free allocated temporary array free(s); // return object return q; } void qdetector_cccf_destroy(qdetector_cccf _q) { // free allocated arrays free(_q->s ); free(_q->S ); free(_q->buf_time_0); free(_q->buf_freq_0); free(_q->buf_freq_1); free(_q->buf_time_1); // destroy objects fft_destroy_plan(_q->fft); fft_destroy_plan(_q->ifft); // free main object memory free(_q); } void qdetector_cccf_print(qdetector_cccf _q) { printf("qdetector_cccf:\n"); printf(" template length (time): %-u\n", _q->s_len); printf(" FFT size : %-u\n", _q->nfft); printf(" detection threshold : %6.4f\n", _q->threshold); printf(" sum{ s^2 } : %.2f\n", _q->s2_sum); } void qdetector_cccf_reset(qdetector_cccf _q) { } void * qdetector_cccf_execute(qdetector_cccf _q, float complex _x) { switch (_q->state) { case QDETECTOR_STATE_SEEK: // seek signal qdetector_cccf_execute_seek(_q, _x); break; case QDETECTOR_STATE_ALIGN: // align signal qdetector_cccf_execute_align(_q, _x); break; } // check if frame was detected if (_q->frame_detected) { // clear flag _q->frame_detected = 0; // return pointer to internal buffer of saved samples return (void*)(_q->buf_time_1); } // frame not yet ready return NULL; } // set detection threshold (should be between 0 and 1, good starting point is 0.5) void qdetector_cccf_set_threshold(qdetector_cccf _q, float _threshold) { if (_threshold <= 0.0f || _threshold > 2.0f) { fprintf(stderr,"warning: threshold (%12.4e) out of range; ignoring\n", _threshold); return; } // set internal threshold value _q->threshold = _threshold; } // set carrier offset search range void qdetector_cccf_set_range(qdetector_cccf _q, float _dphi_max) { if (_dphi_max < 0.0f || _dphi_max > 0.5f) { fprintf(stderr,"warning: carrier offset search range (%12.4e) out of range; ignoring\n", _dphi_max); return; } // set internal search range _q->range = (int)(_dphi_max * _q->nfft / (2*M_PI)); _q->range = _q->range < 0 ? 0 : _q->range; //printf("range: %d / %u\n", _q->range, _q->nfft); } // get sequence length unsigned int qdetector_cccf_get_seq_len(qdetector_cccf _q) { return _q->s_len; } // pointer to sequence const void * qdetector_cccf_get_sequence(qdetector_cccf _q) { return (const void*) _q->s; } // buffer length unsigned int qdetector_cccf_get_buf_len(qdetector_cccf _q) { return _q->nfft; } // fractional timing offset estimate float qdetector_cccf_get_tau(qdetector_cccf _q) { return _q->tau_hat; } // channel gain float qdetector_cccf_get_gamma(qdetector_cccf _q) { return _q->gamma_hat; } // carrier frequency offset estimate float qdetector_cccf_get_dphi(qdetector_cccf _q) { return _q->dphi_hat; } // carrier phase offset estimate float qdetector_cccf_get_phi(qdetector_cccf _q) { return _q->phi_hat; } // // internal methods // // seek signal (initial detection) void qdetector_cccf_execute_seek(qdetector_cccf _q, float complex _x) { // write sample to buffer and increment counter _q->buf_time_0[_q->counter++] = _x; // accumulate signal magnitude _q->x2_sum_1 += crealf(_x)*crealf(_x) + cimagf(_x)*cimagf(_x); if (_q->counter < _q->nfft) return; // reset counter (last half of time buffer) _q->counter = _q->nfft/2; // run forward transform fft_execute(_q->fft); // compute scaling factor (TODO: use median rather than mean signal level) float g0 = sqrtf(_q->x2_sum_0 + _q->x2_sum_1) * sqrtf((float)(_q->s_len) / (float)(_q->nfft)); float g = 1.0f / ( (float)(_q->nfft) * g0 * sqrtf(_q->s2_sum) ); // sweep over carrier frequency offset range int offset; unsigned int i; float rxy_peak = 0.0f; unsigned int rxy_index = 0; int rxy_offset = 0; // NOTE: this offset may be coarse as a fine carrier estimate is computed later for (offset=-_q->range; offset<=_q->range; offset++) { // cross-multiply, aligning appropriately for (i=0; i<_q->nfft; i++) { // shifted index unsigned int j = (i + _q->nfft - offset) % _q->nfft; _q->buf_freq_1[i] = _q->buf_freq_0[i] * conjf(_q->S[j]); } // run inverse transform fft_execute(_q->ifft); // scale output appropriately liquid_vectorcf_mulscalar(_q->buf_time_1, _q->nfft, g, _q->buf_time_1); #if DEBUG_QDETECTOR // debug output char filename[64]; sprintf(filename,"qdetector_out_%u_%d.m", _q->num_transforms, offset+2); FILE * fid = fopen(filename, "w"); fprintf(fid,"clear all; close all;\n"); fprintf(fid,"nfft = %u;\n", _q->nfft); for (i=0; i<_q->nfft; i++) fprintf(fid,"rxy(%6u) = %12.4e + 1i*%12.4e;\n", i+1, crealf(_q->buf_time_1[i]), cimagf(_q->buf_time_1[i])); fprintf(fid,"figure;\n"); fprintf(fid,"t=[0:(nfft-1)];\n"); fprintf(fid,"plot(t,abs(rxy));\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"axis([0 %u 0 1.5]);\n", _q->nfft); fprintf(fid,"[v i] = max(abs(rxy));\n"); fprintf(fid,"title(sprintf('peak of %%12.8f at index %%u', v, i));\n"); fclose(fid); printf("debug: %s\n", filename); #endif // search for peak // TODO: only search over range [-nfft/2, nfft/2) for (i=0; i<_q->nfft; i++) { float rxy_abs = cabsf(_q->buf_time_1[i]); if (rxy_abs > rxy_peak) { rxy_peak = rxy_abs; rxy_index = i; rxy_offset = offset; } } } // increment number of transforms (debugging) _q->num_transforms++; if (rxy_peak > _q->threshold && rxy_index < _q->nfft - _q->s_len) { #if DEBUG_QDETECTOR_PRINT printf("*** frame detected! rxy = %12.8f, time index=%u, freq. offset=%d\n", rxy_peak, rxy_index, rxy_offset); #endif // update state, reset counter, copy buffer appropriately _q->state = QDETECTOR_STATE_ALIGN; _q->offset = rxy_offset; // TODO: check for edge case where rxy_index is zero (signal already aligned) // copy last part of fft input buffer to front memmove(_q->buf_time_0, _q->buf_time_0 + rxy_index, (_q->nfft - rxy_index)*sizeof(float complex)); _q->counter = _q->nfft - rxy_index; return; } #if DEBUG_QDETECTOR_PRINT printf(" no detect, rxy = %12.8f, time index=%u, freq. offset=%d\n", rxy_peak, rxy_index, rxy_offset); #endif // copy last half of fft input buffer to front memmove(_q->buf_time_0, _q->buf_time_0 + _q->nfft/2, (_q->nfft/2)*sizeof(float complex)); // swap accumulated signal levels _q->x2_sum_0 = _q->x2_sum_1; _q->x2_sum_1 = 0.0f; } // align signal in time, compute offset estimates void qdetector_cccf_execute_align(qdetector_cccf _q, float complex _x) { // write sample to buffer and increment counter _q->buf_time_0[_q->counter++] = _x; if (_q->counter < _q->nfft) return; //printf("signal is aligned!\n"); // estimate timing offset fft_execute(_q->fft); // cross-multiply frequency-domain components, aligning appropriately with // estimated FFT offset index due to carrier frequency offset in received signal unsigned int i; for (i=0; i<_q->nfft; i++) { // shifted index unsigned int j = (i + _q->nfft - _q->offset) % _q->nfft; _q->buf_freq_1[i] = _q->buf_freq_0[i] * conjf(_q->S[j]); } fft_execute(_q->ifft); // time aligned to index 0 // NOTE: taking the sqrt removes bias in the timing estimate, but messes up gamma estimate float yneg = cabsf(_q->buf_time_1[_q->nfft-1]); yneg = sqrtf(yneg); float y0 = cabsf(_q->buf_time_1[ 0]); y0 = sqrtf(y0 ); float ypos = cabsf(_q->buf_time_1[ 1]); ypos = sqrtf(ypos); // compute timing offset estimate from quadratic polynomial fit // y = a x^2 + b x + c, [xneg = -1, x0 = 0, xpos = +1] float a = 0.5f*(ypos + yneg) - y0; float b = 0.5f*(ypos - yneg); float c = y0; _q->tau_hat = -b / (2.0f*a); //-0.5f*(ypos - yneg) / (ypos + yneg - 2*y0); float g_hat = (a*_q->tau_hat*_q->tau_hat + b*_q->tau_hat + c); _q->gamma_hat = g_hat * g_hat / ((float)(_q->nfft) * _q->s2_sum); // g_hat^2 because of sqrt for yneg/y0/ypos // copy buffer to preserve data integrity memmove(_q->buf_time_1, _q->buf_time_0, _q->nfft*sizeof(float complex)); // estimate carrier frequency offset for (i=0; i<_q->nfft; i++) _q->buf_time_0[i] *= i < _q->s_len ? conjf(_q->s[i]) : 0.0f; fft_execute(_q->fft); #if DEBUG_QDETECTOR // debug output char filename[64]; sprintf(filename,"qdetector_fft.m"); FILE * fid = fopen(filename, "w"); fprintf(fid,"clear all; close all;\n"); fprintf(fid,"nfft = %u;\n", _q->nfft); for (i=0; i<_q->nfft; i++) fprintf(fid,"V(%6u) = %12.4e + 1i*%12.4e;\n", i+1, crealf(_q->buf_freq_0[i]), cimagf(_q->buf_freq_0[i])); fprintf(fid,"V = fftshift(V) / max(abs(V));\n"); fprintf(fid,"figure;\n"); fprintf(fid,"f=[0:(nfft-1)] - nfft/2;\n"); fprintf(fid,"plot(f,abs(V),'-x');\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"axis([-10 10 0 1.2]);\n"); fclose(fid); printf("debug: %s\n", filename); #endif // search for peak (NOTE: should be at: _q->offset) // TODO: don't search for peak but just use internal offset float v0 = 0.0f; unsigned int i0 = 0; for (i=0; i<_q->nfft; i++) { float v_abs = cabsf(_q->buf_freq_0[i]); if (v_abs > v0) { v0 = v_abs; i0 = i; } } // interpolate using quadratic polynomial for carrier frequency estimate unsigned int ineg = (i0 + _q->nfft - 1)%_q->nfft; unsigned int ipos = (i0 + 1)%_q->nfft; float vneg = cabsf(_q->buf_freq_0[ineg]); float vpos = cabsf(_q->buf_freq_0[ipos]); a = 0.5f*(vpos + vneg) - v0; b = 0.5f*(vpos - vneg); //c = v0; float idx = -b / (2.0f*a); //-0.5f*(vpos - vneg) / (vpos + vneg - 2*v0); float index = (float)i0 + idx; _q->dphi_hat = (i0 > _q->nfft/2 ? index-(float)_q->nfft : index) * 2*M_PI / (float)(_q->nfft); // estimate carrier phase offset #if 0 // METHOD 1: linear interpolation of phase in FFT output buffer float p0 = cargf(_q->buf_freq_0[ idx < 0 ? ineg : i0 ]); float p1 = cargf(_q->buf_freq_0[ idx < 0 ? i0 : ipos ]); float xp = idx < 0 ? 1+idx : idx; _q->phi_hat = (p1-p0)*xp + p0; //printf("v0 = %12.8f, v1 = %12.8f, xp = %12.8f\n", v0, v1, xp); #else // METHOD 2: compute metric by de-rotating signal and measuring resulting phase // NOTE: this is possibly more accurate than the above method but might also // be more computationally complex float complex metric = 0; for (i=0; i<_q->s_len; i++) metric += _q->buf_time_0[i] * cexpf(-_Complex_I*_q->dphi_hat*i); //printf("metric : %12.8f <%12.8f>\n", cabsf(metric), cargf(metric)); _q->phi_hat = cargf(metric); #endif #if DEBUG_QDETECTOR_PRINT printf(" y[ -1] : %12.8f\n", yneg); printf(" y[ 0] : %12.8f\n", y0 ); printf(" y[ +1] : %12.8f\n", ypos); printf(" tau-hat : %12.8f\n", _q->tau_hat); //printf(" g-hat: : %12.8f\n", g_hat); printf(" gamma-hat : %12.8f\n", _q->gamma_hat); printf(" v[%4u-1] : %12.8f\n", i0,vneg); printf(" v[%4u+0] : %12.8f\n", i0,v0 ); printf(" v[%4u+1] : %12.8f\n", i0,vpos); printf(" dphi-hat : %12.8f\n", _q->dphi_hat); printf(" phi-hat : %12.8f\n", _q->phi_hat); #endif // set flag _q->frame_detected = 1; // reset state // copy saved buffer state (last half of buf_time_1 to front half of buf_time_0) memmove(_q->buf_time_0, _q->buf_time_1 + _q->nfft/2, (_q->nfft/2)*sizeof(float complex)); _q->state = QDETECTOR_STATE_SEEK; _q->x2_sum_0 = liquid_sumsqcf(_q->buf_time_0, _q->nfft/2); _q->x2_sum_1 = 0; _q->counter = _q->nfft/2; } liquid-dsp-1.3.1/src/framing/src/qpacketmodem.c000066400000000000000000000270701317124540100214120ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2016 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // qpacketmodem.c // // convenient modulator/demodulator and packet encoder/decoder combination // #include #include #include #include #include #include #include "liquid.internal.h" struct qpacketmodem_s { // properties modem mod_payload; // payload modulator/demodulator packetizer p; // packet encoder/decoder unsigned int bits_per_symbol; // modulator bits/symbol unsigned int payload_dec_len; // number of decoded payload bytes unsigned char * payload_enc; // payload data (encoded bytes) unsigned char * payload_mod; // payload symbols (modulator output, demod input) unsigned int payload_enc_len; // number of encoded payload bytes unsigned int payload_bit_len; // number of bits in encoded payload unsigned int payload_mod_len; // number of symbols in encoded payload }; // create packet encoder qpacketmodem qpacketmodem_create() { // allocate memory for main object qpacketmodem q = (qpacketmodem) malloc(sizeof(struct qpacketmodem_s)); // create payload modem (initially QPSK, overridden by properties) q->mod_payload = modem_create(LIQUID_MODEM_QPSK); q->bits_per_symbol = 2; // initial memory allocation for payload q->payload_dec_len = 1; q->p = packetizer_create(q->payload_dec_len, LIQUID_CRC_NONE, LIQUID_FEC_NONE, LIQUID_FEC_NONE); // number of bytes in encoded payload q->payload_enc_len = packetizer_get_enc_msg_len(q->p); // number of bits in encoded payload q->payload_bit_len = 8*q->payload_enc_len; // number of symbols in encoded payload div_t d = div(q->payload_bit_len, q->bits_per_symbol); q->payload_mod_len = d.quot + (d.rem ? 1 : 0); // soft demodulator uses one byte to represent each soft bit q->payload_enc = (unsigned char*) malloc(q->bits_per_symbol*q->payload_mod_len*sizeof(unsigned char)); // set symbol length appropriately q->payload_mod_len = q->payload_enc_len * q->bits_per_symbol; // for QPSK q->payload_mod = (unsigned char*) malloc(q->payload_mod_len*sizeof(unsigned char)); // return pointer to main object return q; } // destroy object, freeing all internal arrays void qpacketmodem_destroy(qpacketmodem _q) { // free objects packetizer_destroy(_q->p); modem_destroy(_q->mod_payload); // free arrays free(_q->payload_enc); free(_q->payload_mod); } // reset object void qpacketmodem_reset(qpacketmodem _q) { modem_reset(_q->mod_payload); } // print object internals void qpacketmodem_print(qpacketmodem _q) { printf("qpacketmodem:\n"); printf(" check : %s\n", crc_scheme_str[packetizer_get_crc(_q->p)][1]); printf(" fec (inner) : %s\n", fec_scheme_str[packetizer_get_fec0(_q->p)][1]); printf(" fec (outer) : %s\n", fec_scheme_str[packetizer_get_fec1(_q->p)][1]); printf(" modulation scheme : %s\n", modulation_types[modem_get_scheme(_q->mod_payload)].name); printf(" payload dec len : %u\n", _q->payload_dec_len); printf(" payload enc len : %u\n", _q->payload_enc_len); printf(" payload bit len : %u\n", _q->payload_bit_len); printf(" payload mod len : %u\n", _q->payload_mod_len); } // int qpacketmodem_configure(qpacketmodem _q, unsigned int _payload_len, crc_scheme _check, fec_scheme _fec0, fec_scheme _fec1, int _ms) { // set new decoded message length _q->payload_dec_len = _payload_len; // recreate modem object and get new bits per symbol _q->mod_payload = modem_recreate(_q->mod_payload, _ms); _q->bits_per_symbol = modem_get_bps(_q->mod_payload); // recreate packetizer object and compute new encoded payload length _q->p = packetizer_recreate(_q->p, _q->payload_dec_len, _check, _fec0, _fec1); _q->payload_enc_len = packetizer_get_enc_msg_len(_q->p); // number of bits in encoded payload _q->payload_bit_len = 8*_q->payload_enc_len; // number of symbols in encoded payload div_t d = div(_q->payload_bit_len, _q->bits_per_symbol); _q->payload_mod_len = d.quot + (d.rem ? 1 : 0); // encoded payload array (leave room for soft-decision decoding) _q->payload_enc = (unsigned char*) realloc(_q->payload_enc, _q->bits_per_symbol*_q->payload_mod_len*sizeof(unsigned char)); // reallocate memory for modem symbols _q->payload_mod = (unsigned char*) realloc(_q->payload_mod, _q->payload_mod_len*sizeof(unsigned char)); return 0; } // get length of encoded frame in symbols unsigned int qpacketmodem_get_frame_len(qpacketmodem _q) { return _q->payload_mod_len; } // get unencoded/decoded payload length (bytes) unsigned int qpacketmodem_get_payload_len(qpacketmodem _q) { // number of decoded payload bytes return _q->payload_dec_len; } unsigned int qpacketmodem_get_crc(qpacketmodem _q) { return packetizer_get_crc(_q->p); } unsigned int qpacketmodem_get_fec0(qpacketmodem _q) { return packetizer_get_fec0(_q->p); } unsigned int qpacketmodem_get_fec1(qpacketmodem _q) { return packetizer_get_fec1(_q->p); } unsigned int qpacketmodem_get_modscheme(qpacketmodem _q) { return modem_get_scheme(_q->mod_payload); } // encode packet into un-modulated frame symbol indices // _q : qpacketmodem object // _payload : unencoded payload bytes // _syms : encoded but un-modulated payload symbol indices void qpacketmodem_encode_syms(qpacketmodem _q, const unsigned char * _payload, unsigned char * _syms) { // encode payload packetizer_encode(_q->p, _payload, _q->payload_enc); // clear internal payload memset(_q->payload_mod, 0x00, _q->payload_mod_len); // repack 8-bit payload bytes into 'bps'-bit payload symbols unsigned int bps = _q->bits_per_symbol; unsigned int num_written; liquid_repack_bytes(_q->payload_enc, 8, _q->payload_enc_len, _syms, bps, _q->payload_mod_len, &num_written); assert(num_written == _q->payload_mod_len); } // decode packet from demodulated frame symbol indices (hard-decision decoding) // _q : qpacketmodem object // _syms : received hard-decision symbol indices // _payload : recovered decoded payload bytes int qpacketmodem_decode_syms(qpacketmodem _q, unsigned char * _syms, unsigned char * _payload) { // pack bytes into payload array unsigned int bps = _q->bits_per_symbol; unsigned int num_written; liquid_repack_bytes(_syms, bps, _q->payload_mod_len, _q->payload_enc, 8, _q->payload_mod_len, // NOTE: payload_enc allocation is actually payload_mod_len bytes &num_written); //assert(num_written == _q->payload_enc_len); // NOTE: this will fail for bps in {3,5,6,7} // decode payload return packetizer_decode(_q->p, _q->payload_enc, _payload); } // decode packet from demodulated frame bits (soft-decision decoding) // _q : qpacketmodem object // _bits : received soft-decision bits // _payload : recovered decoded payload bytes int qpacketmodem_decode_bits(qpacketmodem _q, unsigned char * _bits, unsigned char * _payload) { // decode payload (soft-decision) return packetizer_decode_soft(_q->p, _bits, _payload); } // encode and modulate packet into modulated frame samples // _q : qpacketmodem object // _payload : unencoded payload bytes // _frame : encoded/modulated payload symbols void qpacketmodem_encode(qpacketmodem _q, const unsigned char * _payload, float complex * _frame) { // encode payload symbols into internal buffer qpacketmodem_encode_syms(_q, _payload, _q->payload_mod); // modulate symbols unsigned int i; for (i=0; i<_q->payload_mod_len; i++) modem_modulate(_q->mod_payload, _q->payload_mod[i], &_frame[i]); } // decode packet from modulated frame samples, returning flag if CRC passed // _q : qpacketmodem object // _frame : encoded/modulated payload symbols // _payload : recovered decoded payload bytes int qpacketmodem_decode(qpacketmodem _q, float complex * _frame, unsigned char * _payload) { unsigned int i; // demodulate and pack bytes into decoder input buffer unsigned int sym; //memset(_q->payload_enc, 0x00, _q->payload_enc_len*sizeof(unsigned char)); for (i=0; i<_q->payload_mod_len; i++) { // demodulate symbol modem_demodulate(_q->mod_payload, _frame[i], &sym); // pack decoded symbol into array liquid_pack_array(_q->payload_enc, _q->payload_enc_len, i * _q->bits_per_symbol, _q->bits_per_symbol, sym); } // decode payload, returning flag if decoded payload is valid return packetizer_decode(_q->p, _q->payload_enc, _payload); } // decode packet from modulated frame samples, returning flag if CRC passed // _q : qpacketmodem object // _frame : encoded/modulated payload symbols // _payload : recovered decoded payload bytes int qpacketmodem_decode_soft(qpacketmodem _q, float complex * _frame, unsigned char * _payload) { unsigned int i; // demodulate and pack bytes into decoder input buffer unsigned int sym; //memset(_q->payload_enc, 0x00, _q->payload_enc_len*sizeof(unsigned char)); unsigned int n = 0; for (i=0; i<_q->payload_mod_len; i++) { // demodulate symbol modem_demodulate_soft(_q->mod_payload, _frame[i], &sym, _q->payload_enc+n); n += _q->bits_per_symbol; } //printf("received %u bits (expected %u)\n", n, _q->payload_mod_len * _q->bits_per_symbol); assert( n == _q->payload_mod_len * _q->bits_per_symbol); // decode payload, returning flag if decoded payload is valid return packetizer_decode_soft(_q->p, _q->payload_enc, _payload); } liquid-dsp-1.3.1/src/framing/src/qpilotgen.c000066400000000000000000000115231317124540100207360ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // qpilotgen.c // // pilot injection // #include #include #include #include #include #include #include #include "liquid.internal.h" struct qpilotgen_s { // properties unsigned int payload_len; // number of samples in payload unsigned int pilot_spacing; // spacing between pilot symbols unsigned int num_pilots; // total number of pilot symbols unsigned int frame_len; // total number of frame symbols float complex * pilots; // pilot sequence }; // create packet encoder qpilotgen qpilotgen_create(unsigned int _payload_len, unsigned int _pilot_spacing) { // validate input if (_payload_len == 0) { fprintf(stderr,"error: qpilotgen_create(), frame length must be at least 1 symbol\n"); exit(1); } else if (_pilot_spacing < 2) { fprintf(stderr,"error: qpilotgen_create(), pilot spacing must be at least 2 symbols\n"); exit(1); } unsigned int i; // allocate memory for main object qpilotgen q = (qpilotgen) malloc(sizeof(struct qpilotgen_s)); // set internal properties q->payload_len = _payload_len; q->pilot_spacing = _pilot_spacing; // derived values div_t d = div(q->payload_len,(q->pilot_spacing - 1)); q->num_pilots = d.quot + (d.rem ? 1 : 0); q->frame_len = q->payload_len + q->num_pilots; // allocate memory for pilots q->pilots = (float complex*) malloc(q->num_pilots*sizeof(float complex)); // find appropriate sequence size unsigned int m = liquid_nextpow2(q->num_pilots); // generate pilot sequence msequence seq = msequence_create_default(m); for (i=0; inum_pilots; i++) { // generate symbol unsigned int s = msequence_generate_symbol(seq, 2); // save modulated symbol float theta = (2 * M_PI * (float)s / 4.0f) + M_PI / 4.0f; q->pilots[i] = cexpf(_Complex_I*theta); } msequence_destroy(seq); // return pointer to main object return q; } // recreate packet encoder qpilotgen qpilotgen_recreate(qpilotgen _q, unsigned int _payload_len, unsigned int _pilot_spacing) { // TODO: only re-generate objects as necessary // destroy object if (_q != NULL) qpilotgen_destroy(_q); // create new object return qpilotgen_create(_payload_len, _pilot_spacing); } void qpilotgen_destroy(qpilotgen _q) { // free arrays free(_q->pilots); // free main object memory free(_q); } void qpilotgen_reset(qpilotgen _q) { } void qpilotgen_print(qpilotgen _q) { printf("qpilotgen:\n"); printf(" payload len : %u\n", _q->payload_len); printf(" pilot spacing : %u\n", _q->pilot_spacing); printf(" num pilots : %u\n", _q->num_pilots); printf(" frame len : %u\n", _q->frame_len); } // get length of frame in symbols unsigned int qpilotgen_get_frame_len(qpilotgen _q) { return _q->frame_len; } // encode packet into modulated frame samples // TODO: include method with just symbol indices? would be useful for // non-linear modulation types void qpilotgen_execute(qpilotgen _q, float complex * _payload, float complex * _frame) { unsigned int i; unsigned int n = 0; unsigned int p = 0; for (i=0; i<_q->frame_len; i++) { if ( (i % _q->pilot_spacing)==0 ) _frame[i] = _q->pilots[p++]; else _frame[i] = _payload[n++]; } //printf("n = %u (expected %u)\n", n, _q->payload_len); //printf("p = %u (expected %u)\n", p, _q->num_pilots); assert(n == _q->payload_len); assert(p == _q->num_pilots); } liquid-dsp-1.3.1/src/framing/src/qpilotsync.c000066400000000000000000000235151317124540100211450ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // qpilotsync.c // // pilot injection // #include #include #include #include #include #include #include #include "liquid.internal.h" #define DEBUG_QPILOTSYNC 0 struct qpilotsync_s { // properties unsigned int payload_len; // number of samples in payload unsigned int pilot_spacing; // spacing between pilot symbols unsigned int num_pilots; // total number of pilot symbols unsigned int frame_len; // total number of frame symbols float complex * pilots; // pilot sequence unsigned int nfft; // FFT size float complex * buf_time; // FFT time buffer float complex * buf_freq; // FFT freq buffer fftplan fft; // transform object float dphi_hat; // carrier frequency offset estimate float phi_hat; // carrier phase offset estimate float g_hat; // gain correction estimate }; // create packet encoder qpilotsync qpilotsync_create(unsigned int _payload_len, unsigned int _pilot_spacing) { // validate input if (_payload_len == 0) { fprintf(stderr,"error: qpilotsync_create(), frame length must be at least 1 symbol\n"); exit(1); } else if (_pilot_spacing < 2) { fprintf(stderr,"error: qpilotsync_create(), pilot spacing must be at least 2 symbols\n"); exit(1); } unsigned int i; // allocate memory for main object qpilotsync q = (qpilotsync) malloc(sizeof(struct qpilotsync_s)); // set internal properties q->payload_len = _payload_len; q->pilot_spacing = _pilot_spacing; // derived values div_t d = div(q->payload_len,(q->pilot_spacing - 1)); q->num_pilots = d.quot + (d.rem ? 1 : 0); q->frame_len = q->payload_len + q->num_pilots; // allocate memory for pilots q->pilots = (float complex*) malloc(q->num_pilots*sizeof(float complex)); // find appropriate sequence size unsigned int m = liquid_nextpow2(q->num_pilots); // generate pilot sequence msequence seq = msequence_create_default(m); for (i=0; inum_pilots; i++) { // generate symbol unsigned int s = msequence_generate_symbol(seq, 2); // save modulated symbol float theta = (2 * M_PI * (float)s / 4.0f) + M_PI / 4.0f; q->pilots[i] = cexpf(_Complex_I*theta); } msequence_destroy(seq); // compute fft size and create transform objects q->nfft = 1 << liquid_nextpow2(q->num_pilots + (q->num_pilots>>1)); q->buf_time = (float complex*) malloc(q->nfft*sizeof(float complex)); q->buf_freq = (float complex*) malloc(q->nfft*sizeof(float complex)); q->fft = fft_create_plan(q->nfft, q->buf_time, q->buf_freq, LIQUID_FFT_FORWARD, 0); // reset and return pointer to main object qpilotsync_reset(q); return q; } // recreate packet encoder qpilotsync qpilotsync_recreate(qpilotsync _q, unsigned int _payload_len, unsigned int _pilot_spacing) { // TODO: only re-generate objects as necessary // destroy object if (_q != NULL) qpilotsync_destroy(_q); // create new object return qpilotsync_create(_payload_len, _pilot_spacing); } void qpilotsync_destroy(qpilotsync _q) { // free arrays free(_q->pilots); free(_q->buf_time); free(_q->buf_freq); // destroy objects fft_destroy_plan(_q->fft); // free main object memory free(_q); } void qpilotsync_reset(qpilotsync _q) { // clear FFT input buffer unsigned int i; for (i=0; i<_q->nfft; i++) _q->buf_time[i] = 0.0f; // reset estimates _q->dphi_hat = 0.0f; _q->phi_hat = 0.0f; _q->g_hat = 1.0f; } void qpilotsync_print(qpilotsync _q) { printf("qpilotsync:\n"); printf(" payload len : %u\n", _q->payload_len); printf(" pilot spacing : %u\n", _q->pilot_spacing); printf(" num pilots : %u\n", _q->num_pilots); printf(" frame len : %u\n", _q->frame_len); printf(" nfft : %u\n", _q->nfft); } // get length of frame in symbols unsigned int qpilotsync_get_frame_len(qpilotsync _q) { return _q->frame_len; } // encode packet into modulated frame samples // TODO: include method with just symbol indices? would be useful for // non-linear modulation types void qpilotsync_execute(qpilotsync _q, float complex * _frame, float complex * _payload) { unsigned int i; unsigned int n = 0; unsigned int p = 0; // extract pilots and de-rotate with known sequence for (i=0; i<_q->num_pilots; i++) { _q->buf_time[i] = _frame[i*_q->pilot_spacing] * conjf(_q->pilots[i]); #if DEBUG_QPILOTSYNC printf("(%8.4f,%8.4f) = (%8.4f,%8.4f) * conj(%8.4f,%8.4f)\n", crealf(_q->buf_time[i]), cimagf(_q->buf_time[i]), crealf(_frame[i*_q->pilot_spacing]), cimagf(_frame[i*_q->pilot_spacing]), crealf(_q->pilots[i]), cimagf(_q->pilots[i])); #endif } // compute frequency offset by computing transform and finding peak fft_execute(_q->fft); unsigned int i0 = 0; float y0 = 0; for (i=0; i<_q->nfft; i++) { #if DEBUG_QPILOTSYNC printf("X(%3u) = %12.8f + 1i*%12.8f; %% %12.8f\n", i+1, crealf(_q->buf_freq[i]), cimagf(_q->buf_freq[i]), cabsf(_q->buf_freq[i])); #endif if (i==0 || cabsf(_q->buf_freq[i]) > y0) { i0 = i; y0 = cabsf(_q->buf_freq[i]); } } // interpolate and recover frequency unsigned int ineg = (i0 + _q->nfft - 1) % _q->nfft; unsigned int ipos = (i0 + 1) % _q->nfft; float ypos = cabsf(_q->buf_freq[ipos]); float yneg = cabsf(_q->buf_freq[ineg]); float a = 0.5f*(ypos + yneg) - y0; float b = 0.5f*(ypos - yneg); //float c = y0; float idx = -b / (2.0f*a); //-0.5f*(ypos - yneg) / (ypos + yneg - 2*y0); float index = (float)i0 + idx; _q->dphi_hat = (i0 > _q->nfft/2 ? index-(float)_q->nfft : index) * 2*M_PI / (float)(_q->nfft * _q->pilot_spacing); #if DEBUG_QPILOTSYNC printf("X[%3u] = %12.8f <%12.8f>\n", ineg, yneg, cargf(_q->buf_freq[ineg])); printf("X[%3u] = %12.8f <%12.8f>\n", i0, y0, cargf(_q->buf_freq[i0])); printf("X[%3u] = %12.8f <%12.8f>\n", ipos, ypos, cargf(_q->buf_freq[ipos])); printf("yneg = %12.8f;\n", yneg); printf("ypos = %12.8f;\n", ypos); printf("y0 = %12.8f;\n", y0); printf("interpolated peak at %12.8f (%u + %12.8f)\n", index, i0, idx); #endif // estimate carrier phase offset #if 0 // METHOD 1: linear interpolation of phase in FFT output buffer float v0 = cargf(_q->buf_freq[ idx < 0 ? ineg : i0 ]); float v1 = cargf(_q->buf_freq[ idx < 0 ? i0 : ipos ]); float xp = idx < 0 ? 1+idx : idx; float phi_hat = (v1-v0)*xp + v0; //printf("v0 = %12.8f, v1 = %12.8f, xp = %12.8f\n", v0, v1, xp); // channel gain: use quadratic interpolation of FFT amplitude to find peak // correlation output in the frequency domain float g_hat = (a*idx*idx + b*idx + c) / (float)(_q->num_pilots); #else // METHOD 2: compute metric by de-rotating pilots and measuring resulting phase // NOTE: this is possibly more accurate than the above method but might also // be more computationally complex float complex metric = 0; for (i=0; i<_q->num_pilots; i++) metric += _q->buf_time[i] * cexpf(-_Complex_I*_q->dphi_hat*i*(float)(_q->pilot_spacing)); //printf("metric : %12.8f <%12.8f>\n", cabsf(metric), cargf(metric)); _q->phi_hat = cargf(metric); _q->g_hat = cabsf(metric) / (float)(_q->num_pilots); #endif #if DEBUG_QPILOTSYNC // print estimates of carrier frequency, phase, gain printf("dphi-hat : %12.8f\n", _q->dphi_hat); printf(" phi-hat : %12.8f\n", _q->phi_hat); printf(" g-hat : %12.8f\n", _q->g_hat); #endif // frequency correction float g = 1.0f / _q->g_hat; // recover frame symbols for (i=0; i<_q->frame_len; i++) { if ( (i % _q->pilot_spacing)==0 ) p++; else _payload[n++] = g * _frame[i] * cexpf(-_Complex_I*(_q->dphi_hat*i + _q->phi_hat)); } #if DEBUG_QPILOTSYNC printf("n = %u (expected %u)\n", n, _q->payload_len); printf("p = %u (expected %u)\n", p, _q->num_pilots); assert(n == _q->payload_len); assert(p == _q->num_pilots); #endif } // get estimates float qpilotsync_get_dphi(qpilotsync _q) { return _q->dphi_hat; } float qpilotsync_get_phi(qpilotsync _q) { return _q->phi_hat; } float qpilotsync_get_gain(qpilotsync _q) { return _q->g_hat; } liquid-dsp-1.3.1/src/framing/src/symstream.c000066400000000000000000000127461317124540100207700ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Symbol streaming generator // #include #include #include #include // internal structure struct SYMSTREAM(_s) { int filter_type; // filter type (e.g. LIQUID_RNYQUIST_RKAISER) unsigned int k; // samples/symbol unsigned int m; // filter semi-length float beta; // filter excess bandwidth int mod_scheme; // demodulator MODEM() mod; // modulator FIRINTERP() interp; // interpolator TO * buf; // output buffer unsigned int buf_index; // output buffer sample index }; // create symstream object using default parameters SYMSTREAM() SYMSTREAM(_create)() { return SYMSTREAM(_create_linear)(LIQUID_FIRFILT_ARKAISER, 2, // samples/symbol 7, // filter delay 0.3f, // filter excess bandwidth LIQUID_MODEM_QPSK); } // create symstream object with linear modulation // _ftype : filter type (e.g. LIQUID_RNYQUIST_RRC) // _k : samples per symbol // _m : filter delay (symbols) // _beta : filter excess bandwidth // _ms : modulation scheme (e.g. LIQUID_MODEM_QPSK) SYMSTREAM() SYMSTREAM(_create_linear)(int _ftype, unsigned int _k, unsigned int _m, float _beta, int _ms) { // validate input if (_k < 2) { fprintf(stderr,"error: symstream%s_create(), samples/symbol must be at least 2\n", EXTENSION); exit(1); } else if (_m == 0) { fprintf(stderr,"error: symstream%s_create(), filter delay must be greater than zero\n", EXTENSION); exit(1); } else if (_beta <= 0.0f || _beta > 1.0f) { fprintf(stderr,"error: symstream%s_create(), filter excess bandwidth must be in (0,1]\n", EXTENSION); exit(1); } else if (_ms == LIQUID_MODEM_UNKNOWN || _ms >= LIQUID_MODEM_NUM_SCHEMES) { fprintf(stderr,"error: symstream%s_create(), invalid modulation scheme\n", EXTENSION); exit(1); } // allocate memory for main object SYMSTREAM() q = (SYMSTREAM()) malloc( sizeof(struct SYMSTREAM(_s)) ); // set input parameters q->filter_type = _ftype; q->k = _k; q->m = _m; q->beta = _beta; q->mod_scheme = _ms; // modulator q->mod = MODEM(_create)(q->mod_scheme); // interpolator q->interp = FIRINTERP(_create_prototype)(q->filter_type, q->k, q->m, q->beta, 0); // sample buffer q->buf = (TO*) malloc(q->k*sizeof(TO)); // reset and return main object SYMSTREAM(_reset)(q); return q; } // destroy symstream object, freeing all internal memory void SYMSTREAM(_destroy)(SYMSTREAM() _q) { // destroy objects MODEM (_destroy)(_q->mod); FIRINTERP(_destroy)(_q->interp); free(_q->buf); // free main object free(_q); } // print symstream object's parameters void SYMSTREAM(_print)(SYMSTREAM() _q) { printf("symstream_%s:\n", EXTENSION); } // reset symstream internal state void SYMSTREAM(_reset)(SYMSTREAM() _q) { // reset objects and counter MODEM(_reset)(_q->mod); FIRINTERP(_reset)(_q->interp); _q->buf_index = 0; } // fill buffer with samples void SYMSTREAM(_fill_buffer)(SYMSTREAM() _q) { // generate random symbol unsigned int sym = MODEM(_gen_rand_sym)(_q->mod); // modulate TO v; MODEM(_modulate)(_q->mod, sym, &v); // interpolate FIRINTERP(_execute)(_q->interp, v, _q->buf); } // write block of samples to output buffer // _q : synchronizer object // _buf : output buffer [size: _buf_len x 1] // _buf_len: output buffer size void SYMSTREAM(_write_samples)(SYMSTREAM() _q, TO * _buf, unsigned int _buf_len) { unsigned int i; for (i=0; i<_buf_len; i++) { // check to see if buffer needs samples if (_q->buf_index==0) SYMSTREAM(_fill_buffer)(_q); // write output sample from internal buffer _buf[i] = _q->buf[_q->buf_index]; // increment internal index _q->buf_index = (_q->buf_index + 1) % _q->k; } } liquid-dsp-1.3.1/src/framing/src/symstreamcf.c000066400000000000000000000032371317124540100212740ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // API: floating-point // #include "liquid.internal.h" // naming extensions (useful for print statements) #define EXTENSION "cf" #define TO float complex // output type #define T float // primitive type #define TO_COMPLEX 1 #define T_COMPLEX 0 // object references #define SYMSTREAM(name) LIQUID_CONCAT(symstreamcf,name) #define MODEM(name) LIQUID_CONCAT(modem,name) #define FIRINTERP(name) LIQUID_CONCAT(firinterp_crcf,name) // source files #include "symstream.c" liquid-dsp-1.3.1/src/framing/src/symtrack.c000066400000000000000000000245651317124540100206030ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Symbol tracker/synchronizer // #include #include #include #include #define DEBUG_SYMTRACK 0 #define DEBUG_SYMTRACK_PRINT 0 #define DEBUG_SYMTRACK_FILENAME "symtrack_internal_debug.m" #define DEBUG_BUFFER_LEN (1024) // // forward declaration of internal methods // // internal structure struct SYMTRACK(_s) { // parameters int filter_type; // filter type (e.g. LIQUID_RNYQUIST_RKAISER) unsigned int k; // samples/symbol unsigned int m; // filter semi-length float beta; // filter excess bandwidth int mod_scheme; // demodulator // automatic gain control AGC() agc; // agc object float agc_bandwidth; // agc bandwidth // symbol timing recovery SYMSYNC() symsync; // symbol timing recovery object float symsync_bandwidth; // symsync loop bandwidth TO symsync_buf[8]; // symsync output buffer unsigned int symsync_index; // symsync output sample index // equalizer/decimator EQLMS() eq; // equalizer (LMS) unsigned int eq_len; // equalizer length float eq_bandwidth; // equalizer bandwidth // nco/phase-locked loop NCO() nco; // nco (carrier recovery) float pll_bandwidth; // phase-locked loop bandwidth // demodulator MODEM() demod; // linear modem demodulator // state and counters unsigned int num_syms_rx; // number of symbols recovered }; // create symtrack object with basic parameters // _ftype : filter type (e.g. LIQUID_RNYQUIST_RRC) // _k : samples per symbol // _m : filter delay (symbols) // _beta : filter excess bandwidth // _ms : modulation scheme (e.g. LIQUID_MODEM_QPSK) SYMTRACK() SYMTRACK(_create)(int _ftype, unsigned int _k, unsigned int _m, float _beta, int _ms) { // validate input if (_m == 0) { fprintf(stderr,"error: symtrack_%s_create(), filter delay must be greater than zero\n", EXTENSION_FULL); exit(1); } else if (_beta <= 0.0f || _beta > 1.0f) { fprintf(stderr,"error: symtrack_%s_create(), filter excess bandwidth must be in (0,1]\n", EXTENSION_FULL); exit(1); } else if (_ms == LIQUID_MODEM_UNKNOWN || _ms >= LIQUID_MODEM_NUM_SCHEMES) { fprintf(stderr,"error: symtrack_%s_create(), invalid modulation scheme\n", EXTENSION_FULL); exit(1); } // allocate memory for main object SYMTRACK() q = (SYMTRACK()) malloc( sizeof(struct SYMTRACK(_s)) ); // set input parameters q->filter_type = _ftype; q->k = _k; q->m = _m; q->beta = _beta; q->mod_scheme = _ms == LIQUID_MODEM_UNKNOWN ? LIQUID_MODEM_BPSK : _ms; // create automatic gain control q->agc = AGC(_create)(); // create symbol synchronizer (output rate: 2 samples per symbol) if (q->filter_type == LIQUID_FIRFILT_UNKNOWN) q->symsync = SYMSYNC(_create_kaiser)(q->k, q->m, 0.9f, 16); else q->symsync = SYMSYNC(_create_rnyquist)(q->filter_type, q->k, q->m, q->beta, 16); SYMSYNC(_set_output_rate)(q->symsync, 2); // create equalizer as default low-pass filter with integer symbol delay (2 samples/symbol) q->eq_len = 2 * 4 + 1; q->eq = EQLMS(_create_lowpass)(q->eq_len,0.45f); // nco and phase-locked loop q->nco = NCO(_create)(LIQUID_VCO); // demodulator q->demod = MODEM(_create)(q->mod_scheme); // set default bandwidth SYMTRACK(_set_bandwidth)(q, 0.9f); // reset and return main object SYMTRACK(_reset)(q); return q; } // create symtrack object using default parameters SYMTRACK() SYMTRACK(_create_default)() { return SYMTRACK(_create)(LIQUID_FIRFILT_ARKAISER, 2, // samples/symbol 7, // filter delay 0.3f, // filter excess bandwidth LIQUID_MODEM_QPSK); } // destroy symtrack object, freeing all internal memory void SYMTRACK(_destroy)(SYMTRACK() _q) { // destroy objects AGC (_destroy)(_q->agc); SYMSYNC(_destroy)(_q->symsync); EQLMS (_destroy)(_q->eq); NCO (_destroy)(_q->nco); MODEM (_destroy)(_q->demod); // free main object free(_q); } // print symtrack object's parameters void SYMTRACK(_print)(SYMTRACK() _q) { printf("symtrack_%s:\n", EXTENSION_FULL); } // reset symtrack internal state void SYMTRACK(_reset)(SYMTRACK() _q) { // reset objects // reset internal counters _q->symsync_index = 0; _q->num_syms_rx = 0; } // set symtrack modulation scheme void SYMTRACK(_set_modscheme)(SYMTRACK() _q, int _ms) { // validate input if (_ms == LIQUID_MODEM_UNKNOWN || _ms >= LIQUID_MODEM_NUM_SCHEMES) { fprintf(stderr,"error: symtrack_%s_set_modscheme(), invalid/unsupported modulation scheme\n", EXTENSION_FULL); exit(1); } // set internal modulation scheme _q->mod_scheme = _ms; // re-create modem _q->demod = MODEM(_recreate)(_q->demod, _q->mod_scheme); } // set symtrack internal bandwidth void SYMTRACK(_set_bandwidth)(SYMTRACK() _q, float _bw) { // validate input if (_bw < 0) { fprintf(stderr,"error: symtrack_%s_set_bandwidth(), bandwidth must be in [0,1]\n", EXTENSION_FULL); exit(1); } // set bandwidths accordingly // TODO: set bandwidths based on input bandwidth float agc_bandwidth = 0.02f * _bw; float symsync_bandwidth = 0.001f * _bw; float eq_bandwidth = 0.02f * _bw; float pll_bandwidth = 0.001f * _bw; // automatic gain control AGC(_set_bandwidth)(_q->agc, agc_bandwidth); // symbol timing recovery SYMSYNC(_set_lf_bw)(_q->symsync, symsync_bandwidth); // equalizer EQLMS(_set_bw)(_q->eq, eq_bandwidth); // phase-locked loop NCO(_pll_set_bandwidth)(_q->nco, pll_bandwidth); } // adjust internal nco by requested phase void SYMTRACK(_adjust_phase)(SYMTRACK() _q, T _dphi) { // adjust internal nco phase NCO(_adjust_phase)(_q->nco, _dphi); } // execute synchronizer on single input sample // _q : synchronizer object // _x : input data sample // _y : output data array // _ny : number of samples written to output buffer void SYMTRACK(_execute)(SYMTRACK() _q, TI _x, TO * _y, unsigned int * _ny) { TO v; // output sample unsigned int i; unsigned int num_outputs = 0; // run sample through automatic gain control AGC(_execute)(_q->agc, _x, &v); // symbol synchronizer unsigned int nw = 0; SYMSYNC(_execute)(_q->symsync, &v, 1, _q->symsync_buf, &nw); // process each output sample for (i=0; inco); nco_crcf_mix_down(_q->nco, _q->symsync_buf[i], &v); // equalizer/decimator EQLMS(_push)(_q->eq, v); // decimate result, noting that symsync outputs at exactly 2 samples/symbol _q->symsync_index++; if ( !(_q->symsync_index % 2) ) continue; // increment number of symbols received _q->num_syms_rx++; // compute equalizer output TO d_hat; EQLMS(_execute)(_q->eq, &d_hat); // demodulate result, apply phase correction unsigned int sym_out; MODEM(_demodulate)(_q->demod, d_hat, &sym_out); float phase_error = MODEM(_get_demodulator_phase_error)(_q->demod); // update equalizer independent of the signal: estimate error // assuming constant modulus signal // TODO: use decision-directed feedback when modulation scheme is known // TODO: check lock conditions of previous object to determine when to run equalizer if (_q->num_syms_rx > 200) EQLMS(_step)(_q->eq, d_hat/cabsf(d_hat), d_hat); // update pll NCO(_pll_step)(_q->nco, phase_error); // save result to output _y[num_outputs++] = d_hat; } #if DEBUG_SYMTRACK printf("symsync wrote %u samples, %u outputs\n", nw, num_outputs); #endif // *_ny = num_outputs; } // execute synchronizer on input data array // _q : synchronizer object // _x : input data array // _nx : number of input samples // _y : output data array // _ny : number of samples written to output buffer void SYMTRACK(_execute_block)(SYMTRACK() _q, TI * _x, unsigned int _nx, TO * _y, unsigned int * _ny) { // unsigned int i; unsigned int num_written = 0; // for (i=0; i<_nx; i++) { unsigned int nw = 0; SYMTRACK(_execute)(_q, _x[i], &_y[num_written], &nw); num_written += nw; } // *_ny = num_written; } liquid-dsp-1.3.1/src/framing/src/symtrack_cccf.c000066400000000000000000000040551317124540100215510ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Framing API: floating-point // #include "liquid.internal.h" // naming extensions (useful for print statements) #define EXTENSION_SHORT "f" #define EXTENSION_FULL "cccf" #define PRINTVAL(x) printf("%12.4e + j%12.4e", crealf(x), cimagf(x)) #define T float #define TO float complex #define TC float complex #define TI float complex #define ABS(X) cabsf(X) // object references #define SYMTRACK(name) LIQUID_CONCAT(symtrack_cccf,name) #define AGC(name) LIQUID_CONCAT(agc_crcf,name) #define SYMSYNC(name) LIQUID_CONCAT(symsync_crcf,name) #define EQLMS(name) LIQUID_CONCAT(eqlms_cccf,name) #define NCO(name) LIQUID_CONCAT(nco_crcf,name) #define MODEM(name) LIQUID_CONCAT(modem,name) #define TO_COMPLEX 1 #define TC_COMPLEX 1 #define TI_COMPLEX 1 // source files #include "symtrack.c" liquid-dsp-1.3.1/src/framing/tests/000077500000000000000000000000001317124540100171415ustar00rootroot00000000000000liquid-dsp-1.3.1/src/framing/tests/bpacketsync_autotest.c000066400000000000000000000064561317124540100235560ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "autotest/autotest.h" #include "liquid.h" static int bpacketsync_autotest_callback(unsigned char * _payload, int _payload_valid, unsigned int _payload_len, framesyncstats_s _stats, void * _userdata) { if (!_payload_valid) return 0; unsigned int * num_packets_found = (unsigned int *) _userdata; *num_packets_found += 1; return 0; } // // AUTOTEST: bpacketsync // void autotest_bpacketsync() { // options unsigned int num_packets = 50; // number of packets to encode unsigned int dec_msg_len = 64; // original data message length crc_scheme check = LIQUID_CRC_32; // data integrity check fec_scheme fec0 = LIQUID_FEC_HAMMING74; // inner code fec_scheme fec1 = LIQUID_FEC_NONE; // outer code // create packet generator bpacketgen pg = bpacketgen_create(0, dec_msg_len, check, fec0, fec1); if (liquid_autotest_verbose) bpacketgen_print(pg); // compute packet length unsigned int enc_msg_len = bpacketgen_get_packet_len(pg); // initialize arrays unsigned char msg_org[dec_msg_len]; // original message unsigned char msg_enc[enc_msg_len]; // encoded message unsigned int num_packets_found=0; // create packet synchronizer bpacketsync ps = bpacketsync_create(0, bpacketsync_autotest_callback, (void*)&num_packets_found); unsigned int i; unsigned int n; for (n=0; n #include #include #include "autotest/autotest.h" #include "liquid.h" // // AUTOTEST : test simple recovery of frame in noise // void autotest_flexframesync() { unsigned int i; unsigned int _payload_len = 400; int _ms = LIQUID_MODEM_QPSK; int _fec0 = LIQUID_FEC_NONE; int _fec1 = LIQUID_FEC_NONE; int _check = LIQUID_CRC_32; // create flexframegen object flexframegenprops_s fgprops; flexframegenprops_init_default(&fgprops); fgprops.mod_scheme = _ms; fgprops.check = _check; fgprops.fec0 = _fec0; fgprops.fec1 = _fec1; flexframegen fg = flexframegen_create(&fgprops); // create flexframesync object flexframesync fs = flexframesync_create(NULL,NULL); // initialize header and payload unsigned char header[14] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; unsigned char payload[_payload_len]; for (i=0; i<_payload_len; i++) payload[i] = rand() & 0xff; // assemble the frame flexframegen_assemble(fg, header, payload, _payload_len); if (liquid_autotest_verbose) flexframegen_print(fg); // generate the frame int frame_complete = 0; float complex buf[2]; while (!frame_complete) { // write samples to buffer frame_complete = flexframegen_write_samples(fg, buf, 2); // run through frame synchronizer flexframesync_execute(fs, buf, 2); } // get frame data statistics framedatastats_s stats = flexframesync_get_framedatastats(fs); if (liquid_autotest_verbose) flexframesync_print(fs); // check to see that frame was recovered CONTEND_EQUALITY( stats.num_frames_detected, 1 ); CONTEND_EQUALITY( stats.num_headers_valid, 1 ); CONTEND_EQUALITY( stats.num_payloads_valid, 1 ); CONTEND_EQUALITY( stats.num_bytes_received, _payload_len ); // destroy objects flexframegen_destroy(fg); flexframesync_destroy(fs); } liquid-dsp-1.3.1/src/framing/tests/framesync64_autotest.c000066400000000000000000000056461317124540100234110ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "autotest/autotest.h" #include "liquid.h" static int callback(unsigned char * _header, int _header_valid, unsigned char * _payload, unsigned int _payload_len, int _payload_valid, framesyncstats_s _stats, void * _userdata) { //printf("callback invoked, payload valid: %s\n", _payload_valid ? "yes" : "no"); int * frame_recovered = (int*) _userdata; if (_header_valid && _payload_valid) *frame_recovered = 1; else *frame_recovered = 0; return 0; } // // AUTOTEST : test simple recovery of frame in noise // void autotest_framesync64() { unsigned int i; framegen64 fg = framegen64_create(); // frame data unsigned char header[8] = {0, 1, 2, 3, 4, 5, 6, 7}; unsigned char payload[64]; // initialize payload for (i=0; i<64; i++) payload[i] = rand() & 0xff; // create framesync64 object int frame_recovered = 0; framesync64 fs = framesync64_create(callback,(void*)&frame_recovered); if (liquid_autotest_verbose) { framesync64_print(fs); framegen64_print(fg); } // generate the frame unsigned int frame_len = LIQUID_FRAME64_LEN; float complex frame[frame_len]; framegen64_execute(fg, header, payload, frame); // add some noise for (i=0; i #include #include "autotest/autotest.h" #include "liquid.h" // autotest helper functions // _sequence_len : sequence length void qdetector_cccf_runtest_linear(unsigned int _sequence_len); void qdetector_cccf_runtest_gmsk (unsigned int _sequence_len); // // AUTOTESTS // // linear tests void autotest_qdetector_cccf_linear_n64() { qdetector_cccf_runtest_linear( 64); } void autotest_qdetector_cccf_linear_n83() { qdetector_cccf_runtest_linear( 83); } void autotest_qdetector_cccf_linear_n128() { qdetector_cccf_runtest_linear( 128); } void autotest_qdetector_cccf_linear_n167() { qdetector_cccf_runtest_linear( 167); } void autotest_qdetector_cccf_linear_n256() { qdetector_cccf_runtest_linear( 256); } void autotest_qdetector_cccf_linear_n335() { qdetector_cccf_runtest_linear( 335); } void autotest_qdetector_cccf_linear_n512() { qdetector_cccf_runtest_linear( 512); } void autotest_qdetector_cccf_linear_n671() { qdetector_cccf_runtest_linear( 671); } void autotest_qdetector_cccf_linear_n1024() { qdetector_cccf_runtest_linear(1024); } void autotest_qdetector_cccf_linear_n1341() { qdetector_cccf_runtest_linear(1341); } // gmsk tests void autotest_qdetector_cccf_gmsk_n64() { qdetector_cccf_runtest_gmsk ( 64); } void autotest_qdetector_cccf_gmsk_n83() { qdetector_cccf_runtest_gmsk ( 83); } void autotest_qdetector_cccf_gmsk_n128() { qdetector_cccf_runtest_gmsk ( 128); } void autotest_qdetector_cccf_gmsk_n167() { qdetector_cccf_runtest_gmsk ( 167); } void autotest_qdetector_cccf_gmsk_n256() { qdetector_cccf_runtest_gmsk ( 256); } void autotest_qdetector_cccf_gmsk_n335() { qdetector_cccf_runtest_gmsk ( 335); } void autotest_qdetector_cccf_gmsk_n512() { qdetector_cccf_runtest_gmsk ( 512); } void autotest_qdetector_cccf_gmsk_n671() { qdetector_cccf_runtest_gmsk ( 671); } void autotest_qdetector_cccf_gmsk_n1024() { qdetector_cccf_runtest_gmsk (1024); } void autotest_qdetector_cccf_gmsk_n1341() { qdetector_cccf_runtest_gmsk (1341); } // autotest helper function // _sequence_len : sequence length void qdetector_cccf_runtest_linear(unsigned int _sequence_len) { unsigned int k = 2; // samples per symbol unsigned int m = 7; // filter delay [symbols] float beta = 0.3f; // excess bandwidth factor int ftype = LIQUID_FIRFILT_ARKAISER; // filter type float gamma = 1.0f; // channel gain float tau = -0.3f; // fractional sample timing offset float dphi = -0.000f; // carrier frequency offset (zero for now) float phi = 0.5f; // carrier phase offset unsigned int i; // derived values unsigned int num_symbols = 8*_sequence_len + 2*m; unsigned int num_samples = k * num_symbols; // arrays float complex x[num_samples]; // transmitted signal float complex y[num_samples]; // received signal // generate synchronization sequence (QPSK symbols) float complex sequence[_sequence_len]; for (i=0; i<_sequence_len; i++) { sequence[i] = (rand() % 2 ? 1.0f : -1.0f) * M_SQRT1_2 + (rand() % 2 ? 1.0f : -1.0f) * M_SQRT1_2 * _Complex_I; } // generate transmitted signal firinterp_crcf interp = firinterp_crcf_create_prototype(ftype, k, m, beta, -tau); unsigned int n = 0; for (i=0; i #include #include #include "autotest/autotest.h" #include "liquid.h" // // AUTOTEST : test simple recovery of frame // void qpacketmodem_modulated(unsigned int _payload_len, int _check, int _fec0, int _fec1, int _ms) { // derived values unsigned int i; // create and configure packet encoder/decoder object qpacketmodem q = qpacketmodem_create(); qpacketmodem_configure(q, _payload_len, _check, _fec0, _fec1, _ms); if (liquid_autotest_verbose) qpacketmodem_print(q); // initialize payload unsigned char payload_tx[_payload_len]; unsigned char payload_rx[_payload_len]; // initialize payload for (i=0; i<_payload_len; i++) { payload_tx[i] = rand() & 0xff; payload_rx[i] = rand() & 0xff; } // get frame length unsigned int frame_len = qpacketmodem_get_frame_len(q); // allocate memory for frame samples float complex frame[frame_len]; // encode frame qpacketmodem_encode(q, payload_tx, frame); // decode frame int crc_pass = qpacketmodem_decode_soft(q, frame, payload_rx); // destroy object qpacketmodem_destroy(q); // check to see that frame was recovered CONTEND_EQUALITY( crc_pass, 1 ); CONTEND_SAME_DATA( payload_tx, payload_rx, _payload_len ); } void autotest_qpacketmodem_bpsk() { qpacketmodem_modulated(400,LIQUID_CRC_32,LIQUID_FEC_NONE,LIQUID_FEC_NONE, LIQUID_MODEM_QPSK); } void autotest_qpacketmodem_qpsk() { qpacketmodem_modulated(400,LIQUID_CRC_32,LIQUID_FEC_NONE,LIQUID_FEC_NONE, LIQUID_MODEM_QPSK); } void autotest_qpacketmodem_psk8() { qpacketmodem_modulated(400,LIQUID_CRC_32,LIQUID_FEC_NONE,LIQUID_FEC_NONE, LIQUID_MODEM_PSK8); } void autotest_qpacketmodem_qam16() { qpacketmodem_modulated(400,LIQUID_CRC_32,LIQUID_FEC_NONE,LIQUID_FEC_NONE, LIQUID_MODEM_QAM16); } void autotest_qpacketmodem_sqam32() { qpacketmodem_modulated(400,LIQUID_CRC_32,LIQUID_FEC_NONE,LIQUID_FEC_NONE, LIQUID_MODEM_SQAM32); } void autotest_qpacketmodem_qam64() { qpacketmodem_modulated(400,LIQUID_CRC_32,LIQUID_FEC_NONE,LIQUID_FEC_NONE, LIQUID_MODEM_QAM64); } void autotest_qpacketmodem_sqam128(){ qpacketmodem_modulated(400,LIQUID_CRC_32,LIQUID_FEC_NONE,LIQUID_FEC_NONE, LIQUID_MODEM_SQAM128); } void autotest_qpacketmodem_qam256() { qpacketmodem_modulated(400,LIQUID_CRC_32,LIQUID_FEC_NONE,LIQUID_FEC_NONE, LIQUID_MODEM_QAM256); } // // AUTOTEST : test un-modulated frame symbols (hard-decision demod) // void qpacketmodem_unmodulated(unsigned int _payload_len, int _check, int _fec0, int _fec1, int _ms) { // derived values unsigned int i; // create and configure packet encoder/decoder object qpacketmodem q = qpacketmodem_create(); qpacketmodem_configure(q, _payload_len, _check, _fec0, _fec1, _ms); if (liquid_autotest_verbose) qpacketmodem_print(q); // initialize payload unsigned char payload_tx[_payload_len]; unsigned char payload_rx[_payload_len]; // initialize payload for (i=0; i<_payload_len; i++) { payload_tx[i] = rand() & 0xff; payload_rx[i] = rand() & 0xff; } // get frame length (symbols) unsigned int frame_len = qpacketmodem_get_frame_len(q); // allocate memory for frame samples unsigned char frame_syms[frame_len]; // encode frame symbols qpacketmodem_encode_syms(q, payload_tx, frame_syms); // decode frame symbols int crc_pass = qpacketmodem_decode_syms(q, frame_syms, payload_rx); // destroy object qpacketmodem_destroy(q); // check to see that frame was recovered CONTEND_EQUALITY( crc_pass, 1 ); CONTEND_SAME_DATA( payload_tx, payload_rx, _payload_len ); } void autotest_qpacketmodem_unmod_bpsk() { qpacketmodem_unmodulated(400,LIQUID_CRC_32,LIQUID_FEC_NONE,LIQUID_FEC_NONE, LIQUID_MODEM_QPSK); } void autotest_qpacketmodem_unmod_qpsk() { qpacketmodem_unmodulated(400,LIQUID_CRC_32,LIQUID_FEC_NONE,LIQUID_FEC_NONE, LIQUID_MODEM_QPSK); } void autotest_qpacketmodem_unmod_psk8() { qpacketmodem_unmodulated(400,LIQUID_CRC_32,LIQUID_FEC_NONE,LIQUID_FEC_NONE, LIQUID_MODEM_PSK8); } void autotest_qpacketmodem_unmod_qam16() { qpacketmodem_unmodulated(400,LIQUID_CRC_32,LIQUID_FEC_NONE,LIQUID_FEC_NONE, LIQUID_MODEM_QAM16); } void autotest_qpacketmodem_unmod_sqam32() { qpacketmodem_unmodulated(400,LIQUID_CRC_32,LIQUID_FEC_NONE,LIQUID_FEC_NONE, LIQUID_MODEM_SQAM32); } void autotest_qpacketmodem_unmod_qam64() { qpacketmodem_unmodulated(400,LIQUID_CRC_32,LIQUID_FEC_NONE,LIQUID_FEC_NONE, LIQUID_MODEM_QAM64); } void autotest_qpacketmodem_unmod_sqam128(){ qpacketmodem_unmodulated(400,LIQUID_CRC_32,LIQUID_FEC_NONE,LIQUID_FEC_NONE, LIQUID_MODEM_SQAM128); } void autotest_qpacketmodem_unmod_qam256() { qpacketmodem_unmodulated(400,LIQUID_CRC_32,LIQUID_FEC_NONE,LIQUID_FEC_NONE, LIQUID_MODEM_QAM256); } liquid-dsp-1.3.1/src/framing/tests/qpilotsync_autotest.c000066400000000000000000000166721317124540100234560ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "autotest/autotest.h" #include "liquid.h" #define DEBUG_QPILOTSYNC_AUTOTEST 0 // // AUTOTEST : test simple recovery of frame in noise // // _ms : modulation scheme (e.g. LIQUID_MODEM_QPSK) // _payload_len : payload length [symbols] // _pilot_spacing : spacing between pilot symbols // _dphi : carrier frequency offset // _phi : carrier phase offset // _gamma : channel gain // _SNRdB : signal-to-noise ratio [dB] void qpilotsync_test(modulation_scheme _ms, unsigned int _payload_len, unsigned int _pilot_spacing, float _dphi, float _phi, float _gamma, float _SNRdB) { unsigned int i; // derived values float nstd = powf(10.0f, -_SNRdB/20.0f); // create pilot generator and synchronizer objects qpilotgen pg = qpilotgen_create( _payload_len, _pilot_spacing); qpilotsync ps = qpilotsync_create(_payload_len, _pilot_spacing); // get frame length unsigned int frame_len = qpilotgen_get_frame_len(pg); // allocate arrays unsigned char payload_sym_tx[_payload_len]; // transmitted payload symbols float complex payload_tx [_payload_len]; // transmitted payload samples float complex frame_tx [frame_len]; // transmitted frame samples float complex frame_rx [frame_len]; // received frame samples float complex payload_rx [_payload_len]; // received payload samples unsigned char payload_sym_rx[_payload_len]; // received payload symbols // create modem objects for payload modem mod = modem_create(_ms); modem dem = modem_create(_ms); // assemble payload symbols for (i=0; i<_payload_len; i++) { // generate random symbol payload_sym_tx[i] = modem_gen_rand_sym(mod); // modulate modem_modulate(mod, payload_sym_tx[i], &payload_tx[i]); } // assemble frame qpilotgen_execute(pg, payload_tx, frame_tx); // add channel impairments for (i=0; i #include "liquid.h" // Helper function to keep code base small void polyf_fit_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _Q, unsigned int _N) { // normalize number of iterations // time ~ 0.2953 + 0.03381 * _N *_num_iterations /= 0.2953 + 0.03381 * _N; if (*_num_iterations < 1) *_num_iterations = 1; float p[_Q+1]; float x[_N]; float y[_N]; unsigned int i; for (i=0; i<_N; i++) { x[i] = randnf(); y[i] = randnf(); } // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { polyf_fit(x,y,_N, p,_Q+1); polyf_fit(x,y,_N, p,_Q+1); polyf_fit(x,y,_N, p,_Q+1); polyf_fit(x,y,_N, p,_Q+1); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; } #define POLYF_FIT_BENCHMARK_API(Q,N) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { polyf_fit_bench(_start, _finish, _num_iterations, Q, N); } void benchmark_polyf_fit_q3_n8 POLYF_FIT_BENCHMARK_API(3, 8) void benchmark_polyf_fit_q3_n16 POLYF_FIT_BENCHMARK_API(3, 16) void benchmark_polyf_fit_q3_n32 POLYF_FIT_BENCHMARK_API(3, 32) void benchmark_polyf_fit_q3_n64 POLYF_FIT_BENCHMARK_API(3, 64) void benchmark_polyf_fit_q3_n128 POLYF_FIT_BENCHMARK_API(3, 128) liquid-dsp-1.3.1/src/math/src/000077500000000000000000000000001317124540100160745ustar00rootroot00000000000000liquid-dsp-1.3.1/src/math/src/math.bessel.c000066400000000000000000000112631317124540100204500ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Bessel Functions // // liquid_lnbesselif : log modified Bessel function of the first kind // liquid_besselif : modified Bessel function of the first kind // liquid_besseli0f : modified Bessel function of the first kind (order 0) // liquid_besseljf : Bessel function of the first kind // liquid_besselj0f : Bessel function of the first kind (order 0) // #include #include #include #include "liquid.internal.h" // log(I_v(z)) : log Modified Bessel function of the first kind #define NUM_BESSELI_ITERATIONS 64 float liquid_lnbesselif(float _nu, float _z) { // TODO : validate input // TODO : compute low-signal approximation to avoid log(0) #if 0 // high-signal approximation: _z >> _nu // I_v(z) ~ exp(z) / sqrt(2*pi*z) // ln I_v(z) ~ z - 0.5*ln(2*pi*z) if ( _nu > 0.0f && logf(_z/_nu) > 8.0f ) return _z - 0.5f*logf(2*M_PI*_z); #endif float t0 = _nu*logf(0.5f*_z); float t1 = 0.0f; float t2 = 0.0f; float t3 = 0.0f; float y = 0.0f; unsigned int k; for (k=0; k 10.0f) return sqrtf(2/(M_PI*fabsf(_z)))*cosf(fabsf(_z)-M_PI/4); unsigned int k; float t, y=0.0f; for (k=0; k #include #include #include "liquid.internal.h" // infty // Q(z) = 1/sqrt(2 pi) int { exp(-u^2/2) du } // z // // Q(z) = (1/2)*(1 - erf(z/sqrt(2))) float liquid_Qf(float _z) { return 0.5f * (1.0f - erff(_z*M_SQRT1_2)); } // Marcum Q-function // TODO : check this computation // [Helstrom:1960], [Proakis:2001], [Helstrom:1992] #define NUM_MARCUMQ_ITERATIONS 16 float liquid_MarcumQf(int _M, float _alpha, float _beta) { #if 0 // expand as: // infty // Q_M(a,b) = exp(-(a^2+b^2)/2) * sum { (a/b)^k I_k(a*b) } // k=1-M return 0.0f #else // use approximation [Helstrom:1992] (Eq. 25) // Q_M(a,b) ~ erfc(x), // x = (b-a-M)/sigma^2, // sigma = M + 2a // compute sigma float sigma = (float)(_M) + 2.0f*_alpha; // compute x float x = (_beta - _alpha - (float)_M) / (sigma*sigma); // return erfc(x) return erfcf(x); #endif } // Marcum Q-function (M=1) // TODO : check this computation // [Helstrom:1960], [Proakis:2001] #define NUM_MARCUMQ1_ITERATIONS 64 float liquid_MarcumQ1f(float _alpha, float _beta) { #if 1 // expand as: infty // Q_1(a,b) = exp(-(a^2+b^2)/2) * sum { (a/b)^k I_k(a*b) } // k=0 float t0 = expf( -0.5f*(_alpha*_alpha + _beta*_beta) ); float t1 = 1.0f; float a_div_b = _alpha / _beta; float a_mul_b = _alpha * _beta; float y = 0.0f; unsigned int k; for (k=0; k 0) { _x >>= 1; n++; } return n; } // (n choose k) = n! / ( k! (n-k)! ) float liquid_nchoosek(unsigned int _n, unsigned int _k) { // if (_k > _n) { fprintf(stderr,"error: liquid_nchoosek(), _k cannot exceed _n\n"); exit(1); } else if (_k == 0 || _k == _n) { return 1; } // take advantage of symmetry and take larger value if (_k < _n/2) _k = _n - _k; // use lngamma() function when _n is large if (_n > 12) { double t0 = lgamma((double)_n + 1.0f); double t1 = lgamma((double)_n - (double)_k + 1.0f); double t2 = lgamma((double)_k + 1.0f); return round(exp( t0 - t1 - t2 )); } // old method float rnum=1, rden=1; unsigned int i; for (i=_n; i>_k; i--) rnum *= i; for (i=1; i<=_n-_k; i++) rden *= i; return rnum / rden; } liquid-dsp-1.3.1/src/math/src/math.complex.c000066400000000000000000000063321317124540100206430ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Complex math functions (trig, log, exp, etc.) // #include #include #include #include "liquid.internal.h" // complex square root float complex liquid_csqrtf(float complex _z) { float r = cabsf(_z); // magnitude of _z float a = crealf(_z); // real component of _z float re = sqrtf(0.5f*(r+a)); // real component of return value float im = sqrtf(0.5f*(r-a)); // imag component of return value // return value, retaining sign of imaginary component return cimagf(_z) > 0 ? re + _Complex_I*im : re - _Complex_I*im; } // complex exponent float complex liquid_cexpf(float complex _z) { float r = expf( crealf(_z) ); float re = cosf( cimagf(_z) ); float im = sinf( cimagf(_z) ); return r * ( re + _Complex_I*im ); } // complex logarithm float complex liquid_clogf(float complex _z) { return logf(cabsf(_z)) + _Complex_I*cargf(_z); } // complex arcsin float complex liquid_casinf(float complex _z) { return 0.5f*M_PI - liquid_cacosf(_z); } // complex arccos float complex liquid_cacosf(float complex _z) { // return based on quadrant int sign_i = crealf(_z) > 0; int sign_q = cimagf(_z) > 0; if (sign_i == sign_q) { return -_Complex_I*liquid_clogf(_z + liquid_csqrtf(_z*_z - 1.0f)); } else { return -_Complex_I*liquid_clogf(_z - liquid_csqrtf(_z*_z - 1.0f)); } // should never get to this state return 0.0f; } // complex arctan float complex liquid_catanf(float complex _z) { float complex t0 = 1.0f - _Complex_I*_z; float complex t1 = 1.0f + _Complex_I*_z; return 0.5f*_Complex_I*liquid_clogf( t0 / t1 ); } // approximation to cargf() but faster float liquid_cargf_approx(float complex _x) { float theta; float xi = crealf(_x); float xq = cimagf(_x); if (xi == 0.0f) { if (xq == 0.0f) return 0.0f; return xq > 0.0f ? M_PI_2 : -M_PI_2; } else { theta = xq / fabsf(xi); } if (theta > M_PI_2) theta = M_PI_2; else if (theta < -M_PI_2) theta = -M_PI_2; return theta; } liquid-dsp-1.3.1/src/math/src/math.gamma.c000066400000000000000000000115651317124540100202620ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // gamma functions // // liquid_lngammaf() : log( Gamma(z) ) // liquid_gammaf() : Gamma(z) // liquid_lnlowergammaf() : log( gamma(z,a) ), lower incomplete // liquid_lnuppergammaf() : log( Gamma(z,a) ), upper incomplete // liquid_lowergammaf() : gamma(z,a), lower incomplete // liquid_uppergammaf() : Gamma(z,a), upper incomplete // liquid_factorialf() : z! // #include #include #include #include "liquid.internal.h" #define NUM_LNGAMMA_ITERATIONS (256) #define EULER_GAMMA (0.57721566490153286) float liquid_lngammaf(float _z) { float g; if (_z < 0) { fprintf(stderr,"error: liquid_lngammaf(), undefined for z <= 0\n"); exit(1); } else if (_z < 10.0f) { #if 0 g = -EULER_GAMMA*_z - logf(_z); unsigned int k; for (k=1; k tmax) tmax = t; // conditions: // 1. minimum number of iterations met // 2. surpassed inflection point: k*log(alpha) - log(Gamma(z+k+1)) // has an inverted parabolic shape // 3. sufficiently beyond peak if ( k > LOWERGAMMA_MIN_ITERATIONS && tprime > t && (tmax-t) > 20.0f) break; } return t0 + t1 + t2 + logf(t3); } // ln( Gamma(z,alpha) ) : upper incomplete gamma function float liquid_lnuppergammaf(float _z, float _alpha) { return logf( liquid_gammaf(_z) - liquid_lowergammaf(_z,_alpha) ); } // gamma(z,alpha) : lower incomplete gamma function float liquid_lowergammaf(float _z, float _alpha) { return expf( liquid_lnlowergammaf(_z,_alpha) ); } // Gamma(z,alpha) : upper incomplete gamma function float liquid_uppergammaf(float _z, float _alpha) { return expf( liquid_lnuppergammaf(_z,_alpha) ); } // compute _n! float liquid_factorialf(unsigned int _n) { return fabsf(liquid_gammaf((float)(_n+1))); } liquid-dsp-1.3.1/src/math/src/math.trig.c000066400000000000000000000037171317124540100201450ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Useful mathematical formulae (trig) // #include #include #include #include "liquid.internal.h" #if 0 #define LIQUID_SINF_POLYORD (4) static float liquid_sinf_poly[LIQUID_SINF_POLYORD] = { -0.113791698328739f, -0.069825754521815f, 1.026821728423492f, 0.000000000000000f }; #endif void liquid_sincosf(float _x, float * _sinf, float * _cosf) { * _sinf = sinf(_x); * _cosf = cosf(_x); } float liquid_sinf(float _x) { float s, c; liquid_sincosf(_x,&s,&c); return s; } float liquid_cosf(float _x) { float s, c; liquid_sincosf(_x,&s,&c); return c; } float liquid_tanf(float _x) { float s, c; liquid_sincosf(_x,&s,&c); return s/c; } float liquid_expf(float _x) { return expf(_x); } float liquid_logf(float _x) { return logf(_x); } liquid-dsp-1.3.1/src/math/src/modular_arithmetic.c000066400000000000000000000143001317124540100221120ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Modular arithmetic and related integer mathematics // #include #include #include "liquid.h" // determine if number is prime (slow, simple method) int liquid_is_prime(unsigned int _n) { if (_n < 4) return 1; unsigned int i; for (i=2; i<_n; i++) { if ( (_n % i) == 0) return 0; } return 1; } // compute number's prime factors // _n : number to factor // _factors : pre-allocated array of factors [size: LIQUID_MAX_FACTORS x 1] // _num_factors: number of factors found, sorted ascending void liquid_factor(unsigned int _n, unsigned int * _factors, unsigned int * _num_factors) { unsigned int k; unsigned int n = _n; unsigned int num_factors = 0; do { for (k=2; k<=n; k++) { if ( (n % k) == 0) { // k factors _n; append to list _factors[num_factors++] = k; n /= k; break; } } } while (n > 1 && num_factors < LIQUID_MAX_FACTORS); if (n > 1 && num_factors == LIQUID_MAX_FACTORS) { fprintf(stderr,"error, liquid_factor(), could not factor %u in %u numbers\n", _n, LIQUID_MAX_FACTORS); exit(1); } *_num_factors = num_factors; } // compute number's unique prime factors // _n : number to factor // _factors : pre-allocated array of factors [size: LIQUID_MAX_FACTORS x 1] // _num_factors: number of unique factors found, sorted ascending void liquid_unique_factor(unsigned int _n, unsigned int * _factors, unsigned int * _num_factors) { unsigned int k; unsigned int n = _n; unsigned int num_factors = 0; do { for (k=2; k<=n; k++) { if ( (n % k) == 0) { // k factors _n; append to list _factors[num_factors] = k; n /= k; if (num_factors == 0) num_factors++; else if (_factors[num_factors-1] != k) num_factors++; break; } } } while (n > 1 && num_factors < LIQUID_MAX_FACTORS); if (n > 1 && num_factors == LIQUID_MAX_FACTORS) { fprintf(stderr,"error, liquid_unqiue_factor(), could not factor %u in %u numbers\n", _n, LIQUID_MAX_FACTORS); exit(1); } *_num_factors = num_factors; } // find smallest primitive root of _n unsigned int liquid_primitive_root(unsigned int _n) { // TODO : flesh out this function return 1; } // find smallest primitive root of _n (assuming _n is prime) unsigned int liquid_primitive_root_prime(unsigned int _n) { // find unique factors of _n-1 unsigned int unique_factors[LIQUID_MAX_FACTORS]; unsigned int num_unique_factors = 0; unsigned int n = _n-1; unsigned int k; do { for (k=2; k<=n; k++) { if ( (n%k)==0 ) { // k is a factor of (_n-1) n /= k; // add element to end of table unique_factors[num_unique_factors] = k; // increment counter only if element is unique if (num_unique_factors == 0) num_unique_factors++; else if (unique_factors[num_unique_factors-1] != k) num_unique_factors++; break; } } } while (n > 1 && num_unique_factors < LIQUID_MAX_FACTORS); #if 0 // print unique factors printf("found %u unique factors of n-1 = %u\n", num_unique_factors, _n-1); for (k=0; k 1); return t; } liquid-dsp-1.3.1/src/math/src/poly.c000066400000000000000000000031551317124540100172270ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Floating-point polynomials (double precision) // #include "liquid.internal.h" #define MATRIX(name) LIQUID_CONCAT(matrix, name) #define POLY(name) LIQUID_CONCAT(poly, name) #define POLY_NAME "poly" #define T double #define TC double complex #define T_COMPLEX 1 #define TI_COMPLEX 1 #define T_ABS(X) fabs(X) #define TC_ABS(X) cabs(X) #include "poly.common.c" #include "poly.expand.c" #include "poly.findroots.c" #include "poly.lagrange.c" liquid-dsp-1.3.1/src/math/src/poly.common.c000066400000000000000000000045401317124540100205150ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // common polynomial routines // polyval // polyfit // #include #include #include #include T POLY(_val)(T * _p, unsigned int _k, T _x) { unsigned int i; T xk = 1; T y = 0.0f; for (i=0; i<_k; i++) { y += _p[i]*xk; xk *= _x; } return y; } void POLY(_fit)(T * _x, T * _y, unsigned int _n, T * _p, unsigned int _k) { // ... T X[_n*_k]; unsigned int r,c; T v; for (r=0; r<_n; r++) { v = 1; for (c=0; c<_k; c++) { matrix_access(X,_n,_k,r,c) = v; v *= _x[r]; } } // compute transpose of X T Xt[_k*_n]; memmove(Xt,X,_k*_n*sizeof(T)); MATRIX(_trans)(Xt,_n,_k); // compute [X']*y T Xty[_k]; MATRIX(_mul)(Xt, _k, _n, _y, _n, 1, Xty,_k, 1); // compute [X']*X T X2[_k*_k]; MATRIX(_mul)(Xt, _k, _n, X, _n, _k, X2, _k, _k); // compute inv([X']*X) T G[_k*_k]; memmove(G,X2,_k*_k*sizeof(T)); MATRIX(_inv)(G,_k,_k); // compute coefficients MATRIX(_mul)(G, _k, _k, Xty,_k, 1, _p, _k, 1); } liquid-dsp-1.3.1/src/math/src/poly.expand.c000066400000000000000000000137611317124540100205110ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // polynomial expansion methods // #include #include #include #include "liquid.internal.h" // expands the polynomial: // P_n(x) = (1+x)^n // as // P_n(x) = p[0] + p[1]*x + p[2]*x^2 + ... + p[n]x^n // NOTE: _p has order n=m+k (array is length n+1) void POLY(_expandbinomial)(unsigned int _n, T * _c) { // no roots; return zero if (_n == 0) { _c[0] = 0.; return; } int i, j; // initialize coefficients array to [1,0,0,....0] for (i=0; i<=_n; i++) _c[i] = (i==0) ? 1 : 0; // iterative polynomial multiplication for (i=0; i<_n; i++) { for (j=i+1; j>0; j--) _c[j] = _c[j] + _c[j-1]; } // assert(_c[0]==1.0f); } // expands the polynomial: // P_n(x) = (1+x)^m * (1-x)^k // as // P_n(x) = p[0] + p[1]*x + p[2]*x^2 + ... + p[n]x^n // NOTE: _p has order n=m+k (array is length n+1) void POLY(_expandbinomial_pm)(unsigned int _m, unsigned int _k, T * _c) { unsigned int n = _m + _k; // no roots; return zero if (n == 0) { _c[0] = 0.; return; } int i, j; // initialize coefficients array to [1,0,0,....0] for (i=0; i<=n; i++) _c[i] = (i==0) ? 1 : 0; // iterative polynomial multiplication (1+x) for (i=0; i<_m; i++) { for (j=i+1; j>0; j--) _c[j] = _c[j] + _c[j-1]; } // iterative polynomial multiplication (1-x) for (i=_m; i0; j--) _c[j] = _c[j] - _c[j-1]; } // assert(_c[0]==1.0f); } #if 0 // expands the polynomial: // (1+x*a[0])*(1+x*a[1]) * ... * (1+x*a[n-1]) // as // c[0] + c[1]*x + c[2]*x^2 + ... + c[n]*x^n void POLY(_expandbinomial)(T * _a, unsigned int _n, T * _c) { // no roots; return zero if (_n == 0) { _c[0] = 0.; return; } int i, j; // initialize coefficients array to [1,0,0,....0] for (i=0; i<=_n; i++) _c[i] = (i==0) ? 1 : 0; // iterative polynomial multiplication for (i=0; i<_n; i++) { for (j=i+1; j>0; j--) _c[j] = _a[i]*_c[j] + _c[j-1]; _c[j] *= _a[i]; } // flip values unsigned int r = (_n+1) % 2; unsigned int L = (_n+1-r)/2; T tmp; for (i=0; i0; j--) _c[j] = -_a[i]*_c[j] + _c[j-1]; _c[j] *= -_a[i]; } // assert(c[_n]==1.0f) } // expands the polynomial: // P_n(x) = // (x*b[0]-a[0]) * (x*b[1]-a[1]) * ... * (x*b[n-1]-a[n-1]) // as // P_n(x) = c[0] + c[1]*x + ... + c[n]*x^n // // c has order _n (array is length _n+1) void POLY(_expandroots2)(T * _a, T * _b, unsigned int _n, T * _c) { unsigned int i; // factor _b[i] from each root : (x*b - a) = (x - a/b)*b T g = 1.0; T r[_n]; for (i=0; i<_n; i++) { g *= -_b[i]; r[i] = _a[i] / _b[i]; } // expand new root set POLY(_expandroots)(r, _n, _c); // multiply by gain for (i=0; i<_n+1; i++) _c[i] *= g; } // expands the multiplication of two polynomials // // (a[0] + a[1]*x + a[2]*x^2 + ...) * (b[0] + b[1]*x + b[]*x^2 + ...2 + ...) // as // c[0] + c[1]*x + c[2]*x^2 + ... + c[n]*x^n // // where order(c) = order(a) + order(b) + 1 // :: length(c) = length(a) + length(b) - 1 // // _a : 1st polynomial coefficients (length is _order_a+1) // _order_a : 1st polynomial order // _b : 2nd polynomial coefficients (length is _order_b+1) // _order_b : 2nd polynomial order // _c : output polynomial coefficients (length is _order_a + _order_b + 1) void POLY(_mul)(T * _a, unsigned int _order_a, T * _b, unsigned int _order_b, T * _c) { unsigned int na = _order_a + 1; unsigned int nb = _order_b + 1; unsigned int nc = na + nb - 1; unsigned int i; for (i=0; i #include #include #include #include #include "liquid.internal.h" // debug polynomial root-finding methods? #define LIQUID_POLY_FINDROOTS_DEBUG 0 // // forward declaration of internal methods // // iterate over Bairstow's method, finding quadratic factor x^2 + u*x + v void POLY(_findroots_bairstow_recursion)(T * _p, unsigned int _k, T * _p1, T * _u, T * _v); // finds the complex roots of the polynomial // _p : polynomial array, ascending powers [size: _k x 1] // _k : polynomials length (poly order = _k - 1) // _roots : resulting complex roots [size: _k-1 x 1] void POLY(_findroots)(T * _p, unsigned int _k, TC * _roots) { // find roots of polynomial using Bairstow's method (more // accurate and reliable than Durand-Kerner) POLY(_findroots_bairstow)(_p,_k,_roots); } // finds the complex roots of the polynomial using the Durand-Kerner method // _p : polynomial array, ascending powers [size: _k x 1] // _k : polynomials length (poly order = _k - 1) // _roots : resulting complex roots [size: _k-1 x 1] void POLY(_findroots_durandkerner)(T * _p, unsigned int _k, TC * _roots) { if (_k < 2) { fprintf(stderr,"%s_findroots_durandkerner(), order must be greater than 0\n", POLY_NAME); exit(1); } else if (_p[_k-1] != 1) { fprintf(stderr,"%s_findroots_durandkerner(), _p[_k-1] must be equal to 1\n", POLY_NAME); exit(1); } unsigned int i; unsigned int num_roots = _k-1; T r0[num_roots]; T r1[num_roots]; // find intial magnitude float g = 0.0f; float gmax = 0.0f; for (i=0; i<_k; i++) { g = T_ABS(_p[i]); if (i==0 || g > gmax) gmax = g; } // initialize roots T t0 = 0.9f * (1 + gmax) * cexpf(_Complex_I*1.1526f); T t = 1.0f; for (i=0; i=0; i--) { b[i] = _p[i+2] - u*b[i+1] - v*b[i+2]; f[i] = b[i+2] - u*f[i+1] - v*f[i+2]; } c = _p[1] - u*b[0] - v*b[1]; g = b[1] - u*f[0] - v*f[1]; d = _p[0] - v*b[0]; h = b[0] - v*f[0]; // compute scaling factor q = 1/(v*g*g + h*(h-u*g)); // compute u, v steps du = - q*(-h*c + g*d); dv = - q*(-g*v*c + (g*u-h)*d); #if LIQUID_POLY_FINDROOTS_DEBUG // print debugging info printf("bairstow [%u] :\n", k); printf(" u : %12.4e + j*%12.4e\n", crealf(u), cimagf(u)); printf(" v : %12.4e + j*%12.4e\n", crealf(v), cimagf(v)); printf(" b : \n"); for (i=0; i #include // Lagrange polynomial exact fit (order _n-1) void POLY(_fit_lagrange)(T * _x, T * _y, unsigned int _n, T * _p) { unsigned int k=_n-1; // polynomial order // clear polynomial coefficients array unsigned int i; for (i=0; i<_n; i++) _p[i] = 0.; // compute roots, gain T roots[k]; // polynomial roots T c[_n]; // expanded polynomial T g; // gain unsigned int j; unsigned int n; for (i=0; i<_n; i++) { n=0; g=1.0f; for (j=0; j<_n; j++) { if (j!=i) { roots[n++] = - _x[j]; g *= (_x[i] - _x[j]); } } g = _y[i] / g; // expand roots POLY(_expandroots)(roots, k, c); for (j=0; j<_n; j++) { _p[j] += g * c[j]; } #if 0 // debug/print printf("****** %3u : **********************\n", i); printf(" g : %12.8f\n", crealf(g)); printf(" roots:\n"); for (j=0; j %16.6f\n", j, crealf(c[j]), crealf(g*c[j])); #endif } } // Lagrange polynomial interpolation T POLY(_interp_lagrange)(T * _x, T * _y, unsigned int _n, T _x0) { T y0 = 0.0; // set output to zero T g; // accumulator unsigned int i, j; for (i=0; i<_n; i++) { g=1.0f; for (j=0; j<_n; j++) { if (j!=i) { g *= (_x0 - _x[j])/(_x[i] - _x[j]); } } y0 += _y[i] * g; } return y0; } // Lagrange polynomial fit (barycentric form) void POLY(_fit_lagrange_barycentric)(T * _x, unsigned int _n, T * _w) { // compute barycentric weights (slow method) unsigned int j, k; for (j=0; j<_n; j++) { _w[j] = 1.; for (k=0; k<_n; k++) { if (j==k) continue; else _w[j] *= (_x[j] - _x[k]); } _w[j] = 1. / _w[j]; } // normalize by _w[0] T w0 = _w[0]; for (j=0; j<_n; j++) _w[j] /= w0; } // Lagrange polynomial interpolation (barycentric form) T POLY(_val_lagrange_barycentric)(T * _x, T * _y, T * _w, T _x0, unsigned int _n) { T t0 = 0.; // numerator sum T t1 = 0.; // denominator sum T g; // _x0 - _x[j] // exact fit tolerance float tol = 1e-6f; unsigned int j; for (j=0; j<_n; j++) { g = _x0 - _x[j]; // test for "exact" fit if (T_ABS(g) < tol) return _y[j]; t0 += _w[j] * _y[j] / g; t1 += _w[j] / g; } return t0 / t1; } liquid-dsp-1.3.1/src/math/src/polyc.c000066400000000000000000000032001317124540100173610ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Complex floating-point polynomials (double precision) // #include "liquid.internal.h" #define MATRIX(name) LIQUID_CONCAT(matrixc, name) #define POLY(name) LIQUID_CONCAT(polyc, name) #define POLY_NAME "polyc" #define T double complex #define TC double complex #define T_COMPLEX 1 #define TI_COMPLEX 1 #define T_ABS(X) cabs(X) #define TC_ABS(X) cabs(X) #include "poly.common.c" #include "poly.expand.c" #include "poly.findroots.c" #include "poly.lagrange.c" liquid-dsp-1.3.1/src/math/src/polycf.c000066400000000000000000000032031317124540100175320ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Complex floating-point polynomials (single precision) // #include "liquid.internal.h" #define MATRIX(name) LIQUID_CONCAT(matrixcf, name) #define POLY(name) LIQUID_CONCAT(polycf, name) #define POLY_NAME "polycf" #define T float complex #define TC float complex #define T_COMPLEX 1 #define TI_COMPLEX 1 #define T_ABS(X) cabsf(X) #define TC_ABS(X) cabsf(X) #include "poly.common.c" #include "poly.expand.c" #include "poly.findroots.c" #include "poly.lagrange.c" liquid-dsp-1.3.1/src/math/src/polyf.c000066400000000000000000000031601317124540100173710ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Floating-point polynomials (single precision) // #include "liquid.internal.h" #define MATRIX(name) LIQUID_CONCAT(matrixf, name) #define POLY(name) LIQUID_CONCAT(polyf, name) #define POLY_NAME "polyf" #define T float #define TC float complex #define T_COMPLEX 1 #define TI_COMPLEX 1 #define T_ABS(X) fabsf(X) #define TC_ABS(X) cabsf(X) #include "poly.common.c" #include "poly.expand.c" #include "poly.findroots.c" #include "poly.lagrange.c" liquid-dsp-1.3.1/src/math/src/windows.c000066400000000000000000000241551317124540100177410ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Windowing functions // // References: // [Kaiser:1980] James F. Kaiser and Ronald W. Schafer, "On // the Use of I0-Sinh Window for Spectrum Analysis," // IEEE Transactions on Acoustics, Speech, and Signal // Processing, vol. ASSP-28, no. 1, pp. 105--107, // February, 1980. // [harris:1978] frederic j. harris, "On the Use of Windows for Harmonic // Analysis with the Discrete Fourier Transform," Proceedings of the // IEEE, vol. 66, no. 1, January, 1978. #include #include #include #include #include "liquid.internal.h" const char * liquid_window_str[LIQUID_WINDOW_NUM_FUNCTIONS][2] = { // short name, long name {"unknown", "unknown" }, {"hamming", "Hamming" }, {"hann", "Hann" }, {"blackmanharris", "Blackman-harris (4-term)" }, {"blackmanharris7", "Blackman-harris (7-term)" }, {"kaiser", "Kaiser-Bessel" }, {"flattop", "flat top" }, {"triangular", "triangular" }, {"rcostaper", "raised-cosine taper" }, {"kbd", "Kaiser-Bessel derived" }, }; // Print compact list of existing and available windowing functions void liquid_print_windows() { unsigned int i; unsigned int len = 10; // print all available MOD schemes printf(" "); for (i=0; i 48 && i != LIQUID_WINDOW_NUM_FUNCTIONS-1) { len = 10; printf("\n "); } } printf("\n"); } // returns modulation_scheme based on input string liquid_window_type liquid_getopt_str2window(const char * _str) { // compare each string to short name unsigned int i; for (i=0; i= _N) { fprintf(stderr,"error: liquid_kbd(), index exceeds maximum\n"); exit(1); } else if (_N == 0) { fprintf(stderr,"error: liquid_kbd(), window length must be greater than zero\n"); exit(1); } else if ( _N % 2 ) { fprintf(stderr,"error: liquid_kbd(), window length must be odd\n"); exit(1); } unsigned int M = _N / 2; if (_n >= M) return liquid_kbd(_N-_n-1,_N,_beta); float w0 = 0.0f; float w1 = 0.0f; float w; unsigned int i; for (i=0; i<=M; i++) { // compute Kaiser window w = kaiser(i,M+1,_beta,0.0f); // accumulate window sums w1 += w; if (i <= _n) w0 += w; } //printf("%12.8f / %12.8f = %12.8f\n", w0, w1, w0/w1); return sqrtf(w0 / w1); } // Kaiser-Bessel derived window (full window function) void liquid_kbd_window(unsigned int _n, float _beta, float * _w) { unsigned int i; // TODO add reference // validate input if (_n == 0) { fprintf(stderr,"error: liquid_kbd_window(), window length must be greater than zero\n"); exit(1); } else if ( _n % 2 ) { fprintf(stderr,"error: liquid_kbd_window(), window length must be odd\n"); exit(1); } else if ( _beta < 0.0f ) { fprintf(stderr,"error: liquid_kbd_window(), _beta must be positive\n"); exit(1); } // compute half length unsigned int M = _n / 2; // generate regular Kaiser window, length M+1 float w_kaiser[M+1]; for (i=0; i<=M; i++) w_kaiser[i] = kaiser(i,M+1,_beta,0.0f); // compute sum(wk[]) float w_sum = 0.0f; for (i=0; i<=M; i++) w_sum += w_kaiser[i]; // accumulate window float w_acc = 0.0f; for (i=0; i _N) { fprintf(stderr,"error: kaiser(), sample index must not exceed window length\n"); exit(1); } else if (_beta < 0) { fprintf(stderr,"error: kaiser(), beta must be greater than or equal to zero\n"); exit(1); } else if (_mu < -0.5 || _mu > 0.5) { fprintf(stderr,"error: kaiser(), fractional sample offset must be in [-0.5,0.5]\n"); exit(1); } float t = (float)_n - (float)(_N-1)/2 + _mu; float r = 2.0f*t/(float)(_N); float a = liquid_besseli0f(_beta*sqrtf(1-r*r)); float b = liquid_besseli0f(_beta); return a / b; } // Hamming window float hamming(unsigned int _n, unsigned int _N) { // validate input if (_n > _N) { fprintf(stderr,"error: hamming(), sample index must not exceed window length\n"); exit(1); } // TODO add reference return 0.53836 - 0.46164*cosf( (2*M_PI*(float)_n) / ((float)(_N-1)) ); } // Hann window float hann(unsigned int _n, unsigned int _N) { // validate input if (_n > _N) { fprintf(stderr,"error: hann(), sample index must not exceed window length\n"); exit(1); } // TODO test this function // TODO add reference return 0.5f - 0.5f*cosf( (2*M_PI*(float)_n) / ((float)(_N-1)) ); } // Blackman-harris window [harris:1978] float blackmanharris(unsigned int _n, unsigned int _N) { // validate input if (_n > _N) { fprintf(stderr,"error: blackmanharris(), sample index must not exceed window length\n"); exit(1); } // TODO test this function // TODO add reference float a0 = 0.35875f; float a1 = 0.48829f; float a2 = 0.14128f; float a3 = 0.01168f; float t = 2*M_PI*(float)_n / ((float)(_N-1)); return a0 - a1*cosf(t) + a2*cosf(2*t) - a3*cosf(3*t); } // 7th-order Blackman-harris window float blackmanharris7(unsigned int _n, unsigned int _N) { // validate input if (_n > _N) { fprintf(stderr,"error: blackmanharris7(), sample index must not exceed window length\n"); exit(1); } float a0 = 0.27105f; float a1 = 0.43329f; float a2 = 0.21812f; float a3 = 0.06592f; float a4 = 0.01081f; float a5 = 0.00077f; float a6 = 0.00001f; float t = 2*M_PI*(float)_n / ((float)(_N-1)); return a0 - a1*cosf( t) + a2*cosf(2*t) - a3*cosf(3*t) + a4*cosf(4*t) - a5*cosf(5*t) + a6*cosf(6*t); } // Flat-top window float flattop(unsigned int _n, unsigned int _N) { // validate input if (_n > _N) { fprintf(stderr,"error: flattop(), sample index must not exceed window length\n"); exit(1); } float a0 = 1.000f; float a1 = 1.930f; float a2 = 1.290f; float a3 = 0.388f; float a4 = 0.028f; float t = 2*M_PI*(float)_n / ((float)(_N-1)); return a0 - a1*cosf(t) + a2*cosf(2*t) - a3*cosf(3*t) + a4*cosf(4*t); } // Triangular window float triangular(unsigned int _n, unsigned int _N, unsigned int _L) { // validate input if (_n > _N) { fprintf(stderr,"error: triangular(), sample index must not exceed window length\n"); exit(1); } else if (_L != _N-1 && _L != _N && _L != _N+1) { fprintf(stderr,"error: triangular(), sub-length must be in _N+{-1,0,1}\n"); exit(1); } else if (_L == 0) { fprintf(stderr,"error: triangular(), sub-length must be greater than zero\n"); exit(1); } float _num = (float)_n - (float)((_N-1)/2.0f); float _denom = ((float)_L)/2.0f; return 1.0 - fabsf(_num / _denom); } // raised-cosine tapering window // _n : window index // _t : taper length // _N : full window length float liquid_rcostaper_windowf(unsigned int _n, unsigned int _t, unsigned int _N) { // validate input if (_n > _N) { fprintf(stderr,"error: liquid_rcostaper_windowf(), sample index must not exceed window length\n"); exit(1); } else if (_t > _N/2) { fprintf(stderr,"error: liquid_rcostaper_windowf(), taper length cannot exceed half window length\n"); exit(1); } // reverse time for ramp-down section if (_n > _N - _t - 1) _n = _N - _n - 1; // return ramp or flat component return (_n < _t) ? 0.5f - 0.5f*cosf(M_PI*((float)_n + 0.5f) / (float)_t) : 1.0f; } liquid-dsp-1.3.1/src/math/tests/000077500000000000000000000000001317124540100164475ustar00rootroot00000000000000liquid-dsp-1.3.1/src/math/tests/kbd_autotest.c000066400000000000000000000037231317124540100213100ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.h" // // AUTOTEST: Kaiser-Bessel derived window // void liquid_kbd_window_test(unsigned int _n, float _beta) { unsigned int i; float tol = 1e-3f; // compute window float w[_n]; liquid_kbd_window(_n,_beta,w); // square window float w2[_n]; for (i=0; i<_n; i++) w2[i] = w[i]*w[i]; // ensure w[i]^2 + w[i+M]^2 == 1 unsigned int M = _n/2; for (i=0; i #include "autotest/autotest.h" #include "liquid.h" // // AUTOTEST: poly_fit 3rd order polynomial, critically sampled // void autotest_polyf_fit_q3n3() { unsigned int Q=2; // polynomial order unsigned int n=3; // input vector size float x[3] = {-1.0f, 0.0f, 1.0f}; float y[3] = { 1.0f, 0.0f, 1.0f}; float p[3]; float p_test[3] = {0.0f, 0.0f, 1.0f}; float tol = 1e-3f; unsigned int k=Q+1; polyf_fit(x,y,n, p,k); if (liquid_autotest_verbose) { unsigned int i; for (i=0; i<3; i++) printf("%3u : %12.8f > %12.8f\n", i, x[i], y[i]); for (i=0; i<3; i++) printf("p[%3u] = %12.8f\n", i, p[i]); } CONTEND_DELTA(p[0], p_test[0], tol); CONTEND_DELTA(p[1], p_test[1], tol); CONTEND_DELTA(p[2], p_test[2], tol); //CONTEND_DELTA(p[3], p_test[3], tol); } #if 0 // // AUTOTEST: poly_expandbinomial // void xautotest_polyf_expandbinomial_4() { float a[4] = { 3, 2, -5, 1 }; float c[5]; float c_test[5] = { 1, 1, -19, -49, -30 }; float tol = 1e-3f; polyf_expandbinomial(a,4,c); if (liquid_autotest_verbose) { unsigned int i; printf("c[5] = "); for (i=0; i<5; i++) printf("%8.2f", c[i]); printf("\n"); } CONTEND_DELTA(c[0], c_test[0], tol); CONTEND_DELTA(c[1], c_test[1], tol); CONTEND_DELTA(c[2], c_test[2], tol); CONTEND_DELTA(c[3], c_test[3], tol); CONTEND_DELTA(c[4], c_test[4], tol); } #endif // // AUTOTEST: poly_expandroots // void autotest_polyf_expandroots_4() { float roots[5] = { -2, -1, -4, 5, 3 }; float c[6]; float c_test[6] = { 120, 146, 1, -27, -1, 1 }; float tol = 1e-3f; polyf_expandroots(roots,5,c); if (liquid_autotest_verbose) { unsigned int i; printf("c[6] = "); for (i=0; i<6; i++) printf("%8.2f", c[i]); printf("\n"); } CONTEND_DELTA(c[0], c_test[0], tol); CONTEND_DELTA(c[1], c_test[1], tol); CONTEND_DELTA(c[2], c_test[2], tol); CONTEND_DELTA(c[3], c_test[3], tol); CONTEND_DELTA(c[4], c_test[4], tol); CONTEND_DELTA(c[5], c_test[5], tol); } // // AUTOTEST: poly_expandroots // void autotest_polyf_expandroots_11() { float roots[11] = { -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11 }; float c[12]; float c_test[12] = {39916800, 120543840, 150917976, 105258076, 45995730, 13339535, 2637558, 357423, 32670, 1925, 66, 1}; float tol = 1e-6f; polyf_expandroots(roots,11,c); unsigned int i; for (i=0; i<12; i++) { if (liquid_autotest_verbose) printf(" c[%3u] : %16.8e (expected %16.8e)\n", i, c[i], c_test[i]); CONTEND_DELTA(c[i], c_test[i], fabsf(tol*c_test[i])); } } // // AUTOTEST: polycf_expandroots // void autotest_polycf_expandroots_4() { // expand complex roots on conjugate pair float theta = 1.7f; float complex a[2] = { -cexpf(_Complex_I*theta), -cexpf(-_Complex_I*theta) }; float complex c[3]; float complex c_test[3] = { 1, 2*cosf(theta), 1 }; float tol = 1e-3f; polycf_expandroots(a,2,c); if (liquid_autotest_verbose) { unsigned int i; for (i=0; i<3; i++) printf("c[%3u] = %12.8f + j*%12.8f\n", i, crealf(c[i]), cimagf(c[i])); } CONTEND_DELTA(crealf(c[0]), crealf(c_test[0]), tol); CONTEND_DELTA(cimagf(c[0]), cimagf(c_test[0]), tol); CONTEND_DELTA(crealf(c[1]), crealf(c_test[1]), tol); CONTEND_DELTA(cimagf(c[1]), cimagf(c_test[1]), tol); CONTEND_DELTA(crealf(c[2]), crealf(c_test[2]), tol); CONTEND_DELTA(cimagf(c[2]), cimagf(c_test[2]), tol); } // // AUTOTEST: poly_expandroots2 // // expand (2*x-5)*(3*x+2)*(-1*x+3) // void autotest_polyf_expandroots2_3() { unsigned int n=3; float a[3] = { 2, 3, -1 }; float b[3] = { 5, -2, -3 }; float c[4]; float c_test[4] = { -6, 29, -23, -30 }; float tol = 1e-3f; polyf_expandroots2(a,b,n,c); if (liquid_autotest_verbose) { unsigned int i; printf("c[%u] = ", n+1); for (i=0; i #include "liquid.h" // Helper function to keep code base small void matrixf_inv_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _n) { // normalize number of iterations // time ~ _n ^ 2 *_num_iterations /= _n * _n; if (*_num_iterations < 1) *_num_iterations = 1; float x[_n*_n]; unsigned int i; for (i=0; i<_n*_n; i++) x[i] = randnf(); // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { matrixf_inv(x,_n,_n); matrixf_inv(x,_n,_n); matrixf_inv(x,_n,_n); matrixf_inv(x,_n,_n); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; } #define MATRIXF_INV_BENCHMARK_API(N) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { matrixf_inv_bench(_start, _finish, _num_iterations, N); } void benchmark_matrixf_inv_n2 MATRIXF_INV_BENCHMARK_API(2) void benchmark_matrixf_inv_n4 MATRIXF_INV_BENCHMARK_API(4) void benchmark_matrixf_inv_n8 MATRIXF_INV_BENCHMARK_API(8) void benchmark_matrixf_inv_n16 MATRIXF_INV_BENCHMARK_API(16) void benchmark_matrixf_inv_n32 MATRIXF_INV_BENCHMARK_API(32) void benchmark_matrixf_inv_n64 MATRIXF_INV_BENCHMARK_API(64) liquid-dsp-1.3.1/src/matrix/bench/matrixf_linsolve_benchmark.c000066400000000000000000000054251317124540100245100ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "liquid.h" // Helper function to keep code base small void matrixf_linsolve_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _n) { // normalize number of iterations // time ~ _n ^ 2 *_num_iterations /= _n * _n; if (*_num_iterations < 1) *_num_iterations = 1; unsigned long int i; float A[_n*_n]; float b[_n]; float x[_n]; for (i=0; i<_n*_n; i++) A[i] = randnf(); for (i=0; i<_n; i++) b[i] = randnf(); // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { matrixf_linsolve(A,_n,b,x,NULL); matrixf_linsolve(A,_n,b,x,NULL); matrixf_linsolve(A,_n,b,x,NULL); matrixf_linsolve(A,_n,b,x,NULL); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; } #define MATRIXF_LINSOLVE_BENCHMARK_API(N) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { matrixf_linsolve_bench(_start, _finish, _num_iterations, N); } void benchmark_matrixf_linsolve_n2 MATRIXF_LINSOLVE_BENCHMARK_API(2) void benchmark_matrixf_linsolve_n4 MATRIXF_LINSOLVE_BENCHMARK_API(4) void benchmark_matrixf_linsolve_n8 MATRIXF_LINSOLVE_BENCHMARK_API(8) void benchmark_matrixf_linsolve_n16 MATRIXF_LINSOLVE_BENCHMARK_API(16) void benchmark_matrixf_linsolve_n32 MATRIXF_LINSOLVE_BENCHMARK_API(32) void benchmark_matrixf_linsolve_n64 MATRIXF_LINSOLVE_BENCHMARK_API(64) liquid-dsp-1.3.1/src/matrix/bench/matrixf_mul_benchmark.c000066400000000000000000000052351317124540100234510ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // Helper function to keep code base small void matrixf_mul_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _n) { // normalize number of iterations // time ~ _n ^ 2 *_num_iterations /= _n * _n; if (*_num_iterations < 1) *_num_iterations = 1; float a[_n*_n]; float b[_n*_n]; float c[_n*_n]; unsigned int i; for (i=0; i<_n*_n; i++) { a[i] = randnf(); b[i] = randnf(); } // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { matrixf_mul(a,_n,_n, b,_n,_n, c,_n,_n); matrixf_mul(a,_n,_n, b,_n,_n, c,_n,_n); matrixf_mul(a,_n,_n, b,_n,_n, c,_n,_n); matrixf_mul(a,_n,_n, b,_n,_n, c,_n,_n); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; } #define MATRIXF_MUL_BENCHMARK_API(N) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { matrixf_mul_bench(_start, _finish, _num_iterations, N); } void benchmark_matrixf_mul_n2 MATRIXF_MUL_BENCHMARK_API(2) void benchmark_matrixf_mul_n4 MATRIXF_MUL_BENCHMARK_API(4) void benchmark_matrixf_mul_n8 MATRIXF_MUL_BENCHMARK_API(8) void benchmark_matrixf_mul_n16 MATRIXF_MUL_BENCHMARK_API(16) void benchmark_matrixf_mul_n32 MATRIXF_MUL_BENCHMARK_API(32) void benchmark_matrixf_mul_n64 MATRIXF_MUL_BENCHMARK_API(64) liquid-dsp-1.3.1/src/matrix/bench/smatrixf_mul_benchmark.c000066400000000000000000000064251317124540100236360ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "liquid.h" // Helper function to keep code base small void smatrixf_mul_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _n) { // normalize number of iterations // time ~ _n ^ 3 *_num_iterations /= _n * _n * _n; if (*_num_iterations < 1) *_num_iterations = 1; unsigned long int i; // generate random matrices smatrixf a = smatrixf_create(_n, _n); smatrixf b = smatrixf_create(_n, _n); smatrixf c = smatrixf_create(_n, _n); // number of random non-zero entries unsigned int nnz = _n / 20 < 4 ? 4 : _n / 20; // initialize _a for (i=0; i #include #include void MATRIX(_print)(T * _X, unsigned int _R, unsigned int _C) { printf("matrix [%u x %u] : \n", _R, _C); unsigned int r,c; for (r=0; r<_R; r++) { for (c=0; c<_C; c++) { MATRIX_PRINT_ELEMENT(_X,_R,_C,r,c); } printf("\n"); } } // initialize square matrix to the identity matrix void MATRIX(_eye)(T * _x, unsigned int _n) { unsigned int r,c,k=0; for (r=0; r<_n; r++) { for (c=0; c<_n; c++) { _x[k++] = r==c ? 1. : 0.; } } } // initialize matrix to ones void MATRIX(_ones)(T * _x, unsigned int _r, unsigned int _c) { unsigned int k; for (k=0; k<_r*_c; k++) _x[k] = 1.; } // initialize matrix to zeros void MATRIX(_zeros)(T * _x, unsigned int _r, unsigned int _c) { unsigned int k; for (k=0; k<_r*_c; k++) _x[k] = 0.; } liquid-dsp-1.3.1/src/matrix/src/matrix.c000066400000000000000000000035221317124540100201210ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Floating-point matrix (double precision) // #include "liquid.internal.h" #define MATRIX(name) LIQUID_CONCAT(matrix, name) #define MATRIX_NAME "matrix" #define T double // general type #define TP double // primitive type #define T_COMPLEX 0 // is type complex? #define T_ABS(X) fabs(X) #define TP_ABS(X) fabs(X) #define MATRIX_PRINT_ELEMENT(X,R,C,r,c) \ printf("%12.8f", matrix_access(X,R,C,r,c)); #include "matrix.base.c" #include "matrix.cgsolve.c" #include "matrix.chol.c" #include "matrix.gramschmidt.c" #include "matrix.inv.c" #include "matrix.linsolve.c" #include "matrix.ludecomp.c" #include "matrix.qrdecomp.c" #include "matrix.math.c" liquid-dsp-1.3.1/src/matrix/src/matrix.cgsolve.c000066400000000000000000000130311317124540100215560ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Solve linear system of equations using conjugate gradient method // // References: // [Schewchuk:1994] Jonathon Richard Shewchuk, "An Introduction to // the Conjugate Gradient Method Without the Agonizing Pain," // Manuscript, August, 1994. // #include #include #include "liquid.internal.h" #define DEBUG_CGSOLVE 0 // solve linear system of equations using conjugate gradient method // _A : symmetric positive definite matrix [size: _n x _n] // _n : system dimension // _b : equality [size: _n x 1] // _x : solution estimate [size: _n x 1] // _opts : options (ignored for now) void MATRIX(_cgsolve)(T * _A, unsigned int _n, T * _b, T * _x, void * _opts) { // validate input if (_n == 0) { fprintf(stderr,"error: matrix_cgsolve(), system dimension cannot be zero\n"); exit(1); } // options unsigned int max_iterations = 4*_n; // maximum number of iterations double tol = 1e-6; // error tolerance unsigned int j; // TODO : check options // 1. set initial _x0 // 2. max number of iterations // 3. residual tolerance // allocate memory for arrays T x0[_n], x1[_n]; // iterative vector x (solution estimate) T d0[_n], d1[_n]; // iterative vector d T r0[_n], r1[_n]; // iterative vector r (step direction) T q[_n]; // A * d0 T Ax1[_n]; // A * x1 // scalars T delta_init; // b^T * b0 T delta0; // r0^T * r0 T delta1; // r1^T * r1 T gamma; // d0^T * q T alpha; T beta; double res; // residual double res_opt=0.0; // residual of best solution // initialize x0 to {0, 0, ... 0} for (j=0; j<_n; j++) x0[j] = 0.0; // d0 = b - A*x0 (assume x0 = {0, 0, 0, ...0}) for (j=0; j<_n; j++) d0[j] = _b[j]; // r0 = d0 memmove(r0, d0, _n*sizeof(T)); // delta_init = b^T * b MATRIX(_transpose_mul)(_b, _n, 1, &delta_init); // delta0 = r0^T * r0 MATRIX(_transpose_mul)(r0, _n, 1, &delta0); // save best solution memmove(_x, x0, _n*sizeof(T)); unsigned int i=0; // iteration counter while ( (i < max_iterations) && (creal(delta0) > tol*tol*creal(delta_init)) ) { #if DEBUG_CGSOLVE printf("*********** %4u / %4u (max) **************\n", i, max_iterations); printf(" comparing %12.4e > %12.4e\n", creal(delta0), tol*tol*creal(delta_init)); #endif // q = A*d0 MATRIX(_mul)(_A, _n, _n, d0, _n, 1, q, _n, 1); // gamma = d0^T * q gamma = 0.0; for (j=0; j<_n; j++) { T prod = conj(d0[j]) * q[j]; gamma += prod; } // step size: alpha = (r0^T * r0) / (d0^T * A * d0) // = delta0 / gamma alpha = delta0 / gamma; #if DEBUG_CGSOLVE printf(" alpha = %12.8f\n", crealf(alpha)); printf(" delta0 = %12.8f\n", crealf(delta0)); #endif // update x for (j=0; j<_n; j++) x1[j] = x0[j] + alpha*d0[j]; #if DEBUG_CGSOLVE printf(" x:\n"); MATRIX(_print)(x1, _n, 1); #endif // update r if ( ((i+1)%50) == 0) { // peridically re-compute: r = b - A*x1 MATRIX(_mul)(_A, _n, _n, x1, _n, 1, Ax1, _n, 1); for (j=0; j<_n; j++) r1[j] = _b[j] - Ax1[j]; } else { for (j=0; j<_n; j++) r1[j] = r0[j] - alpha*q[j]; } // delta1 = r1^T * r1 MATRIX(_transpose_mul)(r1, _n, 1, &delta1); // update beta beta = delta1 / delta0; // d1 = r + beta*d0 for (j=0; j<_n; j++) d1[j] = r1[j] + beta*d0[j]; // compute residual res = sqrt( T_ABS(delta1) / T_ABS(delta_init) ); if (i==0 || res < res_opt) { // save best solution res_opt = res; memmove(_x, x1, _n*sizeof(T)); } #if DEBUG_CGSOLVE printf(" res = %12.4e\n", res); #endif // copy old x, d, r, delta memmove(x0, x1, _n*sizeof(T)); memmove(d0, d1, _n*sizeof(T)); memmove(r0, r1, _n*sizeof(T)); delta0 = delta1; // increment counter i++; } } liquid-dsp-1.3.1/src/matrix/src/matrix.chol.c000066400000000000000000000065511317124540100210520ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Matrix Cholesky decomposition method definitions // #include #include "liquid.internal.h" #define DEBUG_MATRIX_CHOL 0 // Compute Cholesky decomposition of a symmetric/Hermitian positive- // definite matrix as A = L * L^T // _A : input square matrix [size: _n x _n] // _n : input matrix dimension // _L : output lower-triangular matrix void MATRIX(_chol)(T * _A, unsigned int _n, T * _L) { // reset L unsigned int i; for (i=0; i<_n*_n; i++) _L[i] = 0.0; unsigned int j; unsigned int k; T A_jj; T L_jj; T L_ik; T L_jk; TP t0; T t1; for (j=0; j<_n; j++) { // assert that A_jj is real, positive A_jj = matrix_access(_A,_n,_n,j,j); if ( creal(A_jj) < 0.0 ) { fprintf(stderr,"warning: matrix_chol(), matrix is not positive definite (real{A[%u,%u]} = %12.4e < 0)\n",j,j,creal(A_jj)); return; } #if T_COMPLEX if ( fabs(cimag(A_jj)) > 0.0 ) { fprintf(stderr,"warning: matrix_chol(), matrix is not positive definite (|imag{A[%u,%u]}| = %12.4e > 0)\n",j,j,fabs(cimag(A_jj))); return; } #endif // compute L_jj and store it in output matrix t0 = 0.0; for (k=0; k t0 if ( creal(A_jj) < t0 ) { fprintf(stderr,"warning: matrix_chol(), matrix is not positive definite (real{A[%u,%u]} = %12.4e < %12.4e)\n",j,j,creal(A_jj),t0); return; } L_jj = sqrt( A_jj - t0 ); matrix_access(_L,_n,_n,j,j) = L_jj; for (i=j+1; i<_n; i++) { t1 = matrix_access(_A,_n,_n,i,j); for (k=0; k #include "liquid.internal.h" #define DEBUG_MATRIX_GRAMSCHMIDT 0 // compute projection of _u onto _v, store in _e void MATRIX(_proj)(T * _u, T * _v, unsigned int _n, T * _e) { // compute dot-product between _u and _v unsigned int i; T uv = 0.; T uu = 0.; for (i=0; i<_n; i++) { uv += _u[i] * _v[i]; uu += _u[i] * _u[i]; } // TODO : check magnitude of _uu T g = uv / uu; for (i=0; i<_n; i++) _e[i] = _u[i] * g; } // Orthnormalization using the Gram-Schmidt algorithm void MATRIX(_gramschmidt)(T * _x, unsigned int _rx, unsigned int _cx, T * _v) { // validate input if (_rx == 0 || _cx == 0) { fprintf(stderr,"error: matrix_gramschmidt(), input matrix cannot have zero-length dimensions\n"); exit(1); } unsigned int i; unsigned int j; unsigned int k; // copy _x to _u memmove(_v, _x, _rx * _cx * sizeof(T)); unsigned int n = _rx; // dimensionality of each vector T proj_ij[n]; for (j=0; j<_cx; j++) { for (i=0; i v_max || r_hat==r) { r_opt = r_hat; v_max = v; } } // if the maximum is zero, matrix is singular if (v_max == 0.0f) { fprintf(stderr,"warning: matrix_gjelim(), matrix singular to machine precision\n"); } // if row does not match column (e.g. maximum value does not // lie on the diagonal) swap the rows if (r != r_opt) { MATRIX(_swaprows)(_X,_XR,_XC,r,r_opt); } // pivot on the diagonal element MATRIX(_pivot)(_X,_XR,_XC,r,r); } // scale by diagonal T g; for (r=0; r<_XR; r++) { g = 1 / matrix_access(_X,_XR,_XC,r,r); for (c=0; c<_XC; c++) matrix_access(_X,_XR,_XC,r,c) *= g; } } // pivot on element _r, _c void MATRIX(_pivot)(T * _X, unsigned int _XR, unsigned int _XC, unsigned int _r, unsigned int _c) { T v = matrix_access(_X,_XR,_XC,_r,_c); if (v==0) { fprintf(stderr, "warning: matrix_pivot(), pivoting on zero\n"); return; } unsigned int r,c; // pivot using back-substitution T g; // multiplier for (r=0; r<_XR; r++) { // skip over pivot row if (r == _r) continue; // compute multiplier g = matrix_access(_X,_XR,_XC,r,_c) / v; // back-substitution for (c=0; c<_XC; c++) { matrix_access(_X,_XR,_XC,r,c) = g*matrix_access(_X,_XR,_XC,_r,c) - matrix_access(_X,_XR,_XC, r,c); } } } void MATRIX(_swaprows)(T * _X, unsigned int _XR, unsigned int _XC, unsigned int _r1, unsigned int _r2) { if (_r1 == _r2) return; unsigned int c; T v_tmp; for (c=0; c<_XC; c++) { v_tmp = matrix_access(_X,_XR,_XC,_r1,c); matrix_access(_X,_XR,_XC,_r1,c) = matrix_access(_X,_XR,_XC,_r2,c); matrix_access(_X,_XR,_XC,_r2,c) = v_tmp; } } liquid-dsp-1.3.1/src/matrix/src/matrix.linsolve.c000066400000000000000000000052571317124540100217620ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Solve linear system of equations // #include #include "liquid.internal.h" // solve linear system of n equations: Ax = b // _A : system matrix [size: _n x _n] // _n : system size // _b : equality vector [size: _n x 1] // _x : solution vector [size: _n x 1] // _opts : options (ignored for now) void MATRIX(_linsolve)(T * _A, unsigned int _n, T * _b, T * _x, void * _opts) { #if 0 T A_inv[_n*_n]; memmove(A_inv, _A, _n*_n*sizeof(T)); MATRIX(_inv)(A_inv,_n,_n); MATRIX(_mul)(A_inv, _n, _n, _b, _n, 1, _x, _n, 1); #else unsigned int r; unsigned int c; // compute augmented matrix M [size: _n x _n+1] as // T: // A11 A12 A13 ... A1n b1 // A21 A22 A23 ... A2n b2 // A31 A32 A33 ... A3n b3 // ... // An1 An2 An3 ... Ann bn T M[_n*_n + _n]; // allocate array unsigned int m=0; // output matrix index counter unsigned int a=0; // input matrix index counter for (r=0; r<_n; r++) { for (c=0; c<_n; c++) M[m++] = _A[a++]; M[m++] = _b[r]; } // run Gauss-Jordan elimination on M // T: // 1 0 0 ... 0 x1 // 0 1 0 ... 0 x2 // 0 0 1 ... 0 x3 // ... // 0 0 0 ... 1 xn MATRIX(_gjelim)(M, _n, _n+1); // copy result from right-most column of M for (r=0; r<_n; r++) _x[r] = M[(_n+1)*(r+1)-1]; #endif } liquid-dsp-1.3.1/src/matrix/src/matrix.ludecomp.c000066400000000000000000000105121317124540100217250ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Matrix L/U decomposition method definitions // #include "liquid.internal.h" // L/U/P decomposition, Crout's method void MATRIX(_ludecomp_crout)(T * _x, unsigned int _rx, unsigned int _cx, T * _L, T * _U, T * _P) { // validate input if (_rx != _cx) { fprintf(stderr,"error: matrix_ludecomp_crout(), input matrix not square\n"); exit(-1); } unsigned int n = _rx; // reset L, U unsigned int i; for (i=0; i #include #include // add elements of two matrices // _X : 1st input matrix [size: _R x _C] // _Y : 2nd input matrix [size: _R x _C] // _Z : output matrix [size: _R x _C] // _R : number of rows // _C : number of columns void MATRIX(_add)(T * _X, T * _Y, T * _Z, unsigned int _R, unsigned int _C) { unsigned int i; for (i=0; i<(_R*_C); i++) _Z[i] = _X[i] + _Y[i]; } // subtract elements of two matrices // _X : 1st input matrix [size: _R x _C] // _Y : 2nd input matrix [size: _R x _C] // _Z : output matrix [size: _R x _C] // _R : number of rows // _C : number of columns void MATRIX(_sub)(T * _X, T * _Y, T * _Z, unsigned int _R, unsigned int _C) { unsigned int i; for (i=0; i<(_R*_C); i++) _Z[i] = _X[i] - _Y[i]; } // point-wise multiplication // _X : 1st input matrix [size: _R x _C] // _Y : 2nd input matrix [size: _R x _C] // _Z : output matrix [size: _R x _C] // _R : number of rows // _C : number of columns void MATRIX(_pmul)(T * _X, T * _Y, T * _Z, unsigned int _R, unsigned int _C) { unsigned int i; for (i=0; i<(_R*_C); i++) _Z[i] = _X[i] * _Y[i]; } // point-wise division // _X : 1st input matrix [size: _R x _C] // _Y : 2nd input matrix [size: _R x _C] // _Z : output matrix [size: _R x _C] // _R : number of rows // _C : number of columns void MATRIX(_pdiv)(T * _X, T * _Y, T * _Z, unsigned int _R, unsigned int _C) { unsigned int i; for (i=0; i<(_R*_C); i++) _Z[i] = _X[i] / _Y[i]; } // multiply two matrices together void MATRIX(_mul)(T * _X, unsigned int _XR, unsigned int _XC, T * _Y, unsigned int _YR, unsigned int _YC, T * _Z, unsigned int _ZR, unsigned int _ZC) { // ensure lengths are valid if (_ZR != _XR || _ZC != _YC || _XC != _YR ) { fprintf(stderr,"error: matrix_mul(), invalid dimensions\n"); exit(1); } unsigned int r, c, i; for (r=0; r<_ZR; r++) { for (c=0; c<_ZC; c++) { // z(i,j) = dotprod( x(i,:), y(:,j) ) T sum=0.0f; for (i=0; i<_XC; i++) { sum += matrix_access(_X,_XR,_XC,r,i) * matrix_access(_Y,_YR,_YC,i,c); } matrix_access(_Z,_ZR,_ZC,r,c) = sum; #ifdef DEBUG printf("z(%u,%u) = ", r, c); MATRIX_PRINT_ELEMENT(_Z,_ZR,_ZC,r,c); printf("\n"); #endif } } } // augment matrices x and y: // z = [x | y] void MATRIX(_aug)(T * _x, unsigned int _rx, unsigned int _cx, T * _y, unsigned int _ry, unsigned int _cy, T * _z, unsigned int _rz, unsigned int _cz) { // ensure lengths are valid if (_rz != _rx || _rz != _ry || _rx != _ry || _cz != _cx + _cy) { fprintf(stderr,"error: matrix_aug(), invalid dimensions\n"); exit(1); } // TODO: improve speed with memmove unsigned int r, c, n; for (r=0; r<_rz; r++) { n=0; for (c=0; c<_cx; c++) matrix_access(_z,_rz,_cz,r,n++) = matrix_access(_x,_rx,_cx,r,c); for (c=0; c<_cy; c++) matrix_access(_z,_rz,_cz,r,n++) = matrix_access(_y,_ry,_cy,r,c); } } // solve set of linear equations void MATRIX(_div)(T * _X, T * _Y, T * _Z, unsigned int _n) { // compute inv(_Y) T Y_inv[_n*_n]; memmove(Y_inv, _Y, _n*_n*sizeof(T)); MATRIX(_inv)(Y_inv,_n,_n); // _Z = _X * inv(_Y) MATRIX(_mul)(_X, _n, _n, Y_inv, _n, _n, _Z, _n, _n); } // matrix determinant (2 x 2) T MATRIX(_det2x2)(T * _X, unsigned int _r, unsigned int _c) { // validate input if (_r != 2 || _c != 2) { fprintf(stderr,"error: matrix_det2x2(), invalid dimensions\n"); exit(1); } return _X[0]*_X[3] - _X[1]*_X[2]; } // matrix determinant (n x n) T MATRIX(_det)(T * _X, unsigned int _r, unsigned int _c) { // validate input if (_r != _c) { fprintf(stderr,"error: matrix_det(), matrix must be square\n"); exit(1); } unsigned int n = _r; if (n==2) return MATRIX(_det2x2)(_X,2,2); // compute L/U decomposition (Doolittle's method) T L[n*n]; // lower T U[n*n]; // upper T P[n*n]; // permutation MATRIX(_ludecomp_doolittle)(_X,n,n,L,U,P); // evaluate along the diagonal of U T det = 1.0; unsigned int i; for (i=0; i #include "liquid.internal.h" #define DEBUG_MATRIX_QRDECOMP 1 // Q/R decomposition using the Gram-Schmidt algorithm void MATRIX(_qrdecomp_gramschmidt)(T * _x, unsigned int _rx, unsigned int _cx, T * _Q, T * _R) { // validate input if (_rx != _cx) { fprintf(stderr,"error: matrix_qrdecomp_gramschmidt(), input matrix not square\n"); exit(-1); } unsigned int n = _rx; unsigned int i; unsigned int j; unsigned int k; // generate and initialize matrices T e[n*n]; // normalized... for (i=0; iM = _M; q->N = _N; unsigned int i; unsigned int j; // initialize size of each pointer list q->num_mlist = (unsigned int*)malloc( q->M*sizeof(unsigned int) ); q->num_nlist = (unsigned int*)malloc( q->N*sizeof(unsigned int) ); for (i=0; iM; i++) q->num_mlist[i] = 0; for (j=0; jN; j++) q->num_nlist[j] = 0; // initialize lists q->mlist = (unsigned short int **) malloc( q->M*sizeof(unsigned short int *) ); q->nlist = (unsigned short int **) malloc( q->N*sizeof(unsigned short int *) ); for (i=0; iM; i++) q->mlist[i] = (unsigned short int *) malloc( q->num_mlist[i]*sizeof(unsigned short int) ); for (j=0; jN; j++) q->nlist[j] = (unsigned short int *) malloc( q->num_nlist[j]*sizeof(unsigned short int) ); // initialize values q->mvals = (T **) malloc( q->M*sizeof(T*) ); q->nvals = (T **) malloc( q->N*sizeof(T*) ); for (i=0; iM; i++) q->mvals[i] = (T *) malloc( q->num_mlist[i]*sizeof(T) ); for (j=0; jN; j++) q->nvals[j] = (T *) malloc( q->num_nlist[j]*sizeof(T) ); // set maximum list size q->max_num_mlist = 0; q->max_num_nlist = 0; // return main object return q; } // create _M x _N matrix, initialized on array SMATRIX() SMATRIX(_create_array)(T * _v, unsigned int _m, unsigned int _n) { // create object and allocate memory SMATRIX() q = SMATRIX(_create)(_m,_n); // initialize elements unsigned int i; unsigned int j; for (i=0; i<_m; i++) { for (j=0; j<_n; j++) { if (_v[i*_n + j] != 0) SMATRIX(_set)(q,i,j,_v[i*_n + j]); } } // return main object return q; } // destroy object void SMATRIX(_destroy)(SMATRIX() _q) { unsigned int i; unsigned int j; // free internal memory free(_q->num_mlist); free(_q->num_nlist); // free lists for (i=0; i<_q->M; i++) free(_q->mlist[i]); for (j=0; j<_q->N; j++) free(_q->nlist[j]); free(_q->mlist); free(_q->nlist); // free values for (i=0; i<_q->M; i++) free(_q->mvals[i]); for (j=0; j<_q->N; j++) free(_q->nvals[j]); free(_q->mvals); free(_q->nvals); // free main object memory free(_q); } // print compact form void SMATRIX(_print)(SMATRIX() _q) { printf("dims : %u %u\n", _q->M, _q->N); printf("max : %u %u\n", _q->max_num_mlist, _q->max_num_nlist); unsigned int i; unsigned int j; printf("rows :"); for (i=0; i<_q->M; i++) printf(" %u", _q->num_mlist[i]); printf("\n"); printf("cols :"); for (j=0; j<_q->N; j++) printf(" %u", _q->num_nlist[j]); printf("\n"); // print mlist printf("row indices:\n"); for (i=0; i<_q->M; i++) { if (_q->num_mlist[i] == 0) continue; printf(" %3u :", i); for (j=0; j<_q->num_mlist[i]; j++) printf(" %u", _q->mlist[i][j]); printf("\n"); } // print nlist printf("column indices:\n"); for (j=0; j<_q->N; j++) { if (_q->num_nlist[j] == 0) continue; printf(" %3u :", j); for (i=0; i<_q->num_nlist[j]; i++) printf(" %u", _q->nlist[j][i]); printf("\n"); } #if SMATRIX_FLOAT // print mvals printf("row values:\n"); for (i=0; i<_q->M; i++) { printf(" %3u :", i); for (j=0; j<_q->num_mlist[i]; j++) printf(" %6.2f", _q->mvals[i][j]); printf("\n"); } // print nvals printf("column values:\n"); for (j=0; j<_q->N; j++) { printf(" %3u :", j); for (i=0; i<_q->num_nlist[j]; i++) printf(" %6.2f", _q->nvals[j][i]); printf("\n"); } #endif } // print expanded form void SMATRIX(_print_expanded)(SMATRIX() _q) { unsigned int i; unsigned int j; unsigned int t; // print in expanded 'regular' form for (i=0; i<_q->M; i++) { // reset counter t = 0; for (j=0; j<_q->N; j++) { if (t == _q->num_mlist[i]) { PRINTVAL_ZERO(); } else if (_q->mlist[i][t] == j) { PRINTVAL(_q->mvals[i][t]); t++; } else { PRINTVAL_ZERO(); } } printf("\n"); } } // get matrix dimensions void SMATRIX(_size)(SMATRIX() _q, unsigned int * _m, unsigned int * _n) { *_m = _q->M; *_n = _q->N; } // zero all values, retaining memory allocation void SMATRIX(_clear)(SMATRIX() _q) { unsigned int i; unsigned int j; // clear row entries for (i=0; i<_q->M; i++) { for (j=0; j<_q->num_mlist[i]; j++) { _q->mvals[i][j] = 0; } } // clear colum entries for (j=0; j<_q->N; j++) { for (i=0; i<_q->num_nlist[j]; i++) { _q->nvals[j][i] = 0; } } } // zero all values, clearing memory void SMATRIX(_reset)(SMATRIX() _q) { unsigned int i; unsigned int j; for (i=0; i<_q->M; i++) _q->num_mlist[i] = 0; for (j=0; j<_q->N; j++) _q->num_nlist[j] = 0; _q->max_num_mlist = 0; _q->max_num_nlist = 0; } // determine if element is set int SMATRIX(_isset)(SMATRIX() _q, unsigned int _m, unsigned int _n) { // validate input if (_m >= _q->M || _n >= _q->N) { fprintf(stderr,"error: SMATRIX(_isset)(%u,%u), index exceeds matrix dimension (%u,%u)\n", _m, _n, _q->M, _q->N); exit(1); } unsigned int j; for (j=0; j<_q->num_mlist[_m]; j++) { if (_q->mlist[_m][j] == _n) return 1; } return 0; } // insert element at index void SMATRIX(_insert)(SMATRIX() _q, unsigned int _m, unsigned int _n, T _v) { // validate input if (_m >= _q->M || _n >= _q->N) { fprintf(stderr,"error: SMATRIX(_insert)(%u,%u), index exceeds matrix dimension (%u,%u)\n", _m, _n, _q->M, _q->N); exit(1); } // check to see if element is already set if (SMATRIX(_isset)(_q,_m,_n)) { // simply set the value and return printf("SMATRIX(_insert), value already set...\n"); SMATRIX(_set)(_q, _m, _n, _v); return; } // increment list sizes _q->num_mlist[_m]++; _q->num_nlist[_n]++; // reallocate indices lists at this index _q->mlist[_m] = (unsigned short int*) realloc(_q->mlist[_m], _q->num_mlist[_m]*sizeof(unsigned short int)); _q->nlist[_n] = (unsigned short int*) realloc(_q->nlist[_n], _q->num_nlist[_n]*sizeof(unsigned short int)); // reallocate values lists at this index _q->mvals[_m] = (T*) realloc(_q->mvals[_m], _q->num_mlist[_m]*sizeof(T)); _q->nvals[_n] = (T*) realloc(_q->nvals[_n], _q->num_nlist[_n]*sizeof(T)); // find index within list to insert new value unsigned int mindex = smatrix_indexsearch(_q->mlist[_m], _q->num_mlist[_m]-1, _n); unsigned int nindex = smatrix_indexsearch(_q->nlist[_n], _q->num_nlist[_n]-1, _m); //printf("inserting value (n=%3u) at m=%3u, index=%3u\n", _n, _m, mindex); //printf("inserting value (m=%3u) at n=%3u, index=%3u\n", _m, _n, nindex); // insert indices to appropriate place in list memmove(&_q->mlist[_m][mindex+1], &_q->mlist[_m][mindex], (_q->num_mlist[_m]-mindex-1)*sizeof(unsigned short int)); memmove(&_q->nlist[_n][nindex+1], &_q->nlist[_n][nindex], (_q->num_nlist[_n]-nindex-1)*sizeof(unsigned short int)); _q->mlist[_m][mindex] = _n; _q->nlist[_n][nindex] = _m; // insert values to appropriate place in list memmove(&_q->mvals[_m][mindex+1], &_q->mvals[_m][mindex], (_q->num_mlist[_m]-mindex-1)*sizeof(T)); memmove(&_q->nvals[_n][nindex+1], &_q->nvals[_n][nindex], (_q->num_nlist[_n]-nindex-1)*sizeof(T)); _q->mvals[_m][mindex] = _v; _q->nvals[_n][nindex] = _v; // update maximum if (_q->num_mlist[_m] > _q->max_num_mlist) _q->max_num_mlist = _q->num_mlist[_m]; if (_q->num_nlist[_n] > _q->max_num_nlist) _q->max_num_nlist = _q->num_nlist[_n]; } // delete element at index void SMATRIX(_delete)(SMATRIX() _q, unsigned int _m, unsigned int _n) { // validate input if (_m > _q->M || _n > _q->N) { fprintf(stderr,"error: SMATRIX(_delete)(%u,%u), index exceeds matrix dimension (%u,%u)\n", _m, _n, _q->M, _q->N); exit(1); } // check to see if element is already not set if (!SMATRIX(_isset)(_q,_m,_n)) return; // remove value from mlist (shift left) unsigned int i; unsigned int j; unsigned int t=0; for (j=0; j<_q->num_mlist[_m]; j++) { if (_q->mlist[_m][j] == _n) t = j; } for (j=t; j<_q->num_mlist[_m]-1; j++) _q->mlist[_m][j] = _q->mlist[_m][j+1]; // remove value from nlist (shift left) t = 0; for (i=0; i<_q->num_nlist[_n]; i++) { if (_q->nlist[_n][i] == _m) t = i; } for (i=t; i<_q->num_nlist[_n]-1; i++) _q->nlist[_n][i] = _q->nlist[_n][i+1]; // reduce sizes _q->num_mlist[_m]--; _q->num_nlist[_n]--; // reallocate _q->mlist[_m] = (unsigned short int*) realloc(_q->mlist[_m], _q->num_mlist[_m]*sizeof(unsigned short int)); _q->nlist[_n] = (unsigned short int*) realloc(_q->nlist[_n], _q->num_nlist[_n]*sizeof(unsigned short int)); // reset maxima if (_q->max_num_mlist == _q->num_mlist[_m]+1) SMATRIX(_reset_max_mlist)(_q); if (_q->max_num_nlist == _q->num_nlist[_n]+1) SMATRIX(_reset_max_nlist)(_q); } // set element value at index void SMATRIX(_set)(SMATRIX() _q, unsigned int _m, unsigned int _n, T _v) { // validate input if (_m >= _q->M || _n >= _q->N) { fprintf(stderr,"error: SMATRIX(_set)(%u,%u), index exceeds matrix dimension (%u,%u)\n", _m, _n, _q->M, _q->N); exit(1); } // insert new element if not already allocated if (!SMATRIX(_isset)(_q,_m,_n)) { SMATRIX(_insert)(_q,_m,_n,_v); return; } // set value unsigned int i; unsigned int j; for (j=0; j<_q->num_mlist[_m]; j++) { if (_q->mlist[_m][j] == _n) _q->mvals[_m][j] = _v; } for (i=0; i<_q->num_nlist[_n]; i++) { if (_q->nlist[_n][i] == _m) _q->nvals[_n][i] = _v; } } // get element value at index (return zero if not set) T SMATRIX(_get)(SMATRIX() _q, unsigned int _m, unsigned int _n) { // validate input if (_m >= _q->M || _n >= _q->N) { fprintf(stderr,"error: SMATRIX(_get)(%u,%u), index exceeds matrix dimension (%u,%u)\n", _m, _n, _q->M, _q->N); exit(1); } unsigned int j; for (j=0; j<_q->num_mlist[_m]; j++) { if (_q->mlist[_m][j] == _n) return _q->mvals[_m][j]; } return 0; } // initialize to identity matrix void SMATRIX(_eye)(SMATRIX() _q) { // reset all elements SMATRIX(_reset)(_q); // set values along diagonal unsigned int i; unsigned int dmin = _q->M < _q->N ? _q->M : _q->N; for (i=0; iM != _a->M || _c->N != _b->N || _a->N != _b->M) { fprintf(stderr,"error: SMATRIX(_mul)(), invalid dimensions\n"); exit(1); } // clear output matrix (retain memory allocation) SMATRIX(_clear)(_c); unsigned int r; // output row unsigned int c; // output column unsigned int i; unsigned int j; for (r=0; r<_c->M; r++) { // find number of non-zero entries in row 'r' of matrix '_a' unsigned int nnz_a_row = _a->num_mlist[r]; // if this number is zero, there will not be any non-zero // entries in the corresponding row of the output matrix '_c' if (nnz_a_row == 0) continue; for (c=0; c<_c->N; c++) { // find number of non-zero entries in column 'c' of matrix '_b' unsigned int nnz_b_col = _b->num_nlist[c]; T p = 0; int set_value = 0; // find common elements between non-zero elements in // row 'r' of matrix '_a' and col 'c' of matrix '_b' i=0; // reset array index for rows of '_a' j=0; // reset array index for cols of '_b' while (i < nnz_a_row && j < nnz_b_col) { // unsigned int ca = _a->mlist[r][i]; unsigned int rb = _b->nlist[c][j]; if (ca == rb) { // match found between _a[r,ca] and _b[rb,c] p += _a->mvals[r][i] * _b->nvals[c][j]; set_value = 1; i++; j++; } else if (ca < rb) i++; // increment index for '_a' else j++; // increment index for '_b' } // set value if any multiplications have been made if (set_value) { #if SMATRIX_BOOL // set result modulo 2 SMATRIX(_set)(_c, r, c, p % 2); #else SMATRIX(_set)(_c, r, c, p); #endif } } } } // multiply by vector // _q : sparse matrix // _x : input vector [size: _N x 1] // _y : output vector [size: _M x 1] void SMATRIX(_vmul)(SMATRIX() _q, T * _x, T * _y) { unsigned int i; unsigned int j; // initialize to zero for (i=0; i<_q->M; i++) _y[i] = 0; for (i=0; i<_q->M; i++) { // running total T p = 0; // only compute multiplications on non-zero entries for (j=0; j<_q->num_mlist[i]; j++) p += _q->mvals[i][j] * _x[ _q->mlist[i][j] ]; // set output value appropriately #if SMATRIX_BOOL _y[i] = p % 2; #else _y[i] = p; #endif } } // // internal methods // // find maximum mlist length void SMATRIX(_reset_max_mlist)(SMATRIX() _q) { unsigned int i; _q->max_num_mlist = 0; for (i=0; i<_q->M; i++) { if (_q->num_mlist[i] > _q->max_num_mlist) _q->max_num_mlist = _q->num_mlist[i]; } } // find maximum nlist length void SMATRIX(_reset_max_nlist)(SMATRIX() _q) { unsigned int j; _q->max_num_nlist = 0; for (j=0; j<_q->N; j++) { if (_q->num_nlist[j] > _q->max_num_nlist) _q->max_num_nlist = _q->num_nlist[j]; } } liquid-dsp-1.3.1/src/matrix/src/smatrix.common.c000066400000000000000000000030771317124540100216000ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // sparse matrices: common methods // // search for index placement in list unsigned short int smatrix_indexsearch(unsigned short int * _list, unsigned int _num_elements, unsigned short int _value) { // TODO: use bisection method unsigned int i; for (i=0; i<_num_elements; i++) { if (_list[i] > _value) break; } // return i; } liquid-dsp-1.3.1/src/matrix/src/smatrixb.c000066400000000000000000000064011317124540100204450ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // sparse matrix API: boolean // #include #include #include #include "liquid.internal.h" // name-mangling macro #define SMATRIX(name) LIQUID_CONCAT(smatrixb,name) // primitive type #define T unsigned char // category (float/int/bool) #define SMATRIX_FLOAT 0 #define SMATRIX_INT 0 #define SMATRIX_BOOL 1 // print macros #define PRINTVAL_ZERO() printf(" ."); #define PRINTVAL(V) printf(" %1u", V); // source files #include "smatrix.c" // // smatrix cross methods // // multiply sparse binary matrix by floating-point matrix // _q : sparse matrix [size: A->M x A->N] // _x : input vector [size: mx x nx ] // _y : output vector [size: my x ny ] void smatrixb_mulf(smatrixb _A, float * _x, unsigned int _mx, unsigned int _nx, float * _y, unsigned int _my, unsigned int _ny) { // ensure lengths are valid if (_my != _A->M || _ny != _nx || _A->N != _mx ) { fprintf(stderr,"error: matrix_mul(), invalid dimensions\n"); exit(1); } unsigned int i; unsigned int j; // clear output matrix for (i=0; i<_my*_ny; i++) _y[i] = 0.0f; // for (i=0; i<_A->M; i++) { // find non-zero column entries in this row unsigned int p; for (p=0; p<_A->num_mlist[i]; p++) { for (j=0; j<_ny; j++) { //_y(i,j) += _x( _A->mlist[i][p], j); _y[i*_ny + j] += _x[ _A->mlist[i][p]*_nx + j]; } } } } // multiply sparse binary matrix by floating-point vector // _q : sparse matrix // _x : input vector [size: _N x 1] // _y : output vector [size: _M x 1] void smatrixb_vmulf(smatrixb _q, float * _x, float * _y) { unsigned int i; unsigned int j; for (i=0; i<_q->M; i++) { // reset total _y[i] = 0.0f; // only accumulate values on non-zero entries for (j=0; j<_q->num_mlist[i]; j++) _y[i] += _x[ _q->mlist[i][j] ]; } } liquid-dsp-1.3.1/src/matrix/src/smatrixf.c000066400000000000000000000031541317124540100204530ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // sparse matrix API: float // #include #include #include #include "liquid.internal.h" // macro #define SMATRIX(name) LIQUID_CONCAT(smatrixf,name) // primitive type #define T float // category (float/int/bool) #define SMATRIX_FLOAT 1 #define SMATRIX_INT 0 #define SMATRIX_BOOL 0 // print macros #define PRINTVAL_ZERO() printf(" %6s", "."); #define PRINTVAL(V) printf(" %6.2f", V); // source files #include "smatrix.c" liquid-dsp-1.3.1/src/matrix/src/smatrixi.c000066400000000000000000000032051317124540100204530ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // sparse matrix API: short signed integer // #include #include #include #include "liquid.internal.h" // name-mangling macro #define SMATRIX(name) LIQUID_CONCAT(smatrixi,name) // primitive type #define T short int // category (float/int/bool) #define SMATRIX_FLOAT 0 #define SMATRIX_INT 1 #define SMATRIX_BOOL 0 // print macros #define PRINTVAL_ZERO() printf(" ."); #define PRINTVAL(V) printf(" %3d", V); // source files #include "smatrix.c" liquid-dsp-1.3.1/src/matrix/tests/000077500000000000000000000000001317124540100170225ustar00rootroot00000000000000liquid-dsp-1.3.1/src/matrix/tests/data/000077500000000000000000000000001317124540100177335ustar00rootroot00000000000000liquid-dsp-1.3.1/src/matrix/tests/data/README.md000066400000000000000000000002051317124540100212070ustar00rootroot00000000000000 matrix test data ================ This directory contains all of the data files for testing matrix operations within liquid-dsp. liquid-dsp-1.3.1/src/matrix/tests/data/matrixcf_data_add.c000066400000000000000000000122261317124540100235200ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing matrix addition // #include // matrixcf_data_add_x [size: 5 x 4] float complex matrixcf_data_add_x[] = { 1.366575479507 + -1.463535666466*_Complex_I /* ( 0, 0) */, 1.982354640961 + 0.090445250273*_Complex_I /* ( 0, 1) */, 0.913504719734 + -0.689249753952*_Complex_I /* ( 0, 2) */, 0.671039104462 + -0.184951126575*_Complex_I /* ( 0, 3) */, 0.264611721039 + 0.204716682434*_Complex_I /* ( 1, 0) */, 0.995791137218 + -0.192152589560*_Complex_I /* ( 1, 1) */, -1.983934879303 + -0.306251227856*_Complex_I /* ( 1, 2) */, -0.375840932131 + -0.751154422760*_Complex_I /* ( 1, 3) */, 0.245937779546 + -0.470900952816*_Complex_I /* ( 2, 0) */, -0.343152791262 + 1.205224752426*_Complex_I /* ( 2, 1) */, -0.143777698278 + -0.457689523697*_Complex_I /* ( 2, 2) */, -1.387172579765 + 0.225333094597*_Complex_I /* ( 2, 3) */, 0.781192481518 + -1.102205991745*_Complex_I /* ( 3, 0) */, 1.444583415985 + 0.660028517246*_Complex_I /* ( 3, 1) */, 0.043851174414 + 0.049496211112*_Complex_I /* ( 3, 2) */, 0.399744838476 + -1.435891628265*_Complex_I /* ( 3, 3) */, -0.488068610430 + -0.211131110787*_Complex_I /* ( 4, 0) */, 0.573721885681 + 0.016210200265*_Complex_I /* ( 4, 1) */, -1.381630182266 + -0.026558181271*_Complex_I /* ( 4, 2) */, -0.176615595818 + -0.414863616228*_Complex_I /* ( 4, 3) */}; // matrixcf_data_add_y [size: 5 x 4] float complex matrixcf_data_add_y[] = { -0.345586329699 + 0.240964725614*_Complex_I /* ( 0, 0) */, -0.025732314214 + 1.212726473808*_Complex_I /* ( 0, 1) */, 0.907316803932 + 1.614625453949*_Complex_I /* ( 0, 2) */, -1.277831077576 + -0.193561494350*_Complex_I /* ( 0, 3) */, -0.566267848015 + -0.477513909340*_Complex_I /* ( 1, 0) */, -0.220387980342 + 0.152425482869*_Complex_I /* ( 1, 1) */, 1.062286615372 + -1.132043361664*_Complex_I /* ( 1, 2) */, 0.560977220535 + -0.981467425823*_Complex_I /* ( 1, 3) */, 0.025816366076 + -0.697246491909*_Complex_I /* ( 2, 0) */, 0.658244788647 + -1.403432965279*_Complex_I /* ( 2, 1) */, -1.326129436493 + -0.529069602489*_Complex_I /* ( 2, 2) */, -1.535833358765 + -1.406206607819*_Complex_I /* ( 2, 3) */, 0.101660177112 + -1.552777647972*_Complex_I /* ( 3, 0) */, 1.834807038307 + 0.647780478001*_Complex_I /* ( 3, 1) */, -0.620168924332 + -0.103246472776*_Complex_I /* ( 3, 2) */, -0.063054643571 + -0.756766498089*_Complex_I /* ( 3, 3) */, 0.280569136143 + 0.560459613800*_Complex_I /* ( 4, 0) */, -0.069713011384 + -0.971132814884*_Complex_I /* ( 4, 1) */, 0.225165605545 + -1.117488980293*_Complex_I /* ( 4, 2) */, -0.290932357311 + 0.302335798740*_Complex_I /* ( 4, 3) */}; // matrixcf_data_add_z [size: 5 x 4] float complex matrixcf_data_add_z[] = { 1.020989149809 + -1.222570940852*_Complex_I /* ( 0, 0) */, 1.956622326747 + 1.303171724081*_Complex_I /* ( 0, 1) */, 1.820821523666 + 0.925375699997*_Complex_I /* ( 0, 2) */, -0.606791973114 + -0.378512620926*_Complex_I /* ( 0, 3) */, -0.301656126976 + -0.272797226906*_Complex_I /* ( 1, 0) */, 0.775403156877 + -0.039727106690*_Complex_I /* ( 1, 1) */, -0.921648263931 + -1.438294589520*_Complex_I /* ( 1, 2) */, 0.185136288404 + -1.732621848583*_Complex_I /* ( 1, 3) */, 0.271754145622 + -1.168147444725*_Complex_I /* ( 2, 0) */, 0.315091997385 + -0.198208212852*_Complex_I /* ( 2, 1) */, -1.469907134771 + -0.986759126186*_Complex_I /* ( 2, 2) */, -2.923005938530 + -1.180873513222*_Complex_I /* ( 2, 3) */, 0.882852658629 + -2.654983639717*_Complex_I /* ( 3, 0) */, 3.279390454292 + 1.307808995247*_Complex_I /* ( 3, 1) */, -0.576317749918 + -0.053750261664*_Complex_I /* ( 3, 2) */, 0.336690194905 + -2.192658126354*_Complex_I /* ( 3, 3) */, -0.207499474287 + 0.349328503013*_Complex_I /* ( 4, 0) */, 0.504008874297 + -0.954922614619*_Complex_I /* ( 4, 1) */, -1.156464576721 + -1.144047161564*_Complex_I /* ( 4, 2) */, -0.467547953129 + -0.112527817488*_Complex_I /* ( 4, 3) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixcf_data_aug.c000066400000000000000000000134321317124540100235440ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing matrix augmentation // #include // matrixcf_data_aug_x [size: 5 x 4] float complex matrixcf_data_aug_x[] = { -1.383545994759 + 0.803655147552*_Complex_I /* ( 0, 0) */, -0.918114125729 + -1.194809913635*_Complex_I /* ( 0, 1) */, 0.090901032090 + 0.484884619713*_Complex_I /* ( 0, 2) */, 0.109402157366 + 1.450437188148*_Complex_I /* ( 0, 3) */, -2.269510746002 + -0.606436431408*_Complex_I /* ( 1, 0) */, -0.195189133286 + 0.416639328003*_Complex_I /* ( 1, 1) */, 1.940145850182 + 0.895506143570*_Complex_I /* ( 1, 2) */, -0.784153759480 + -0.345893263817*_Complex_I /* ( 1, 3) */, 0.652509629726 + 0.994532823563*_Complex_I /* ( 2, 0) */, -2.253150939941 + 0.327611356974*_Complex_I /* ( 2, 1) */, 1.012208938599 + -0.677044689655*_Complex_I /* ( 2, 2) */, -0.700399398804 + -0.330108255148*_Complex_I /* ( 2, 3) */, -1.175772666931 + 0.248428389430*_Complex_I /* ( 3, 0) */, 0.412228941917 + -2.519471645355*_Complex_I /* ( 3, 1) */, -1.667356371880 + -1.187105178833*_Complex_I /* ( 3, 2) */, 1.243350982666 + -0.736937880516*_Complex_I /* ( 3, 3) */, 0.033468723297 + 0.131351217628*_Complex_I /* ( 4, 0) */, -0.617851972580 + 1.434038400650*_Complex_I /* ( 4, 1) */, -1.009798288345 + 0.758803665638*_Complex_I /* ( 4, 2) */, 1.450994849205 + -0.595933079720*_Complex_I /* ( 4, 3) */}; // matrixcf_data_aug_y [size: 5 x 3] float complex matrixcf_data_aug_y[] = { 0.301848381758 + 0.353115469217*_Complex_I /* ( 0, 0) */, 0.703616917133 + 0.044240720570*_Complex_I /* ( 0, 1) */, 0.268176555634 + 1.071476221085*_Complex_I /* ( 0, 2) */, -0.717849135399 + -0.764326214790*_Complex_I /* ( 1, 0) */, -0.108926303685 + -0.315297245979*_Complex_I /* ( 1, 1) */, 0.357895255089 + -1.419853448868*_Complex_I /* ( 1, 2) */, -0.831380963326 + 1.003911018372*_Complex_I /* ( 2, 0) */, -0.361211270094 + -0.926369905472*_Complex_I /* ( 2, 1) */, 2.307183980942 + -0.432167291641*_Complex_I /* ( 2, 2) */, -0.694230437279 + -1.021739125252*_Complex_I /* ( 3, 0) */, 0.412434548140 + -1.840429663658*_Complex_I /* ( 3, 1) */, 0.342358648777 + -1.084336757660*_Complex_I /* ( 3, 2) */, -0.314995974302 + -0.811702668667*_Complex_I /* ( 4, 0) */, 0.912520587444 + -2.686280250549*_Complex_I /* ( 4, 1) */, 0.204153224826 + -0.616621196270*_Complex_I /* ( 4, 2) */}; // matrixcf_data_aug_z [size: 5 x 7] float complex matrixcf_data_aug_z[] = { -1.383545994759 + 0.803655147552*_Complex_I /* ( 0, 0) */, -0.918114125729 + -1.194809913635*_Complex_I /* ( 0, 1) */, 0.090901032090 + 0.484884619713*_Complex_I /* ( 0, 2) */, 0.109402157366 + 1.450437188148*_Complex_I /* ( 0, 3) */, 0.301848381758 + 0.353115469217*_Complex_I /* ( 0, 4) */, 0.703616917133 + 0.044240720570*_Complex_I /* ( 0, 5) */, 0.268176555634 + 1.071476221085*_Complex_I /* ( 0, 6) */, -2.269510746002 + -0.606436431408*_Complex_I /* ( 1, 0) */, -0.195189133286 + 0.416639328003*_Complex_I /* ( 1, 1) */, 1.940145850182 + 0.895506143570*_Complex_I /* ( 1, 2) */, -0.784153759480 + -0.345893263817*_Complex_I /* ( 1, 3) */, -0.717849135399 + -0.764326214790*_Complex_I /* ( 1, 4) */, -0.108926303685 + -0.315297245979*_Complex_I /* ( 1, 5) */, 0.357895255089 + -1.419853448868*_Complex_I /* ( 1, 6) */, 0.652509629726 + 0.994532823563*_Complex_I /* ( 2, 0) */, -2.253150939941 + 0.327611356974*_Complex_I /* ( 2, 1) */, 1.012208938599 + -0.677044689655*_Complex_I /* ( 2, 2) */, -0.700399398804 + -0.330108255148*_Complex_I /* ( 2, 3) */, -0.831380963326 + 1.003911018372*_Complex_I /* ( 2, 4) */, -0.361211270094 + -0.926369905472*_Complex_I /* ( 2, 5) */, 2.307183980942 + -0.432167291641*_Complex_I /* ( 2, 6) */, -1.175772666931 + 0.248428389430*_Complex_I /* ( 3, 0) */, 0.412228941917 + -2.519471645355*_Complex_I /* ( 3, 1) */, -1.667356371880 + -1.187105178833*_Complex_I /* ( 3, 2) */, 1.243350982666 + -0.736937880516*_Complex_I /* ( 3, 3) */, -0.694230437279 + -1.021739125252*_Complex_I /* ( 3, 4) */, 0.412434548140 + -1.840429663658*_Complex_I /* ( 3, 5) */, 0.342358648777 + -1.084336757660*_Complex_I /* ( 3, 6) */, 0.033468723297 + 0.131351217628*_Complex_I /* ( 4, 0) */, -0.617851972580 + 1.434038400650*_Complex_I /* ( 4, 1) */, -1.009798288345 + 0.758803665638*_Complex_I /* ( 4, 2) */, 1.450994849205 + -0.595933079720*_Complex_I /* ( 4, 3) */, -0.314995974302 + -0.811702668667*_Complex_I /* ( 4, 4) */, 0.912520587444 + -2.686280250549*_Complex_I /* ( 4, 5) */, 0.204153224826 + -0.616621196270*_Complex_I /* ( 4, 6) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixcf_data_chol.c000066400000000000000000000065221317124540100237170ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing Cholesky decomposition // #include // matrixcf_data_chol_L [size: 4 x 4] float complex matrixcf_data_chol_L[] = { 1.010000000000 + 0.000000000000*_Complex_I /* ( 0, 0) */, 0.000000000000 + 0.000000000000*_Complex_I /* ( 0, 1) */, 0.000000000000 + 0.000000000000*_Complex_I /* ( 0, 2) */, 0.000000000000 + 0.000000000000*_Complex_I /* ( 0, 3) */, -1.420000000000 + 0.250000000000*_Complex_I /* ( 1, 0) */, 0.500000000000 + 0.000000000000*_Complex_I /* ( 1, 1) */, 0.000000000000 + 0.000000000000*_Complex_I /* ( 1, 2) */, 0.000000000000 + 0.000000000000*_Complex_I /* ( 1, 3) */, 0.320000000000 + -1.230000000000*_Complex_I /* ( 2, 0) */, 2.010000000000 + 0.780000000000*_Complex_I /* ( 2, 1) */, 0.300000000000 + 0.000000000000*_Complex_I /* ( 2, 2) */, 0.000000000000 + 0.000000000000*_Complex_I /* ( 2, 3) */, -1.020000000000 + 1.020000000000*_Complex_I /* ( 3, 0) */, -0.320000000000 + -0.030000000000*_Complex_I /* ( 3, 1) */, -1.650000000000 + 2.010000000000*_Complex_I /* ( 3, 2) */, 1.070000000000 + 0.000000000000*_Complex_I /* ( 3, 3) */}; // matrixcf_data_chol_A [size: 4 x 4] float complex matrixcf_data_chol_A[] = { 1.020100000000 + 0.000000000000*_Complex_I /* ( 0, 0) */, -1.434200000000 + -0.252500000000*_Complex_I /* ( 0, 1) */, 0.323200000000 + 1.242300000000*_Complex_I /* ( 0, 2) */, -1.030200000000 + -1.030200000000*_Complex_I /* ( 0, 3) */, -1.434200000000 + 0.252500000000*_Complex_I /* ( 1, 0) */, 2.328900000000 + 0.000000000000*_Complex_I /* ( 1, 1) */, 0.243100000000 + -2.056600000000*_Complex_I /* ( 1, 2) */, 1.543400000000 + 1.208400000000*_Complex_I /* ( 1, 3) */, 0.323200000000 + -1.242300000000*_Complex_I /* ( 2, 0) */, 0.243100000000 + 2.056600000000*_Complex_I /* ( 2, 1) */, 6.353800000000 + 0.000000000000*_Complex_I /* ( 2, 2) */, -2.742600000000 + 0.135900000000*_Complex_I /* ( 2, 3) */, -1.030200000000 + 1.030200000000*_Complex_I /* ( 3, 0) */, 1.543400000000 + -1.208400000000*_Complex_I /* ( 3, 1) */, -2.742600000000 + -0.135900000000*_Complex_I /* ( 3, 2) */, 10.091600000000 + 0.000000000000*_Complex_I /* ( 3, 3) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixcf_data_inv.c000066400000000000000000000107101317124540100235600ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing matrix inversion // #include // matrixcf_data_inv_x [size: 5 x 5] float complex matrixcf_data_inv_x[] = { -0.911099433899 + -0.436777323484*_Complex_I /* ( 0, 0) */, 0.598295390606 + -0.283340752125*_Complex_I /* ( 0, 1) */, -0.264758616686 + -0.421906232834*_Complex_I /* ( 0, 2) */, -0.066837862134 + -0.934806823730*_Complex_I /* ( 0, 3) */, 0.393610686064 + -1.011345505714*_Complex_I /* ( 0, 4) */, -0.543692529202 + -1.426580429077*_Complex_I /* ( 1, 0) */, -1.006833553314 + 0.448534607887*_Complex_I /* ( 1, 1) */, 0.048818156123 + -0.540948212147*_Complex_I /* ( 1, 2) */, 0.180871278048 + 0.331172674894*_Complex_I /* ( 1, 3) */, -1.100448012352 + 1.841731786728*_Complex_I /* ( 1, 4) */, 2.341797351837 + -1.200128436089*_Complex_I /* ( 2, 0) */, 0.239693909883 + 0.206349417567*_Complex_I /* ( 2, 1) */, -0.815828502178 + -0.349400132895*_Complex_I /* ( 2, 2) */, 1.213637232780 + 0.298941820860*_Complex_I /* ( 2, 3) */, -1.522765398026 + 1.651986479759*_Complex_I /* ( 2, 4) */, 1.481738448143 + 0.055169839412*_Complex_I /* ( 3, 0) */, -1.241538286209 + -0.077680915594*_Complex_I /* ( 3, 1) */, 1.046607017517 + -0.843883395195*_Complex_I /* ( 3, 2) */, -1.564810752869 + 1.346152186394*_Complex_I /* ( 3, 3) */, 0.786287426949 + -1.010108113289*_Complex_I /* ( 3, 4) */, 1.234361886978 + -1.305809140205*_Complex_I /* ( 4, 0) */, 0.053748749197 + 0.403882414103*_Complex_I /* ( 4, 1) */, -0.081336200237 + -0.462558329105*_Complex_I /* ( 4, 2) */, -1.370563983917 + -0.284755766392*_Complex_I /* ( 4, 3) */, 0.200873896480 + -0.036809749901*_Complex_I /* ( 4, 4) */}; // matrixcf_data_inv_y [size: 5 x 5] float complex matrixcf_data_inv_y[] = { -0.127852678827 + -0.009178191835*_Complex_I /* ( 0, 0) */, -0.199905444866 + 0.033789259175*_Complex_I /* ( 0, 1) */, 0.168465876479 + -0.059607902071*_Complex_I /* ( 0, 2) */, 0.087700609092 + -0.030597427908*_Complex_I /* ( 0, 3) */, 0.084793376582 + 0.131223765916*_Complex_I /* ( 0, 4) */, 0.209779356201 + 0.642123753363*_Complex_I /* ( 1, 0) */, -0.045651767577 + -0.019599459364*_Complex_I /* ( 1, 1) */, 0.137284052424 + 0.504637287094*_Complex_I /* ( 1, 2) */, -0.333643348460 + 0.455368743084*_Complex_I /* ( 1, 3) */, 0.244939020151 + -0.609710193351*_Complex_I /* ( 1, 4) */, -0.114524820581 + 0.963012925652*_Complex_I /* ( 2, 0) */, 0.303499486096 + 0.348121666797*_Complex_I /* ( 2, 1) */, -0.327372880299 + 0.397314645420*_Complex_I /* ( 2, 2) */, -0.231096370464 + 0.372958732742*_Complex_I /* ( 2, 3) */, 0.089363987094 + -0.240520272187*_Complex_I /* ( 2, 4) */, 0.072169240922 + 0.159456098576*_Complex_I /* ( 3, 0) */, -0.064066539188 + 0.069570707500*_Complex_I /* ( 3, 1) */, 0.090335627717 + -0.121329478735*_Complex_I /* ( 3, 2) */, 0.053196220990 + -0.158230982223*_Complex_I /* ( 3, 3) */, -0.413653285108 + 0.167815066469*_Complex_I /* ( 3, 4) */, 0.089194647874 + -0.035492413461*_Complex_I /* ( 4, 0) */, -0.192303472410 + -0.221655891788*_Complex_I /* ( 4, 1) */, 0.111730542618 + -0.221903756183*_Complex_I /* ( 4, 2) */, 0.303835472120 + -0.022543572811*_Complex_I /* ( 4, 3) */, -0.167008031325 + 0.051911194273*_Complex_I /* ( 4, 4) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixcf_data_linsolve.c000066400000000000000000000071621317124540100246260ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing linear solver // #include // matrixcf_data_linsolve_A [size: 5 x 5] float complex matrixcf_data_linsolve_A[] = { -0.482884645462 + -0.221723198891*_Complex_I /* ( 0, 0) */, -0.387645065784 + 0.086682170630*_Complex_I /* ( 0, 1) */, 1.580931067467 + 0.883717715740*_Complex_I /* ( 0, 2) */, 1.570333838463 + 1.783135294914*_Complex_I /* ( 0, 3) */, -1.081483244896 + -0.691094517708*_Complex_I /* ( 0, 4) */, 0.248138338327 + -0.250954031944*_Complex_I /* ( 1, 0) */, 0.790891706944 + -0.313775628805*_Complex_I /* ( 1, 1) */, -0.146090522408 + -1.320674061775*_Complex_I /* ( 1, 2) */, 0.672296106815 + 1.346951484680*_Complex_I /* ( 1, 3) */, -0.352442741394 + 0.056975554675*_Complex_I /* ( 1, 4) */, 0.707973957062 + -0.069402769208*_Complex_I /* ( 2, 0) */, -0.894841134548 + -1.854133605957*_Complex_I /* ( 2, 1) */, 0.397095054388 + -0.924011290073*_Complex_I /* ( 2, 2) */, 0.054669041187 + 0.017023870721*_Complex_I /* ( 2, 3) */, 0.515784740448 + -0.455956429243*_Complex_I /* ( 2, 4) */, 0.570774257183 + 0.538610219955*_Complex_I /* ( 3, 0) */, -0.389531791210 + 0.200702637434*_Complex_I /* ( 3, 1) */, 0.159817531705 + 1.283960223198*_Complex_I /* ( 3, 2) */, 1.571215510368 + 0.574963092804*_Complex_I /* ( 3, 3) */, -2.452192783356 + -0.583715677261*_Complex_I /* ( 3, 4) */, -0.603657603264 + 0.617622077465*_Complex_I /* ( 4, 0) */, 0.935181498528 + 0.949800848961*_Complex_I /* ( 4, 1) */, 0.043205004185 + 1.351160168648*_Complex_I /* ( 4, 2) */, 0.674502849579 + 0.340750336647*_Complex_I /* ( 4, 3) */, -0.241452947259 + 1.540177464485*_Complex_I /* ( 4, 4) */}; // matrixcf_data_linsolve_x [size: 5 x 1] float complex matrixcf_data_linsolve_x[] = { -0.686784207821 + 0.516409814358*_Complex_I /* ( 0, 0) */, 0.725918948650 + -0.725804686546*_Complex_I /* ( 1, 0) */, 0.048043362796 + 1.415739893913*_Complex_I /* ( 2, 0) */, 1.184294700623 + -1.108955144882*_Complex_I /* ( 3, 0) */, 1.000079274178 + 0.117630988359*_Complex_I /* ( 4, 0) */}; // matrixcf_data_linsolve_b [size: 5 x 1] float complex matrixcf_data_linsolve_b[] = { 1.889372086452 + 2.079795053851*_Complex_I /* ( 0, 0) */, 4.099006087145 + 0.093571115573*_Complex_I /* ( 1, 0) */, -0.465385431770 + -0.201195243205*_Complex_I /* ( 2, 0) */, -2.502649126311 + -1.292489487343*_Complex_I /* ( 3, 0) */, 0.307098947642 + 0.568345470088*_Complex_I /* ( 4, 0) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixcf_data_ludecomp.c000066400000000000000000000124041317124540100245760ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing L/U decomposition // #include // matrixcf_data_ludecomp_A [size: 8 x 8] float complex matrixcf_data_ludecomp_A[] = { 0.455808967352 + 0.239869371057*_Complex_I /* ( 0, 0) */, 1.076113820076 + 0.303303003311*_Complex_I /* ( 0, 1) */, -1.174549579620 + -1.593330740929*_Complex_I /* ( 0, 2) */, 1.428434848785 + -2.108702898026*_Complex_I /* ( 0, 3) */, 1.944794058800 + 1.039716124535*_Complex_I /* ( 0, 4) */, -0.003220892511 + -1.070197224617*_Complex_I /* ( 0, 5) */, 2.282850980759 + 0.567153334618*_Complex_I /* ( 0, 6) */, 0.677789986134 + -0.110934779048*_Complex_I /* ( 0, 7) */, -0.541479706764 + 0.508462309837*_Complex_I /* ( 1, 0) */, 0.659551382065 + 0.341979026794*_Complex_I /* ( 1, 1) */, 0.422295093536 + -0.748002707958*_Complex_I /* ( 1, 2) */, 0.991572380066 + -1.739566326141*_Complex_I /* ( 1, 3) */, -0.973251938820 + -0.314995020628*_Complex_I /* ( 1, 4) */, -0.348222613335 + 1.216362476349*_Complex_I /* ( 1, 5) */, -0.444941103458 + -0.435953140259*_Complex_I /* ( 1, 6) */, 0.664277911186 + 0.398205667734*_Complex_I /* ( 1, 7) */, 1.578197240829 + -0.245545297861*_Complex_I /* ( 2, 0) */, -0.734657287598 + -0.314642846584*_Complex_I /* ( 2, 1) */, -0.185400843620 + 0.411517560482*_Complex_I /* ( 2, 2) */, -0.141458645463 + 2.540255069733*_Complex_I /* ( 2, 3) */, -1.887707233429 + 1.261052608490*_Complex_I /* ( 2, 4) */, 1.356706976891 + -0.073478087783*_Complex_I /* ( 2, 5) */, 0.382849365473 + 1.176013708115*_Complex_I /* ( 2, 6) */, 0.088731415570 + -0.000313452416*_Complex_I /* ( 2, 7) */, 0.694614350796 + 0.107012517750*_Complex_I /* ( 3, 0) */, -0.541421890259 + -1.525843501091*_Complex_I /* ( 3, 1) */, 1.210077285767 + -0.249905958772*_Complex_I /* ( 3, 2) */, 0.051122765988 + 0.576834678650*_Complex_I /* ( 3, 3) */, 2.360952138901 + -0.439353585243*_Complex_I /* ( 3, 4) */, 0.927220702171 + 0.293185442686*_Complex_I /* ( 3, 5) */, -0.235832184553 + -0.484229415655*_Complex_I /* ( 3, 6) */, -1.589996099472 + 0.180045768619*_Complex_I /* ( 3, 7) */, 1.345695137978 + -0.080361045897*_Complex_I /* ( 4, 0) */, -0.245824366808 + -1.841626405716*_Complex_I /* ( 4, 1) */, 0.978698849678 + 1.369340777397*_Complex_I /* ( 4, 2) */, -1.106017351151 + -1.615537166595*_Complex_I /* ( 4, 3) */, 0.627505123615 + 1.024900913239*_Complex_I /* ( 4, 4) */, 1.808397769928 + -0.614134788513*_Complex_I /* ( 4, 5) */, -0.322292149067 + -0.765307128429*_Complex_I /* ( 4, 6) */, -0.674273192883 + 0.044275555760*_Complex_I /* ( 4, 7) */, -2.861634492874 + 2.582857608795*_Complex_I /* ( 5, 0) */, -1.920535564423 + -0.081001155078*_Complex_I /* ( 5, 1) */, -1.339942932129 + -0.246527969837*_Complex_I /* ( 5, 2) */, 0.540911912918 + 0.283990591764*_Complex_I /* ( 5, 3) */, -0.800716042519 + 0.764756917953*_Complex_I /* ( 5, 4) */, 1.206449866295 + 0.518103539944*_Complex_I /* ( 5, 5) */, -0.377558648586 + 0.065486297011*_Complex_I /* ( 5, 6) */, -1.090067625046 + 0.741791069508*_Complex_I /* ( 5, 7) */, -1.424072742462 + 0.091005645692*_Complex_I /* ( 6, 0) */, 0.340615779161 + 1.995890378952*_Complex_I /* ( 6, 1) */, -0.395366579294 + 0.685165762901*_Complex_I /* ( 6, 2) */, 0.367168039083 + -1.265154719353*_Complex_I /* ( 6, 3) */, 0.716018438339 + 1.003421306610*_Complex_I /* ( 6, 4) */, -0.648339152336 + 2.441966056824*_Complex_I /* ( 6, 5) */, 0.788251757622 + 1.254729628563*_Complex_I /* ( 6, 6) */, -0.776828289032 + -0.615517139435*_Complex_I /* ( 6, 7) */, 1.112848401070 + -0.297139286995*_Complex_I /* ( 7, 0) */, 0.366721868515 + 0.650049626827*_Complex_I /* ( 7, 1) */, 0.072020366788 + -0.518339037895*_Complex_I /* ( 7, 2) */, 1.033115744591 + -0.196805760264*_Complex_I /* ( 7, 3) */, -1.083071947098 + -1.565491795540*_Complex_I /* ( 7, 4) */, 1.409144878387 + 0.992799341679*_Complex_I /* ( 7, 5) */, 0.387732833624 + -1.445696353912*_Complex_I /* ( 7, 6) */, -0.528750956059 + -1.205648779869*_Complex_I /* ( 7, 7) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixcf_data_mul.c000066400000000000000000000105341317124540100235650ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing matrix multiplication // #include // matrixcf_data_mul_x [size: 5 x 4] float complex matrixcf_data_mul_x[] = { 1.131277322769 + -2.908640623093*_Complex_I /* ( 0, 0) */, 0.847201466560 + -1.637244105339*_Complex_I /* ( 0, 1) */, -2.173580169678 + 0.096817605197*_Complex_I /* ( 0, 2) */, 0.792498826981 + -0.358158409595*_Complex_I /* ( 0, 3) */, -0.243082717061 + 0.824095964432*_Complex_I /* ( 1, 0) */, -1.889652967453 + 0.283876717091*_Complex_I /* ( 1, 1) */, 0.044418141246 + -0.882465064526*_Complex_I /* ( 1, 2) */, 0.515216410160 + -0.366532146931*_Complex_I /* ( 1, 3) */, 0.579283773899 + 1.173513293266*_Complex_I /* ( 2, 0) */, 0.059265002608 + -0.497733235359*_Complex_I /* ( 2, 1) */, -0.877321839333 + 0.404732406139*_Complex_I /* ( 2, 2) */, -0.794282734394 + 0.456011295319*_Complex_I /* ( 2, 3) */, -1.174414634705 + -1.358565688133*_Complex_I /* ( 3, 0) */, -0.418152034283 + 1.380919337273*_Complex_I /* ( 3, 1) */, -0.747197151184 + 1.584241986275*_Complex_I /* ( 3, 2) */, -0.522293865681 + -0.573823392391*_Complex_I /* ( 3, 3) */, -1.866284489632 + -0.199214607477*_Complex_I /* ( 4, 0) */, -0.453905433416 + 0.452787637711*_Complex_I /* ( 4, 1) */, 1.989426016808 + -1.771166682243*_Complex_I /* ( 4, 2) */, 2.234328985214 + 0.855401337147*_Complex_I /* ( 4, 3) */}; // matrixcf_data_mul_y [size: 4 x 3] float complex matrixcf_data_mul_y[] = { 0.122429788113 + -1.041572093964*_Complex_I /* ( 0, 0) */, -1.123313307762 + -1.396123170853*_Complex_I /* ( 0, 1) */, -0.318034142256 + -0.537796914577*_Complex_I /* ( 0, 2) */, 0.096901215613 + -0.035752061754*_Complex_I /* ( 1, 0) */, 0.423960685730 + -0.379842221737*_Complex_I /* ( 1, 1) */, -0.184147700667 + 0.022100308910*_Complex_I /* ( 1, 2) */, 0.189968794584 + 0.919595599174*_Complex_I /* ( 2, 0) */, 0.621766507626 + -0.634516119957*_Complex_I /* ( 2, 1) */, 0.605251312256 + 1.410223841667*_Complex_I /* ( 2, 2) */, 0.427330523729 + 0.042397715151*_Complex_I /* ( 3, 0) */, 0.204851210117 + 0.611065924168*_Complex_I /* ( 3, 1) */, 0.562124013901 + 0.047597970814*_Complex_I /* ( 3, 2) */}; // matrixcf_data_mul_z [size: 5 x 3] float complex matrixcf_data_mul_z[] = { -3.015598273252 + -3.823225604286*_Complex_I /* ( 0, 0) */, -6.503138041472 + 2.522251659946*_Complex_I /* ( 0, 1) */, -3.033435877267 + -2.533375977709*_Complex_I /* ( 0, 2) */, 1.711291176504 + 0.187568584413*_Complex_I /* ( 1, 0) */, 0.527484730969 + -0.085346610822*_Complex_I /* ( 1, 1) */, 2.440625470928 + -0.878385559540*_Complex_I /* ( 1, 2) */, 0.383559143593 + -1.078745633782*_Complex_I /* ( 2, 0) */, 0.093675017974 + -1.944126015771*_Complex_I /* ( 2, 1) */, -1.122987739839 + -1.365514815630*_Complex_I /* ( 2, 2) */, -3.347645581625 + 0.552152171890*_Complex_I /* ( 3, 0) */, 0.554058303745 + 4.932442551750*_Complex_I /* ( 3, 1) */, -3.263304464031 + 0.357861697730*_Complex_I /* ( 3, 2) */, 2.461434774758 + 3.932854324787*_Complex_I /* ( 4, 0) */, 1.845966920717 + 2.370697350446*_Complex_I /* ( 4, 1) */, 5.477082880684 + 3.294354034834*_Complex_I /* ( 4, 2) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixcf_data_qrdecomp.c000066400000000000000000000106661317124540100246100ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing Q/R decomposition // #include // matrixcf_data_qrdecomp_A [size: 4 x 4] float complex matrixcf_data_qrdecomp_A[] = { 2.114020000000 + -0.576040000000*_Complex_I /* ( 0, 0) */, 0.417500000000 + 1.008330000000*_Complex_I /* ( 0, 1) */, -0.962640000000 + -3.621960000000*_Complex_I /* ( 0, 2) */, -0.206790000000 + -1.026680000000*_Complex_I /* ( 0, 3) */, 0.008540000000 + 1.616260000000*_Complex_I /* ( 1, 0) */, 0.846950000000 + -0.327360000000*_Complex_I /* ( 1, 1) */, -1.018620000000 + -1.107860000000*_Complex_I /* ( 1, 2) */, -1.788770000000 + 1.844560000000*_Complex_I /* ( 1, 3) */, -2.979010000000 + -1.303840000000*_Complex_I /* ( 2, 0) */, 0.522890000000 + 1.891100000000*_Complex_I /* ( 2, 1) */, 1.325760000000 + -0.367370000000*_Complex_I /* ( 2, 2) */, 0.047170000000 + 0.206280000000*_Complex_I /* ( 2, 3) */, 0.289700000000 + 0.642470000000*_Complex_I /* ( 3, 0) */, -0.559160000000 + 0.683020000000*_Complex_I /* ( 3, 1) */, 1.406150000000 + 0.623980000000*_Complex_I /* ( 3, 2) */, -0.127670000000 + -0.539970000000*_Complex_I /* ( 3, 3) */}; // matrixcf_data_qrdecomp_Q [size: 4 x 4] float complex matrixcf_data_qrdecomp_Q[] = { 0.491706158979 + -0.133982845866*_Complex_I /* ( 0, 0) */, 0.429660711419 + 0.559833033911*_Complex_I /* ( 0, 1) */, -0.309333641162 + -0.278321211351*_Complex_I /* ( 0, 2) */, 0.215207397547 + -0.150957196713*_Complex_I /* ( 0, 3) */, 0.001986343837 + 0.375930689639*_Complex_I /* ( 1, 0) */, 0.242768204454 + 0.009257007128*_Complex_I /* ( 1, 1) */, -0.422306122793 + -0.032511505165*_Complex_I /* ( 1, 2) */, -0.503566009661 + 0.605534385769*_Complex_I /* ( 1, 3) */, -0.692896739226 + -0.303263998601*_Complex_I /* ( 2, 0) */, 0.054111560749 + 0.468071856237*_Complex_I /* ( 2, 1) */, -0.082147488614 + 0.069653107384*_Complex_I /* ( 2, 2) */, 0.279669645547 + 0.340721083028*_Complex_I /* ( 2, 3) */, 0.067382179098 + 0.149433995875*_Complex_I /* ( 3, 0) */, -0.270466351267 + 0.384428384950*_Complex_I /* ( 3, 1) */, -0.285071449427 + 0.744704670261*_Complex_I /* ( 3, 2) */, -0.173581995183 + -0.293616086507*_Complex_I /* ( 3, 3) */}; // matrixcf_data_qrdecomp_R [size: 4 x 4] float complex matrixcf_data_qrdecomp_R[] = { 4.299356356224 + 0.000000000000*_Complex_I /* ( 0, 0) */, -0.922616273377 + -0.789487259898*_Complex_I /* ( 0, 1) */, -1.025768821795 + -1.040664085433*_Complex_I /* ( 0, 2) */, 0.541217397816 + -0.002345615451*_Complex_I /* ( 0, 3) */, 0.000000000000 + 0.000000000000*_Complex_I /* ( 1, 0) */, 2.273733268802 + 0.000000000000*_Complex_I /* ( 1, 1) */, -2.939502710322 + -2.626579524510*_Complex_I /* ( 1, 2) */, -1.154743344912 + 0.323209860623*_Complex_I /* ( 1, 3) */, 0.000000000000 + 0.000000000000*_Complex_I /* ( 2, 0) */, 0.000000000000 + 0.000000000000*_Complex_I /* ( 2, 1) */, 1.701364174878 + 0.000000000000*_Complex_I /* ( 2, 2) */, 0.689923063328 + -0.348316412767*_Complex_I /* ( 2, 3) */, 0.000000000000 + 0.000000000000*_Complex_I /* ( 3, 0) */, 0.000000000000 + 0.000000000000*_Complex_I /* ( 3, 1) */, 0.000000000000 + 0.000000000000*_Complex_I /* ( 3, 2) */, 2.392371328442 + 0.000000000000*_Complex_I /* ( 3, 3) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixcf_data_transmul.c000066400000000000000000000177711317124540100246470ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing multiply/transpose // #include // matrixcf_data_transmul_x [size: 5 x 4] float complex matrixcf_data_transmul_x[] = { 0.897770464420 + -1.137341141701*_Complex_I /* ( 0, 0) */, 0.816529691219 + -0.575469911098*_Complex_I /* ( 0, 1) */, 2.407611131668 + 0.901603281498*_Complex_I /* ( 0, 2) */, -1.024818181992 + -1.785745739937*_Complex_I /* ( 0, 3) */, 1.494256496429 + -0.826167643070*_Complex_I /* ( 1, 0) */, -0.908512234688 + 0.119766108692*_Complex_I /* ( 1, 1) */, -0.215938329697 + -2.537411689758*_Complex_I /* ( 1, 2) */, -1.348789930344 + -0.935531198978*_Complex_I /* ( 1, 3) */, -0.398543357849 + 0.101190350950*_Complex_I /* ( 2, 0) */, -0.083604514599 + 1.493514776230*_Complex_I /* ( 2, 1) */, 0.477280050516 + -0.074863225222*_Complex_I /* ( 2, 2) */, -0.283995777369 + 0.336168438196*_Complex_I /* ( 2, 3) */, -0.030109925196 + -1.602186083794*_Complex_I /* ( 3, 0) */, 2.220442056656 + -0.208865001798*_Complex_I /* ( 3, 1) */, 1.889614224434 + -0.896111547947*_Complex_I /* ( 3, 2) */, -0.317830920219 + 0.215485602617*_Complex_I /* ( 3, 3) */, -0.945744097233 + -0.822628259659*_Complex_I /* ( 4, 0) */, -0.238264903426 + 0.054408840835*_Complex_I /* ( 4, 1) */, 0.532425582409 + 0.438958346844*_Complex_I /* ( 4, 2) */, 0.089408367872 + -1.864659070969*_Complex_I /* ( 4, 3) */}; // matrixcf_data_transmul_xxT [size: 5 x 5] float complex matrixcf_data_transmul_xxT[] = { 13.946043026996 + 0.000000000000*_Complex_I /* ( 0, 0) */, 1.715635857916 + 6.831514803023*_Complex_I /* ( 0, 1) */, -0.628286275869 + 0.653261344190*_Complex_I /* ( 0, 2) */, 7.410888277177 + 5.014956782605*_Complex_I /* ( 0, 3) */, 4.776506544166 + -0.740548606324*_Complex_I /* ( 0, 4) */, 1.715635857916 + -6.831514803023*_Complex_I /* ( 1, 0) */, 12.934634198959 + 0.000000000000*_Complex_I /* ( 1, 1) */, -0.268847669275 + 1.016808442009*_Complex_I /* ( 1, 2) */, 1.329226044140 + -1.905118394989*_Complex_I /* ( 1, 3) */, -0.115507997317 + -1.823416830395*_Complex_I /* ( 1, 4) */, -0.628286275869 + -0.653261344190*_Complex_I /* ( 2, 0) */, -0.268847669275 + -1.016808442009*_Complex_I /* ( 2, 1) */, 2.833715966403 + 0.000000000000*_Complex_I /* ( 2, 2) */, 0.483955462699 + 2.897799335427*_Complex_I /* ( 2, 3) */, -0.036118440085 + -1.523720724413*_Complex_I /* ( 2, 4) */, 7.410888277177 + -5.014956782605*_Complex_I /* ( 3, 0) */, 1.329226044140 + 1.905118394989*_Complex_I /* ( 3, 1) */, 0.483955462699 + -2.897799335427*_Complex_I /* ( 3, 2) */, 12.063002732969 + 0.000000000000*_Complex_I /* ( 3, 3) */, 0.988561701830 + -0.460512464248*_Complex_I /* ( 3, 4) */, 4.776506544166 + 0.740548606324*_Complex_I /* ( 4, 0) */, -0.115507997317 + 1.823416830395*_Complex_I /* ( 4, 1) */, -0.036118440085 + 1.523720724413*_Complex_I /* ( 4, 2) */, 0.988561701830 + 0.460512464248*_Complex_I /* ( 4, 3) */, 5.591988375464 + 0.000000000000*_Complex_I /* ( 4, 4) */}; // matrixcf_data_transmul_xxH [size: 5 x 5] float complex matrixcf_data_transmul_xxH[] = { 2.693069394806 + 5.019630491560*_Complex_I /* ( 0, 0) */, 1.208446246635 + -4.757020341403*_Complex_I /* ( 0, 1) */, 2.656451825557 + 2.224444954914*_Complex_I /* ( 0, 2) */, 5.911512147844 + -2.959566260460*_Complex_I /* ( 0, 3) */, -4.483236639053 + 3.806796594938*_Complex_I /* ( 0, 4) */, 1.208446246635 + -4.757020341403*_Complex_I /* ( 1, 0) */, -3.086513006704 + 0.932888319797*_Complex_I /* ( 1, 1) */, -0.210317709361 + -2.269045302266*_Complex_I /* ( 1, 2) */, -5.412513485879 + -6.508039464439*_Complex_I /* ( 1, 3) */, -2.749055759920 + 0.459776624619*_Complex_I /* ( 1, 4) */, 2.656451825557 + 2.224444954914*_Complex_I /* ( 2, 0) */, -0.210317709361 + -2.269045302266*_Complex_I /* ( 2, 1) */, -1.885163224141 + -0.592788922020*_Complex_I /* ( 2, 2) */, 1.153042421508 + 3.232018360881*_Complex_I /* ( 2, 3) */, 1.287247559495 + 0.601010412549*_Complex_I /* ( 2, 4) */, 5.911512147844 + -2.959566260460*_Complex_I /* ( 3, 0) */, -5.412513485879 + -6.508039464439*_Complex_I /* ( 3, 1) */, 1.153042421508 + 3.232018360881*_Complex_I /* ( 3, 2) */, 5.142853158215 + -4.354648092153*_Complex_I /* ( 3, 3) */, -0.034391537899 + 2.674865932467*_Complex_I /* ( 3, 4) */, -4.483236639053 + 3.806796594938*_Complex_I /* ( 4, 0) */, -2.749055759920 + 0.459776624619*_Complex_I /* ( 4, 1) */, 1.287247559495 + 0.601010412549*_Complex_I /* ( 4, 2) */, -0.034391537899 + 2.674865932467*_Complex_I /* ( 4, 3) */, -3.106642538055 + 1.664057265760*_Complex_I /* ( 4, 4) */}; // matrixcf_data_transmul_xTx [size: 4 x 4] float complex matrixcf_data_transmul_xTx[] = { 9.323024431917 + 0.000000000000*_Complex_I /* ( 0, 0) */, 0.563876592623 + 2.570030362211*_Complex_I /* ( 0, 1) */, 3.226123027525 + 2.636644463529*_Complex_I /* ( 0, 2) */, 1.129305368076 + -4.064920271606*_Complex_I /* ( 0, 3) */, 0.563876592623 + -2.570030362211*_Complex_I /* ( 1, 0) */, 9.108918860377 + 0.000000000000*_Complex_I /* ( 1, 1) */, 5.467585123601 + 2.017612849734*_Complex_I /* ( 1, 2) */, 0.956522192172 + 0.211168853425*_Complex_I /* ( 1, 3) */, 3.226123027525 + -2.636644463529*_Complex_I /* ( 2, 0) */, 5.467585123601 + -2.017612849734*_Complex_I /* ( 2, 1) */, 18.177787287820 + 0.000000000000*_Complex_I /* ( 2, 2) */, -3.137608134941 + -7.366300567700*_Complex_I /* ( 2, 3) */, 1.129305368076 + 4.064920271606*_Complex_I /* ( 3, 0) */, 0.956522192172 + -0.211168853425*_Complex_I /* ( 3, 1) */, -3.137608134941 + 7.366300567700*_Complex_I /* ( 3, 2) */, 10.759653720678 + 0.000000000000*_Complex_I /* ( 3, 3) */}; // matrixcf_data_transmul_xHx [size: 4 x 4] float complex matrixcf_data_transmul_xHx[] = { -1.137085237839 + -2.939337742229*_Complex_I /* ( 0, 0) */, -1.429264118470 + -4.526184217761*_Complex_I /* ( 0, 1) */, -1.049795781222 + -9.317515018345*_Complex_I /* ( 0, 2) */, -6.923890470327 + 1.308742276041*_Complex_I /* ( 0, 3) */, -1.429264118470 + -4.526184217761*_Complex_I /* ( 1, 0) */, 3.863557186128 + -2.360596346275*_Complex_I /* ( 1, 1) */, 6.914587648894 + -0.110888488534*_Complex_I /* ( 1, 2) */, -1.585896210450 + 0.361787209777*_Complex_I /* ( 1, 3) */, -1.049795781222 + -9.317515018345*_Complex_I /* ( 2, 0) */, 6.914587648894 + -0.110888488534*_Complex_I /* ( 2, 1) */, 1.672484488523 + 2.446622681596*_Complex_I /* ( 2, 2) */, -2.591648390404 + -1.678750072577*_Complex_I /* ( 2, 3) */, -6.923890470327 + 1.308742276041*_Complex_I /* ( 3, 0) */, -1.585896210450 + 0.361787209777*_Complex_I /* ( 3, 1) */, -2.591648390404 + -1.678750072577*_Complex_I /* ( 3, 2) */, -4.641352652692 + 5.522450469852*_Complex_I /* ( 3, 3) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixf_data_add.c000066400000000000000000000065601317124540100233610ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing matrix addition // #include // matrixf_data_add_x [size: 5 x 4] float matrixf_data_add_x[] = { -2.153858900070 /* ( 0, 0) */, 0.374406367540 /* ( 0, 1) */, -0.356648415327 /* ( 0, 2) */, 0.673922061920 /* ( 0, 3) */, -1.686753273010 /* ( 1, 0) */, -0.382442235947 /* ( 1, 1) */, 0.287308961153 /* ( 1, 2) */, -0.479356884956 /* ( 1, 3) */, -0.336519986391 /* ( 2, 0) */, 0.173820436001 /* ( 2, 1) */, -1.243059277534 /* ( 2, 2) */, -1.508571028709 /* ( 2, 3) */, 0.903724849224 /* ( 3, 0) */, 0.490690946579 /* ( 3, 1) */, 0.242906242609 /* ( 3, 2) */, 0.192125678062 /* ( 3, 3) */, 0.053418140858 /* ( 4, 0) */, 0.389735013247 /* ( 4, 1) */, 0.781731247902 /* ( 4, 2) */, -1.207890510559 /* ( 4, 3) */}; // matrixf_data_add_y [size: 5 x 4] float matrixf_data_add_y[] = { -1.569433808327 /* ( 0, 0) */, 0.182892739773 /* ( 0, 1) */, 2.420134067535 /* ( 0, 2) */, -0.114732131362 /* ( 0, 3) */, -1.274159908295 /* ( 1, 0) */, -1.230959534645 /* ( 1, 1) */, 0.574799835682 /* ( 1, 2) */, -0.756966531277 /* ( 1, 3) */, 1.426752924919 /* ( 2, 0) */, 1.018160581589 /* ( 2, 1) */, -0.099268406630 /* ( 2, 2) */, 0.683501064777 /* ( 2, 3) */, 0.145665585995 /* ( 3, 0) */, 0.337123543024 /* ( 3, 1) */, 0.754367768764 /* ( 3, 2) */, 0.908503055573 /* ( 3, 3) */, -1.320610523224 /* ( 4, 0) */, -1.090982913971 /* ( 4, 1) */, 0.494600951672 /* ( 4, 2) */, 0.713486075401 /* ( 4, 3) */}; // matrixf_data_add_z [size: 5 x 4] float matrixf_data_add_z[] = { -3.723292708397 /* ( 0, 0) */, 0.557299107313 /* ( 0, 1) */, 2.063485652208 /* ( 0, 2) */, 0.559189930558 /* ( 0, 3) */, -2.960913181305 /* ( 1, 0) */, -1.613401770592 /* ( 1, 1) */, 0.862108796835 /* ( 1, 2) */, -1.236323416233 /* ( 1, 3) */, 1.090232938528 /* ( 2, 0) */, 1.191981017590 /* ( 2, 1) */, -1.342327684164 /* ( 2, 2) */, -0.825069963932 /* ( 2, 3) */, 1.049390435219 /* ( 3, 0) */, 0.827814489603 /* ( 3, 1) */, 0.997274011374 /* ( 3, 2) */, 1.100628733635 /* ( 3, 3) */, -1.267192382365 /* ( 4, 0) */, -0.701247900724 /* ( 4, 1) */, 1.276332199574 /* ( 4, 2) */, -0.494404435158 /* ( 4, 3) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixf_data_aug.c000066400000000000000000000073101317124540100233770ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing matrix augmentation // #include // matrixf_data_aug_x [size: 5 x 4] float matrixf_data_aug_x[] = { -0.747572302818 /* ( 0, 0) */, 1.023007512093 /* ( 0, 1) */, -0.806419134140 /* ( 0, 2) */, 1.476346969604 /* ( 0, 3) */, -0.456311076880 /* ( 1, 0) */, 1.049571633339 /* ( 1, 1) */, 0.041211493313 /* ( 1, 2) */, 0.870350718498 /* ( 1, 3) */, -0.585918903351 /* ( 2, 0) */, -2.498867988586 /* ( 2, 1) */, 1.247432827950 /* ( 2, 2) */, -1.840264678001 /* ( 2, 3) */, 0.618996977806 /* ( 3, 0) */, -1.083691835403 /* ( 3, 1) */, -1.827050209045 /* ( 3, 2) */, -0.579039454460 /* ( 3, 3) */, 1.507880568504 /* ( 4, 0) */, 1.633087396622 /* ( 4, 1) */, -0.439950227737 /* ( 4, 2) */, -0.058893665671 /* ( 4, 3) */}; // matrixf_data_aug_y [size: 5 x 3] float matrixf_data_aug_y[] = { 0.376702636480 /* ( 0, 0) */, 0.790158689022 /* ( 0, 1) */, 2.111151933670 /* ( 0, 2) */, -0.690664231777 /* ( 1, 0) */, -0.598035037518 /* ( 1, 1) */, -0.137144193053 /* ( 1, 2) */, 1.078616261482 /* ( 2, 0) */, 0.907722294331 /* ( 2, 1) */, -0.432205766439 /* ( 2, 2) */, -1.615019798279 /* ( 3, 0) */, 0.122782632709 /* ( 3, 1) */, 1.174023866653 /* ( 3, 2) */, 0.233828529716 /* ( 4, 0) */, 0.032883912325 /* ( 4, 1) */, -0.896481394768 /* ( 4, 2) */}; // matrixf_data_aug_z [size: 5 x 7] float matrixf_data_aug_z[] = { -0.747572302818 /* ( 0, 0) */, 1.023007512093 /* ( 0, 1) */, -0.806419134140 /* ( 0, 2) */, 1.476346969604 /* ( 0, 3) */, 0.376702636480 /* ( 0, 4) */, 0.790158689022 /* ( 0, 5) */, 2.111151933670 /* ( 0, 6) */, -0.456311076880 /* ( 1, 0) */, 1.049571633339 /* ( 1, 1) */, 0.041211493313 /* ( 1, 2) */, 0.870350718498 /* ( 1, 3) */, -0.690664231777 /* ( 1, 4) */, -0.598035037518 /* ( 1, 5) */, -0.137144193053 /* ( 1, 6) */, -0.585918903351 /* ( 2, 0) */, -2.498867988586 /* ( 2, 1) */, 1.247432827950 /* ( 2, 2) */, -1.840264678001 /* ( 2, 3) */, 1.078616261482 /* ( 2, 4) */, 0.907722294331 /* ( 2, 5) */, -0.432205766439 /* ( 2, 6) */, 0.618996977806 /* ( 3, 0) */, -1.083691835403 /* ( 3, 1) */, -1.827050209045 /* ( 3, 2) */, -0.579039454460 /* ( 3, 3) */, -1.615019798279 /* ( 3, 4) */, 0.122782632709 /* ( 3, 5) */, 1.174023866653 /* ( 3, 6) */, 1.507880568504 /* ( 4, 0) */, 1.633087396622 /* ( 4, 1) */, -0.439950227737 /* ( 4, 2) */, -0.058893665671 /* ( 4, 3) */, 0.233828529716 /* ( 4, 4) */, 0.032883912325 /* ( 4, 5) */, -0.896481394768 /* ( 4, 6) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixf_data_cgsolve.c000066400000000000000000000100721317124540100242640ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing conjugate gradient solver // #include // matrixf_data_cgsolve_A [size: 8 x 8] float matrixf_data_cgsolve_A[] = { 12.722920400000 /* ( 0, 0) */, 0.000000000000 /* ( 0, 1) */, -7.952912300000 /* ( 0, 2) */, 0.000000000000 /* ( 0, 3) */, 4.111499800000 /* ( 0, 4) */, 0.000000000000 /* ( 0, 5) */, 0.000000000000 /* ( 0, 6) */, 0.000000000000 /* ( 0, 7) */, 0.000000000000 /* ( 1, 0) */, 0.065151200000 /* ( 1, 1) */, 0.000000000000 /* ( 1, 2) */, -0.218259800000 /* ( 1, 3) */, 0.000000000000 /* ( 1, 4) */, 0.000000000000 /* ( 1, 5) */, 0.000000000000 /* ( 1, 6) */, 0.000000000000 /* ( 1, 7) */, -7.952912300000 /* ( 2, 0) */, 0.000000000000 /* ( 2, 1) */, 5.031585200000 /* ( 2, 2) */, 0.000000000000 /* ( 2, 3) */, -2.570038800000 /* ( 2, 4) */, -0.110545700000 /* ( 2, 5) */, 0.000000000000 /* ( 2, 6) */, 0.000000000000 /* ( 2, 7) */, 0.000000000000 /* ( 3, 0) */, -0.218259800000 /* ( 3, 1) */, 0.000000000000 /* ( 3, 2) */, 0.733045600000 /* ( 3, 3) */, 0.000000000000 /* ( 3, 4) */, 0.000000000000 /* ( 3, 5) */, 0.000000000000 /* ( 3, 6) */, 0.000000000000 /* ( 3, 7) */, 4.111499800000 /* ( 4, 0) */, 0.000000000000 /* ( 4, 1) */, -2.570038800000 /* ( 4, 2) */, 0.000000000000 /* ( 4, 3) */, 1.338132900000 /* ( 4, 4) */, 0.239381000000 /* ( 4, 5) */, 0.078430200000 /* ( 4, 6) */, 0.000000000000 /* ( 4, 7) */, 0.000000000000 /* ( 5, 0) */, 0.000000000000 /* ( 5, 1) */, -0.110545700000 /* ( 5, 2) */, 0.000000000000 /* ( 5, 3) */, 0.239381000000 /* ( 5, 4) */, 7.472388300000 /* ( 5, 5) */, 1.981894700000 /* ( 5, 6) */, -1.373365000000 /* ( 5, 7) */, 0.000000000000 /* ( 6, 0) */, 0.000000000000 /* ( 6, 1) */, 0.000000000000 /* ( 6, 2) */, 0.000000000000 /* ( 6, 3) */, 0.078430200000 /* ( 6, 4) */, 1.981894700000 /* ( 6, 5) */, 3.489272600000 /* ( 6, 6) */, 0.000000000000 /* ( 6, 7) */, 0.000000000000 /* ( 7, 0) */, 0.000000000000 /* ( 7, 1) */, 0.000000000000 /* ( 7, 2) */, 0.000000000000 /* ( 7, 3) */, 0.000000000000 /* ( 7, 4) */, -1.373365000000 /* ( 7, 5) */, 0.000000000000 /* ( 7, 6) */, 2.063114900000 /* ( 7, 7) */}; // matrixf_data_cgsolve_x [size: 8 x 1] float matrixf_data_cgsolve_x[] = { 0.162052200000 /* ( 0, 0) */, -0.012720300000 /* ( 1, 0) */, 1.043375100000 /* ( 2, 0) */, 0.006205200000 /* ( 3, 0) */, 0.878157000000 /* ( 4, 0) */, 0.146412900000 /* ( 5, 0) */, 0.782585200000 /* ( 6, 0) */, -0.825784600000 /* ( 7, 0) */}; // matrixf_data_cgsolve_b [size: 8 x 1] float matrixf_data_cgsolve_b[] = { -2.625551095190 /* ( 0, 0) */, -0.002183088520 /* ( 1, 0) */, 1.687960897575 /* ( 2, 0) */, 0.007325024691 /* ( 3, 0) */, -0.743719348831 /* ( 4, 0) */, 3.874032638311 /* ( 5, 0) */, 3.089702075189 /* ( 6, 0) */, -1.904766864859 /* ( 7, 0) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixf_data_chol.c000066400000000000000000000045761317124540100235630ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing Cholesky decomposition // #include // matrixf_data_chol_L [size: 4 x 4] float matrixf_data_chol_L[] = { 1.010000000000 /* ( 0, 0) */, 0.000000000000 /* ( 0, 1) */, 0.000000000000 /* ( 0, 2) */, 0.000000000000 /* ( 0, 3) */, -1.420000000000 /* ( 1, 0) */, 0.500000000000 /* ( 1, 1) */, 0.000000000000 /* ( 1, 2) */, 0.000000000000 /* ( 1, 3) */, 0.320000000000 /* ( 2, 0) */, 2.010000000000 /* ( 2, 1) */, 0.300000000000 /* ( 2, 2) */, 0.000000000000 /* ( 2, 3) */, -1.020000000000 /* ( 3, 0) */, -0.320000000000 /* ( 3, 1) */, -1.650000000000 /* ( 3, 2) */, 1.070000000000 /* ( 3, 3) */}; // matrixf_data_chol_A [size: 4 x 4] float matrixf_data_chol_A[] = { 1.020100000000 /* ( 0, 0) */, -1.434200000000 /* ( 0, 1) */, 0.323200000000 /* ( 0, 2) */, -1.030200000000 /* ( 0, 3) */, -1.434200000000 /* ( 1, 0) */, 2.266400000000 /* ( 1, 1) */, 0.550600000000 /* ( 1, 2) */, 1.288400000000 /* ( 1, 3) */, 0.323200000000 /* ( 2, 0) */, 0.550600000000 /* ( 2, 1) */, 4.232500000000 /* ( 2, 2) */, -1.464600000000 /* ( 2, 3) */, -1.030200000000 /* ( 3, 0) */, 1.288400000000 /* ( 3, 1) */, -1.464600000000 /* ( 3, 2) */, 5.010200000000 /* ( 3, 3) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixf_data_gramschmidt.c000066400000000000000000000042231317124540100251250ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing Gram-Schmidt orthonormalization // #include // matrixf_data_gramschmidt_A [size: 4 x 3] float matrixf_data_gramschmidt_A[] = { 1.000000000000 /* ( 0, 0) */, 2.000000000000 /* ( 0, 1) */, 1.000000000000 /* ( 0, 2) */, 0.000000000000 /* ( 1, 0) */, 2.000000000000 /* ( 1, 1) */, 0.000000000000 /* ( 1, 2) */, 2.000000000000 /* ( 2, 0) */, 3.000000000000 /* ( 2, 1) */, 1.000000000000 /* ( 2, 2) */, 1.000000000000 /* ( 3, 0) */, 1.000000000000 /* ( 3, 1) */, 0.000000000000 /* ( 3, 2) */}; // matrixf_data_gramschmidt_V [size: 4 x 3] float matrixf_data_gramschmidt_V[] = { 0.408248290464 /* ( 0, 0) */, 0.235702260396 /* ( 0, 1) */, 0.666666666667 /* ( 0, 2) */, 0.000000000000 /* ( 1, 0) */, 0.942809041582 /* ( 1, 1) */, -0.333333333333 /* ( 1, 2) */, 0.816496580928 /* ( 2, 0) */, 0.000000000000 /* ( 2, 1) */, 0.000000000000 /* ( 2, 2) */, 0.408248290464 /* ( 3, 0) */, -0.235702260396 /* ( 3, 1) */, -0.666666666667 /* ( 3, 2) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixf_data_inv.c000066400000000000000000000057301317124540100234230ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing matrix inversion // #include // matrixf_data_inv_x [size: 5 x 5] float matrixf_data_inv_x[] = { 0.145655393600 /* ( 0, 0) */, -2.292126655579 /* ( 0, 1) */, 0.928358852863 /* ( 0, 2) */, 0.995244622231 /* ( 0, 3) */, -0.719965457916 /* ( 0, 4) */, 1.625229239464 /* ( 1, 0) */, 1.179069876671 /* ( 1, 1) */, 0.023814691231 /* ( 1, 2) */, -0.458529949188 /* ( 1, 3) */, 0.870123147964 /* ( 1, 4) */, 1.599076509476 /* ( 2, 0) */, 1.012132167816 /* ( 2, 1) */, 0.240342438221 /* ( 2, 2) */, -0.663878023624 /* ( 2, 3) */, 1.523158550262 /* ( 2, 4) */, 1.400263786316 /* ( 3, 0) */, -0.016515849158 /* ( 3, 1) */, 0.525676131248 /* ( 3, 2) */, -0.526886940002 /* ( 3, 3) */, -0.605886101723 /* ( 3, 4) */, -0.291201651096 /* ( 4, 0) */, 0.635409533978 /* ( 4, 1) */, 0.016531571746 /* ( 4, 2) */, 0.113017730415 /* ( 4, 3) */, -0.886025428772 /* ( 4, 4) */}; // matrixf_data_inv_y [size: 5 x 5] float matrixf_data_inv_y[] = { 0.123047731616 /* ( 0, 0) */, 1.264793339850 /* ( 0, 1) */, -0.888020214878 /* ( 0, 2) */, 0.146648698334 /* ( 0, 3) */, -0.484762774689 /* ( 0, 4) */, 0.031615676756 /* ( 1, 0) */, -0.041217620573 /* ( 1, 1) */, 0.486809371567 /* ( 1, 2) */, -0.307386761818 /* ( 1, 3) */, 0.980900315396 /* ( 1, 4) */, 0.456515830075 /* ( 2, 0) */, -2.168499777786 /* ( 2, 1) */, 2.469455722213 /* ( 2, 2) */, 0.010642598564 /* ( 2, 3) */, 1.737407148356 /* ( 2, 4) */, 0.690799395919 /* ( 3, 0) */, 1.532809684521 /* ( 3, 1) */, -0.611813824735 /* ( 3, 2) */, -1.028413056396 /* ( 3, 3) */, 0.595460566672 /* ( 3, 4) */, 0.078865348162 /* ( 4, 0) */, -0.290188077617 /* ( 4, 1) */, 0.609005594780 /* ( 4, 2) */, -0.399620351004 /* ( 4, 3) */, -0.157493442155 /* ( 4, 4) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixf_data_linsolve.c000066400000000000000000000050721317124540100244610ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing linear solver // #include // matrixf_data_linsolve_A [size: 5 x 5] float matrixf_data_linsolve_A[] = { 0.359868824482 /* ( 0, 0) */, -0.821193814278 /* ( 0, 1) */, -0.267460018396 /* ( 0, 2) */, 0.886115014553 /* ( 0, 3) */, 0.153591111302 /* ( 0, 4) */, 0.298885852098 /* ( 1, 0) */, -1.239024162292 /* ( 1, 1) */, -0.948822617531 /* ( 1, 2) */, -0.779868483543 /* ( 1, 3) */, -0.334943383932 /* ( 1, 4) */, -0.071195065975 /* ( 2, 0) */, 0.763968944550 /* ( 2, 1) */, 0.294695496559 /* ( 2, 2) */, 0.060610540211 /* ( 2, 3) */, 0.016189640388 /* ( 2, 4) */, 1.150504231453 /* ( 3, 0) */, -0.605459213257 /* ( 3, 1) */, 0.055004067719 /* ( 3, 2) */, 1.185544967651 /* ( 3, 3) */, 0.555612862110 /* ( 3, 4) */, 1.054118633270 /* ( 4, 0) */, -0.494105964899 /* ( 4, 1) */, -0.824876368046 /* ( 4, 2) */, 0.667240202427 /* ( 4, 3) */, 1.367745161057 /* ( 4, 4) */}; // matrixf_data_linsolve_x [size: 5 x 1] float matrixf_data_linsolve_x[] = { -0.848446607590 /* ( 0, 0) */, 1.041861057281 /* ( 1, 0) */, 0.453321367502 /* ( 2, 0) */, -0.949143886566 /* ( 3, 0) */, 1.200846910477 /* ( 4, 0) */}; // matrixf_data_linsolve_b [size: 5 x 1] float matrixf_data_linsolve_b[] = { -1.938755917550 /* ( 0, 0) */, -1.636609601788 /* ( 1, 0) */, 0.951859625938 /* ( 2, 0) */, -2.040058038471 /* ( 3, 0) */, -0.773941632607 /* ( 4, 0) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixf_data_ludecomp.c000066400000000000000000000065721317124540100244440ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing L/U decomposition // #include // matrixf_data_ludecomp_A [size: 8 x 8] float matrixf_data_ludecomp_A[] = { 0.936903119087 /* ( 0, 0) */, 1.048182249069 /* ( 0, 1) */, 0.464600890875 /* ( 0, 2) */, 1.122355699539 /* ( 0, 3) */, -0.661124527454 /* ( 0, 4) */, -0.953127145767 /* ( 0, 5) */, -0.759313285351 /* ( 0, 6) */, 1.418183445930 /* ( 0, 7) */, -0.272643178701 /* ( 1, 0) */, -1.166662335396 /* ( 1, 1) */, 1.556591391563 /* ( 1, 2) */, -0.323065608740 /* ( 1, 3) */, -0.267991930246 /* ( 1, 4) */, 0.396302074194 /* ( 1, 5) */, 0.238355115056 /* ( 1, 6) */, -0.437593698502 /* ( 1, 7) */, 0.431114047766 /* ( 2, 0) */, -0.916567981243 /* ( 2, 1) */, 0.108782351017 /* ( 2, 2) */, -0.714223206043 /* ( 2, 3) */, 0.197309300303 /* ( 2, 4) */, 1.105972766876 /* ( 2, 5) */, -0.014590717852 /* ( 2, 6) */, 0.288964867592 /* ( 2, 7) */, 1.536642432213 /* ( 3, 0) */, 1.810190558434 /* ( 3, 1) */, 0.722570478916 /* ( 3, 2) */, 0.184841006994 /* ( 3, 3) */, -0.239855647087 /* ( 3, 4) */, 0.494688391685 /* ( 3, 5) */, -0.372100114822 /* ( 3, 6) */, -0.754012823105 /* ( 3, 7) */, 0.139140784740 /* ( 4, 0) */, -0.755531311035 /* ( 4, 1) */, 1.567769289017 /* ( 4, 2) */, -0.774845600128 /* ( 4, 3) */, 1.536481976509 /* ( 4, 4) */, -1.498587012291 /* ( 4, 5) */, 0.262655615807 /* ( 4, 6) */, -1.045227766037 /* ( 4, 7) */, 0.445236086845 /* ( 5, 0) */, -0.573900520802 /* ( 5, 1) */, 0.550646543503 /* ( 5, 2) */, 0.073093712330 /* ( 5, 3) */, 0.700358152390 /* ( 5, 4) */, 0.659417688847 /* ( 5, 5) */, 0.990632474422 /* ( 5, 6) */, -0.596979260445 /* ( 5, 7) */, -1.469601035118 /* ( 6, 0) */, -1.366319775581 /* ( 6, 1) */, -1.536668300629 /* ( 6, 2) */, 0.301474511623 /* ( 6, 3) */, 0.205486327410 /* ( 6, 4) */, 1.184612751007 /* ( 6, 5) */, 1.984294533730 /* ( 6, 6) */, 0.846946001053 /* ( 6, 7) */, -0.780786097050 /* ( 7, 0) */, -1.778358221054 /* ( 7, 1) */, -0.621561229229 /* ( 7, 2) */, 0.809134125710 /* ( 7, 3) */, -0.395780056715 /* ( 7, 4) */, 0.095775716007 /* ( 7, 5) */, 1.116999864578 /* ( 7, 6) */, -0.937837302685 /* ( 7, 7) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixf_data_mul.c000066400000000000000000000056741317124540100234330ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing matrix multiplication // #include // matrixf_data_mul_x [size: 5 x 4] float matrixf_data_mul_x[] = { -0.348304957151 /* ( 0, 0) */, 1.638695955276 /* ( 0, 1) */, 0.618153512478 /* ( 0, 2) */, 0.580581486225 /* ( 0, 3) */, 1.125966548920 /* ( 1, 0) */, 0.590879321098 /* ( 1, 1) */, -0.499333083630 /* ( 1, 2) */, -0.144607886672 /* ( 1, 3) */, -0.169909551740 /* ( 2, 0) */, 1.626509308815 /* ( 2, 1) */, -0.776567280293 /* ( 2, 2) */, -1.341656446457 /* ( 2, 3) */, 0.492572665215 /* ( 3, 0) */, -0.075633287430 /* ( 3, 1) */, 1.035362601280 /* ( 3, 2) */, 0.842321217060 /* ( 3, 3) */, -0.209287241101 /* ( 4, 0) */, -0.789002001286 /* ( 4, 1) */, -0.397730469704 /* ( 4, 2) */, 0.034179374576 /* ( 4, 3) */}; // matrixf_data_mul_y [size: 4 x 3] float matrixf_data_mul_y[] = { 0.445414155722 /* ( 0, 0) */, 0.233421698213 /* ( 0, 1) */, -0.682938814163 /* ( 0, 2) */, -0.934787094593 /* ( 1, 0) */, 0.500407993793 /* ( 1, 1) */, -0.053248234093 /* ( 1, 2) */, -0.784089267254 /* ( 2, 0) */, 0.127269089222 /* ( 2, 1) */, -0.477077603340 /* ( 2, 2) */, -0.105383664370 /* ( 3, 0) */, -1.556528329849 /* ( 3, 1) */, -0.184585332870 /* ( 3, 2) */}; // matrixf_data_mul_z [size: 5 x 3] float matrixf_data_mul_z[] = { -2.232843128510 /* ( 0, 0) */, -0.086305075740 /* ( 0, 1) */, -0.251460714553 /* ( 0, 2) */, 0.355936096586 /* ( 1, 0) */, 0.720042365177 /* ( 1, 1) */, -0.535516414414 /* ( 1, 2) */, -0.845833288222 /* ( 2, 0) */, 2.763750941354 /* ( 2, 1) */, 0.647562038031 /* ( 2, 2) */, -0.610483740991 /* ( 3, 0) */, -1.102197535527 /* ( 3, 1) */, -0.981798103518 /* ( 3, 2) */, 0.952583633427 /* ( 4, 0) */, -0.547495051253 /* ( 4, 1) */, 0.368382631550 /* ( 4, 2) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixf_data_qrdecomp.c000066400000000000000000000057701317124540100244450ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing Q/R decomposition // #include // matrixf_data_qrdecomp_A [size: 4 x 4] float matrixf_data_qrdecomp_A[] = { 1.000000000000 /* ( 0, 0) */, 2.000000000000 /* ( 0, 1) */, 3.000000000000 /* ( 0, 2) */, 4.000000000000 /* ( 0, 3) */, 5.000000000000 /* ( 1, 0) */, 5.000000000000 /* ( 1, 1) */, 7.000000000000 /* ( 1, 2) */, 8.000000000000 /* ( 1, 3) */, 6.000000000000 /* ( 2, 0) */, 4.000000000000 /* ( 2, 1) */, 8.000000000000 /* ( 2, 2) */, 7.000000000000 /* ( 2, 3) */, 1.000000000000 /* ( 3, 0) */, 0.000000000000 /* ( 3, 1) */, 3.000000000000 /* ( 3, 2) */, 1.000000000000 /* ( 3, 3) */}; // matrixf_data_qrdecomp_Q [size: 4 x 4] float matrixf_data_qrdecomp_Q[] = { 0.125988157670 /* ( 0, 0) */, 0.617707763884 /* ( 0, 1) */, 0.571886263590 /* ( 0, 2) */, 0.524890659168 /* ( 0, 3) */, 0.629940788349 /* ( 1, 0) */, 0.494166211107 /* ( 1, 1) */, -0.137252703262 /* ( 1, 2) */, -0.583211843520 /* ( 1, 3) */, 0.755928946018 /* ( 2, 0) */, -0.444749589997 /* ( 2, 1) */, -0.114377252718 /* ( 2, 2) */, 0.466569474816 /* ( 2, 3) */, 0.125988157670 /* ( 3, 0) */, -0.420041279441 /* ( 3, 1) */, 0.800640769025 /* ( 3, 2) */, -0.408248290464 /* ( 3, 3) */}; // matrixf_data_qrdecomp_R [size: 4 x 4] float matrixf_data_qrdecomp_R[] = { 7.937253933194 /* ( 0, 0) */, 6.425396041157 /* ( 0, 1) */, 11.212946032607 /* ( 0, 2) */, 10.960969717268 /* ( 0, 3) */, 0.000000000000 /* ( 1, 0) */, 1.927248223319 /* ( 1, 1) */, 0.494166211107 /* ( 1, 2) */, 2.890872334978 /* ( 1, 3) */, 0.000000000000 /* ( 2, 0) */, 0.000000000000 /* ( 2, 1) */, 2.241794153271 /* ( 2, 2) */, 1.189523428266 /* ( 2, 3) */, 0.000000000000 /* ( 3, 0) */, 0.000000000000 /* ( 3, 1) */, 0.000000000000 /* ( 3, 2) */, 0.291605921760 /* ( 3, 3) */}; liquid-dsp-1.3.1/src/matrix/tests/data/matrixf_data_transmul.c000066400000000000000000000117231317124540100244730ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // data for testing multiply/transpose // #include // matrixf_data_transmul_x [size: 5 x 4] float matrixf_data_transmul_x[] = { 1.366575479507 /* ( 0, 0) */, 1.982354640961 /* ( 0, 1) */, 0.913504719734 /* ( 0, 2) */, 0.671039104462 /* ( 0, 3) */, 0.264611721039 /* ( 1, 0) */, 0.995791137218 /* ( 1, 1) */, -1.983934879303 /* ( 1, 2) */, -0.375840932131 /* ( 1, 3) */, 0.245937779546 /* ( 2, 0) */, -0.343152791262 /* ( 2, 1) */, -0.143777698278 /* ( 2, 2) */, -1.387172579765 /* ( 2, 3) */, 0.781192481518 /* ( 3, 0) */, 1.444583415985 /* ( 3, 1) */, 0.043851174414 /* ( 3, 2) */, 0.399744838476 /* ( 3, 3) */, -0.488068610430 /* ( 4, 0) */, 0.573721885681 /* ( 4, 1) */, -1.381630182266 /* ( 4, 2) */, -0.176615595818 /* ( 4, 3) */}; // matrixf_data_transmul_xxT [size: 5 x 5] float matrixf_data_transmul_xxT[] = { 7.082042816423 /* ( 0, 0) */, 0.271085233449 /* ( 0, 1) */, -1.406346640934 /* ( 0, 2) */, 4.239537802168 /* ( 0, 3) */, -0.910304016309 /* ( 0, 4) */, 0.271085233449 /* ( 1, 0) */, 5.138873363454 /* ( 1, 1) */, 0.529971336750 /* ( 1, 2) */, 1.407977702482 /* ( 1, 3) */, 3.249602173055 /* ( 1, 4) */, -1.406346640934 /* ( 2, 0) */, 0.529971336750 /* ( 2, 1) */, 2.123159022134 /* ( 2, 2) */, -0.864407986864 /* ( 2, 3) */, 0.126735142361 /* ( 2, 4) */, 4.239537802168 /* ( 3, 0) */, 1.407977702482 /* ( 3, 1) */, -0.864407986864 /* ( 3, 2) */, 2.858801800305 /* ( 3, 3) */, 0.316326313589 /* ( 3, 4) */, -0.910304016309 /* ( 4, 0) */, 3.249602173055 /* ( 4, 1) */, 0.126735142361 /* ( 4, 2) */, 0.316326313589 /* ( 4, 3) */, 2.507462799831 /* ( 4, 4) */}; // matrixf_data_transmul_xxH [size: 5 x 5] float matrixf_data_transmul_xxH[] = { 7.082042816423 /* ( 0, 0) */, 0.271085233449 /* ( 0, 1) */, -1.406346640934 /* ( 0, 2) */, 4.239537802168 /* ( 0, 3) */, -0.910304016309 /* ( 0, 4) */, 0.271085233449 /* ( 1, 0) */, 5.138873363454 /* ( 1, 1) */, 0.529971336750 /* ( 1, 2) */, 1.407977702482 /* ( 1, 3) */, 3.249602173055 /* ( 1, 4) */, -1.406346640934 /* ( 2, 0) */, 0.529971336750 /* ( 2, 1) */, 2.123159022134 /* ( 2, 2) */, -0.864407986864 /* ( 2, 3) */, 0.126735142361 /* ( 2, 4) */, 4.239537802168 /* ( 3, 0) */, 1.407977702482 /* ( 3, 1) */, -0.864407986864 /* ( 3, 2) */, 2.858801800305 /* ( 3, 3) */, 0.316326313589 /* ( 3, 4) */, -0.910304016309 /* ( 4, 0) */, 3.249602173055 /* ( 4, 1) */, 0.126735142361 /* ( 4, 2) */, 0.316326313589 /* ( 4, 3) */, 2.507462799831 /* ( 4, 4) */}; // matrixf_data_transmul_xTx [size: 4 x 4] float matrixf_data_transmul_xTx[] = { 2.846505957177 /* ( 0, 0) */, 3.736623075087 /* ( 0, 1) */, 1.396626890644 /* ( 0, 2) */, 0.874893716720 /* ( 0, 3) */, 3.736623075087 /* ( 1, 0) */, 7.455061797501 /* ( 1, 1) */, -0.844681524592 /* ( 1, 2) */, 1.908127088099 /* ( 1, 3) */, 1.396626890644 /* ( 2, 0) */, -0.844681524592 /* ( 2, 1) */, 6.701985390860 /* ( 2, 2) */, 1.819632522483 /* ( 2, 3) */, 0.874893716720 /* ( 3, 0) */, 1.908127088099 /* ( 3, 1) */, 1.819632522483 /* ( 3, 2) */, 2.706786656609 /* ( 3, 3) */}; // matrixf_data_transmul_xHx [size: 4 x 4] float matrixf_data_transmul_xHx[] = { 2.846505957177 /* ( 0, 0) */, 3.736623075087 /* ( 0, 1) */, 1.396626890644 /* ( 0, 2) */, 0.874893716720 /* ( 0, 3) */, 3.736623075087 /* ( 1, 0) */, 7.455061797501 /* ( 1, 1) */, -0.844681524592 /* ( 1, 2) */, 1.908127088099 /* ( 1, 3) */, 1.396626890644 /* ( 2, 0) */, -0.844681524592 /* ( 2, 1) */, 6.701985390860 /* ( 2, 2) */, 1.819632522483 /* ( 2, 3) */, 0.874893716720 /* ( 3, 0) */, 1.908127088099 /* ( 3, 1) */, 1.819632522483 /* ( 3, 2) */, 2.706786656609 /* ( 3, 3) */}; liquid-dsp-1.3.1/src/matrix/tests/gendata_write_autotests.m000066400000000000000000000224471317124540100241410ustar00rootroot00000000000000% % Write matrix autotest data % clear all; close all; % global options dirname = 'data/'; % output directory name randn('seed',0.0); % set random seed for normal distribution rand('seed',0.0); % set random seed for uniform distribution % % real floating-point data % % % matrix_add % x = randn(5,4); y = randn(5,4); z = x + y; basename = 'matrixf_data_add'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing matrix addition'); gendata_write_matrix(fid,x,[basename '_x']); gendata_write_matrix(fid,y,[basename '_y']); gendata_write_matrix(fid,z,[basename '_z']); fclose(fid); % % matrix_aug % x = randn(5,4); y = randn(5,3); z = [x y]; basename = 'matrixf_data_aug'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing matrix augmentation'); gendata_write_matrix(fid,x,[basename '_x']); gendata_write_matrix(fid,y,[basename '_y']); gendata_write_matrix(fid,z,[basename '_z']); fclose(fid); % % matrix_cgsolve % A = [ 12.7229204 0.0000000 -7.9529123 0.0000000 4.1114998 0.0000000 0.0000000 0.0000000 0.0000000 0.0651512 0.0000000 -0.2182598 0.0000000 0.0000000 0.0000000 0.0000000 -7.9529123 0.0000000 5.0315852 0.0000000 -2.5700388 -0.1105457 0.0000000 0.0000000 0.0000000 -0.2182598 0.0000000 0.7330456 0.0000000 0.0000000 0.0000000 0.0000000 4.1114998 0.0000000 -2.5700388 0.0000000 1.3381329 0.2393810 0.0784302 0.0000000 0.0000000 0.0000000 -0.1105457 0.0000000 0.2393810 7.4723883 1.9818947 -1.3733650 0.0000000 0.0000000 0.0000000 0.0000000 0.0784302 1.9818947 3.4892726 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 -1.3733650 0.0000000 2.0631149]; x = [ 0.1620522 -0.0127203 1.0433751 0.0062052 0.8781570 0.1464129 0.7825852 -0.8257846]; b = A*x; basename = 'matrixf_data_cgsolve'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing conjugate gradient solver'); gendata_write_matrix(fid,A,[basename '_A']); gendata_write_matrix(fid,x,[basename '_x']); gendata_write_matrix(fid,b,[basename '_b']); fclose(fid); % % matrix_chol % L = [ 1.01, 0, 0, 0; -1.42, 0.5, 0, 0; 0.32, 2.01, 0.3, 0; -1.02, -0.32, -1.65, 1.07]; A = L * L'; basename = 'matrixf_data_chol'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing Cholesky decomposition'); gendata_write_matrix(fid,L,[basename '_L']); gendata_write_matrix(fid,A,[basename '_A']); fclose(fid); % % matrix_gramschmidt % A = [1 2 1; 0 2 0; 2 3 1; 1 1 0]; V = [sqrt(6)/6, sqrt(2)/6, 2/3 ; 0 2*sqrt(2)/3, -1/3 ; sqrt(6)/3, 0, 0 ; sqrt(6)/6, -sqrt(2)/6, -2/3 ]; basename = 'matrixf_data_gramschmidt'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing Gram-Schmidt orthonormalization'); gendata_write_matrix(fid,A,[basename '_A']); gendata_write_matrix(fid,V,[basename '_V']); fclose(fid); % % matrix_inv % x = randn(5,5); y = inv(x); basename = 'matrixf_data_inv'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing matrix inversion'); gendata_write_matrix(fid,x,[basename '_x']); gendata_write_matrix(fid,y,[basename '_y']); fclose(fid); % % matrix_linsolve % A = randn(5,5); x = randn(5,1); b = A*x; basename = 'matrixf_data_linsolve'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing linear solver'); gendata_write_matrix(fid,A,[basename '_A']); gendata_write_matrix(fid,x,[basename '_x']); gendata_write_matrix(fid,b,[basename '_b']); fclose(fid); % % matrix_ludecomp % A = randn(8,8); basename = 'matrixf_data_ludecomp'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing L/U decomposition'); gendata_write_matrix(fid,A,[basename '_A']); fclose(fid); % % matrix_mul % x = randn(5,4); y = randn(4,3); z = x*y; basename = 'matrixf_data_mul'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing matrix multiplication'); gendata_write_matrix(fid,x,[basename '_x']); gendata_write_matrix(fid,y,[basename '_y']); gendata_write_matrix(fid,z,[basename '_z']); fclose(fid); % % matrix_qrdecomp % A = [1 2 3 4; 5 5 7 8; 6 4 8 7; 1 0 3 1]; [Q R] = qr(A); basename = 'matrixf_data_qrdecomp'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing Q/R decomposition'); gendata_write_matrix(fid,A,[basename '_A']); gendata_write_matrix(fid,Q,[basename '_Q']); gendata_write_matrix(fid,R,[basename '_R']); fclose(fid); % % matrix_transmul % % transpose_mul % hermitian_mul % mul_transpose % mul_hermitian % x = randn(5,4); xxT = x * x'; xxH = x * x.'; xTx = x' * x; xHx = x.' * x; basename = 'matrixf_data_transmul'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing multiply/transpose'); gendata_write_matrix(fid,x, [basename '_x']); gendata_write_matrix(fid,xxT,[basename '_xxT']); gendata_write_matrix(fid,xxH,[basename '_xxH']); gendata_write_matrix(fid,xTx,[basename '_xTx']); gendata_write_matrix(fid,xHx,[basename '_xHx']); fclose(fid); % % complex floating-point data % % % matrix_add % x = randn(5,4) + j*randn(5,4); y = randn(5,4) + j*randn(5,4); z = x + y; basename = 'matrixcf_data_add'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing matrix addition'); gendata_write_matrix(fid,x,[basename '_x']); gendata_write_matrix(fid,y,[basename '_y']); gendata_write_matrix(fid,z,[basename '_z']); fclose(fid); % % matrix_aug % x = randn(5,4) + j*randn(5,4); y = randn(5,3) + j*randn(5,3); z = [x y]; basename = 'matrixcf_data_aug'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing matrix augmentation'); gendata_write_matrix(fid,x,[basename '_x']); gendata_write_matrix(fid,y,[basename '_y']); gendata_write_matrix(fid,z,[basename '_z']); fclose(fid); % % matrix_chol % L = [ 1.01, 0, 0, 0; -1.42+0.25j, 0.5, 0, 0; 0.32-1.23j, 2.01+0.78j, 0.3, 0; -1.02+1.02j,-0.32-0.03j,-1.65+2.01j, 1.07]; A = L * L'; basename = 'matrixcf_data_chol'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing Cholesky decomposition'); gendata_write_matrix(fid,L,[basename '_L']); gendata_write_matrix(fid,A,[basename '_A']); fclose(fid); % % matrix_inv % x = randn(5,5) +j*randn(5,5); y = inv(x); basename = 'matrixcf_data_inv'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing matrix inversion'); gendata_write_matrix(fid,x,[basename '_x']); gendata_write_matrix(fid,y,[basename '_y']); fclose(fid); % % matrix_linsolve % A = randn(5,5) + j*randn(5,5); x = randn(5,1) + j*randn(5,1); b = A*x; basename = 'matrixcf_data_linsolve'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing linear solver'); gendata_write_matrix(fid,A,[basename '_A']); gendata_write_matrix(fid,x,[basename '_x']); gendata_write_matrix(fid,b,[basename '_b']); fclose(fid); % % matrix_ludecomp % A = randn(8,8) + j*randn(8,8); basename = 'matrixcf_data_ludecomp'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing L/U decomposition'); gendata_write_matrix(fid,A,[basename '_A']); fclose(fid); % % matrix_mul % x = randn(5,4) + j*randn(5,4); y = randn(4,3) + j*randn(4,3); z = x*y; basename = 'matrixcf_data_mul'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing matrix multiplication'); gendata_write_matrix(fid,x,[basename '_x']); gendata_write_matrix(fid,y,[basename '_y']); gendata_write_matrix(fid,z,[basename '_z']); fclose(fid); % % matrix_qrdecomp % A = [ 2.11402 - 0.57604i, 0.41750 + 1.00833i, -0.96264 - 3.62196i, -0.20679 - 1.02668i, 0.00854 + 1.61626i, 0.84695 - 0.32736i, -1.01862 - 1.10786i, -1.78877 + 1.84456i, -2.97901 - 1.30384i, 0.52289 + 1.89110i, 1.32576 - 0.36737i, 0.04717 + 0.20628i, 0.28970 + 0.64247i, -0.55916 + 0.68302i, 1.40615 + 0.62398i, -0.12767 - 0.53997i]; [Q R] = qr(A); basename = 'matrixcf_data_qrdecomp'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing Q/R decomposition'); gendata_write_matrix(fid,A,[basename '_A']); gendata_write_matrix(fid,Q,[basename '_Q']); gendata_write_matrix(fid,R,[basename '_R']); fclose(fid); % % matrix_transmul % % transpose_mul % hermitian_mul % mul_transpose % mul_hermitian % x = randn(5,4) + j*randn(5,4); xxT = x * x'; xxH = x * x.'; xTx = x' * x; xHx = x.' * x; basename = 'matrixcf_data_transmul'; filename = [dirname basename '.c']; fid = fopen(filename,'w'); gendata_write_header(fid,'data for testing multiply/transpose'); gendata_write_matrix(fid,x, [basename '_x']); gendata_write_matrix(fid,xxT,[basename '_xxT']); gendata_write_matrix(fid,xxH,[basename '_xxH']); gendata_write_matrix(fid,xTx,[basename '_xTx']); gendata_write_matrix(fid,xHx,[basename '_xHx']); fclose(fid); liquid-dsp-1.3.1/src/matrix/tests/gendata_write_header.m000066400000000000000000000035221317124540100233270ustar00rootroot00000000000000% % write_header(fid,comment) % % write copyright and header to file descriptor 'fid' with optional comment % function gendata_write_header(fid,comment) if nargin < 2, comment = 'auto-generated data file'; end; fprintf(fid,'/* Copyright (c) 2007 - 2015 Joseph Gaeddert\n'); fprintf(fid,' *\n'); fprintf(fid,' * Permission is hereby granted, free of charge, to any person obtaining a copy\n'); fprintf(fid,' * of this software and associated documentation files (the "Software"), to deal\n'); fprintf(fid,' * in the Software without restriction, including without limitation the rights\n'); fprintf(fid,' * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n'); fprintf(fid,' * copies of the Software, and to permit persons to whom the Software is\n'); fprintf(fid,' * furnished to do so, subject to the following conditions:\n'); fprintf(fid,' * \n'); fprintf(fid,' * The above copyright notice and this permission notice shall be included in\n'); fprintf(fid,' * all copies or substantial portions of the Software.\n'); fprintf(fid,' *\n'); fprintf(fid,' * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n'); fprintf(fid,' * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n'); fprintf(fid,' * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n'); fprintf(fid,' * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n'); fprintf(fid,' * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n'); fprintf(fid,' * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n'); fprintf(fid,' * THE SOFTWARE.\n'); fprintf(fid,' */\n'); fprintf(fid,'\n'); fprintf(fid,'//\n'); fprintf(fid,'// %s\n', comment); fprintf(fid,'//\n'); fprintf(fid,'\n'); fprintf(fid,'#include \n'); fprintf(fid,'\n'); liquid-dsp-1.3.1/src/matrix/tests/gendata_write_matrix.m000066400000000000000000000027021317124540100234020ustar00rootroot00000000000000% % write_matrix(fid,x,comment) % % write matrix 'x' to file descriptor 'fid' with optional comment % function gendata_write_matrix(fid,x,varname,comment) if nargin < 3, error('must specify output file descriptor, input matrix, and variable name'); elseif nargin < 4, comment = varname; end; % other options one_line_per_element = 1; % display one line per element? print_index_as_comment = 1; % print index of element as comment? % get size of matrix [rows cols] = size(x); % even though matrix might have two dimensions, we store it as % a one-dimensional array n = rows*cols; % determine if matrix is complex or not if iscomplex(x), type = 'float complex'; else, type = 'float'; end; % write array comment fprintf(fid,'// %s [size: %u x %u]\n', comment, rows, cols); % write variable declaration fprintf(fid,'%s %s[] = {\n',type, varname); % write array data n=0; for r=1:rows, for c=1:cols, n = n+1; if iscomplex(x), fprintf(fid,' %16.12f + %16.12f*_Complex_I', real(x(r,c)), imag(x(r,c))); else, fprintf(fid,' %16.12f', real(x(r,c))); end; if print_index_as_comment, fprintf(fid,' /* (%2u,%2u) */', r-1, c-1); end; if r==rows && c==cols, fprintf(fid,'};\n'); elseif c==cols || one_line_per_element, fprintf(fid,',\n'); else, fprintf(fid,', '); end; end; end; fprintf(fid,'\n'); liquid-dsp-1.3.1/src/matrix/tests/matrix_data.h000066400000000000000000000075151317124540100215000ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest matrix data definitions // #ifndef __LIQUID_MATRIX_DATA_H__ #define __LIQUID_MATRIX_DATA_H__ // // single-precision real floating-point data // // add extern float matrixf_data_add_x[]; extern float matrixf_data_add_y[]; extern float matrixf_data_add_z[]; // aug extern float matrixf_data_aug_x[]; extern float matrixf_data_aug_y[]; extern float matrixf_data_aug_z[]; // cgsolve extern float matrixf_data_cgsolve_A[]; extern float matrixf_data_cgsolve_x[]; extern float matrixf_data_cgsolve_b[]; // chol extern float matrixf_data_chol_A[]; extern float matrixf_data_chol_L[]; // gramschmidt extern float matrixf_data_gramschmidt_A[]; extern float matrixf_data_gramschmidt_V[]; // inv extern float matrixf_data_inv_x[]; extern float matrixf_data_inv_y[]; // linsolve extern float matrixf_data_linsolve_A[]; extern float matrixf_data_linsolve_x[]; extern float matrixf_data_linsolve_b[]; // ludecomp extern float matrixf_data_ludecomp_A[]; // mul extern float matrixf_data_mul_x[]; extern float matrixf_data_mul_y[]; extern float matrixf_data_mul_z[]; // qrdecomp extern float matrixf_data_qrdecomp_A[]; extern float matrixf_data_qrdecomp_Q[]; extern float matrixf_data_qrdecomp_R[]; // transmul extern float matrixf_data_transmul_x[]; extern float matrixf_data_transmul_xxT[]; extern float matrixf_data_transmul_xxH[]; extern float matrixf_data_transmul_xTx[]; extern float matrixf_data_transmul_xHx[]; // // single-precision complex floating-point data // // add extern float complex matrixcf_data_add_x[]; extern float complex matrixcf_data_add_y[]; extern float complex matrixcf_data_add_z[]; // aug extern float complex matrixcf_data_aug_x[]; extern float complex matrixcf_data_aug_y[]; extern float complex matrixcf_data_aug_z[]; // chol extern float complex matrixcf_data_chol_A[]; extern float complex matrixcf_data_chol_L[]; // inv extern float complex matrixcf_data_inv_x[]; extern float complex matrixcf_data_inv_y[]; // linsolve extern float complex matrixcf_data_linsolve_A[]; extern float complex matrixcf_data_linsolve_x[]; extern float complex matrixcf_data_linsolve_b[]; // ludecomp extern float complex matrixcf_data_ludecomp_A[]; // mul extern float complex matrixcf_data_mul_x[]; extern float complex matrixcf_data_mul_y[]; extern float complex matrixcf_data_mul_z[]; // qrdecomp extern float complex matrixcf_data_qrdecomp_A[]; extern float complex matrixcf_data_qrdecomp_Q[]; extern float complex matrixcf_data_qrdecomp_R[]; // transmul extern float complex matrixcf_data_transmul_x[]; extern float complex matrixcf_data_transmul_xxT[]; extern float complex matrixcf_data_transmul_xxH[]; extern float complex matrixcf_data_transmul_xTx[]; extern float complex matrixcf_data_transmul_xHx[]; #endif // __LIQUID_MATRIX_DATA_H__ liquid-dsp-1.3.1/src/matrix/tests/matrixcf_autotest.c000066400000000000000000000327501317124540100227420ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "autotest/autotest.h" #include "liquid.h" // autotest data definitions #include "src/matrix/tests/matrix_data.h" // test matrix addition void autotest_matrixcf_add() { float tol = 1e-6f; // x [size: 5 x 4] // y [size: 5 x 4] // z [size: 5 x 4] float complex z[20]; matrixcf_add(matrixcf_data_add_x, matrixcf_data_add_y, z, 5, 4); unsigned int i; for (i=0; i<20; i++) { CONTEND_DELTA( crealf(matrixcf_data_add_z[i]), crealf(z[i]), tol ); CONTEND_DELTA( cimagf(matrixcf_data_add_z[i]), cimagf(z[i]), tol ); } } // test matrix augmentation void autotest_matrixcf_aug() { float tol = 1e-6f; // x [size: 5 x 4] // y [size: 5 x 3] // z [size: 5 x 7] float complex z[35]; matrixcf_aug(matrixcf_data_aug_x, 5, 4, matrixcf_data_aug_y, 5, 3, z, 5, 7); // print result if (liquid_autotest_verbose) { printf("augment:\n"); printf(" x: "); matrixcf_print(matrixcf_data_aug_x, 5, 4); printf(" y: "); matrixcf_print(matrixcf_data_aug_y, 5, 3); printf(" expected: "); matrixcf_print(matrixcf_data_aug_z, 5, 7); printf(" z: "); matrixcf_print(z,5,3); } unsigned int i; for (i=0; i<35; i++) { CONTEND_DELTA( crealf(matrixcf_data_aug_z[i]), crealf(z[i]), tol ); CONTEND_DELTA( cimagf(matrixcf_data_aug_z[i]), cimagf(z[i]), tol ); } } // Cholesky decomposition void autotest_matrixcf_chol() { float tol = 1e-3f; // error tolerance // A [size: 4 x 4] // L [size: 4 x 4] float complex L[16]; // run decomposition matrixcf_chol(matrixcf_data_chol_A, 4, L); if (liquid_autotest_verbose) { printf("chol:\n"); printf(" A: "); matrixcf_print(matrixcf_data_chol_A, 4, 4); printf(" expected: "); matrixcf_print(matrixcf_data_chol_L, 4, 4); printf(" L: "); matrixcf_print(L, 4, 4); } unsigned int i; for (i=0; i<16; i++) { CONTEND_DELTA( crealf(matrixcf_data_chol_L[i]), crealf(L[i]), tol ); CONTEND_DELTA( cimagf(matrixcf_data_chol_L[i]), cimagf(L[i]), tol ); } } // matrix inversion void autotest_matrixcf_inv() { float tol = 1e-6f; // error tolerance // x [size: 5 x 5] // y [size: 5 x 5] float complex y[25]; memmove(y, matrixcf_data_inv_x, 5*5*sizeof(float complex)); matrixcf_inv(y, 5, 5); if (liquid_autotest_verbose) { printf("inv:\n"); printf(" x: "); matrixcf_print(matrixcf_data_inv_x, 5, 5); printf(" expected: "); matrixcf_print(matrixcf_data_inv_y, 5, 5); printf(" y: "); matrixcf_print(y, 5, 5); } unsigned int i; for (i=0; i<25; i++) { CONTEND_DELTA( crealf(matrixcf_data_inv_y[i]), crealf(y[i]), tol ); CONTEND_DELTA( cimagf(matrixcf_data_inv_y[i]), cimagf(y[i]), tol ); } } // linsolve (solve linear system of equations) void autotest_matrixcf_linsolve() { float tol = 1e-6f; // error tolerance // A [size: 5 x 5] // x [size: 5 x 1] // b [size: 5 x 1] float complex x[5]; // run solver matrixcf_linsolve(matrixcf_data_linsolve_A, 5, matrixcf_data_linsolve_b, x, NULL); if (liquid_autotest_verbose) { printf("linsolve:\n"); printf(" A: "); matrixcf_print(matrixcf_data_linsolve_A, 5, 5); printf(" b: "); matrixcf_print(matrixcf_data_linsolve_b, 5, 1); printf(" expected: "); matrixcf_print(matrixcf_data_linsolve_x, 5, 1); printf(" x: "); matrixcf_print(x, 5, 1); } unsigned int i; for (i=0; i<5; i++) { CONTEND_DELTA( crealf(matrixcf_data_linsolve_x[i]), crealf(x[i]), tol ); CONTEND_DELTA( cimagf(matrixcf_data_linsolve_x[i]), cimagf(x[i]), tol ); } } // L/U decomp (Crout) void autotest_matrixcf_ludecomp_crout() { float tol = 1e-5f; // error tolerance float complex L[64]; float complex U[64]; float complex P[64]; float complex LU_test[64]; // run decomposition matrixcf_ludecomp_crout(matrixcf_data_ludecomp_A, 8, 8, L, U, P); // multiply LU matrixcf_mul(L, 8, 8, U, 8, 8, LU_test, 8, 8); if (liquid_autotest_verbose) { printf("ludecomp_crout:\n"); printf(" A: "); matrixcf_print(matrixcf_data_ludecomp_A, 8, 8); printf(" L: "); matrixcf_print(L, 8, 8); printf(" U: "); matrixcf_print(U, 8, 8); printf(" LU: "); matrixcf_print(LU_test, 8, 8); } unsigned int r,c; for (r=0; r<8; r++) { for (c=0; c<8; c++) { if (r < c) { CONTEND_DELTA( crealf(matrix_access(L,8,8,r,c)), 0.0f, tol ); CONTEND_DELTA( cimagf(matrix_access(L,8,8,r,c)), 0.0f, tol ); } else if (r==c) { CONTEND_DELTA( crealf(matrix_access(U,8,8,r,c)), 1.0f, tol ); CONTEND_DELTA( cimagf(matrix_access(U,8,8,r,c)), 0.0f, tol ); } else { CONTEND_DELTA( crealf(matrix_access(U,8,8,r,c)), 0.0f, tol ); CONTEND_DELTA( cimagf(matrix_access(U,8,8,r,c)), 0.0f, tol ); } } } unsigned int i; for (i=0; i<64; i++) { CONTEND_DELTA( crealf(matrixcf_data_ludecomp_A[i]), crealf(LU_test[i]), tol ); CONTEND_DELTA( cimagf(matrixcf_data_ludecomp_A[i]), cimagf(LU_test[i]), tol ); } } // L/U decomp (Doolittle) void autotest_matrixcf_ludecomp_doolittle() { float tol = 1e-5f; // error tolerance float complex L[64]; float complex U[64]; float complex P[64]; float complex LU_test[64]; // run decomposition matrixcf_ludecomp_doolittle(matrixcf_data_ludecomp_A, 8, 8, L, U, P); // multiply LU matrixcf_mul(L, 8, 8, U, 8, 8, LU_test, 8, 8); if (liquid_autotest_verbose) { printf("ludecomp_doolittle:\n"); printf(" A: "); matrixcf_print(matrixcf_data_ludecomp_A, 8, 8); printf(" L: "); matrixcf_print(L, 8, 8); printf(" U: "); matrixcf_print(U, 8, 8); printf(" LU: "); matrixcf_print(LU_test, 8, 8); } unsigned int r,c; for (r=0; r<8; r++) { for (c=0; c<8; c++) { if (r < c) { CONTEND_DELTA( crealf(matrix_access(L,8,8,r,c)), 0.0f, tol ); CONTEND_DELTA( cimagf(matrix_access(L,8,8,r,c)), 0.0f, tol ); } else if (r==c) { CONTEND_DELTA( crealf(matrix_access(L,8,8,r,c)), 1.0f, tol ); CONTEND_DELTA( cimagf(matrix_access(L,8,8,r,c)), 0.0f, tol ); } else { CONTEND_DELTA( crealf(matrix_access(U,8,8,r,c)), 0.0f, tol ); CONTEND_DELTA( cimagf(matrix_access(U,8,8,r,c)), 0.0f, tol ); } } } unsigned int i; for (i=0; i<64; i++) { CONTEND_DELTA( crealf(matrixcf_data_ludecomp_A[i]), crealf(LU_test[i]), tol ); CONTEND_DELTA( cimagf(matrixcf_data_ludecomp_A[i]), cimagf(LU_test[i]), tol ); } } // test matrix multiplication void autotest_matrixcf_mul() { float tol = 1e-6f; // x [size: 5 x 4] // y [size: 4 x 3] // z [size: 5 x 3] float complex z[35]; matrixcf_mul(matrixcf_data_mul_x, 5, 4, matrixcf_data_mul_y, 4, 3, z, 5, 3); // print result if (liquid_autotest_verbose) { printf("multiplication:\n"); printf(" x: "); matrixcf_print(matrixcf_data_mul_x,5,4); printf(" y: "); matrixcf_print(matrixcf_data_mul_y,4,3); printf(" expected: "); matrixcf_print(matrixcf_data_mul_z,5,3); printf(" z: "); matrixcf_print(z,5,3); } unsigned int i; for (i=0; i<15; i++) { CONTEND_DELTA( crealf(matrixcf_data_mul_z[i]), crealf(z[i]), tol ); CONTEND_DELTA( cimagf(matrixcf_data_mul_z[i]), cimagf(z[i]), tol ); } } // Q/R decomp (Gram-Schmidt) void autotest_matrixcf_qrdecomp() { float tol = 1e-4f; // error tolerance float complex Q[16]; float complex R[16]; float complex QR_test[16]; // Q*R float complex QQT_test[16]; // Q*Q^T // run decomposition matrixcf_qrdecomp_gramschmidt(matrixcf_data_qrdecomp_A, 4, 4, Q, R); // compute Q*R matrixcf_mul(Q, 4, 4, R, 4, 4, QR_test, 4, 4); // compute Q*Q^T matrixcf_mul_transpose(Q, 4, 4, QQT_test); if (liquid_autotest_verbose) { printf("qrdecomp_gramschmidt:\n"); printf(" A: "); matrixcf_print(matrixcf_data_qrdecomp_A, 4, 4); printf(" Q: "); matrixcf_print(Q, 4, 4); printf(" R: "); matrixcf_print(R, 4, 4); printf(" Q expected: "); matrixcf_print(matrixcf_data_qrdecomp_Q, 4, 4); printf(" R expected: "); matrixcf_print(matrixcf_data_qrdecomp_R, 4, 4); printf(" QR: "); matrixcf_print(QR_test, 4, 4); printf(" QQ: "); matrixcf_print(QQT_test, 4, 4); } unsigned int i; // ensure Q*R = A for (i=0; i<16; i++) { CONTEND_DELTA( crealf(matrixcf_data_qrdecomp_A[i]), crealf(QR_test[i]), tol ); CONTEND_DELTA( cimagf(matrixcf_data_qrdecomp_A[i]), cimagf(QR_test[i]), tol ); } // ensure Q*Q^T = I(4) float complex I4[16]; matrixcf_eye(I4,4); for (i=0; i<16; i++) CONTEND_DELTA( QQT_test[i], I4[i], tol ); // ensure Q and R are correct for (i=0; i<16; i++) { CONTEND_DELTA( crealf(matrixcf_data_qrdecomp_Q[i]), crealf(Q[i]), tol ); CONTEND_DELTA( cimagf(matrixcf_data_qrdecomp_Q[i]), cimagf(Q[i]), tol ); CONTEND_DELTA( crealf(matrixcf_data_qrdecomp_R[i]), crealf(R[i]), tol ); CONTEND_DELTA( cimagf(matrixcf_data_qrdecomp_R[i]), cimagf(R[i]), tol ); } } // transpose/multiply void autotest_matrixcf_transmul() { float tol = 1e-4f; // error tolerance float complex xxT[25]; // [size: 5 x 5] float complex xxH[25]; // [size: 5 x 5] float complex xTx[16]; // [size: 4 x 4] float complex xHx[16]; // [size: 4 x 4] // run matrix multiplications matrixcf_mul_transpose(matrixcf_data_transmul_x, 5, 4, xxT); matrixcf_mul_hermitian(matrixcf_data_transmul_x, 5, 4, xxH); matrixcf_transpose_mul(matrixcf_data_transmul_x, 5, 4, xTx); matrixcf_hermitian_mul(matrixcf_data_transmul_x, 5, 4, xHx); if (liquid_autotest_verbose) { printf("transmul:\n"); printf(" x: "); matrixcf_print(matrixcf_data_transmul_x, 5,4); printf("\n"); printf(" xxT: "); matrixcf_print(xxT, 5,5); printf(" xxT expected: "); matrixcf_print(matrixcf_data_transmul_xxT,5,5); printf("\n"); printf(" xxH: "); matrixcf_print(xxH, 5,5); printf(" xxH expected: "); matrixcf_print(matrixcf_data_transmul_xxH,5,5); printf("\n"); printf(" xTx: "); matrixcf_print(xTx, 4,4); printf(" xTx expected: "); matrixcf_print(matrixcf_data_transmul_xTx,4,4); printf("\n"); printf(" xHx: "); matrixcf_print(xHx, 4,4); printf(" xHx expected: "); matrixcf_print(matrixcf_data_transmul_xHx,4,4); printf("\n"); } // run tests unsigned int i; for (i=0; i<25; i++) { CONTEND_DELTA( crealf(matrixcf_data_transmul_xxT[i]), crealf(xxT[i]), tol); CONTEND_DELTA( cimagf(matrixcf_data_transmul_xxT[i]), cimagf(xxT[i]), tol); } for (i=0; i<25; i++) { CONTEND_DELTA( crealf(matrixcf_data_transmul_xxH[i]), crealf(xxH[i]), tol); CONTEND_DELTA( cimagf(matrixcf_data_transmul_xxH[i]), cimagf(xxH[i]), tol); } for (i=0; i<16; i++) { CONTEND_DELTA( crealf(matrixcf_data_transmul_xTx[i]), crealf(xTx[i]), tol); CONTEND_DELTA( cimagf(matrixcf_data_transmul_xTx[i]), cimagf(xTx[i]), tol); } for (i=0; i<16; i++) { CONTEND_DELTA( crealf(matrixcf_data_transmul_xHx[i]), crealf(xHx[i]), tol); CONTEND_DELTA( cimagf(matrixcf_data_transmul_xHx[i]), cimagf(xHx[i]), tol); } } liquid-dsp-1.3.1/src/matrix/tests/matrixf_autotest.c000066400000000000000000000311631317124540100225740ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "autotest/autotest.h" #include "liquid.h" // autotest data definitions #include "src/matrix/tests/matrix_data.h" // test matrix addition void autotest_matrixf_add() { float tol = 1e-6f; // x [size: 5 x 4] // y [size: 5 x 4] // z [size: 5 x 4] float z[20]; matrixf_add(matrixf_data_add_x, matrixf_data_add_y, z, 5, 4); unsigned int i; for (i=0; i<20; i++) CONTEND_DELTA( matrixf_data_add_z[i], z[i], tol ); } // test matrix augmentation void autotest_matrixf_aug() { float tol = 1e-6f; // x [size: 5 x 4] // y [size: 5 x 3] // z [size: 5 x 7] float z[35]; matrixf_aug(matrixf_data_aug_x, 5, 4, matrixf_data_aug_y, 5, 3, z, 5, 7); // print result if (liquid_autotest_verbose) { printf("augment:\n"); printf(" x: "); matrixf_print(matrixf_data_aug_x,5,4); printf(" y: "); matrixf_print(matrixf_data_aug_y,5,3); printf(" expected: "); matrixf_print(matrixf_data_aug_z,5,7); printf(" z: "); matrixf_print(z,5,3); } unsigned int i; for (i=0; i<35; i++) CONTEND_DELTA( matrixf_data_aug_z[i], z[i], tol ); } // conjugate gradient solver void autotest_matrixf_cgsolve() { float tol = 0.01; // error tolerance // A [size: 8 x 8], symmetric positive definite matrx // x [size: 8 x 1] // b [size: 8 x 1] float x[8]; matrixf_cgsolve(matrixf_data_cgsolve_A, 8, matrixf_data_cgsolve_b, x, NULL); if (liquid_autotest_verbose) { printf("cgsolve:\n"); printf(" A: "); matrixf_print(matrixf_data_cgsolve_A, 8, 8); printf(" b: "); matrixf_print(matrixf_data_cgsolve_b, 8, 1); printf(" expected: "); matrixf_print(matrixf_data_cgsolve_x, 8, 1); printf(" x: "); matrixf_print(x, 8, 1); } unsigned int i; for (i=0; i<8; i++) CONTEND_DELTA( matrixf_data_cgsolve_x[i], x[i], tol ); } // Cholesky decomposition void autotest_matrixf_chol() { float tol = 1e-4f; // error tolerance // A [size: 4 x 4] // L [size: 4 x 4] float L[16]; // run decomposition matrixf_chol(matrixf_data_chol_A, 4, L); if (liquid_autotest_verbose) { printf("chol:\n"); printf(" A: "); matrixf_print(matrixf_data_chol_A, 4, 4); printf(" expected: "); matrixf_print(matrixf_data_chol_L, 4, 4); printf(" L: "); matrixf_print(L, 4, 4); } unsigned int i; for (i=0; i<16; i++) CONTEND_DELTA( matrixf_data_chol_L[i], L[i], tol ); } // Gram-Schmidt Orthonormalization void autotest_matrixf_gramschmidt() { float tol = 1e-6f; // error tolerance // A [size: 4 x 3] // V [size: 4 x 3] float V[12]; matrixf_gramschmidt(matrixf_data_gramschmidt_A, 4, 3, V); if (liquid_autotest_verbose) { printf("gramschmidt:\n"); printf(" A: "); matrixf_print(matrixf_data_gramschmidt_A, 4, 3); printf(" expected: "); matrixf_print(matrixf_data_gramschmidt_V, 4, 3); printf(" V: "); matrixf_print(V, 4, 3); } unsigned int i; for (i=0; i<12; i++) CONTEND_DELTA( matrixf_data_gramschmidt_V[i], V[i], tol ); } // matrix inversion void autotest_matrixf_inv() { float tol = 1e-6f; // error tolerance // x [size: 5 x 5] // y [size: 5 x 5] float y[25]; memmove(y, matrixf_data_inv_x, 5*5*sizeof(float)); matrixf_inv(y, 5, 5); if (liquid_autotest_verbose) { printf("inv:\n"); printf(" x: "); matrixf_print(matrixf_data_inv_x, 5, 5); printf(" expected: "); matrixf_print(matrixf_data_inv_y, 5, 5); printf(" y: "); matrixf_print(y, 5, 5); } unsigned int i; for (i=0; i<25; i++) CONTEND_DELTA( matrixf_data_inv_y[i], y[i], tol ); } // linsolve (solve linear system of equations) void autotest_matrixf_linsolve() { float tol = 1e-6f; // error tolerance // A [size: 5 x 5] // x [size: 5 x 1] // b [size: 5 x 1] float x[5]; // run solver matrixf_linsolve(matrixf_data_linsolve_A, 5, matrixf_data_linsolve_b, x, NULL); if (liquid_autotest_verbose) { printf("linsolve:\n"); printf(" A: "); matrixf_print(matrixf_data_linsolve_A, 5, 5); printf(" b: "); matrixf_print(matrixf_data_linsolve_b, 5, 1); printf(" expected: "); matrixf_print(matrixf_data_linsolve_x, 5, 1); printf(" x: "); matrixf_print(x, 5, 1); } unsigned int i; for (i=0; i<5; i++) CONTEND_DELTA( matrixf_data_linsolve_x[i], x[i], tol ); } // L/U decomp (Crout) void autotest_matrixf_ludecomp_crout() { float tol = 1e-6f; // error tolerance float L[64]; float U[64]; float P[64]; float LU_test[64]; // run decomposition matrixf_ludecomp_crout(matrixf_data_ludecomp_A, 8, 8, L, U, P); // multiply LU matrixf_mul(L, 8, 8, U, 8, 8, LU_test, 8, 8); if (liquid_autotest_verbose) { printf("ludecomp_crout:\n"); printf(" A: "); matrixf_print(matrixf_data_ludecomp_A,8,8); printf(" L: "); matrixf_print(L, 8,8); printf(" U: "); matrixf_print(U, 8,8); printf(" LU: "); matrixf_print(LU_test, 8,8); } unsigned int r,c; for (r=0; r<8; r++) { for (c=0; c<8; c++) { if (r < c) { CONTEND_DELTA( matrix_access(L,8,8,r,c), 0.0f, tol ); } else if (r==c) { CONTEND_DELTA( matrix_access(U,8,8,r,c), 1.0f, tol ); } else { CONTEND_DELTA( matrix_access(U,8,8,r,c), 0.0f, tol ); } } } unsigned int i; for (i=0; i<64; i++) CONTEND_DELTA( matrixf_data_ludecomp_A[i], LU_test[i], tol ); } // L/U decomp (Doolittle) void autotest_matrixf_ludecomp_doolittle() { float tol = 1e-6f; // error tolerance float L[64]; float U[64]; float P[64]; float LU_test[64]; // run decomposition matrixf_ludecomp_doolittle(matrixf_data_ludecomp_A, 8, 8, L, U, P); // multiply LU matrixf_mul(L, 8, 8, U, 8, 8, LU_test, 8, 8); if (liquid_autotest_verbose) { printf("ludecomp_doolittle:\n"); printf(" A: "); matrixf_print(matrixf_data_ludecomp_A,8,8); printf(" L: "); matrixf_print(L, 8,8); printf(" U: "); matrixf_print(U, 8,8); printf(" LU: "); matrixf_print(LU_test, 8,8); } unsigned int r,c; for (r=0; r<8; r++) { for (c=0; c<8; c++) { if (r < c) { CONTEND_DELTA( matrix_access(L,8,8,r,c), 0.0f, tol ); } else if (r==c) { CONTEND_DELTA( matrix_access(L,8,8,r,c), 1.0f, tol ); } else { CONTEND_DELTA( matrix_access(U,8,8,r,c), 0.0f, tol ); } } } unsigned int i; for (i=0; i<64; i++) CONTEND_DELTA( matrixf_data_ludecomp_A[i], LU_test[i], tol ); } // test matrix multiplication void autotest_matrixf_mul() { float tol = 1e-6f; // x [size: 5 x 4] // y [size: 4 x 3] // z [size: 5 x 3] float z[35]; matrixf_mul(matrixf_data_mul_x, 5, 4, matrixf_data_mul_y, 4, 3, z, 5, 3); // print result if (liquid_autotest_verbose) { printf("multiplication:\n"); printf(" x: "); matrixf_print(matrixf_data_mul_x,5,4); printf(" y: "); matrixf_print(matrixf_data_mul_y,4,3); printf(" expected: "); matrixf_print(matrixf_data_mul_z,5,3); printf(" z: "); matrixf_print(z,5,3); } unsigned int i; for (i=0; i<15; i++) CONTEND_DELTA( matrixf_data_mul_z[i], z[i], tol ); } // Q/R decomp (Gram-Schmidt) void autotest_matrixf_qrdecomp() { float tol = 1e-4f; // error tolerance float Q[16]; float R[16]; float QR_test[16]; // Q*R float QQT_test[16]; // Q*Q^T // run decomposition matrixf_qrdecomp_gramschmidt(matrixf_data_qrdecomp_A, 4, 4, Q, R); // compute Q*R matrixf_mul(Q, 4, 4, R, 4, 4, QR_test, 4, 4); // compute Q*Q^T matrixf_mul_transpose(Q, 4, 4, QQT_test); if (liquid_autotest_verbose) { printf("qrdecomp_gramschmidt:\n"); printf(" A: "); matrixf_print(matrixf_data_qrdecomp_A,4,4); printf(" Q: "); matrixf_print(Q, 4,4); printf(" R: "); matrixf_print(R, 4,4); printf(" Q expected: "); matrixf_print(matrixf_data_qrdecomp_Q,4,4); printf(" R expected: "); matrixf_print(matrixf_data_qrdecomp_R,4,4); printf(" QR: "); matrixf_print(QR_test, 4,4); printf(" QQ: "); matrixf_print(QQT_test, 4,4); } unsigned int i; // ensure Q*R = A for (i=0; i<16; i++) CONTEND_DELTA( matrixf_data_qrdecomp_A[i], QR_test[i], tol ); // ensure Q*Q = I(4) float I4[16]; matrixf_eye(I4,4); for (i=0; i<16; i++) CONTEND_DELTA( QQT_test[i], I4[i], tol ); // ensure Q and R are correct for (i=0; i<16; i++) { CONTEND_DELTA( matrixf_data_qrdecomp_Q[i], Q[i], tol ); CONTEND_DELTA( matrixf_data_qrdecomp_R[i], R[i], tol ); } } // transpose/multiply void autotest_matrixf_transmul() { float tol = 1e-4f; // error tolerance float xxT[25]; // [size: 5 x 5] float xxH[25]; // [size: 5 x 5] float xTx[16]; // [size: 4 x 4] float xHx[16]; // [size: 4 x 4] // run matrix multiplications matrixf_mul_transpose(matrixf_data_transmul_x, 5, 4, xxT); matrixf_mul_hermitian(matrixf_data_transmul_x, 5, 4, xxH); matrixf_transpose_mul(matrixf_data_transmul_x, 5, 4, xTx); matrixf_hermitian_mul(matrixf_data_transmul_x, 5, 4, xHx); if (liquid_autotest_verbose) { printf("transmul:\n"); printf(" x: "); matrixf_print(matrixf_data_transmul_x, 5,4); printf("\n"); printf(" xxT: "); matrixf_print(xxT, 5,5); printf(" xxT expected: "); matrixf_print(matrixf_data_transmul_xxT,5,5); printf("\n"); printf(" xxH: "); matrixf_print(xxH, 5,5); printf(" xxH expected: "); matrixf_print(matrixf_data_transmul_xxH,5,5); printf("\n"); printf(" xTx: "); matrixf_print(xTx, 4,4); printf(" xTx expected: "); matrixf_print(matrixf_data_transmul_xTx,4,4); printf("\n"); printf(" xHx: "); matrixf_print(xHx, 4,4); printf(" xHx expected: "); matrixf_print(matrixf_data_transmul_xHx,4,4); printf("\n"); } // run tests unsigned int i; for (i=0; i<25; i++) CONTEND_DELTA( matrixf_data_transmul_xxT[i], xxT[i], tol); for (i=0; i<25; i++) CONTEND_DELTA( matrixf_data_transmul_xxH[i], xxH[i], tol); for (i=0; i<16; i++) CONTEND_DELTA( matrixf_data_transmul_xTx[i], xTx[i], tol); for (i=0; i<16; i++) CONTEND_DELTA( matrixf_data_transmul_xHx[i], xHx[i], tol); } liquid-dsp-1.3.1/src/matrix/tests/smatrixb_autotest.c000066400000000000000000000245221317124540100227540ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "autotest/autotest.h" #include "liquid.internal.h" // // AUTOTESTS: basic sparse matrix functionality // // test sparse binary matrix methods void autotest_smatrixb_vmul() { // A = [ // 1 0 0 0 0 0 0 0 0 0 0 0 // 0 0 0 1 0 0 0 0 0 0 0 0 // 1 0 0 0 0 0 0 0 1 1 0 0 // 0 0 1 0 0 0 1 1 0 0 0 0 // 0 0 0 0 0 0 0 0 0 0 0 0 // 0 0 0 0 0 0 1 0 1 0 1 0 // 1 0 1 0 0 0 0 0 0 0 1 1 // 0 0 1 0 0 1 1 0 0 0 0 0] // // x = [ 1 1 0 0 1 0 0 1 1 1 0 1 ] // y = [ 1 0 1 1 0 1 0 0 ] // // create sparse matrix and set values smatrixb A = smatrixb_create(8,12); smatrixb_set(A,0,0, 1); smatrixb_set(A,2,0, 1); smatrixb_set(A,6,0, 1); smatrixb_set(A,3,2, 1); smatrixb_set(A,6,2, 1); smatrixb_set(A,7,2, 1); smatrixb_set(A,1,3, 1); smatrixb_set(A,7,5, 1); smatrixb_set(A,3,6, 1); smatrixb_set(A,5,6, 1); smatrixb_set(A,7,6, 1); smatrixb_set(A,3,7, 1); smatrixb_set(A,2,8, 1); smatrixb_set(A,5,8, 1); smatrixb_set(A,2,9, 1); smatrixb_set(A,5,10, 1); smatrixb_set(A,6,10, 1); smatrixb_set(A,6,11, 1); // generate vectors unsigned char x[12] = {1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1}; unsigned char y_test[8] = {1, 0, 1, 1, 0, 1, 0, 0}; unsigned char y[8]; // multiply and run test smatrixb_vmul(A,x,y); CONTEND_EQUALITY( y[0], y_test[0] ); CONTEND_EQUALITY( y[1], y_test[1] ); CONTEND_EQUALITY( y[2], y_test[2] ); CONTEND_EQUALITY( y[3], y_test[3] ); CONTEND_EQUALITY( y[4], y_test[4] ); CONTEND_EQUALITY( y[5], y_test[5] ); CONTEND_EQUALITY( y[6], y_test[6] ); CONTEND_EQUALITY( y[7], y_test[7] ); // print results (verbose) if (liquid_autotest_verbose) { printf("\ncompact form:\n"); smatrixb_print(A); printf("\nexpanded form:\n"); smatrixb_print_expanded(A); unsigned int i; unsigned int j; printf("x = ["); for (j=0; j<12; j++) printf("%2u", x[j]); printf(" ];\n"); printf("y = ["); for (i=0; i<8; i++) printf("%2u", y[i]); printf(" ];\n"); printf("y_test = ["); for (i=0; i<8; i++) printf("%2u", y_test[i]); printf(" ];\n"); } // destroy matrix object smatrixb_destroy(A); } // test sparse binary matrix multiplication void autotest_smatrixb_mul() { // a: [8 x 12] unsigned char a_test[96] = { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}; // b: [12 x 5] unsigned char b_test[60] = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0}; // output: [8 x 5] unsigned char c_test[40] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0}; smatrixb a = smatrixb_create_array(a_test, 8,12); smatrixb b = smatrixb_create_array(b_test, 12, 5); smatrixb c = smatrixb_create(8, 5); // compute output smatrixb_mul(a,b,c); // print results (verbose) if (liquid_autotest_verbose) { printf("a:\n"); smatrixb_print_expanded(a); printf("b:\n"); smatrixb_print_expanded(b); printf("c:\n"); smatrixb_print_expanded(c); } unsigned int i; unsigned int j; for (i=0; i<8; i++) { for (j=0; j<5; j++) { CONTEND_EQUALITY( smatrixb_get(c,i,j), c_test[i*5+j]); } } // destroy objects smatrixb_destroy(a); smatrixb_destroy(b); smatrixb_destroy(c); } // void autotest_smatrixb_mulf() { // A = [ // 1 0 0 0 0 0 0 0 0 0 0 0 // 0 0 0 1 0 0 0 0 0 0 0 0 // 1 0 0 0 0 0 0 0 1 1 0 0 // 0 0 1 0 0 0 1 1 0 0 0 0 // 0 0 0 0 0 0 0 0 0 0 0 0 // 0 0 0 0 0 0 1 0 1 0 1 0 // 1 0 1 0 0 0 0 0 0 0 1 1 // 0 0 1 0 0 1 1 0 0 0 0 0] // float tol = 1e-6f; // create sparse matrix and set values smatrixb A = smatrixb_create(8,12); smatrixb_set(A,0,0, 1); smatrixb_set(A,2,0, 1); smatrixb_set(A,6,0, 1); smatrixb_set(A,3,2, 1); smatrixb_set(A,6,2, 1); smatrixb_set(A,7,2, 1); smatrixb_set(A,1,3, 1); smatrixb_set(A,7,5, 1); smatrixb_set(A,3,6, 1); smatrixb_set(A,5,6, 1); smatrixb_set(A,7,6, 1); smatrixb_set(A,3,7, 1); smatrixb_set(A,2,8, 1); smatrixb_set(A,5,8, 1); smatrixb_set(A,2,9, 1); smatrixb_set(A,5,10, 1); smatrixb_set(A,6,10, 1); smatrixb_set(A,6,11, 1); // generate vectors float x[36] = { -4.3, -0.7, 3.7, -1.7, 2.8, 4.3, 2.0, 1.9, 0.6, 3.6, 1.0, -3.7, 4.3, 0.7, 2.1, 4.6, 0.5, 0.8, 1.6, -3.8, -0.8, -1.9, -2.1, 2.8, -1.5, 2.5, 0.8, 8.4, 1.5, -3.1, -5.8, 0.0, 2.5, -4.9, -2.1, -1.5}; float y_test[24] = { -4.3, -0.7, 3.7, 3.6, 1.0, -3.7, 2.6, 3.3, 1.4, 1.7, -4.0, 2.6, 0.0, 0.0, 0.0, -5.7, -1.3, 2.5, -13.0, -0.9, 5.3, 8.2, -1.4, 0.6}; float y[24]; // multiply and run test smatrixb_mulf(A, x,12,3, y, 8,3); unsigned int i; for (i=0; i<24; i++) CONTEND_DELTA( y[i], y_test[i], tol ); // print results (verbose) if (liquid_autotest_verbose) { printf("A:\n"); smatrixb_print_expanded(A); printf("x = [\n"); for (i=0; i<36; i++) printf("%6.2f%s", x[i], ((i+1)%3)==0 ? "\n" : ""); printf(" ];\n"); printf("y = [\n"); for (i=0; i<24; i++) printf("%6.2f%s", y[i], ((i+1)%3)==0 ? "\n" : ""); printf(" ];\n"); printf("y_test = [\n"); for (i=0; i<24; i++) printf("%6.2f%s", y_test[i], ((i+1)%3)==0 ? "\n" : ""); printf(" ];\n"); } // destroy matrix object smatrixb_destroy(A); } // void autotest_smatrixb_vmulf() { // A = [ // 1 0 0 0 0 0 0 0 0 0 0 0 // 0 0 0 1 0 0 0 0 0 0 0 0 // 1 0 0 0 0 0 0 0 1 1 0 0 // 0 0 1 0 0 0 1 1 0 0 0 0 // 0 0 0 0 0 0 0 0 0 0 0 0 // 0 0 0 0 0 0 1 0 1 0 1 0 // 1 0 1 0 0 0 0 0 0 0 1 1 // 0 0 1 0 0 1 1 0 0 0 0 0] // // x = [3.4,-5.7, 0.3, 2.3, 1.9, 3.9, 2.3,-4.0,-0.5, 1.5,-0.6,-1.0]^T // y = [3.4, 2.3, 4.4,-1.4, 0.0, 1.2, 2.1, 6.5]^T // float tol = 1e-6f; // create sparse matrix and set values smatrixb A = smatrixb_create(8,12); smatrixb_set(A,0,0, 1); smatrixb_set(A,2,0, 1); smatrixb_set(A,6,0, 1); smatrixb_set(A,3,2, 1); smatrixb_set(A,6,2, 1); smatrixb_set(A,7,2, 1); smatrixb_set(A,1,3, 1); smatrixb_set(A,7,5, 1); smatrixb_set(A,3,6, 1); smatrixb_set(A,5,6, 1); smatrixb_set(A,7,6, 1); smatrixb_set(A,3,7, 1); smatrixb_set(A,2,8, 1); smatrixb_set(A,5,8, 1); smatrixb_set(A,2,9, 1); smatrixb_set(A,5,10, 1); smatrixb_set(A,6,10, 1); smatrixb_set(A,6,11, 1); // generate vectors float x[12] = { 3.4, -5.7, 0.3, 2.3, 1.9, 3.9, 2.3, -4.0, -0.5, 1.5, -0.6, -1.0}; float y_test[8] = { 3.4, 2.3, 4.4, -1.4, 0.0, 1.2, 2.1, 6.5}; float y[8]; // multiply and run test smatrixb_vmulf(A,x,y); CONTEND_DELTA( y[0], y_test[0], tol ); CONTEND_DELTA( y[1], y_test[1], tol ); CONTEND_DELTA( y[2], y_test[2], tol ); CONTEND_DELTA( y[3], y_test[3], tol ); CONTEND_DELTA( y[4], y_test[4], tol ); CONTEND_DELTA( y[5], y_test[5], tol ); CONTEND_DELTA( y[6], y_test[6], tol ); CONTEND_DELTA( y[7], y_test[7], tol ); // print results (verbose) if (liquid_autotest_verbose) { printf("\ncompact form:\n"); smatrixb_print(A); printf("\nexpanded form:\n"); smatrixb_print_expanded(A); unsigned int i; unsigned int j; printf("x = ["); for (j=0; j<12; j++) printf("%8.4f", x[j]); printf(" ];\n"); printf("y = ["); for (i=0; i<8; i++) printf("%8.4f", y[i]); printf(" ];\n"); printf("y_test = ["); for (i=0; i<8; i++) printf("%8.4f", y_test[i]); printf(" ];\n"); } // destroy matrix object smatrixb_destroy(A); } liquid-dsp-1.3.1/src/matrix/tests/smatrixf_autotest.c000066400000000000000000000064361317124540100227640ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "autotest/autotest.h" #include "liquid.internal.h" // // AUTOTESTS: basic sparse matrix functionality // // test sparse floating-point vector multiplication void autotest_smatrixf_vmul() { float tol = 1e-6f; // A = [ // 0 0 0 0 4 // 0 0 0 0 0 // 0 0 0 3 0 // 2 0 0 0 1 // create sparse matrix and set values smatrixf A = smatrixf_create(4, 5); smatrixf_set(A, 0,4, 4); smatrixf_set(A, 2,3, 3); smatrixf_set(A, 3,0, 2); smatrixf_set(A, 3,4, 0); smatrixf_set(A, 3,4, 1); // initialize input vector float x[5] = {7, 1, 5, 2, 2}; float y_test[4] = {8, 0, 6, 16}; float y[4]; // multiply and run test smatrixf_vmul(A,x,y); // check values CONTEND_DELTA( y[0], y_test[0], tol ); CONTEND_DELTA( y[1], y_test[1], tol ); CONTEND_DELTA( y[2], y_test[2], tol ); CONTEND_DELTA( y[3], y_test[3], tol ); smatrixf_destroy(A); } // test sparse floating-point matrix multiplication void autotest_smatrixf_mul() { float tol = 1e-6f; // intialize matrices smatrixf a = smatrixf_create(4, 5); smatrixf b = smatrixf_create(5, 3); smatrixf c = smatrixf_create(4, 3); // initialize 'a' // 0 0 0 0 4 // 0 0 0 0 0 // 0 0 0 3 0 // 2 0 0 0 1 smatrixf_set(a, 0,4, 4); smatrixf_set(a, 2,3, 3); smatrixf_set(a, 3,0, 2); smatrixf_set(a, 3,4, 0); smatrixf_set(a, 3,4, 1); // initialize 'b' // 7 6 0 // 0 0 0 // 0 0 0 // 0 5 0 // 2 0 0 smatrixf_set(b, 0,0, 7); smatrixf_set(b, 0,1, 6); smatrixf_set(b, 3,1, 5); smatrixf_set(b, 4,0, 2); // compute 'c' // 8 0 0 // 0 0 0 // 0 15 0 // 16 12 0 smatrixf_mul(a,b,c); float c_test[12] = { 8, 0, 0, 0, 0, 0, 0, 15, 0, 16, 12, 0}; // check values unsigned int i; unsigned int j; for (i=0; i<4; i++) { for (j=0; j<3; j++) { CONTEND_DELTA(smatrixf_get(c,i,j), matrixf_access(c_test,4,3,i,j), tol); } } smatrixf_destroy(a); smatrixf_destroy(b); smatrixf_destroy(c); } liquid-dsp-1.3.1/src/matrix/tests/smatrixi_autotest.c000066400000000000000000000063171317124540100227650ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "autotest/autotest.h" #include "liquid.internal.h" // // AUTOTESTS: basic sparse matrix functionality // // test sparse integer vector multiplication void autotest_smatrixi_vmul() { // A = [ // 0 0 0 0 4 // 0 0 0 0 0 // 0 0 0 3 0 // 2 0 0 0 1 // create sparse matrix and set values smatrixi A = smatrixi_create(4, 5); smatrixi_set(A, 0,4, 4); smatrixi_set(A, 2,3, 3); smatrixi_set(A, 3,0, 2); smatrixi_set(A, 3,4, 0); smatrixi_set(A, 3,4, 1); // initialize input vector short int x[5] = {7, 1, 5, 2, 2}; short int y_test[4] = {8, 0, 6, 16}; short int y[4]; // multiply and run test smatrixi_vmul(A,x,y); // check values CONTEND_EQUALITY( y[0], y_test[0] ); CONTEND_EQUALITY( y[1], y_test[1] ); CONTEND_EQUALITY( y[2], y_test[2] ); CONTEND_EQUALITY( y[3], y_test[3] ); smatrixi_destroy(A); } // test sparse integer matrix multiplication void autotest_smatrixi_mul() { // intialize matrices smatrixi a = smatrixi_create(4, 5); smatrixi b = smatrixi_create(5, 3); smatrixi c = smatrixi_create(4, 3); // initialize 'a' // 0 0 0 0 4 // 0 0 0 0 0 // 0 0 0 3 0 // 2 0 0 0 1 smatrixi_set(a, 0,4, 4); smatrixi_set(a, 2,3, 3); smatrixi_set(a, 3,0, 2); smatrixi_set(a, 3,4, 0); smatrixi_set(a, 3,4, 1); // initialize 'b' // 7 6 0 // 0 0 0 // 0 0 0 // 0 5 0 // 2 0 0 smatrixi_set(b, 0,0, 7); smatrixi_set(b, 0,1, 6); smatrixi_set(b, 3,1, 5); smatrixi_set(b, 4,0, 2); // compute 'c' // 8 0 0 // 0 0 0 // 0 15 0 // 16 12 0 smatrixi_mul(a,b,c); short int c_test[12] = { 8, 0, 0, 0, 0, 0, 0, 15, 0, 16, 12, 0}; // check values unsigned int i; unsigned int j; for (i=0; i<4; i++) { for (j=0; j<3; j++) { CONTEND_EQUALITY(smatrixi_get(c,i,j), matrixf_access(c_test,4,3,i,j)) } } smatrixi_destroy(a); smatrixi_destroy(b); smatrixi_destroy(c); } liquid-dsp-1.3.1/src/modem/000077500000000000000000000000001317124540100154555ustar00rootroot00000000000000liquid-dsp-1.3.1/src/modem/bench/000077500000000000000000000000001317124540100165345ustar00rootroot00000000000000liquid-dsp-1.3.1/src/modem/bench/freqdem_benchmark.c000066400000000000000000000056241317124540100223440ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "liquid.h" // frequency demodulator benchmark void benchmark_freqdem(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations) { // create demodulator float kf = 0.05f; // modulation index freqdem dem = freqdem_create(kf); float complex r[20]; // modulated signal float m[20]; // message signal unsigned long int i; // generate modulated signal for (i=0; i<20; i++) r[i] = 0.3f*cexpf(_Complex_I*2*M_PI*i/20.0f); // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { freqdem_demodulate(dem, r[ 0], &m[ 0]); freqdem_demodulate(dem, r[ 1], &m[ 1]); freqdem_demodulate(dem, r[ 2], &m[ 2]); freqdem_demodulate(dem, r[ 3], &m[ 3]); freqdem_demodulate(dem, r[ 4], &m[ 4]); freqdem_demodulate(dem, r[ 5], &m[ 5]); freqdem_demodulate(dem, r[ 6], &m[ 6]); freqdem_demodulate(dem, r[ 7], &m[ 7]); freqdem_demodulate(dem, r[ 8], &m[ 8]); freqdem_demodulate(dem, r[ 9], &m[ 9]); freqdem_demodulate(dem, r[10], &m[10]); freqdem_demodulate(dem, r[11], &m[11]); freqdem_demodulate(dem, r[12], &m[12]); freqdem_demodulate(dem, r[13], &m[13]); freqdem_demodulate(dem, r[14], &m[14]); freqdem_demodulate(dem, r[15], &m[15]); freqdem_demodulate(dem, r[16], &m[16]); freqdem_demodulate(dem, r[17], &m[17]); freqdem_demodulate(dem, r[18], &m[18]); freqdem_demodulate(dem, r[19], &m[19]); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 20; // destroy demodulator freqdem_destroy(dem); } liquid-dsp-1.3.1/src/modem/bench/freqmod_benchmark.c000066400000000000000000000057401317124540100223550ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "liquid.h" // frequency modulator benchmark void benchmark_freqmod(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations) { // create modulator float kf = 0.05f; // modulation index freqmod mod = freqmod_create(kf); float m[20]; // message signal float complex r[20]; // modulated signal unsigned long int i; // generate message signal (sum of sines) for (i=0; i<20; i++) { m[i] = 0.3f*cosf(2*M_PI*1*i/20.0f + 0.0f) + 0.2f*cosf(2*M_PI*2*i/20.0f + 0.4f) + 0.4f*cosf(2*M_PI*3*i/20.0f + 1.7f); } // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { freqmod_modulate(mod, m[ 0], &r[ 0]); freqmod_modulate(mod, m[ 1], &r[ 1]); freqmod_modulate(mod, m[ 2], &r[ 2]); freqmod_modulate(mod, m[ 3], &r[ 3]); freqmod_modulate(mod, m[ 4], &r[ 4]); freqmod_modulate(mod, m[ 5], &r[ 5]); freqmod_modulate(mod, m[ 6], &r[ 6]); freqmod_modulate(mod, m[ 7], &r[ 7]); freqmod_modulate(mod, m[ 8], &r[ 8]); freqmod_modulate(mod, m[ 9], &r[ 9]); freqmod_modulate(mod, m[10], &r[10]); freqmod_modulate(mod, m[11], &r[11]); freqmod_modulate(mod, m[12], &r[12]); freqmod_modulate(mod, m[13], &r[13]); freqmod_modulate(mod, m[14], &r[14]); freqmod_modulate(mod, m[15], &r[15]); freqmod_modulate(mod, m[16], &r[16]); freqmod_modulate(mod, m[17], &r[17]); freqmod_modulate(mod, m[18], &r[18]); freqmod_modulate(mod, m[19], &r[19]); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 20; // destroy modulator freqmod_destroy(mod); } liquid-dsp-1.3.1/src/modem/bench/fskdem_benchmark.c000066400000000000000000000106271317124540100221710ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "liquid.h" #define FSKDEM_BENCH_API(m,k,bandwidth) \ ( struct rusage * _start, \ struct rusage * _finish, \ unsigned long int * _num_iterations) \ { fskdem_bench(_start, _finish, _num_iterations, m, k, bandwidth); } // Helper function to keep code base small void fskdem_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _m, unsigned int _k, float _bandwidth) { // normalize number of iterations *_num_iterations /= _k; if (*_num_iterations < 1) *_num_iterations = 1; // initialize demodulator fskdem dem = fskdem_create(_m,_k,_bandwidth); //unsigned int M = 1 << _m; // constellation size unsigned long int i; // generate input vector to demodulate (spiral) float complex buf[_k+10]; for (i=0; i<_k+10; i++) buf[i] = 0.07 * i * cexpf(_Complex_I*2*M_PI*0.1*i); // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { fskdem_demodulate(dem, &buf[0]); fskdem_demodulate(dem, &buf[1]); fskdem_demodulate(dem, &buf[2]); fskdem_demodulate(dem, &buf[3]); fskdem_demodulate(dem, &buf[4]); fskdem_demodulate(dem, &buf[5]); fskdem_demodulate(dem, &buf[6]); fskdem_demodulate(dem, &buf[7]); fskdem_demodulate(dem, &buf[8]); fskdem_demodulate(dem, &buf[9]); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 10; fskdem_destroy(dem); } // BENCHMARKS: basic properties: M=2^m, k = 2*M, bandwidth = 0.25 void benchmark_fskdem_norm_M2 FSKDEM_BENCH_API( 1, 4, 0.25f ) void benchmark_fskdem_norm_M4 FSKDEM_BENCH_API( 2, 8, 0.25f ) void benchmark_fskdem_norm_M8 FSKDEM_BENCH_API( 3, 16, 0.25f ) void benchmark_fskdem_norm_M16 FSKDEM_BENCH_API( 4, 32, 0.25f ) void benchmark_fskdem_norm_M32 FSKDEM_BENCH_API( 5, 64, 0.25f ) void benchmark_fskdem_norm_M64 FSKDEM_BENCH_API( 6, 128, 0.25f ) void benchmark_fskdem_norm_M128 FSKDEM_BENCH_API( 7, 256, 0.25f ) void benchmark_fskdem_norm_M256 FSKDEM_BENCH_API( 8, 512, 0.25f ) void benchmark_fskdem_norm_M512 FSKDEM_BENCH_API( 9, 1024, 0.25f ) void benchmark_fskdem_norm_M1024 FSKDEM_BENCH_API(10, 2048, 0.25f ) // BENCHMARKS: obscure properties: M=2^m, k not relative to M, bandwidth basically irrational void benchmark_fskdem_misc_M2 FSKDEM_BENCH_API( 1, 5, 0.3721451) void benchmark_fskdem_misc_M4 FSKDEM_BENCH_API( 2, 10, 0.3721451) void benchmark_fskdem_misc_M8 FSKDEM_BENCH_API( 3, 20, 0.3721451) void benchmark_fskdem_misc_M16 FSKDEM_BENCH_API( 4, 30, 0.3721451) void benchmark_fskdem_misc_M32 FSKDEM_BENCH_API( 5, 60, 0.3721451) void benchmark_fskdem_misc_M64 FSKDEM_BENCH_API( 6, 100, 0.3721451) void benchmark_fskdem_misc_M128 FSKDEM_BENCH_API( 7, 200, 0.3721451) void benchmark_fskdem_misc_M256 FSKDEM_BENCH_API( 8, 500, 0.3721451) void benchmark_fskdem_misc_M512 FSKDEM_BENCH_API( 9, 1000, 0.3721451) void benchmark_fskdem_misc_M1024 FSKDEM_BENCH_API(10, 2000, 0.3721451) liquid-dsp-1.3.1/src/modem/bench/fskmod_benchmark.c000066400000000000000000000105271317124540100222020ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "liquid.h" #define FSKMOD_BENCH_API(m,k,bandwidth) \ ( struct rusage * _start, \ struct rusage * _finish, \ unsigned long int * _num_iterations) \ { fskmod_bench(_start, _finish, _num_iterations, m, k, bandwidth); } // Helper function to keep code base small void fskmod_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _m, unsigned int _k, float _bandwidth) { // normalize number of iterations *_num_iterations /= _k; if (*_num_iterations < 1) *_num_iterations = 1; // initialize modulator fskmod mod = fskmod_create(_m,_k,_bandwidth); unsigned int M = 1 << _m; // constellation size float complex buf[_k]; // transmit buffer unsigned long int i; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { fskmod_modulate(mod, (i+ 0) % M, buf); fskmod_modulate(mod, (i+ 1) % M, buf); fskmod_modulate(mod, (i+ 2) % M, buf); fskmod_modulate(mod, (i+ 3) % M, buf); fskmod_modulate(mod, (i+ 4) % M, buf); fskmod_modulate(mod, (i+ 5) % M, buf); fskmod_modulate(mod, (i+ 6) % M, buf); fskmod_modulate(mod, (i+ 7) % M, buf); fskmod_modulate(mod, (i+ 8) % M, buf); fskmod_modulate(mod, (i+ 9) % M, buf); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 10; fskmod_destroy(mod); } // BENCHMARKS: basic properties: M=2^m, k = 2*M, bandwidth = 0.25 void benchmark_fskmod_norm_M2 FSKMOD_BENCH_API( 1, 4, 0.25f ) void benchmark_fskmod_norm_M4 FSKMOD_BENCH_API( 2, 8, 0.25f ) void benchmark_fskmod_norm_M8 FSKMOD_BENCH_API( 3, 16, 0.25f ) void benchmark_fskmod_norm_M16 FSKMOD_BENCH_API( 4, 32, 0.25f ) void benchmark_fskmod_norm_M32 FSKMOD_BENCH_API( 5, 64, 0.25f ) void benchmark_fskmod_norm_M64 FSKMOD_BENCH_API( 6, 128, 0.25f ) void benchmark_fskmod_norm_M128 FSKMOD_BENCH_API( 7, 256, 0.25f ) void benchmark_fskmod_norm_M256 FSKMOD_BENCH_API( 8, 512, 0.25f ) void benchmark_fskmod_norm_M512 FSKMOD_BENCH_API( 9, 1024, 0.25f ) void benchmark_fskmod_norm_M1024 FSKMOD_BENCH_API(10, 2048, 0.25f ) // BENCHMARKS: obscure properties: M=2^m, k not relative to M, bandwidth basically irrational void benchmark_fskmod_misc_M2 FSKMOD_BENCH_API( 1, 5, 0.3721451) void benchmark_fskmod_misc_M4 FSKMOD_BENCH_API( 2, 10, 0.3721451) void benchmark_fskmod_misc_M8 FSKMOD_BENCH_API( 3, 20, 0.3721451) void benchmark_fskmod_misc_M16 FSKMOD_BENCH_API( 4, 30, 0.3721451) void benchmark_fskmod_misc_M32 FSKMOD_BENCH_API( 5, 60, 0.3721451) void benchmark_fskmod_misc_M64 FSKMOD_BENCH_API( 6, 100, 0.3721451) void benchmark_fskmod_misc_M128 FSKMOD_BENCH_API( 7, 200, 0.3721451) void benchmark_fskmod_misc_M256 FSKMOD_BENCH_API( 8, 500, 0.3721451) void benchmark_fskmod_misc_M512 FSKMOD_BENCH_API( 9, 1000, 0.3721451) void benchmark_fskmod_misc_M1024 FSKMOD_BENCH_API(10, 2000, 0.3721451) liquid-dsp-1.3.1/src/modem/bench/gmskmodem_benchmark.c000066400000000000000000000061741317124540100227050ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "liquid.h" // void benchmark_gmskmodem_modulate(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { // options unsigned int k=2; // filter samples/symbol unsigned int m=3; // filter delay (symbols) float BT=0.3f; // bandwidth-time product // create modem object gmskmod mod = gmskmod_create(k, m, BT); float complex x[k]; unsigned int symbol_in = 0; unsigned long int i; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { gmskmod_modulate(mod, symbol_in, x); gmskmod_modulate(mod, symbol_in, x); gmskmod_modulate(mod, symbol_in, x); gmskmod_modulate(mod, symbol_in, x); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; // destroy modem objects gmskmod_destroy(mod); } // void benchmark_gmskmodem_demodulate(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { // options unsigned int k=2; // filter samples/symbol unsigned int m=3; // filter delay (symbols) float BT=0.3f; // bandwidth-time product // create modem object gmskdem demod = gmskdem_create(k, m, BT); float complex x[k]; unsigned int symbol_out = 0; unsigned long int i; for (i=0; i #include #include #include #include "liquid.h" #define MODEM_DEMODSOFT_BENCH_API(MS) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { modem_demodulate_soft_bench(_start, _finish, _num_iterations, MS); } // Helper function to keep code base small void modem_demodulate_soft_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, modulation_scheme _ms) { // normalize number of iterations switch (_ms) { case LIQUID_MODEM_UNKNOWN: fprintf(stderr,"error: modem_modulate_bench(), unknown modem scheme\n"); exit(1); case LIQUID_MODEM_BPSK: *_num_iterations *= 2; break; case LIQUID_MODEM_QPSK: *_num_iterations *= 2; break; case LIQUID_MODEM_OOK: *_num_iterations *= 2; break; case LIQUID_MODEM_SQAM32: *_num_iterations /= 10; break; case LIQUID_MODEM_SQAM128: *_num_iterations /= 20; break; case LIQUID_MODEM_V29: *_num_iterations /= 16; break; case LIQUID_MODEM_ARB16OPT: *_num_iterations /= 16; break; case LIQUID_MODEM_ARB32OPT: *_num_iterations /= 32; break; case LIQUID_MODEM_ARB64VT: *_num_iterations /= 64; break; default:; *_num_iterations /= 8; } if (*_num_iterations < 1) *_num_iterations = 1; // initialize modulator modem demod = modem_create(_ms); unsigned int bps = modem_get_bps(demod); unsigned long int i; // generate input vector to demodulate (spiral) float complex x[20]; for (i=0; i<20; i++) x[i] = 0.07 * i * cexpf(_Complex_I*2*M_PI*0.1*i); unsigned int symbol_out; unsigned char soft_bits[bps]; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { modem_demodulate_soft(demod, x[ 0], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[ 1], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[ 2], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[ 3], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[ 4], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[ 5], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[ 6], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[ 7], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[ 8], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[ 9], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[10], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[11], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[12], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[13], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[14], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[15], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[16], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[17], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[18], &symbol_out, soft_bits); modem_demodulate_soft(demod, x[19], &symbol_out, soft_bits); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 20; modem_destroy(demod); } // specific modems void benchmark_demodsoft_bpsk MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_BPSK) void benchmark_demodsoft_qpsk MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_QPSK) void benchmark_demodsoft_ook MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_OOK) void benchmark_demodsoft_sqam32 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_SQAM32) void benchmark_demodsoft_sqam128 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_SQAM128) // ASK void benchmark_demodsoft_ask2 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_ASK2) void benchmark_demodsoft_ask4 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_ASK4) void benchmark_demodsoft_ask8 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_ASK8) void benchmark_demodsoft_ask16 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_ASK16) // PSK void benchmark_demodsoft_psk2 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_PSK2) void benchmark_demodsoft_psk4 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_PSK4) void benchmark_demodsoft_psk8 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_PSK8) void benchmark_demodsoft_psk16 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_PSK16) void benchmark_demodsoft_psk32 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_PSK32) void benchmark_demodsoft_psk64 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_PSK64) // Differential PSK void benchmark_demodsoft_dpsk2 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_DPSK2) void benchmark_demodsoft_dpsk4 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_DPSK4) void benchmark_demodsoft_dpsk8 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_DPSK8) void benchmark_demodsoft_dpsk16 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_DPSK16) void benchmark_demodsoft_dpsk32 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_DPSK32) void benchmark_demodsoft_dpsk64 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_DPSK64) // QAM void benchmark_demodsoft_qam4 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_QAM4) void benchmark_demodsoft_qam8 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_QAM8) void benchmark_demodsoft_qam16 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_QAM16) void benchmark_demodsoft_qam32 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_QAM32) void benchmark_demodsoft_qam64 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_QAM64) void benchmark_demodsoft_qam128 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_QAM128) void benchmark_demodsoft_qam256 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_QAM256) // APSK void benchmark_demodsoft_apsk4 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_APSK4) void benchmark_demodsoft_apsk8 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_APSK8) void benchmark_demodsoft_apsk16 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_APSK16) void benchmark_demodsoft_apsk32 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_APSK32) void benchmark_demodsoft_apsk64 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_APSK64) void benchmark_demodsoft_apsk128 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_APSK128) void benchmark_demodsoft_apsk256 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_APSK256) // ARB void benchmark_demodsoft_arbV29 MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_V29) void benchmark_demodsoft_arb16opt MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_ARB16OPT) void benchmark_demodsoft_arb32opt MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_ARB32OPT) void benchmark_demodsoft_arb64opt MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_ARB64OPT) void benchmark_demodsoft_arb128opt MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_ARB128OPT) void benchmark_demodsoft_arb256opt MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_ARB256OPT) void benchmark_demodsoft_arb64vt MODEM_DEMODSOFT_BENCH_API(LIQUID_MODEM_ARB64VT) liquid-dsp-1.3.1/src/modem/bench/modem_demodulate_benchmark.c000066400000000000000000000173211317124540100242220ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "liquid.h" #define MODEM_DEMODULATE_BENCH_API(MS) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { modem_demodulate_bench(_start, _finish, _num_iterations, MS); } // Helper function to keep code base small void modem_demodulate_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, modulation_scheme _ms) { // normalize number of iterations switch (_ms) { case LIQUID_MODEM_UNKNOWN: fprintf(stderr,"error: modem_demodulate_bench(), unknown modem scheme\n"); exit(1); case LIQUID_MODEM_BPSK: *_num_iterations *= 2; break; case LIQUID_MODEM_QPSK: *_num_iterations *= 2; break; case LIQUID_MODEM_OOK: *_num_iterations *= 2; break; case LIQUID_MODEM_SQAM32: *_num_iterations /= 10; break; case LIQUID_MODEM_SQAM128: *_num_iterations /= 20; break; case LIQUID_MODEM_V29: *_num_iterations /= 16; break; case LIQUID_MODEM_ARB16OPT: *_num_iterations /= 8; break; case LIQUID_MODEM_ARB32OPT: *_num_iterations /= 16; break; case LIQUID_MODEM_ARB64OPT: *_num_iterations /= 32; break; case LIQUID_MODEM_ARB128OPT: *_num_iterations /= 64; break; case LIQUID_MODEM_ARB256OPT: *_num_iterations /= 128; break; case LIQUID_MODEM_ARB64VT: *_num_iterations /= 64; break; default:; *_num_iterations /= 8; } if (*_num_iterations < 1) *_num_iterations = 1; // initialize modulator modem demod = modem_create(_ms); unsigned long int i; // generate input vector to demodulate (spiral) float complex x[20]; for (i=0; i<20; i++) x[i] = 0.07 * i * cexpf(_Complex_I*2*M_PI*0.1*i); unsigned int symbol_out; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { modem_demodulate(demod, x[ 0], &symbol_out); modem_demodulate(demod, x[ 1], &symbol_out); modem_demodulate(demod, x[ 2], &symbol_out); modem_demodulate(demod, x[ 3], &symbol_out); modem_demodulate(demod, x[ 4], &symbol_out); modem_demodulate(demod, x[ 5], &symbol_out); modem_demodulate(demod, x[ 6], &symbol_out); modem_demodulate(demod, x[ 7], &symbol_out); modem_demodulate(demod, x[ 8], &symbol_out); modem_demodulate(demod, x[ 9], &symbol_out); modem_demodulate(demod, x[10], &symbol_out); modem_demodulate(demod, x[11], &symbol_out); modem_demodulate(demod, x[12], &symbol_out); modem_demodulate(demod, x[13], &symbol_out); modem_demodulate(demod, x[14], &symbol_out); modem_demodulate(demod, x[15], &symbol_out); modem_demodulate(demod, x[16], &symbol_out); modem_demodulate(demod, x[17], &symbol_out); modem_demodulate(demod, x[18], &symbol_out); modem_demodulate(demod, x[19], &symbol_out); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 20; modem_destroy(demod); } // specific modems void benchmark_demodulate_bpsk MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_BPSK) void benchmark_demodulate_qpsk MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_QPSK) void benchmark_demodulate_ook MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_OOK) void benchmark_demodulate_sqam32 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_SQAM32) void benchmark_demodulate_sqam128 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_SQAM128) // ASK void benchmark_demodulate_ask2 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_ASK2) void benchmark_demodulate_ask4 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_ASK4) void benchmark_demodulate_ask8 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_ASK8) void benchmark_demodulate_ask16 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_ASK16) // PSK void benchmark_demodulate_psk2 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_PSK2) void benchmark_demodulate_psk4 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_PSK4) void benchmark_demodulate_psk8 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_PSK8) void benchmark_demodulate_psk16 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_PSK16) void benchmark_demodulate_psk32 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_PSK32) void benchmark_demodulate_psk64 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_PSK64) // Differential PSK void benchmark_demodulate_dpsk2 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_DPSK2) void benchmark_demodulate_dpsk4 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_DPSK4) void benchmark_demodulate_dpsk8 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_DPSK8) void benchmark_demodulate_dpsk16 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_DPSK16) void benchmark_demodulate_dpsk32 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_DPSK32) void benchmark_demodulate_dpsk64 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_DPSK64) // QAM void benchmark_demodulate_qam4 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_QAM4) void benchmark_demodulate_qam8 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_QAM8) void benchmark_demodulate_qam16 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_QAM16) void benchmark_demodulate_qam32 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_QAM32) void benchmark_demodulate_qam64 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_QAM64) void benchmark_demodulate_qam128 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_QAM128) void benchmark_demodulate_qam256 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_QAM256) // APSK void benchmark_demodulate_apsk4 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_APSK4) void benchmark_demodulate_apsk8 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_APSK8) void benchmark_demodulate_apsk16 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_APSK16) void benchmark_demodulate_apsk32 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_APSK32) void benchmark_demodulate_apsk64 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_APSK64) void benchmark_demodulate_apsk128 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_APSK128) void benchmark_demodulate_apsk256 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_APSK256) // ARB void benchmark_demodulate_arbV29 MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_V29) void benchmark_demodulate_arb16opt MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_ARB16OPT) void benchmark_demodulate_arb32opt MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_ARB32OPT) void benchmark_demodulate_arb64opt MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_ARB64OPT) void benchmark_demodulate_arb128opt MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_ARB128OPT) void benchmark_demodulate_arb256opt MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_ARB256OPT) void benchmark_demodulate_arb64vt MODEM_DEMODULATE_BENCH_API(LIQUID_MODEM_ARB64VT) liquid-dsp-1.3.1/src/modem/bench/modem_modulate_benchmark.c000066400000000000000000000150161317124540100237100ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include "liquid.h" #define MODEM_MODULATE_BENCH_API(MS) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { modem_modulate_bench(_start, _finish, _num_iterations, MS); } // Helper function to keep code base small void modem_modulate_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, modulation_scheme _ms) { // normalize number of iterations switch (_ms) { case LIQUID_MODEM_UNKNOWN: fprintf(stderr,"error: modem_modulate_bench(), unknown modem scheme\n"); exit(1); case LIQUID_MODEM_BPSK: *_num_iterations *= 64; break; case LIQUID_MODEM_QPSK: *_num_iterations *= 64; break; case LIQUID_MODEM_OOK: *_num_iterations *= 64; break; case LIQUID_MODEM_SQAM32: *_num_iterations *= 16; break; case LIQUID_MODEM_SQAM128: *_num_iterations *= 16; break; case LIQUID_MODEM_V29: *_num_iterations *= 100; break; case LIQUID_MODEM_ARB16OPT: *_num_iterations *= 100; break; case LIQUID_MODEM_ARB32OPT: *_num_iterations *= 100; break; case LIQUID_MODEM_ARB64OPT: *_num_iterations *= 100; break; case LIQUID_MODEM_ARB128OPT: *_num_iterations *= 100; break; case LIQUID_MODEM_ARB256OPT: *_num_iterations *= 100; break; case LIQUID_MODEM_ARB64VT: *_num_iterations *= 100; break; default:; *_num_iterations *= 32; } if (*_num_iterations < 1) *_num_iterations = 1; // initialize modulator modem mod = modem_create(_ms); float complex x; unsigned int symbol_in = 0; unsigned long int i; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { modem_modulate(mod, symbol_in, &x); modem_modulate(mod, symbol_in, &x); modem_modulate(mod, symbol_in, &x); modem_modulate(mod, symbol_in, &x); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; modem_destroy(mod); } // specific modems void benchmark_modulate_bpsk MODEM_MODULATE_BENCH_API(LIQUID_MODEM_BPSK) void benchmark_modulate_qpsk MODEM_MODULATE_BENCH_API(LIQUID_MODEM_QPSK) void benchmark_modulate_ook MODEM_MODULATE_BENCH_API(LIQUID_MODEM_OOK) void benchmark_modulate_sqam32 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_SQAM32) void benchmark_modulate_sqam128 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_SQAM128) // ASK void benchmark_modulate_ask2 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_ASK2) void benchmark_modulate_ask4 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_ASK4) void benchmark_modulate_ask8 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_ASK8) void benchmark_modulate_ask16 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_ASK16) // PSK void benchmark_modulate_psk2 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_PSK2) void benchmark_modulate_psk4 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_PSK4) void benchmark_modulate_psk8 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_PSK8) void benchmark_modulate_psk16 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_PSK16) void benchmark_modulate_psk32 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_PSK32) void benchmark_modulate_psk64 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_PSK64) // Differential PSK void benchmark_modulate_dpsk2 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_DPSK2) void benchmark_modulate_dpsk4 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_DPSK4) void benchmark_modulate_dpsk8 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_DPSK8) void benchmark_modulate_dpsk16 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_DPSK16) void benchmark_modulate_dpsk32 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_DPSK32) void benchmark_modulate_dpsk64 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_DPSK64) // QAM void benchmark_modulate_qam4 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_QAM4) void benchmark_modulate_qam8 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_QAM8) void benchmark_modulate_qam16 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_QAM16) void benchmark_modulate_qam32 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_QAM32) void benchmark_modulate_qam64 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_QAM64) void benchmark_modulate_qam128 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_QAM128) void benchmark_modulate_qam256 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_QAM256) // APSK void benchmark_modulate_apsk4 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_APSK4) void benchmark_modulate_apsk8 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_APSK8) void benchmark_modulate_apsk16 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_APSK16) void benchmark_modulate_apsk32 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_APSK32) void benchmark_modulate_apsk64 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_APSK64) void benchmark_modulate_apsk128 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_APSK128) void benchmark_modulate_apsk256 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_APSK256) // ARB void benchmark_modulate_arbV29 MODEM_MODULATE_BENCH_API(LIQUID_MODEM_V29) void benchmark_modulate_arb16opt MODEM_MODULATE_BENCH_API(LIQUID_MODEM_ARB16OPT) void benchmark_modulate_arb32opt MODEM_MODULATE_BENCH_API(LIQUID_MODEM_ARB32OPT) void benchmark_modulate_arb64opt MODEM_MODULATE_BENCH_API(LIQUID_MODEM_ARB64OPT) void benchmark_modulate_arb128opt MODEM_MODULATE_BENCH_API(LIQUID_MODEM_ARB128OPT) void benchmark_modulate_arb256opt MODEM_MODULATE_BENCH_API(LIQUID_MODEM_ARB256OPT) void benchmark_modulate_arb64vt MODEM_MODULATE_BENCH_API(LIQUID_MODEM_ARB64VT) liquid-dsp-1.3.1/src/modem/src/000077500000000000000000000000001317124540100162445ustar00rootroot00000000000000liquid-dsp-1.3.1/src/modem/src/ampmodem.c000066400000000000000000000232211317124540100202070ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Amplitude modulator/demodulator // #include #include #include #include "liquid.internal.h" #define DEBUG_AMPMODEM 0 #define DEBUG_AMPMODEM_FILENAME "ampmodem_internal_debug.m" #define DEBUG_AMPMODEM_BUFFER_LEN (400) #if DEBUG_AMPMODEM void ampmodem_debug_print(ampmodem _q, const char * _filename); #endif struct ampmodem_s { float m; // modulation index liquid_ampmodem_type type; // modulation type int suppressed_carrier; // suppressed carrier flag float fc; // carrier frequency // demod objects nco_crcf oscillator; // suppressed carrier // TODO : replace DC bias removal with iir filter object float ssb_alpha; // dc bias removal float ssb_q_hat; // single side-band firhilbf hilbert; // hilbert transform // double side-band // debugging #if DEBUG_AMPMODEM windowcf debug_x; windowf debug_phase_error; windowf debug_freq_error; #endif }; // create ampmodem object // _m : modulation index // _fc : carrier frequency // _type : AM type (e.g. LIQUID_AMPMODEM_DSB) // _suppressed_carrier : carrier suppression flag ampmodem ampmodem_create(float _m, float _fc, liquid_ampmodem_type _type, int _suppressed_carrier) { ampmodem q = (ampmodem) malloc(sizeof(struct ampmodem_s)); q->type = _type; q->m = _m; q->fc = _fc; q->suppressed_carrier = (_suppressed_carrier == 0) ? 0 : 1; // create nco, pll objects q->oscillator = nco_crcf_create(LIQUID_NCO); nco_crcf_set_frequency(q->oscillator, 2*M_PI*q->fc); nco_crcf_pll_set_bandwidth(q->oscillator,0.05f); // suppressed carrier q->ssb_alpha = 0.01f; q->ssb_q_hat = 0.0f; // single side-band q->hilbert = firhilbf_create(9, 60.0f); // double side-band ampmodem_reset(q); // debugging #if DEBUG_AMPMODEM q->debug_x = windowcf_create(DEBUG_AMPMODEM_BUFFER_LEN); q->debug_phase_error = windowf_create(DEBUG_AMPMODEM_BUFFER_LEN); q->debug_freq_error = windowf_create(DEBUG_AMPMODEM_BUFFER_LEN); #endif return q; } void ampmodem_destroy(ampmodem _q) { #if DEBUG_AMPMODEM // export output debugging file ampmodem_debug_print(_q, DEBUG_AMPMODEM_FILENAME); // destroy debugging objects windowcf_destroy(_q->debug_x); windowf_destroy(_q->debug_phase_error); windowf_destroy(_q->debug_freq_error); #endif // destroy nco object nco_crcf_destroy(_q->oscillator); // destroy hilbert transform firhilbf_destroy(_q->hilbert); // free main object memory free(_q); } void ampmodem_print(ampmodem _q) { printf("ampmodem:\n"); printf(" type : "); switch (_q->type) { case LIQUID_AMPMODEM_DSB: printf("double side-band\n"); break; case LIQUID_AMPMODEM_USB: printf("single side-band (upper)\n"); break; case LIQUID_AMPMODEM_LSB: printf("single side-band (lower)\n"); break; default: printf("unknown\n"); } printf(" supp. carrier : %s\n", _q->suppressed_carrier ? "yes" : "no"); printf(" mod. index : %-8.4f\n", _q->m); } void ampmodem_reset(ampmodem _q) { // single side-band _q->ssb_q_hat = 0.5f; } void ampmodem_modulate(ampmodem _q, float _x, float complex *_y) { float complex x_hat = 0.0f; float complex y_hat; if (_q->type == LIQUID_AMPMODEM_DSB) { x_hat = _x; } else { // push through Hilbert transform // LIQUID_AMPMODEM_USB: // LIQUID_AMPMODEM_LSB: conjugate Hilbert transform output firhilbf_r2c_execute(_q->hilbert, _x, &x_hat); if (_q->type == LIQUID_AMPMODEM_LSB) x_hat = conjf(x_hat); } if (_q->suppressed_carrier) y_hat = x_hat; else y_hat = 0.5f*(x_hat + 1.0f); // mix up nco_crcf_mix_up(_q->oscillator, y_hat, _y); nco_crcf_step(_q->oscillator); } // modulate block of samples // _q : ampmodem object // _m : message signal m(t), [size: _n x 1] // _n : number of input, output samples // _s : complex baseband signal s(t) [size: _n x 1] void ampmodem_modulate_block(ampmodem _q, float * _m, unsigned int _n, float complex * _s) { // TODO: implement more efficient method unsigned int i; for (i=0; i<_n; i++) ampmodem_modulate(_q, _m[i], &_s[i]); } void ampmodem_demodulate(ampmodem _q, float complex _y, float *_x) { #if DEBUG_AMPMODEM windowcf_push(_q->debug_x, _y); #endif if (_q->suppressed_carrier) { // single side-band suppressed carrier if (_q->type != LIQUID_AMPMODEM_DSB) { *_x = crealf(_y); return; } // coherent demodulation // mix signal down float complex y_hat; nco_crcf_mix_down(_q->oscillator, _y, &y_hat); // compute phase error float phase_error = tanhf( crealf(y_hat) * cimagf(y_hat) ); #if DEBUG_AMPMODEM // compute frequency error float nco_freq = nco_crcf_get_frequency(_q->oscillator); float freq_error = nco_freq/(2*M_PI) - _q->fc/(2*M_PI); // retain phase and frequency errors windowf_push(_q->debug_phase_error, phase_error); windowf_push(_q->debug_freq_error, freq_error); #endif // adjust nco, pll objects nco_crcf_pll_step(_q->oscillator, phase_error); // step NCO nco_crcf_step(_q->oscillator); // set output *_x = crealf(y_hat); } else { // non-coherent demodulation (peak detector) float t = cabsf(_y); // remove DC bias _q->ssb_q_hat = ( _q->ssb_alpha)*t + (1 - _q->ssb_alpha)*_q->ssb_q_hat; *_x = 2.0f*(t - _q->ssb_q_hat); } } // demodulate block of samples // _q : frequency demodulator object // _r : received signal r(t) [size: _n x 1] // _n : number of input, output samples // _m : message signal m(t), [size: _n x 1] void ampmodem_demodulate_block(ampmodem _q, float complex * _r, unsigned int _n, float * _m) { // TODO: implement more efficient method unsigned int i; for (i=0; i<_n; i++) ampmodem_demodulate(_q, _r[i], &_m[i]); } // export debugging file void ampmodem_debug_print(ampmodem _q, const char * _filename) { FILE * fid = fopen(_filename,"w"); if (!fid) { fprintf(stderr,"error: ofdmframe_debug_print(), could not open '%s' for writing\n", _filename); return; } fprintf(fid,"%% %s : auto-generated file\n", DEBUG_AMPMODEM_FILENAME); #if DEBUG_AMPMODEM fprintf(fid,"close all;\n"); fprintf(fid,"clear all;\n"); fprintf(fid,"n = %u;\n", DEBUG_AMPMODEM_BUFFER_LEN); unsigned int i; float complex * rc; float * r; // plot received signal fprintf(fid,"x = zeros(1,n);\n"); windowcf_read(_q->debug_x, &rc); for (i=0; idebug_phase_error, &r); for (i=0; idebug_freq_error, &r); for (i=0; i #include #include #include "liquid.internal.h" #define DEBUG_CPFSKDEM 0 // // internal methods // // initialize coherent demodulator void cpfskdem_init_coherent(cpfskdem _q); // initialize non-coherent demodulator void cpfskdem_init_noncoherent(cpfskdem _q); #if 0 // demodulate array of samples (coherent) void cpfskdem_demodulate_coherent(cpfskdem _q, float complex _y, unsigned int * _s, unsigned int * _nw); // demodulate array of samples (non-coherent) void cpfskdem_demodulate_noncoherent(cpfskdem _q, float complex _y, unsigned int * _s, unsigned int * _nw); #else // demodulate array of samples (coherent) unsigned int cpfskdem_demodulate_coherent(cpfskdem _q, float complex * _y); // demodulate array of samples (non-coherent) unsigned int cpfskdem_demodulate_noncoherent(cpfskdem _q, float complex * _y); #endif // cpfskdem struct cpfskdem_s { // common unsigned int bps; // bits per symbol unsigned int k; // samples per symbol unsigned int m; // filter delay (symbols) float beta; // filter bandwidth parameter float h; // modulation index int type; // filter type (e.g. LIQUID_CPFSK_GMSK) unsigned int M; // constellation size unsigned int symbol_delay; // receiver filter delay [symbols] // demodulator type enum { CPFSKDEM_COHERENT=0, // coherent demodulator CPFSKDEM_NONCOHERENT // non-coherent demodulator } demod_type; // demodulation function pointer #if 0 void (*demodulate)(cpfskdem _q, float complex _y, unsigned int * _s, unsigned int * _nw); #else unsigned int (*demodulate)(cpfskdem _q, float complex * _y); #endif // common data structure shared between coherent and non-coherent // demodulator receivers union { // coherent demodulator struct { /* nco_crcf nco; // oscillator/phase-locked loop firpfb_crcf mf; // matched filter firpfb_crcf dmf; // matched filter (derivative) */ firfilt_crcf mf; // matched filter } coherent; // non-coherent demodulator struct { firpfb_rrrf mf; // matched filter firpfb_rrrf dmf; // matched filter (derivative) eqlms_rrrf equalizer; } noncoherent; } data; // state variables unsigned int index; // debug unsigned int counter; // sample counter float complex z_prime; // (coherent only) }; // create cpfskdem object (frequency demodulator) // _bps : bits per symbol, _bps > 0 // _h : modulation index, _h > 0 // _k : samples/symbol, _k > 1, _k even // _m : filter delay (symbols), _m > 0 // _beta : filter bandwidth parameter, _beta > 0 // _type : filter type (e.g. LIQUID_CPFSK_SQUARE) cpfskdem cpfskdem_create(unsigned int _bps, float _h, unsigned int _k, unsigned int _m, float _beta, int _type) { // validate input if (_bps == 0) { fprintf(stderr,"error: cpfskdem_create(), bits/symbol must be greater than 0\n"); exit(1); } else if (_k < 2 || (_k%2)) { fprintf(stderr,"error: cpfskmod_create(), samples/symbol must be greater than 2 and even\n"); } else if (_m == 0) { fprintf(stderr,"error: cpfskdem_create(), filter delay must be greater than 0\n"); exit(1); } else if (_beta <= 0.0f || _beta > 1.0f) { fprintf(stderr,"error: cpfskdem_create(), filter roll-off must be in (0,1]\n"); exit(1); } else if (_h <= 0.0f) { fprintf(stderr,"error: cpfskdem_create(), modulation index must be greater than 0\n"); exit(1); } // create main object memory cpfskdem q = (cpfskdem) malloc(sizeof(struct cpfskdem_s)); // set basic internal properties q->bps = _bps; // bits per symbol q->h = _h; // modulation index q->k = _k; // samples per symbol q->m = _m; // filter delay (symbols) q->beta = _beta; // filter roll-off factor (only for certain filters) q->type = _type; // filter type // derived values q->M = 1 << q->bps; // constellation size // coherent or non-coherent? // TODO: allow user to specify if (q->h > 0.66667f) { cpfskdem_init_noncoherent(q); } else { cpfskdem_init_coherent(q); } // reset modem object cpfskdem_reset(q); return q; } // initialize coherent demodulator void cpfskdem_init_coherent(cpfskdem _q) { // specify coherent receiver _q->demod_type = CPFSKDEM_COHERENT; // set demodulate function pointer _q->demodulate = cpfskdem_demodulate_coherent; // create object depending upon input type float bw = 0.0f; float beta = 0.0f; float gmsk_bt = _q->beta; switch(_q->type) { case LIQUID_CPFSK_SQUARE: //bw = 0.9f / (float)k; bw = 0.4f; _q->symbol_delay = _q->m; _q->data.coherent.mf = firfilt_crcf_create_kaiser(2*_q->k*_q->m+1, bw, 60.0f, 0.0f); firfilt_crcf_set_scale(_q->data.coherent.mf, 2.0f * bw); break; case LIQUID_CPFSK_RCOS_FULL: if (_q->M==2) { _q->data.coherent.mf = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,_q->k,_q->m,0.5f,0); firfilt_crcf_set_scale(_q->data.coherent.mf, 1.33f / (float)_q->k); _q->symbol_delay = _q->m; } else { _q->data.coherent.mf = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,_q->k/2,2*_q->m,0.9f,0); firfilt_crcf_set_scale(_q->data.coherent.mf, 3.25f / (float)_q->k); _q->symbol_delay = 0; // TODO: fix this value } break; case LIQUID_CPFSK_RCOS_PARTIAL: if (_q->M==2) { _q->data.coherent.mf = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,_q->k,_q->m,0.3f,0); firfilt_crcf_set_scale(_q->data.coherent.mf, 1.10f / (float)_q->k); _q->symbol_delay = _q->m; } else { _q->data.coherent.mf = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,_q->k/2,2*_q->m,0.27f,0); firfilt_crcf_set_scale(_q->data.coherent.mf, 2.90f / (float)_q->k); _q->symbol_delay = 0; // TODO: fix this value } break; case LIQUID_CPFSK_GMSK: bw = 0.5f / (float)_q->k; // TODO: figure out beta value here beta = (_q->M == 2) ? 0.8*gmsk_bt : 1.0*gmsk_bt; _q->data.coherent.mf = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,_q->k,_q->m,_q->beta,0); firfilt_crcf_set_scale(_q->data.coherent.mf, 2.0f * bw); _q->symbol_delay = _q->m; break; default: fprintf(stderr,"error: cpfskdem_init_coherent(), invalid tx filter type\n"); exit(1); } } // initialize non-coherent demodulator void cpfskdem_init_noncoherent(cpfskdem _q) { // specify non-coherent receiver _q->demod_type = CPFSKDEM_NONCOHERENT; // set demodulate function pointer _q->demodulate = cpfskdem_demodulate_noncoherent; // create object depending upon input type switch(_q->type) { case LIQUID_CPFSK_SQUARE: case LIQUID_CPFSK_RCOS_FULL: case LIQUID_CPFSK_RCOS_PARTIAL: case LIQUID_CPFSK_GMSK: break; } } // destroy modem object void cpfskdem_destroy(cpfskdem _q) { switch(_q->demod_type) { case CPFSKDEM_COHERENT: firfilt_crcf_destroy(_q->data.coherent.mf); break; case CPFSKDEM_NONCOHERENT: break; } // free main object memory free(_q); } // print modulation internals void cpfskdem_print(cpfskdem _q) { printf("cpfskdem:\n"); printf(" k : %u\n", _q->k); } // reset modem object void cpfskdem_reset(cpfskdem _q) { switch(_q->demod_type) { case CPFSKDEM_COHERENT: firfilt_crcf_reset(_q->data.coherent.mf); break; case CPFSKDEM_NONCOHERENT: break; default: break; } _q->index = 0; _q->counter = _q->k-1; _q->z_prime = 0; } // get transmit delay [symbols] unsigned int cpfskdem_get_delay(cpfskdem _q) { return _q->symbol_delay; } #if 0 // demodulate array of samples // _q : continuous-phase frequency demodulator object // _y : input sample array [size: _n x 1] // _n : input sample array length // _s : output symbol array // _nw : number of output symbols written void cpfskdem_demodulate(cpfskdem _q, float complex * _y, unsigned int _n, unsigned int * _s, unsigned int * _nw) { // iterate through each sample calling type-specific demodulation function unsigned int i; unsigned int num_written = 0; for (i=0; i<_n; i++) { unsigned int nw; _q->demodulate(_q, _y[i], &_s[num_written], &nw); // update number of symbols written num_written += nw; } // set output number of bits written *_nw = num_written; } // demodulate array of samples (coherent) void cpfskdem_demodulate_coherent(cpfskdem _q, float complex _y, unsigned int * _s, unsigned int * _nw) { // clear output counter *_nw = 0; // push input sample through filter firfilt_crcf_push(_q->data.coherent.mf, _y); #if DEBUG_CPFSKDEM // compute output sample float complex zp; firfilt_crcf_execute(_q->data.coherent.mf, &zp); printf("y(end+1) = %12.8f + 1i*%12.8f;\n", crealf(_y), cimagf(_y)); printf("z(end+1) = %12.8f + 1i*%12.8f;\n", crealf(zp), cimagf(zp)); #endif // decimate output _q->counter++; if ( (_q->counter % _q->k)==0 ) { // reset sample counter _q->counter = 0; // compute output sample float complex z; firfilt_crcf_execute(_q->data.coherent.mf, &z); // compute instantaneous frequency scaled by modulation index // TODO: pre-compute scaling factor float phi_hat = cargf(conjf(_q->z_prime) * z) / (_q->h * M_PI); // estimate transmitted symbol float v = (phi_hat + (_q->M-1.0))*0.5f; unsigned int sym_out = ((int) roundf(v)) % _q->M; // save current point _q->z_prime = z; #if 1 // print result to screen printf(" %3u : %12.8f + j%12.8f, (%1u)\n", _q->index++, crealf(z), cimagf(z), phi_hat, v, sym_out); #endif // save output *_s = sym_out; *_nw = 1; } } // demodulate array of samples (non-coherent) void cpfskdem_demodulate_noncoherent(cpfskdem _q, float complex _y, unsigned int * _s, unsigned int * _nw) { *_nw = 0; } #else // demodulate array of samples // _q : continuous-phase frequency demodulator object // _y : input sample array [size: _k x 1] unsigned int cpfskdem_demodulate(cpfskdem _q, float complex * _y) { return _q->demodulate(_q, _y); } // demodulate array of samples (coherent) unsigned int cpfskdem_demodulate_coherent(cpfskdem _q, float complex * _y) { unsigned int i; unsigned int sym_out = 0; for (i=0; i<_q->k; i++) { // push input sample through filter firfilt_crcf_push(_q->data.coherent.mf, _y[i]); #if DEBUG_CPFSKDEM // compute output sample float complex zp; firfilt_crcf_execute(_q->data.coherent.mf, &zp); printf("y(end+1) = %12.8f + 1i*%12.8f;\n", crealf(_y), cimagf(_y)); printf("z(end+1) = %12.8f + 1i*%12.8f;\n", crealf(zp), cimagf(zp)); #endif // decimate output if ( i == 0 ) { // compute output sample float complex z; firfilt_crcf_execute(_q->data.coherent.mf, &z); // compute instantaneous frequency scaled by modulation index // TODO: pre-compute scaling factor float phi_hat = cargf(conjf(_q->z_prime) * z) / (_q->h * M_PI); // estimate transmitted symbol float v = (phi_hat + (_q->M-1.0))*0.5f; sym_out = ((int) roundf(v)) % _q->M; // save current point _q->z_prime = z; #if DEBUG_CPFSKDEM // print result to screen printf(" %3u : %12.8f + j%12.8f, (%1u)\n", _q->index++, crealf(z), cimagf(z), phi_hat, v, sym_out); #endif } } return sym_out; } // demodulate array of samples (non-coherent) unsigned int cpfskdem_demodulate_noncoherent(cpfskdem _q, float complex * _y) { return 0; } #endif liquid-dsp-1.3.1/src/modem/src/cpfskmod.c000066400000000000000000000241431317124540100202220ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // continuous phase frequency-shift keying modulator // #include #include #include #include "liquid.internal.h" // // internal methods // // design transmit filter void cpfskmod_firdes(unsigned int _k, unsigned int _m, float _beta, int _type, float * _h, unsigned int _h_len); // cpfskmod struct cpfskmod_s { // common unsigned int bps; // bits per symbol unsigned int k; // samples per symbol unsigned int m; // filter delay (symbols) float beta; // filter bandwidth parameter float h; // modulation index int type; // filter type (e.g. LIQUID_CPFSK_SQUARE) unsigned int M; // constellation size unsigned int symbol_delay; // transmit filter delay [symbols] // pulse-shaping filter float * ht; // filter coefficients unsigned int ht_len; // filter length firinterp_rrrf interp; // interpolator // phase integrator float * phase_interp; // phase interpolation buffer iirfilt_rrrf integrator; // integrator }; // create cpfskmod object (frequency modulator) // _bps : bits per symbol, _bps > 0 // _h : modulation index, _h > 0 // _k : samples/symbol, _k > 1, _k even // _m : filter delay (symbols), _m > 0 // _beta : filter bandwidth parameter, _beta > 0 // _type : filter type (e.g. LIQUID_CPFSK_SQUARE) cpfskmod cpfskmod_create(unsigned int _bps, float _h, unsigned int _k, unsigned int _m, float _beta, int _type) { // validate input if (_bps == 0) { fprintf(stderr,"error: cpfskmod_create(), bits/symbol must be greater than 0\n"); exit(1); } else if (_k < 2 || (_k%2)) { fprintf(stderr,"error: cpfskmod_create(), samples/symbol must be greater than 2 and even\n"); exit(1); } else if (_m == 0) { fprintf(stderr,"error: cpfskmod_create(), filter delay must be greater than 0\n"); exit(1); } else if (_beta <= 0.0f || _beta > 1.0f) { fprintf(stderr,"error: cpfskmod_create(), filter roll-off must be in (0,1]\n"); exit(1); } else if (_h <= 0.0f) { fprintf(stderr,"error: cpfskmod_create(), modulation index must be greater than 0\n"); exit(1); } // create main object memory cpfskmod q = (cpfskmod) malloc(sizeof(struct cpfskmod_s)); // set basic internal properties q->bps = _bps; // bits per symbol q->h = _h; // modulation index q->k = _k; // samples per symbol q->m = _m; // filter delay (symbols) q->beta = _beta; // filter roll-off factor (only for certain filters) q->type = _type; // filter type // derived values q->M = 1 << q->bps; // constellation size // create object depending upon input type float b[2] = {0.5f, 0.5f}; // integrator feed-forward coefficients float a[2] = {1.0f, -1.0f}; // integrator feed-back coefficients q->ht_len = 0; q->ht = NULL; unsigned int i; switch(q->type) { case LIQUID_CPFSK_SQUARE: q->ht_len = q->k; q->symbol_delay = 1; // modify integrator b[0] = 0.0f; b[1] = 1.0f; break; case LIQUID_CPFSK_RCOS_FULL: q->ht_len = q->k; q->symbol_delay = 1; break; case LIQUID_CPFSK_RCOS_PARTIAL: // TODO: adjust reponse based on 'm' q->ht_len = 3*q->k; q->symbol_delay = 2; break; case LIQUID_CPFSK_GMSK: q->symbol_delay = q->m + 1; q->ht_len = 2*(q->k)*(q->m) + (q->k) + 1; break; default: fprintf(stderr,"error: cpfskmodem_create(), invalid filter type '%d'\n", q->type); exit(1); } // create pulse-shaping filter and scale by modulation index q->ht = (float*) malloc(q->ht_len *sizeof(float)); cpfskmod_firdes(q->k, q->m, q->beta, q->type, q->ht, q->ht_len); for (i=0; iht_len; i++) q->ht[i] *= M_PI * q->h; q->interp = firinterp_rrrf_create(q->k, q->ht, q->ht_len); // create phase integrator q->phase_interp = (float*) malloc(q->k*sizeof(float)); q->integrator = iirfilt_rrrf_create(b,2,a,2); // reset modem object cpfskmod_reset(q); return q; } // destroy cpfskmod object void cpfskmod_destroy(cpfskmod _q) { // destroy pulse-shaping filter/interpolator free(_q->ht); free(_q->phase_interp); firinterp_rrrf_destroy(_q->interp); // destroy phase integrator iirfilt_rrrf_destroy(_q->integrator); // free main object memory free(_q); } // print cpfskmod object internals void cpfskmod_print(cpfskmod _q) { printf("cpfskmod : continuous-phase frequency-shift keying modem\n"); printf(" bits/symbol : %u\n", _q->bps); printf(" modulation index: %-6.3f\n", _q->h); printf(" samples/symbol : %u\n", _q->k); printf(" filter delay : %u symbols\n", _q->m); printf(" filter roll-off : %-6.3f\n", _q->beta); printf(" filter type : "); switch(_q->type) { case LIQUID_CPFSK_SQUARE: printf("square\n"); break; case LIQUID_CPFSK_RCOS_FULL: printf("rcos (full)\n"); break; case LIQUID_CPFSK_RCOS_PARTIAL: printf("rcos (partial)\n"); break; case LIQUID_CPFSK_GMSK: printf("gmsk\n"); break; default: printf("unknown\n"); break; } printf(" filter :\n"); // print filter coefficients unsigned int i; for (i=0; i<_q->ht_len; i++) printf(" h(%3u) = %12.8f;\n", i+1, _q->ht[i]); } // reset state void cpfskmod_reset(cpfskmod _q) { // reset interpolator firinterp_rrrf_reset(_q->interp); // reset phase integrator iirfilt_rrrf_reset(_q->integrator); } // get transmit delay [symbols] unsigned int cpfskmod_get_delay(cpfskmod _q) { return _q->symbol_delay; } // modulate sample // _q : frequency modulator object // _s : input symbol // _y : output sample array [size: _k x 1] void cpfskmod_modulate(cpfskmod _q, unsigned int _s, float complex * _y) { // run interpolator float v = 2.0f*_s - (float)(_q->M) + 1.0f; firinterp_rrrf_execute(_q->interp, v, _q->phase_interp); // integrate phase state unsigned int i; float theta; for (i=0; i<_q->k; i++) { // push phase through integrator iirfilt_rrrf_execute(_q->integrator, _q->phase_interp[i], &theta); // compute output _y[i] = liquid_cexpjf(theta); } } // // internal methods // // design transmit filter void cpfskmod_firdes(unsigned int _k, unsigned int _m, float _beta, int _type, float * _ht, unsigned int _ht_len) { unsigned int i; // create filter based on specified type switch(_type) { case LIQUID_CPFSK_SQUARE: // square pulse if (_ht_len != _k) { fprintf(stderr,"error: cpfskmodem_firdes(), invalid filter length (square)\n"); exit(1); } for (i=0; i<_ht_len; i++) _ht[i] = 1.0f; break; case LIQUID_CPFSK_RCOS_FULL: // full-response raised-cosine pulse if (_ht_len != _k) { fprintf(stderr,"error: cpfskmodem_firdes(), invalid filter length (rcos)\n"); exit(1); } for (i=0; i<_ht_len; i++) _ht[i] = 1.0f - cosf(2.0f*M_PI*i/(float)_ht_len); break; case LIQUID_CPFSK_RCOS_PARTIAL: // full-response raised-cosine pulse if (_ht_len != 3*_k) { fprintf(stderr,"error: cpfskmodem_firdes(), invalid filter length (rcos)\n"); exit(1); } // initialize with zeros for (i=0; i<_ht_len; i++) _ht[i] = 0.0f; // adding raised-cosine pulse with half-symbol delay for (i=0; i<2*_k; i++) _ht[i+_k/2] = 1.0f - cosf(2.0f*M_PI*i/(float)(2*_k)); break; case LIQUID_CPFSK_GMSK: // Gauss minimum-shift keying pulse if (_ht_len != 2*_k*_m + _k + 1) { fprintf(stderr,"error: cpfskmodem_firdes(), invalid filter length (gmsk)\n"); exit(1); } // initialize with zeros for (i=0; i<_ht_len; i++) _ht[i] = 0.0f; // adding Gauss pulse with half-symbol delay liquid_firdes_gmsktx(_k,_m,_beta,0.0f,&_ht[_k/2]); break; default: fprintf(stderr,"error: cpfskmodem_firdes(), invalid filter type '%d'\n", _type); exit(1); } // normalize pulse area to unity float ht_sum = 0.0f; for (i=0; i<_ht_len; i++) ht_sum += _ht[i]; for (i=0; i<_ht_len; i++) _ht[i] *= 1.0f / ht_sum; } liquid-dsp-1.3.1/src/modem/src/freqdem.c000066400000000000000000000064561317124540100200460ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Frequency demodulator // #include #include #include #include "liquid.internal.h" // freqdem struct FREQDEM(_s) { // common float kf; // modulation index T ref; // 1/(2*pi*kf) TC r_prime; // previous received sample }; // create freqdem object // _kf : modulation factor FREQDEM() FREQDEM(_create)(float _kf) { // validate input if (_kf <= 0.0f || _kf > 1.0) { fprintf(stderr,"error: freqdem_create(), modulation factor %12.4e out of range [0,1]\n", _kf); exit(1); } // create main object memory FREQDEM() q = (freqdem) malloc(sizeof(struct FREQDEM(_s))); // set internal modulation factor q->kf = _kf; // compute derived values q->ref = 1.0f / (2*M_PI*q->kf); // reset modem object FREQDEM(_reset)(q); // return object return q; } // destroy modem object void FREQDEM(_destroy)(FREQDEM() _q) { // free main object memory free(_q); } // print modulation internals void FREQDEM(_print)(FREQDEM() _q) { printf("freqdem:\n"); printf(" mod. factor : %8.4f\n", _q->kf); } // reset modem object void FREQDEM(_reset)(FREQDEM() _q) { // clear complex phase term _q->r_prime = 0; } // demodulate sample // _q : FM demodulator object // _r : received signal // _m : output message signal void FREQDEM(_demodulate)(FREQDEM() _q, TC _r, T * _m) { // compute phase difference and normalize by modulation index *_m = cargf( conjf(_q->r_prime)*_r ) * _q->ref; // save previous input sample _q->r_prime = _r; } // demodulate block of samples // _q : frequency demodulator object // _r : received signal r(t) [size: _n x 1] // _n : number of input, output samples // _m : message signal m(t), [size: _n x 1] void FREQDEM(_demodulate_block)(FREQDEM() _q, TC * _r, unsigned int _n, T * _m) { // TODO: implement more efficient method unsigned int i; for (i=0; i<_n; i++) FREQDEM(_demodulate)(_q, _r[i], &_m[i]); } liquid-dsp-1.3.1/src/modem/src/freqmod.c000066400000000000000000000104321317124540100200450ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Frequency modulator // #include #include #include #include #include "liquid.internal.h" // freqmod struct FREQMOD(_s) { float kf; // modulation factor for FM T ref; // phase reference: kf*2^16 // look-up table unsigned int sincos_table_len; // table length: 10 bits uint16_t sincos_table_phase; // accumulated phase: 16 bits TC * sincos_table; // sin|cos look-up table: 2^10 entries }; // create freqmod object // _kf : modulation factor FREQMOD() FREQMOD(_create)(float _kf) { // validate input if (_kf <= 0.0f || _kf > 1.0) { fprintf(stderr,"error: freqmod_create(), modulation factor %12.4e out of range [0,1]\n", _kf); exit(1); } // create main object memory FREQMOD() q = (freqmod) malloc(sizeof(struct FREQMOD(_s))); // set modulation factor q->kf = _kf; q->ref = q->kf * (1<<16); // initialize look-up table q->sincos_table_len = 1024; q->sincos_table = (TC*) malloc( q->sincos_table_len*sizeof(TC) ); unsigned int i; for (i=0; isincos_table_len; i++) { q->sincos_table[i] = cexpf(_Complex_I*2*M_PI*(float)i / (float)(q->sincos_table_len) ); } // reset modem object FREQMOD(_reset)(q); // return object return q; } // destroy modem object void FREQMOD(_destroy)(FREQMOD() _q) { // free table free(_q->sincos_table); // free main object memory free(_q); } // print modulation internals void FREQMOD(_print)(FREQMOD() _q) { printf("freqmod:\n"); printf(" mod. factor : %8.4f\n", _q->kf); printf(" sincos table len : %u\n", _q->sincos_table_len); } // reset modem object void FREQMOD(_reset)(FREQMOD() _q) { // reset phase accumulation _q->sincos_table_phase = 0; } // modulate sample // _q : frequency modulator object // _m : message signal m(t) // _s : complex baseband signal s(t) void FREQMOD(_modulate)(FREQMOD() _q, T _m, TC * _s) { // accumulate phase; this wraps around a 16-bit boundary and ensures // that negative numbers are mapped to positive numbers _q->sincos_table_phase = (_q->sincos_table_phase + (1<<16) + (int)roundf(_q->ref*_m)) & 0xffff; // compute table index: mask out 10 most significant bits with rounding // (adding 0x0020 effectively rounds to nearest value with 10 bits of // precision) unsigned int index = ( (_q->sincos_table_phase+0x0020) >> 6) & 0x03ff; // return table value at index *_s = _q->sincos_table[index]; } // modulate block of samples // _q : frequency modulator object // _m : message signal m(t), [size: _n x 1] // _n : number of input, output samples // _s : complex baseband signal s(t) [size: _n x 1] void FREQMOD(_modulate_block)(FREQMOD() _q, T * _m, unsigned int _n, TC * _s) { // TODO: implement more efficient method unsigned int i; for (i=0; i<_n; i++) FREQMOD(_modulate)(_q, _m[i], &_s[i]); } liquid-dsp-1.3.1/src/modem/src/fskdem.c000066400000000000000000000171311317124540100176640ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // M-ary frequency-shift keying demodulator // #include #include #include #include #include "liquid.internal.h" #define DEBUG_FSKDEM 0 // // internal methods // // fskdem struct fskdem_s { // common unsigned int m; // bits per symbol unsigned int k; // samples per symbol float bandwidth; // filter bandwidth parameter // derived values unsigned int M; // constellation size float M2; // (M-1)/2 unsigned int K; // FFT size float complex * buf_time; // FFT input buffer float complex * buf_freq; // FFT output buffer FFT_PLAN fft; // FFT object unsigned int * demod_map; // demodulation map // state variables unsigned int s_demod; // demodulated symbol (used for frequency error) }; // create fskdem object (frequency demodulator) // _m : bits per symbol, _m > 0 // _k : samples/symbol, _k >= 2^_m // _bandwidth : total signal bandwidth, (0,0.5) fskdem fskdem_create(unsigned int _m, unsigned int _k, float _bandwidth) { // validate input if (_m == 0) { fprintf(stderr,"error: fskdem_create(), bits/symbol must be greater than 0\n"); exit(1); } else if (_k < 2 || _k > 2048) { fprintf(stderr,"error: fskdem_create(), samples/symbol must be in [2^_m, 2048]\n"); exit(1); } else if (_bandwidth <= 0.0f || _bandwidth >= 0.5f) { fprintf(stderr,"error: fskdem_create(), bandwidth must be in (0,0.5)\n"); exit(1); } // create main object memory fskdem q = (fskdem) malloc(sizeof(struct fskdem_s)); // set basic internal properties q->m = _m; // bits per symbol q->k = _k; // samples per symbol q->bandwidth = _bandwidth; // signal bandwidth // derived values q->M = 1 << q->m; // constellation size q->M2 = 0.5f*(float)(q->M-1); // (M-1)/2 // compute demodulation FFT size such that FFT output bin frequencies are // as close to modulated frequencies as possible float df = q->bandwidth / q->M2; // frequency spacing float err_min = 1e9f; // minimum error value unsigned int K_min = q->k; // minimum FFT size unsigned int K_max = q->k*4 < 16 ? 16 : q->k*4; // maximum FFT size unsigned int K_hat; for (K_hat=K_min; K_hat<=K_max; K_hat++) { // compute candidate FFT size float v = 0.5f*df*(float)K_hat; // bin spacing float err = fabsf( roundf(v) - v ); // fractional bin spacing #if DEBUG_FSKDEM // print results printf(" K_hat = %4u : v = %12.8f, err=%12.8f %s\n", K_hat, v, err, err < err_min ? "*" : ""); #endif // save best result if (K_hat==K_min || err < err_min) { q->K = K_hat; err_min = err; } // perfect match; no need to continue searching if (err < 1e-6f) break; } // determine demodulation mapping between tones and frequency bins // TODO: use gray coding q->demod_map = (unsigned int *) malloc(q->M * sizeof(unsigned int)); unsigned int i; for (i=0; iM; i++) { // print frequency bins float freq = ((float)i - q->M2) * q->bandwidth / q->M2; float idx = freq * (float)(q->K); unsigned int index = (unsigned int) (idx < 0 ? roundf(idx + q->K) : roundf(idx)); q->demod_map[i] = index; #if DEBUG_FSKDEM printf(" s=%3u, f = %12.8f, index=%3u\n", i, freq, index); #endif } // check for uniqueness for (i=1; iM; i++) { if (q->demod_map[i] == q->demod_map[i-1]) { fprintf(stderr,"warning: fskdem_create(), demod map is not unique; consider increasing bandwidth\n"); break; } } // allocate memory for transform q->buf_time = (float complex*) malloc(q->K * sizeof(float complex)); q->buf_freq = (float complex*) malloc(q->K * sizeof(float complex)); q->fft = FFT_CREATE_PLAN(q->K, q->buf_time, q->buf_freq, FFT_DIR_FORWARD, 0); // reset modem object fskdem_reset(q); // return main object return q; } // destroy fskdem object void fskdem_destroy(fskdem _q) { // free allocated arrays free(_q->demod_map); free(_q->buf_time); free(_q->buf_freq); FFT_DESTROY_PLAN(_q->fft); // free main object memory free(_q); } // print fskdem object internals void fskdem_print(fskdem _q) { printf("fskdem : frequency-shift keying demodulator\n"); printf(" bits/symbol : %u\n", _q->m); printf(" samples/symbol : %u\n", _q->k); printf(" bandwidth : %8.5f\n", _q->bandwidth); } // reset state void fskdem_reset(fskdem _q) { // reset time and frequency buffers unsigned int i; for (i=0; i<_q->K; i++) { _q->buf_time[i] = 0.0f; _q->buf_freq[i] = 0.0f; } // clear state variables _q->s_demod = 0; } // demodulate symbol, assuming perfect symbol timing // _q : fskdem object // _y : input sample array [size: _k x 1] unsigned int fskdem_demodulate(fskdem _q, float complex * _y) { // copy input to internal time buffer memmove(_q->buf_time, _y, _q->k*sizeof(float complex)); // compute transform, storing result in 'buf_freq' FFT_EXECUTE(_q->fft); // find maximum by looking at particular bins float vmax = 0; unsigned int s = 0; // run search for (s=0; s<_q->M; s++) { float v = cabsf( _q->buf_freq[_q->demod_map[s]] ); if (s==0 || v > vmax) { // save optimal output symbol _q->s_demod = s; // save peak FFT bin value vmax = v; } } // save best result return _q->s_demod; } // get demodulator frequency error float fskdem_get_frequency_error(fskdem _q) { // get index of peak bin //unsigned int index = _q->buf_freq[ _q->s_demod ]; // extract peak value of previous, post FFT index float vm = cabsf(_q->buf_freq[(_q->s_demod+_q->K-1)%_q->K]); // previous float v0 = cabsf(_q->buf_freq[ _q->s_demod ]); // peak float vp = cabsf(_q->buf_freq[(_q->s_demod+ 1)%_q->K]); // post // compute derivative // TODO: compensate for bin spacing // TODO: just find peak using polynomial interpolation return (vp - vm) / v0; } liquid-dsp-1.3.1/src/modem/src/fskmod.c000066400000000000000000000105611317124540100176760ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // M-ary frequency-shift keying modulator // #include #include #include #include "liquid.internal.h" // // internal methods // // fskmod struct fskmod_s { // common unsigned int m; // bits per symbol unsigned int k; // samples per symbol float bandwidth; // filter bandwidth parameter unsigned int M; // constellation size float M2; // (M-1)/2 nco_crcf oscillator; // nco }; // create fskmod object (frequency modulator) // _m : bits per symbol, _m > 0 // _k : samples/symbol, _k >= 2^_m // _bandwidth : total signal bandwidth, (0,0.5) fskmod fskmod_create(unsigned int _m, unsigned int _k, float _bandwidth) { // validate input if (_m == 0) { fprintf(stderr,"error: fskmod_create(), bits/symbol must be greater than 0\n"); exit(1); } else if (_k < 2 || _k > 2048) { fprintf(stderr,"error: fskmod_create(), samples/symbol must be in [2^_m, 2048]\n"); exit(1); } else if (_bandwidth <= 0.0f || _bandwidth >= 0.5f) { fprintf(stderr,"error: fskmod_create(), bandwidth must be in (0,0.5)\n"); exit(1); } // create main object memory fskmod q = (fskmod) malloc(sizeof(struct fskmod_s)); // set basic internal properties q->m = _m; // bits per symbol q->k = _k; // samples per symbol q->bandwidth = _bandwidth; // signal bandwidth // derived values q->M = 1 << q->m; // constellation size q->M2 = 0.5f*(float)(q->M-1); // (M-1)/2 q->oscillator = nco_crcf_create(LIQUID_VCO); // reset modem object fskmod_reset(q); // return main object return q; } // destroy fskmod object void fskmod_destroy(fskmod _q) { // destroy oscillator object nco_crcf_destroy(_q->oscillator); // free main object memory free(_q); } // print fskmod object internals void fskmod_print(fskmod _q) { printf("fskmod : frequency-shift keying modulator\n"); printf(" bits/symbol : %u\n", _q->m); printf(" samples/symbol : %u\n", _q->k); printf(" bandwidth : %8.5f\n", _q->bandwidth); } // reset state void fskmod_reset(fskmod _q) { // reset internal objects nco_crcf_reset(_q->oscillator); } // modulate sample // _q : frequency modulator object // _s : input symbol // _y : output sample array [size: _k x 1] void fskmod_modulate(fskmod _q, unsigned int _s, float complex * _y) { // validate input if (_s >= _q->M) { fprintf(stderr,"warning: fskmod_modulate(), input symbol (%u) exceeds maximum (%u)\n", _s, _q->M); _s = 0; } // compute appropriate frequency float dphi = ((float)_s - _q->M2) * 2 * M_PI * _q->bandwidth / _q->M2; // set frequency appropriately nco_crcf_set_frequency(_q->oscillator, dphi); // generate output tone unsigned int i; for (i=0; i<_q->k; i++) { // compute complex output nco_crcf_cexpf(_q->oscillator, &_y[i]); // step oscillator nco_crcf_step(_q->oscillator); } } liquid-dsp-1.3.1/src/modem/src/gmskdem.c000066400000000000000000000221471317124540100200450ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // gmskdem.c : Gauss minimum-shift keying modem // #include #include #include #include #include "liquid.internal.h" #define DEBUG_GMSKDEM 0 #define DEBUG_GMSKDEM_FILENAME "gmskdem_internal_debug.m" #define DEBUG_BUFFER_LEN (1000) #define GMSKDEM_USE_EQUALIZER 1 void gmskdem_debug_print(gmskdem _q, const char * _filename); struct gmskdem_s { unsigned int k; // samples/symbol unsigned int m; // symbol delay float BT; // bandwidth/time product unsigned int h_len; // filter length float * h; // pulse shaping filter // filter object #if GMSKDEM_USE_EQUALIZER eqlms_rrrf eq; // receiver matched filter/equalizer float k_inv; // 1 / k #else firfilt_rrrf filter; // receiver matched filter #endif float complex x_prime; // received signal state // demodulated symbols counter unsigned int num_symbols_demod; #if DEBUG_GMSKDEM windowf debug_mfout; #endif }; // create gmskdem object // _k : samples/symbol // _m : filter delay (symbols) // _BT : excess bandwidth factor gmskdem gmskdem_create(unsigned int _k, unsigned int _m, float _BT) { if (_k < 2) { fprintf(stderr,"error: gmskdem_create(), samples/symbol must be at least 2\n"); exit(1); } else if (_m < 1) { fprintf(stderr,"error: gmskdem_create(), symbol delay must be at least 1\n"); exit(1); } else if (_BT <= 0.0f || _BT >= 1.0f) { fprintf(stderr,"error: gmskdem_create(), bandwidth/time product must be in (0,1)\n"); exit(1); } // allocate memory for main object gmskdem q = (gmskdem)malloc(sizeof(struct gmskdem_s)); // set properties q->k = _k; q->m = _m; q->BT = _BT; // allocate memory for filter taps q->h_len = 2*(q->k)*(q->m)+1; q->h = (float*) malloc(q->h_len * sizeof(float)); // compute filter coefficients liquid_firdes_gmskrx(q->k, q->m, q->BT, 0.0f, q->h); #if GMSKDEM_USE_EQUALIZER // receiver matched filter/equalizer q->eq = eqlms_rrrf_create_rnyquist(LIQUID_FIRFILT_GMSKRX, q->k, q->m, q->BT, 0.0f); eqlms_rrrf_set_bw(q->eq, 0.01f); q->k_inv = 1.0f / (float)(q->k); #else // create filter object q->filter = firfilt_rrrf_create(q->h, q->h_len); #endif // reset modem state gmskdem_reset(q); #if DEBUG_GMSKDEM q->debug_mfout = windowf_create(DEBUG_BUFFER_LEN); #endif // return modem object return q; } void gmskdem_destroy(gmskdem _q) { #if DEBUG_GMSKDEM // print to external file gmskdem_debug_print(_q, DEBUG_GMSKDEM_FILENAME); // destroy debugging objects windowf_destroy(_q->debug_mfout); #endif // destroy filter object #if GMSKDEM_USE_EQUALIZER eqlms_rrrf_destroy(_q->eq); #else firfilt_rrrf_destroy(_q->filter); #endif // free filter array free(_q->h); // free main object memory free(_q); } void gmskdem_print(gmskdem _q) { printf("gmskdem [k=%u, m=%u, BT=%8.3f]\n", _q->k, _q->m, _q->BT); #if GMSKDEM_USE_EQUALIZER printf(" equalizer bandwidth : %12.8f\n", eqlms_rrrf_get_bw(_q->eq)); #endif unsigned int i; for (i=0; i<_q->h_len; i++) printf(" hr(%4u) = %12.8f;\n", i+1, _q->h[i]); } void gmskdem_reset(gmskdem _q) { // reset phase state _q->x_prime = 0.0f; // set demod. counter to zero _q->num_symbols_demod = 0; // clear filter buffer #if GMSKDEM_USE_EQUALIZER eqlms_rrrf_reset(_q->eq); #else firfilt_rrrf_reset(_q->filter); #endif } // set equalizer bandwidth void gmskdem_set_eq_bw(gmskdem _q, float _bw) { // validate input if (_bw < 0.0f || _bw > 0.5f) { fprintf(stderr,"error: gmskdem_set_eq_bw(), bandwith must be in [0,0.5]\n"); exit(1); } #if GMSKDEM_USE_EQUALIZER // set internal equalizer bandwidth eqlms_rrrf_set_bw(_q->eq, _bw); #else fprintf(stderr,"warning: gmskdem_set_eq_bw(), equalizer is disabled\n"); #endif } void gmskdem_demodulate(gmskdem _q, float complex * _x, unsigned int * _s) { // increment symbol counter _q->num_symbols_demod++; // run matched filter unsigned int i; float phi; float d_hat; for (i=0; i<_q->k; i++) { // compute phase difference phi = cargf( conjf(_q->x_prime)*_x[i] ); _q->x_prime = _x[i]; // run through matched filter #if GMSKDEM_USE_EQUALIZER eqlms_rrrf_push(_q->eq, phi); #else firfilt_rrrf_push(_q->filter, phi); #endif #if DEBUG_GMSKDEM // compute output float d_tmp; # if GMSKDEM_USE_EQUALIZER eqlms_rrrf_execute(_q->eq, &d_tmp); # else firfilt_rrrf_execute(_q->filter, &d_tmp); # endif windowf_push(_q->debug_mfout, d_tmp); #endif // decimate by k if ( i != 0 ) continue; #if GMSKDEM_USE_EQUALIZER // compute filter/equalizer output eqlms_rrrf_execute(_q->eq, &d_hat); #else // compute filter output firfilt_rrrf_execute(_q->filter, &d_hat); #endif } // make decision *_s = d_hat > 0.0f ? 1 : 0; #if GMSKDEM_USE_EQUALIZER // update equalizer, after appropriate delay if (_q->num_symbols_demod >= 2*_q->m) { // compute expected output, scaling by samples/symbol float d_prime = d_hat > 0 ? _q->k_inv : -_q->k_inv; eqlms_rrrf_step(_q->eq, d_prime, d_hat); } #endif } // // output debugging file // void gmskdem_debug_print(gmskdem _q, const char * _filename) { // open output filen for writing FILE * fid = fopen(_filename,"w"); if (!fid) { fprintf(stderr,"error: gmskdem_debug_print(), could not open '%s' for writing\n", _filename); exit(1); } fprintf(fid,"%% %s : auto-generated file\n", _filename); fprintf(fid,"clear all\n"); fprintf(fid,"close all\n"); #if DEBUG_GMSKDEM // unsigned int i; float * r; fprintf(fid,"n = %u;\n", DEBUG_BUFFER_LEN); fprintf(fid,"k = %u;\n", _q->k); fprintf(fid,"m = %u;\n", _q->m); fprintf(fid,"t = [0:(n-1)]/k;\n"); // plot receive filter response fprintf(fid,"ht = zeros(1,2*k*m+1);\n"); float ht[_q->h_len]; liquid_firdes_gmsktx(_q->k, _q->m, _q->BT, 0.0f, ht); for (i=0; i<_q->h_len; i++) fprintf(fid,"ht(%4u) = %12.4e;\n", i+1, ht[i]); #if GMSKDEM_USE_EQUALIZER float hr[_q->h_len]; eqlms_rrrf_get_weights(_q->eq, hr); for (i=0; i<_q->h_len; i++) fprintf(fid,"hr(%4u) = %12.4e * %u;\n", i+1, hr[i], _q->k); #else for (i=0; i<_q->h_len; i++) fprintf(fid,"hr(%4u) = %12.4e;\n", i+1, _q->h[i]); #endif fprintf(fid,"hc = conv(ht,hr)/k;\n"); fprintf(fid,"nfft = 1024;\n"); fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n"); fprintf(fid,"Ht = 20*log10(abs(fftshift(fft(ht/k, nfft))));\n"); fprintf(fid,"Hr = 20*log10(abs(fftshift(fft(hr/k, nfft))));\n"); fprintf(fid,"Hc = 20*log10(abs(fftshift(fft(hc/k, nfft))));\n"); fprintf(fid,"figure;\n"); fprintf(fid,"plot(f,Ht, f,Hr, f,Hc,'-k','LineWidth',2);\n"); fprintf(fid,"axis([-0.5 0.5 -50 10]);\n"); fprintf(fid,"xlabel('Normalized Frequency');\n"); fprintf(fid,"ylabel('Power Spectral Density [dB]');\n"); fprintf(fid,"legend('transmit','receive','composite',1);\n"); fprintf(fid,"grid on;\n"); fprintf(fid,"mfout = zeros(1,n);\n"); windowf_read(_q->debug_mfout, &r); for (i=0; i #include #include #include #include "liquid.internal.h" struct gmskmod_s { unsigned int k; // samples/symbol unsigned int m; // symbol delay float BT; // bandwidth/time product unsigned int h_len; // filter length float * h; // pulse shaping filter // interpolator firinterp_rrrf interp_tx; float theta; // phase state float k_inv; // 1/k }; // create gmskmod object // _k : samples/symbol // _m : filter delay (symbols) // _BT : excess bandwidth factor gmskmod gmskmod_create(unsigned int _k, unsigned int _m, float _BT) { if (_k < 2) { fprintf(stderr,"error: gmskmod_create(), samples/symbol must be at least 2\n"); exit(1); } else if (_m < 1) { fprintf(stderr,"error: gmskmod_create(), symbol delay must be at least 1\n"); exit(1); } else if (_BT <= 0.0f || _BT >= 1.0f) { fprintf(stderr,"error: gmskmod_create(), bandwidth/time product must be in (0,1)\n"); exit(1); } gmskmod q = (gmskmod)malloc(sizeof(struct gmskmod_s)); // set properties q->k = _k; q->m = _m; q->BT = _BT; // derived values q->k_inv = 1.0f / (float)(q->k); // allocate memory for filter taps q->h_len = 2*(q->k)*(q->m)+1; q->h = (float*) malloc(q->h_len * sizeof(float)); // compute filter coefficients liquid_firdes_gmsktx(q->k, q->m, q->BT, 0.0f, q->h); // create interpolator object q->interp_tx = firinterp_rrrf_create_prototype(LIQUID_FIRFILT_GMSKTX, q->k, q->m, q->BT, 0); // reset modem state gmskmod_reset(q); // return modem object return q; } void gmskmod_destroy(gmskmod _q) { // destroy interpolator firinterp_rrrf_destroy(_q->interp_tx); // free transmit filter array free(_q->h); // free main object memory free(_q); } void gmskmod_print(gmskmod _q) { printf("gmskmod [k=%u, m=%u, BT=%8.3f]\n", _q->k, _q->m, _q->BT); unsigned int i; for (i=0; i<_q->h_len; i++) printf(" ht(%4u) = %12.8f;\n", i+1, _q->h[i]); } void gmskmod_reset(gmskmod _q) { // reset phase state _q->theta = 0.0f; // clear interpolator buffer firinterp_rrrf_reset(_q->interp_tx); } void gmskmod_modulate(gmskmod _q, unsigned int _s, float complex * _y) { // generate sample from symbol float x = _s==0 ? -_q->k_inv : _q->k_inv; // run interpolator float phi[_q->k]; firinterp_rrrf_execute(_q->interp_tx, x, phi); // integrate phase state unsigned int i; for (i=0; i<_q->k; i++) { // integrate phase state _q->theta += phi[i]; // ensure phase in [-pi, pi] if (_q->theta > M_PI) _q->theta -= 2*M_PI; if (_q->theta < -M_PI) _q->theta += 2*M_PI; // compute output _y[i] = liquid_cexpjf(_q->theta); } } liquid-dsp-1.3.1/src/modem/src/modem_apsk.c000066400000000000000000000141311317124540100205270ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // modem_apsk.c // // create an apsk (amplitude/phase-shift keying) modem object MODEM() MODEM(_create_apsk)(unsigned int _bits_per_symbol) { // pointer to APSK definition container struct liquid_apsk_s * apskdef = NULL; switch (_bits_per_symbol) { case 2: apskdef = &liquid_apsk4; break; case 3: apskdef = &liquid_apsk8; break; case 4: apskdef = &liquid_apsk16; break; case 5: apskdef = &liquid_apsk32; break; case 6: apskdef = &liquid_apsk64; break; case 7: apskdef = &liquid_apsk128; break; case 8: apskdef = &liquid_apsk256; break; default: fprintf(stderr,"error: modem_create_apsk(), unsupported modulation level (%u)\n", _bits_per_symbol); exit(1); } MODEM() q = (MODEM()) malloc( sizeof(struct MODEM(_s)) ); q->scheme = apskdef->scheme; MODEM(_init)(q, _bits_per_symbol); // set APSK internals unsigned int i; q->data.apsk.num_levels = apskdef->num_levels; for (i=0; idata.apsk.num_levels; i++) { q->data.apsk.p[i] = apskdef->p[i]; q->data.apsk.r[i] = apskdef->r[i]; q->data.apsk.phi[i] = apskdef->phi[i]; } // radius slicer for (i=0; idata.apsk.num_levels-1; i++) q->data.apsk.r_slicer[i] = apskdef->r_slicer[i]; // copy symbol map q->data.apsk.map = (unsigned char *) malloc(q->M*sizeof(unsigned char)); memmove(q->data.apsk.map, apskdef->map, q->M*sizeof(unsigned char)); // set modulation/demodulation function pointers q->modulate_func = &MODEM(_modulate_apsk); q->demodulate_func = &MODEM(_demodulate_apsk); // initialize soft-demodulation look-up table switch (q->m) { case 2: MODEM(_demodsoft_gentab)(q, 3); break; case 3: MODEM(_demodsoft_gentab)(q, 3); break; case 4: MODEM(_demodsoft_gentab)(q, 4); break; case 5: MODEM(_demodsoft_gentab)(q, 4); break; case 6: MODEM(_demodsoft_gentab)(q, 4); break; case 7: MODEM(_demodsoft_gentab)(q, 5); break; case 8: MODEM(_demodsoft_gentab)(q, 5); break; default:; } // initialize symbol map q->symbol_map = (TC*)malloc(q->M*sizeof(TC)); MODEM(_init_map)(q); q->modulate_using_map = 1; // reset modem and return MODEM(_reset)(q); return q; } // modulate APSK void MODEM(_modulate_apsk)(MODEM() _q, unsigned int _sym_in, TC * _y) { if (_sym_in >= _q->M) { fprintf(stderr,"error: modem_modulate_apsk(), input symbol exceeds maximum\n"); return; } // map input symbol to constellation symbol unsigned int i; unsigned int s = _q->data.apsk.map[_sym_in]; // determine in which level the symbol is located unsigned int p=0; // level unsigned int t=0; // accumulated number of points per level for (i=0; i<_q->data.apsk.num_levels; i++) { if (s < t + _q->data.apsk.p[i]) { p = i; break; } t += _q->data.apsk.p[i]; } unsigned int s0 = s - t; unsigned int s1 = _q->data.apsk.p[p]; #if 0 printf(" s : %3u -> %3u in level %3u (t = %3u) [symbol %3u / %3u]\n", _sym_in, s, p, t, s0,s1); #endif // map symbol to constellation point (radius, angle) T r = _q->data.apsk.r[p]; T phi = _q->data.apsk.phi[p] + (T)(s0)*2.0f*M_PI / (T)(s1); // compute output symbol *_y = r * liquid_cexpjf(phi); } // demodulate APSK void MODEM(_demodulate_apsk)(MODEM() _q, TC _x, unsigned int * _sym_out) { // compute amplitude T r = cabsf(_x); // determine which ring to demodulate with unsigned int i, p=0; for (i=0; i<_q->data.apsk.num_levels-1; i++) { if (r < _q->data.apsk.r_slicer[i]) { p = i; break; } else { p = _q->data.apsk.num_levels-1; } } // find closest point in ring T theta = cargf(_x); if (theta < 0.0f) theta += 2.0f*M_PI; T dphi = 2.0f*M_PI / (T) _q->data.apsk.p[p]; unsigned int s_hat=0; T i_hat = (theta - _q->data.apsk.phi[p]) / dphi; s_hat = roundf(i_hat); // compute symbol (closest angle) s_hat %= _q->data.apsk.p[p]; // ensure symbol is in range //printf(" i_hat : %12.8f (%3u)\n", i_hat, s_hat); // accumulate symbol points for (i=0; idata.apsk.p[i]; //assert(s_hat < _q->M); // reverse symbol mapping unsigned int s_prime=0; for (i=0; i<_q->M; i++) { if ( _q->data.apsk.map[i] == s_hat) { s_prime = i; break; } } #if 0 printf(" x : %12.8f + j*%12.8f\n", crealf(_x), cimagf(_x)); printf(" p : %3u\n", p); printf(" theta : %12.8f\n", theta); printf(" dmin : %12.8f\n", dmin); printf(" s : %3u > %3u\n", s_hat, s_prime); #endif *_sym_out = s_prime; // re-modulate symbol and store state MODEM(_modulate)(_q, s_prime, &_q->x_hat); _q->r = _x; } liquid-dsp-1.3.1/src/modem/src/modem_apsk_const.c000066400000000000000000000163721317124540100217460ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // modem_apsk_const.c // // APSK modem constants // #include #include "liquid.internal.h" // APSK4(1,3) unsigned int apsk4_num_levels = 2; unsigned int apsk4_p[2] = {1,3}; float apsk4_r[2] = {0.0f, 1.15470052}; float apsk4_phi[2] = {0.0f, 0.0f}; float apsk4_r_slicer[1] = {0.57735026}; unsigned char apsk4_map[4] = {3,2,1,0}; struct liquid_apsk_s liquid_apsk4 = { LIQUID_MODEM_APSK4, 2, apsk4_p, apsk4_r, apsk4_phi, apsk4_r_slicer, apsk4_map}; // APSK8(1,7) unsigned int apsk8_num_levels = 2; unsigned int apsk8_p[2] = {1,7}; float apsk8_r[2] = {0.0, 1.06904495}; float apsk8_phi[2] = {0.0, 0.0}; float apsk8_r_slicer[1] = {0.53452247}; unsigned char apsk8_map[8] = { 0, 2, 4, 3, 1, 7, 5, 6}; struct liquid_apsk_s liquid_apsk8 = { LIQUID_MODEM_APSK8, 2, apsk8_p, apsk8_r, apsk8_phi, apsk8_r_slicer, apsk8_map}; // APSK16(4,12) unsigned int apsk16_num_levels = 2; unsigned int apsk16_p[2] = {4,12}; float apsk16_r[2] = {0.43246540f, 1.12738252f}; float apsk16_phi[2] = {0.0f, 0.0f}; float apsk16_r_slicer[1] = {0.77992396f}; unsigned char apsk16_map[16] = { 11, 10, 8, 9, 12, 2, 7, 1, 14, 15, 5, 4, 13, 3, 6, 0}; struct liquid_apsk_s liquid_apsk16 = { LIQUID_MODEM_APSK16, 2, apsk16_p, apsk16_r, apsk16_phi, apsk16_r_slicer, apsk16_map}; // APSK32(4,12,16) unsigned int apsk32_num_levels = 3; unsigned int apsk32_p[3] = {4,12,16}; float apsk32_r[3] = { 0.27952856f, 0.72980529f, 1.25737989f}; float apsk32_phi[3] = { 0.0f, 0.0f, 0.0f}; float apsk32_r_slicer[2] = { 0.504666925, 0.993592590}; unsigned char apsk32_map[32] = { 26, 25, 22, 23, 27, 11, 21, 9, 13, 3, 7, 1, 12, 10, 8, 24, 30, 31, 18, 17, 29, 15, 19, 5, 28, 0, 20, 2, 14, 16, 6, 4}; struct liquid_apsk_s liquid_apsk32 = { LIQUID_MODEM_APSK32, 3, apsk32_p, apsk32_r, apsk32_phi, apsk32_r_slicer, apsk32_map}; // APSK64(4,14,20,26) unsigned int apsk64_num_levels = 4; unsigned int apsk64_p[4] = {4, 14, 20, 26}; float apsk64_r[4] = { 0.18916586, 0.52466476, 0.88613129, 1.30529201}; float apsk64_phi[4] = {0.0f, 0.0f, 0.0f, 0.0f}; float apsk64_r_slicer[3] = { 0.35691531, 0.70539802, 1.09571165}; unsigned char apsk64_map[64] = { 54, 53, 51, 52, 48, 49, 28, 50, 55, 30, 11, 29, 47, 25, 27, 26, 57, 32, 2, 14, 45, 23, 1, 8, 56, 31, 12, 13, 46, 24, 10, 9, 61, 62, 38, 63, 41, 40, 18, 39, 60, 35, 37, 36, 42, 20, 4, 19, 58, 33, 3, 15, 44, 22, 0, 7, 59, 34, 17, 16, 43, 21, 5, 6}; struct liquid_apsk_s liquid_apsk64 = { LIQUID_MODEM_APSK64, 4, apsk64_p, apsk64_r, apsk64_phi, apsk64_r_slicer, apsk64_map}; // APSK128(8,18,24,36,42) unsigned int apsk128_num_levels = 5; unsigned int apsk128_p[5] = {8,18,24,36,42}; float apsk128_r[5] = { 0.20241030, 0.46255755, 0.70972824, 0.99172282, 1.34806108}; float apsk128_phi[5] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; float apsk128_r_slicer[4] = { 0.33248392, 0.58614290, 0.85072553, 1.16989195}; unsigned char apsk128_map[128] = { 112, 111, 108, 109, 102, 103, 106, 105, 113, 110, 107, 71, 101, 104, 67, 66, 115, 73, 39, 41, 99, 63, 38, 36, 114, 72, 69, 70, 100, 64, 68, 65, 117, 77, 1, 21, 97, 59, 2, 13, 76, 43, 4, 20, 60, 33, 3, 14, 116, 74, 18, 40, 98, 62, 37, 35, 75, 42, 17, 19, 61, 34, 16, 15, 123, 124, 127, 126, 91, 90, 87, 88, 122, 125, 85, 84, 92, 89, 51, 53, 120, 81, 49, 48, 94, 55, 26, 29, 121, 82, 50, 83, 93, 54, 27, 52, 118, 44, 7, 5, 96, 32, 0, 10, 78, 45, 6, 22, 58, 30, 86, 12, 80, 79, 25, 47, 57, 56, 9, 28, 119, 46, 24, 23, 95, 31, 8, 11}; struct liquid_apsk_s liquid_apsk128 = { LIQUID_MODEM_APSK128, 5, apsk128_p, apsk128_r, apsk128_phi, apsk128_r_slicer, apsk128_map}; // APSK256(6,18,32,36,46,54,64) unsigned int apsk256_num_levels = 7; unsigned int apsk256_p[7] = {6,18,32,36,46,54,64}; float apsk256_r[7] = { 0.19219166, 0.41951191, 0.60772800, 0.77572918, 0.94819963, 1.12150347, 1.31012368}; float apsk256_phi[7] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; float apsk256_r_slicer[6] = { 0.30585179, 0.51361996, 0.69172859, 0.86196440, 1.03485155, 1.21581364}; unsigned char apsk256_map[256] = { 232, 231, 229, 230, 224, 225, 227, 226, 216, 217, 219, 218, 164, 223, 221, 222, 233, 228, 170, 171, 166, 167, 169, 168, 215, 220, 160, 159, 165, 163, 161, 162, 235, 173, 123, 121, 75, 76, 78, 77, 213, 157, 70, 109, 73, 115, 71, 72, 234, 172, 120, 174, 116, 117, 119, 118, 214, 158, 110, 156, 114, 113, 111, 112, 239, 178, 82, 126, 255, 19, 47, 5, 209, 152, 66, 105, 56, 12, 33, 13, 238, 177, 81, 125, 138, 193, 46, 4, 210, 153, 67, 106, 7, 1, 34, 2, 236, 175, 79, 122, 74, 42, 44, 43, 212, 155, 69, 108, 39, 38, 36, 37, 237, 176, 80, 124, 3, 40, 45, 41, 211, 154, 68, 107, 16, 15, 35, 14, 248, 249, 251, 250, 191, 190, 252, 253, 200, 199, 197, 198, 139, 140, 196, 195, 247, 185, 187, 186, 137, 136, 188, 189, 201, 145, 143, 144, 93, 94, 142, 141, 245, 183, 87, 131, 54, 53, 88, 89, 203, 147, 61, 99, 26, 27, 60, 59, 246, 184, 133, 132, 91, 90, 134, 135, 202, 146, 97, 98, 57, 58, 96, 95, 240, 179, 83, 127, 23, 192, 48, 17, 208, 151, 65, 104, 6, 11, 32, 206, 241, 180, 84, 128, 254, 242, 49, 18, 207, 150, 64, 102, 92, 194, 31, 10, 244, 182, 86, 130, 55, 21, 52, 51, 204, 148, 62, 100, 25, 8, 28, 29, 243, 181, 85, 129, 0, 22, 50, 20, 205, 149, 63, 101, 24, 9, 30, 103}; struct liquid_apsk_s liquid_apsk256 = { LIQUID_MODEM_APSK256, 7, apsk256_p, apsk256_r, apsk256_phi, apsk256_r_slicer, apsk256_map}; liquid-dsp-1.3.1/src/modem/src/modem_arb.c000066400000000000000000000223651317124540100203450ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // modem_arb.c // // create arbitrary digital modem object MODEM() MODEM(_create_arbitrary)(TC * _table, unsigned int _M) { // strip out bits/symbol unsigned int m = liquid_nextpow2(_M); if ( (1<scheme = LIQUID_MODEM_ARB; MODEM(_init)(q, _bits_per_symbol); q->M = q->M; q->symbol_map = (TC*) calloc( q->M, sizeof(TC) ); q->modulate_func = &MODEM(_modulate_arb); q->demodulate_func = &MODEM(_demodulate_arb); return q; } // modulate arbitrary modem type void MODEM(_modulate_arb)(MODEM() _q, unsigned int _sym_in, TC * _y) { if (_sym_in >= _q->M) { fprintf(stderr,"error: modulate_arb(), input symbol exceeds maximum\n"); exit(1); } // map sample directly to output *_y = _q->symbol_map[_sym_in]; } // demodulate arbitrary modem type void MODEM(_demodulate_arb)(MODEM() _q, TC _x, unsigned int * _sym_out) { //printf("modem_demodulate_arb() invoked with I=%d, Q=%d\n", x); // search for symbol nearest to received sample unsigned int i; unsigned int s=0; T d; // distance T d_min = 0.0f; // minimum distance for (i=0; i<_q->M; i++) { // compute distance from received symbol to constellation point d = cabsf(_x - _q->symbol_map[i]); // retain symbol with minimum distance if ( i==0 || d < d_min ) { d_min = d; s = i; } } // set output symbol *_sym_out = s; // re-modulate symbol and store state MODEM(_modulate_arb)(_q, *_sym_out, &_q->x_hat); _q->r = _x; } // create a V.29 modem object (4 bits/symbol) MODEM() MODEM(_create_V29)() { MODEM() q = MODEM(_create_arb)(4); #if T == float MODEM(_arb_init)(q,(TC*)modem_arb_V29,16); #endif return q; } // create an arb16opt (optimal 16-qam) modem object MODEM() MODEM(_create_arb16opt)() { MODEM() q = MODEM(_create_arb)(4); #if T == float MODEM(_arb_init)(q,(TC*)modem_arb16opt,16); #endif return q; } // create an arb32opt (optimal 32-qam) modem object MODEM() MODEM(_create_arb32opt)() { MODEM() q = MODEM(_create_arb)(5); #if T == float MODEM(_arb_init)(q,(TC*)modem_arb32opt,32); #endif return q; } // create an arb64opt (optimal 64-qam) modem object MODEM() MODEM(_create_arb64opt)() { MODEM() q = MODEM(_create_arb)(6); #if T == float MODEM(_arb_init)(q,(TC*)modem_arb64opt,64); #endif return q; } // create an arb128opt (optimal 128-qam) modem object MODEM() MODEM(_create_arb128opt)() { MODEM() q = MODEM(_create_arb)(7); #if T == float MODEM(_arb_init)(q,(TC*)modem_arb128opt,128); #endif return q; } // create an arb256opt (optimal 256-qam) modem object MODEM() MODEM(_create_arb256opt)() { MODEM() q = MODEM(_create_arb)(8); #if T == float MODEM(_arb_init)(q,(TC*)modem_arb256opt,256); #endif return q; } // create an arb64vt (64-qam vt logo) modem object MODEM() MODEM(_create_arb64vt)() { MODEM() q = MODEM(_create_arb)(6); #if T == float MODEM(_arb_init)(q,(TC*)modem_arb_vt64,64); #endif return q; } // initialize an arbitrary modem object // _mod : modem object // _symbol_map : arbitrary modem symbol map // _len : number of symbols in the map void MODEM(_arb_init)(MODEM() _q, TC * _symbol_map, unsigned int _len) { #ifdef LIQUID_VALIDATE_INPUT if (_q->scheme != LIQUID_MODEM_ARB) { fprintf(stderr,"error: modem_arb_init(), modem is not of arbitrary type\n"); exit(1); } else if (_len != _q->M) { fprintf(stderr,"error: modem_arb_init(), array sizes do not match\n"); exit(1); } #endif unsigned int i; for (i=0; i<_len; i++) _q->symbol_map[i] = _symbol_map[i]; // balance I/Q channels if (_q->scheme == LIQUID_MODEM_ARB) MODEM(_arb_balance_iq)(_q); // scale modem to have unity energy MODEM(_arb_scale)(_q); } // initialize an arbitrary modem object on a file // _mod : modem object // _filename : name of the data file void MODEM(_arb_init_file)(MODEM() _q, char * _filename) { // try to open file FILE * fid = fopen(_filename, "r"); if (fid == NULL) { fprintf(stderr,"error: modem_arb_init_file(), could not open file\n"); exit(1); } unsigned int i, results; T sym_i, sym_q; for (i=0; i<_q->M; i++) { if ( feof(fid) ) { fprintf(stderr,"error: modem_arb_init_file(), premature EOF for '%s'\n", _filename); exit(1); } results = fscanf(fid, "%f %f\n", &sym_i, &sym_q); _q->symbol_map[i] = sym_i + _Complex_I*sym_q; // ensure proper number of symbols were read if (results < 2) { fprintf(stderr,"error: modem_arb_init_file(), unable to parse line\n"); exit(1); } } fclose(fid); // balance I/Q channels if (_q->scheme == LIQUID_MODEM_ARB) MODEM(_arb_balance_iq)(_q); // scale modem to have unity energy MODEM(_arb_scale)(_q); } // scale arbitrary modem constellation points void MODEM(_arb_scale)(MODEM() _q) { unsigned int i; // calculate energy T mag, e = 0.0f; for (i=0; i<_q->M; i++) { mag = cabsf(_q->symbol_map[i]); e += mag*mag; } e = sqrtf( e / _q->M ); for (i=0; i<_q->M; i++) { _q->symbol_map[i] /= e; } } // balance an arbitrary modem's I/Q points void MODEM(_arb_balance_iq)(MODEM() _q) { TC mean=0.0f; unsigned int i; // accumulate average signal for (i=0; i<_q->M; i++) { mean += _q->symbol_map[i]; } mean /= (T) (_q->M); // subtract mean value from reference levels for (i=0; i<_q->M; i++) { _q->symbol_map[i] -= mean; } } // demodulate arbitrary modem type (soft) void MODEM(_demodulate_soft_arb)(MODEM() _q, TC _r, unsigned int * _s, unsigned char * _soft_bits) { unsigned int bps = _q->m; unsigned int M = _q->M; // gamma = 1/(2*sigma^2), approximate for constellation size T gamma = 1.2f*_q->M; unsigned int s=0; // hard decision output unsigned int k; // bit index unsigned int i; // symbol index T d; // distance for this symbol TC x_hat; // re-modulated symbol T dmin_0[bps]; T dmin_1[bps]; for (k=0; ksymbol_map[i]; d = crealf( (_r-x_hat)*conjf(_r-x_hat) ); // set hard-decision... if (d < dmin || i==0) { s = i; dmin = d; } for (k=0; k> (bps-k-1)) & 0x01 ) { if (d < dmin_1[k]) dmin_1[k] = d; } else { if (d < dmin_0[k]) dmin_0[k] = d; } } } // make assignments for (k=0; k 255) soft_bit = 255; if (soft_bit < 0) soft_bit = 0; _soft_bits[k] = (unsigned char)soft_bit; } // hard decision // set hard output symbol *_s = s; // re-modulate symbol and store state MODEM(_modulate_arb)(_q, *_s, &_q->x_hat); _q->r = _r; } liquid-dsp-1.3.1/src/modem/src/modem_arb_const.c000066400000000000000000000673101317124540100215520ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // modem_arb_const.c // // Constant arbitrary linear modems // #include #include "liquid.internal.h" // 'square' 32-QAM (first quadrant) const float complex modem_arb_sqam32[8] = { 0.22361000+ 0.22361000*_Complex_I, 0.67082000+ 0.22361000*_Complex_I, 0.67082000+ 1.11800000*_Complex_I, 1.11800000+ 0.22361000*_Complex_I, 0.22361000+ 0.67082000*_Complex_I, 0.67082000+ 0.67082000*_Complex_I, 0.22361000+ 1.11800000*_Complex_I, 1.11800000+ 0.67082000*_Complex_I }; // 'square' 128-QAM (first quadrant) const float complex modem_arb_sqam128[32] = { 0.11043000+ 0.11043000*_Complex_I, 0.33129000+ 0.11043000*_Complex_I, 0.11043000+ 0.33129000*_Complex_I, 0.33129000+ 0.33129000*_Complex_I, 0.77302000+ 0.11043000*_Complex_I, 0.55216000+ 0.11043000*_Complex_I, 0.77302000+ 0.33129000*_Complex_I, 0.55216000+ 0.33129000*_Complex_I, 0.77302000+ 0.99388000*_Complex_I, 0.55216000+ 0.99388000*_Complex_I, 0.77302000+ 1.21470000*_Complex_I, 0.55216000+ 1.21470000*_Complex_I, 0.99388000+ 0.11043000*_Complex_I, 1.21470000+ 0.11043000*_Complex_I, 0.99388000+ 0.33129000*_Complex_I, 1.21470000+ 0.33129000*_Complex_I, 0.11043000+ 0.77302000*_Complex_I, 0.33129000+ 0.77302000*_Complex_I, 0.11043000+ 0.55216000*_Complex_I, 0.33129000+ 0.55216000*_Complex_I, 0.77302000+ 0.77302000*_Complex_I, 0.55216000+ 0.77302000*_Complex_I, 0.77302000+ 0.55216000*_Complex_I, 0.55216000+ 0.55216000*_Complex_I, 0.11043000+ 0.99388000*_Complex_I, 0.33129000+ 0.99388000*_Complex_I, 0.11043000+ 1.21470000*_Complex_I, 0.33129000+ 1.21470000*_Complex_I, 0.99388000+ 0.77302000*_Complex_I, 1.21470000+ 0.77302000*_Complex_I, 0.99388000+ 0.55216000*_Complex_I, 1.21470000+ 0.55216000*_Complex_I }; // V.29 star constellation const float complex modem_arb_V29[16] = { 0.06804100+ 0.06804100*_Complex_I, 0.20412000+ 0.00000000*_Complex_I, 0.00000000+ 0.20412000*_Complex_I, -0.06804100+ 0.06804100*_Complex_I, 0.00000000+ -0.20412000*_Complex_I, 0.06804100+ -0.06804100*_Complex_I, -0.06804100+ -0.06804100*_Complex_I, -0.20412000+ 0.00000000*_Complex_I, 0.20412000+ 0.20412000*_Complex_I, 0.34021000+ 0.00000000*_Complex_I, 0.00000000+ 0.34021000*_Complex_I, -0.20412000+ 0.20412000*_Complex_I, 0.00000000+ -0.34021000*_Complex_I, 0.20412000+ -0.20412000*_Complex_I, -0.20412000+ -0.20412000*_Complex_I, -0.34021000+ 0.00000000*_Complex_I }; // Virginia Tech logo const float complex modem_arb_vt64[64] = { -1.5633e+00+ 5.5460e-01*_Complex_I, -1.3833e+00+ 5.5460e-01*_Complex_I, -1.0234e+00+ 5.5460e-01*_Complex_I, -1.2034e+00+ 5.5460e-01*_Complex_I, -7.3553e-01+ 5.0751e-02*_Complex_I, -8.0750e-01+ 1.7671e-01*_Complex_I, -9.5146e-01+ 4.2863e-01*_Complex_I, -8.7948e-01+ 3.0267e-01*_Complex_I, -3.3741e-02+ 5.5460e-01*_Complex_I, -2.1368e-01+ 5.5460e-01*_Complex_I, -4.4761e-01+ 4.2863e-01*_Complex_I, -3.9363e-01+ 5.5460e-01*_Complex_I, -6.6355e-01+ -7.5211e-02*_Complex_I, -6.0956e-01+ 5.0751e-02*_Complex_I, -5.0160e-01+ 3.0267e-01*_Complex_I, -5.5558e-01+ 1.7671e-01*_Complex_I, 9.5596e-01+ 1.0473e-01*_Complex_I, 1.1359e+00+ 1.0473e-01*_Complex_I, 1.4958e+00+ 1.0473e-01*_Complex_I, 1.3158e+00+ 1.0473e-01*_Complex_I, 1.5858e+00+ 5.5460e-01*_Complex_I, 1.7657e+00+ 5.5460e-01*_Complex_I, 1.5858e+00+ 2.5499e-01*_Complex_I, 1.6757e+00+ 4.0434e-01*_Complex_I, 1.4621e-01+ 5.5460e-01*_Complex_I, 3.2615e-01+ 5.5460e-01*_Complex_I, 6.8604e-01+ 5.5460e-01*_Complex_I, 5.0610e-01+ 5.5460e-01*_Complex_I, 1.4058e+00+ 5.5460e-01*_Complex_I, 1.2259e+00+ 5.5460e-01*_Complex_I, 8.6599e-01+ 5.5460e-01*_Complex_I, 1.0459e+00+ 5.5460e-01*_Complex_I, -1.4508e+00+ 3.6385e-01*_Complex_I, -1.3383e+00+ 1.7221e-01*_Complex_I, -1.1134e+00+ -2.1017e-01*_Complex_I, -1.2259e+00+ -1.8529e-02*_Complex_I, -6.6355e-01+ -9.7494e-01*_Complex_I, -7.7601e-01+ -7.8420e-01*_Complex_I, -1.0009e+00+ -4.0181e-01*_Complex_I, -8.8848e-01+ -5.9255e-01*_Complex_I, 1.4621e-01+ 1.0473e-01*_Complex_I, 1.1246e-02+ 1.0473e-01*_Complex_I, -2.1368e-01+ -7.5211e-02*_Complex_I, -1.2371e-01+ 1.0473e-01*_Complex_I, -5.7358e-01+ -7.9499e-01*_Complex_I, -4.8360e-01+ -6.1505e-01*_Complex_I, -3.0366e-01+ -2.5516e-01*_Complex_I, -3.9363e-01+ -4.3510e-01*_Complex_I, 8.5069e-01+ -7.5211e-02*_Complex_I, 7.4632e-01+ -2.5516e-01*_Complex_I, 5.3579e-01+ -6.1505e-01*_Complex_I, 6.4105e-01+ -4.3510e-01*_Complex_I, -3.3741e-02+ -9.7494e-01*_Complex_I, 1.4621e-01+ -9.7494e-01*_Complex_I, 4.3142e-01+ -7.9499e-01*_Complex_I, 3.2615e-01+ -9.7494e-01*_Complex_I, 2.8116e-01+ 1.0473e-01*_Complex_I, 4.1612e-01+ 1.0473e-01*_Complex_I, 2.0649e-01+ -2.5516e-01*_Complex_I, 3.1086e-01+ -7.5211e-02*_Complex_I, -2.1368e-01+ -9.7494e-01*_Complex_I, -1.0842e-01+ -7.9499e-01*_Complex_I, 1.0122e-01+ -4.3510e-01*_Complex_I, -4.0500e-03+ -6.1505e-01*_Complex_I }; // optimal 16-QAM const float complex modem_arb16opt[16] = { -0.87119000+ -0.87970000*_Complex_I, -1.15090000+ -0.26101000*_Complex_I, -1.10090000+ 0.87457000*_Complex_I, -0.81088000+ 0.29689000*_Complex_I, -0.21295000+ -0.91897000*_Complex_I, -0.46984000+ -0.29804000*_Complex_I, -0.43443000+ 0.91820000*_Complex_I, -0.16786000+ 0.30338000*_Complex_I, 1.10000000+ -0.87511000*_Complex_I, 0.81125000+ -0.29671000*_Complex_I, 0.87134000+ 0.87989000*_Complex_I, 1.15170000+ 0.26143000*_Complex_I, 0.43379000+ -0.91801000*_Complex_I, 0.16807000+ -0.30335000*_Complex_I, 0.21246000+ 0.91867000*_Complex_I, 0.47033000+ 0.29787000*_Complex_I }; // optimal 32-QAM const float complex modem_arb32opt[32] = { -1.04570000+ -0.72639000*_Complex_I, -1.26710000+ -0.00824020*_Complex_I, -0.99868000+ 0.92359000*_Complex_I, -1.13660000+ 0.45833000*_Complex_I, -0.67812000+ -1.07470000*_Complex_I, -0.88363000+ -0.25914000*_Complex_I, -0.64443000+ 0.62407000*_Complex_I, -0.76238000+ 0.18163000*_Complex_I, -0.20985000+ -0.91032000*_Complex_I, -0.08603100+ -0.45730000*_Complex_I, -0.18073000+ 0.75747000*_Complex_I, 0.02826900+ -0.01908400*_Complex_I, -0.55206000+ -0.61092000*_Complex_I, -0.42946000+ -0.16611000*_Complex_I, -0.51187000+ 1.09190000*_Complex_I, -0.30769000+ 0.27731000*_Complex_I, 1.20280000+ -0.58421000*_Complex_I, 1.29120000+ -0.09249800*_Complex_I, 1.10450000+ 0.69170000*_Complex_I, 0.96433000+ 0.24011000*_Complex_I, 0.60130000+ -1.16500000*_Complex_I, 0.83106000+ -0.23576000*_Complex_I, 0.73090000+ 1.01880000*_Complex_I, 0.62090000+ 0.54470000*_Complex_I, 0.23884000+ -0.81583000*_Complex_I, 0.36064000+ -0.36749000*_Complex_I, -0.02439300+ 1.23570000*_Complex_I, 0.15492000+ 0.41465000*_Complex_I, 0.11172000+ -1.28340000*_Complex_I, 0.70560000+ -0.68005000*_Complex_I, 0.28323000+ 0.89268000*_Complex_I, 0.48844000+ 0.10367000*_Complex_I }; // optimal 64-QAM const float complex modem_arb64opt[64] = { -9.6048e-01 + -1.0031e+00*_Complex_I, -1.1105e+00 + -6.8896e-01*_Complex_I, -1.1029e+00 + -9.5064e-02*_Complex_I, -1.2692e+00 + -3.8774e-01*_Complex_I, -7.9322e-01 + 1.1014e+00*_Complex_I, -9.5999e-01 + 7.9701e-01*_Complex_I, -1.2734e+00 + 1.9621e-01*_Complex_I, -1.1121e+00 + 4.9520e-01*_Complex_I, -6.2388e-01 + -9.8614e-01*_Complex_I, -7.7108e-01 + -6.8653e-01*_Complex_I, -7.6793e-01 + -1.0097e-01*_Complex_I, -9.1812e-01 + -3.9210e-01*_Complex_I, -4.5416e-01 + 1.0712e+00*_Complex_I, -6.1578e-01 + 7.7701e-01*_Complex_I, -9.1845e-01 + 1.9699e-01*_Complex_I, -7.7026e-01 + 4.8601e-01*_Complex_I, -1.1067e-01 + -1.2612e+00*_Complex_I, -2.6544e-01 + -9.6343e-01*_Complex_I, 1.3076e+00 + 4.5615e-01*_Complex_I, -2.5827e-01 + -3.9458e-01*_Complex_I, -1.0044e-01 + 1.0486e+00*_Complex_I, 3.9086e-02 + 7.4394e-01*_Complex_I, -2.6144e-01 + 1.7968e-01*_Complex_I, -1.1912e-01 + 4.5495e-01*_Complex_I, -4.5452e-01 + -1.2733e+00*_Complex_I, -4.3866e-01 + -6.8570e-01*_Complex_I, -4.3802e-01 + -1.0872e-01*_Complex_I, -5.8466e-01 + -3.9550e-01*_Complex_I, -2.6246e-01 + 1.3479e+00*_Complex_I, -2.8816e-01 + 7.5672e-01*_Complex_I, -5.8784e-01 + 1.8705e-01*_Complex_I, -4.4008e-01 + 4.7244e-01*_Complex_I, 7.9849e-01 + -1.0124e+00*_Complex_I, 9.5371e-01 + -7.1194e-01*_Complex_I, 1.2696e+00 + -1.1448e-01*_Complex_I, 1.1145e+00 + -4.2441e-01*_Complex_I, 9.0580e-01 + 1.0653e+00*_Complex_I, 1.0641e+00 + 7.6363e-01*_Complex_I, 1.0837e+00 + 1.7467e-01*_Complex_I, 9.1489e-01 + 4.6389e-01*_Complex_I, 5.8983e-01 + -1.2906e+00*_Complex_I, 6.0746e-01 + -7.0336e-01*_Complex_I, 9.1373e-01 + -1.3004e-01*_Complex_I, 7.4917e-01 + -4.1576e-01*_Complex_I, 5.6608e-01 + 1.0707e+00*_Complex_I, 7.1464e-01 + 7.5794e-01*_Complex_I, 7.4460e-01 + 1.6652e-01*_Complex_I, 5.7594e-01 + 4.5036e-01*_Complex_I, 7.6128e-02 + -9.7664e-01*_Complex_I, -9.2551e-02 + -6.8763e-01*_Complex_I, -9.4285e-02 + -1.0993e-01*_Complex_I, 6.5368e-02 + -4.0109e-01*_Complex_I, 1.0945e-01 + 1.3350e+00*_Complex_I, 2.2470e-01 + 4.7166e-01*_Complex_I, 5.5987e-01 + -1.1259e-01*_Complex_I, 7.0006e-02 + 1.9154e-01*_Complex_I, 2.4876e-01 + -1.2685e+00*_Complex_I, 4.2452e-01 + -9.8023e-01*_Complex_I, 2.5356e-01 + -6.8613e-01*_Complex_I, 4.0576e-01 + -4.1184e-01*_Complex_I, 2.4615e-01 + 1.0373e+00*_Complex_I, 3.9219e-01 + 7.4440e-01*_Complex_I, 2.4704e-01 + -1.0509e-01*_Complex_I, 3.9791e-01 + 1.8370e-01*_Complex_I, }; // optimal 128-QAM const float complex modem_arb128opt[128] = { -1.0682e+00 + -9.2598e-01*_Complex_I, -1.1831e+00 + -7.0704e-01*_Complex_I, -1.3029e+00 + -1.0555e-01*_Complex_I, -1.3061e+00 + -4.9292e-01*_Complex_I, -9.4032e-01 + 9.7928e-01*_Complex_I, -1.1807e+00 + 5.4821e-01*_Complex_I, -1.4078e+00 + 1.1265e-01*_Complex_I, -1.2954e+00 + 3.3623e-01*_Complex_I, -7.3838e-01 + -1.1381e+00*_Complex_I, -9.4161e-01 + -7.0518e-01*_Complex_I, -1.1625e+00 + -2.9080e-01*_Complex_I, -1.0477e+00 + -4.9556e-01*_Complex_I, -1.0664e+00 + 7.7185e-01*_Complex_I, -8.3123e-01 + 7.4171e-01*_Complex_I, -1.1636e+00 + 1.1831e-01*_Complex_I, -1.0506e+00 + 3.2582e-01*_Complex_I, -4.8913e-01 + -1.1074e+00*_Complex_I, -5.8148e-01 + -8.9486e-01*_Complex_I, -8.0747e-01 + -9.4398e-02*_Complex_I, -9.1178e-01 + -2.9590e-01*_Complex_I, -7.0503e-01 + 9.5290e-01*_Complex_I, -5.8794e-01 + 7.4046e-01*_Complex_I, -6.9655e-01 + 1.0350e-01*_Complex_I, -6.8968e-01 + 5.2969e-01*_Complex_I, -8.2001e-01 + -9.1531e-01*_Complex_I, -7.0810e-01 + -7.0021e-01*_Complex_I, -1.0403e+00 + -8.9321e-02*_Complex_I, -8.0893e-01 + -4.9762e-01*_Complex_I, -6.1299e-01 + 1.1733e+00*_Complex_I, -9.2994e-01 + 5.3436e-01*_Complex_I, -9.2384e-01 + 1.1851e-01*_Complex_I, -8.0873e-01 + 3.2535e-01*_Complex_I, 8.5789e-03 + -1.1069e+00*_Complex_I, 1.3354e-01 + -9.0426e-01*_Complex_I, 1.2277e+00 + -3.0336e-01*_Complex_I, -2.1578e-01 + -2.9289e-01*_Complex_I, 2.5555e-03 + 1.3535e+00*_Complex_I, -1.0737e-01 + 7.4055e-01*_Complex_I, 5.0972e-03 + 1.1376e-01*_Complex_I, -4.5018e-03 + 5.4428e-01*_Complex_I, -1.0895e-01 + -1.3162e+00*_Complex_I, -2.2365e-01 + -6.9809e-01*_Complex_I, 1.3461e+00 + -9.5212e-02*_Complex_I, -4.3183e-01 + -2.9421e-01*_Complex_I, -1.1598e-01 + 1.1402e+00*_Complex_I, -2.2730e-01 + 9.3180e-01*_Complex_I, -2.1915e-01 + 1.1528e-01*_Complex_I, -2.2953e-01 + 5.3517e-01*_Complex_I, -3.6962e-01 + -1.3195e+00*_Complex_I, -4.6545e-01 + -6.9766e-01*_Complex_I, -6.7387e-01 + -2.8466e-01*_Complex_I, -5.6923e-01 + -4.9130e-01*_Complex_I, -3.6828e-01 + 1.1445e+00*_Complex_I, -4.6503e-01 + 9.3615e-01*_Complex_I, -5.7039e-01 + -8.3381e-02*_Complex_I, -4.6304e-01 + 5.2568e-01*_Complex_I, -2.4438e-01 + -1.1062e+00*_Complex_I, -3.4724e-01 + -8.9072e-01*_Complex_I, -3.3719e-01 + -8.1507e-02*_Complex_I, -3.4116e-01 + -4.9075e-01*_Complex_I, -2.5467e-01 + 1.3510e+00*_Complex_I, -3.4640e-01 + 7.4004e-01*_Complex_I, -4.5303e-01 + 1.1207e-01*_Complex_I, -5.7498e-01 + 3.1560e-01*_Complex_I, 8.7471e-01 + -9.3403e-01*_Complex_I, 1.1932e+00 + -7.1750e-01*_Complex_I, 1.0817e+00 + -9.5165e-02*_Complex_I, 1.0850e+00 + -5.0487e-01*_Complex_I, 9.7521e-01 + 9.8123e-01*_Complex_I, 1.0879e+00 + 7.6120e-01*_Complex_I, 1.1902e+00 + 1.1187e-01*_Complex_I, 1.1983e+00 + 5.4100e-01*_Complex_I, 7.5089e-01 + -1.1405e+00*_Complex_I, 9.5031e-01 + -7.0315e-01*_Complex_I, 9.6679e-01 + -2.8997e-01*_Complex_I, 8.4619e-01 + -4.8958e-01*_Complex_I, 7.4379e-01 + 9.5772e-01*_Complex_I, 8.4793e-01 + 7.4658e-01*_Complex_I, 9.4820e-01 + 1.1332e-01*_Complex_I, 9.5910e-01 + 5.3750e-01*_Complex_I, 5.0524e-01 + -1.1045e+00*_Complex_I, 4.9092e-01 + -6.9263e-01*_Complex_I, 6.0143e-01 + -8.7696e-02*_Complex_I, 6.0078e-01 + -4.8901e-01*_Complex_I, 5.0450e-01 + 9.5208e-01*_Complex_I, 7.1207e-01 + 5.3740e-01*_Complex_I, 1.0790e+00 + 3.1868e-01*_Complex_I, 6.0339e-01 + 3.3768e-01*_Complex_I, 6.2518e-01 + -9.0613e-01*_Complex_I, 7.2199e-01 + -6.9979e-01*_Complex_I, 8.2756e-01 + -9.3837e-02*_Complex_I, 7.2238e-01 + -2.9345e-01*_Complex_I, 6.4006e-01 + 1.1740e+00*_Complex_I, 6.1312e-01 + 7.3911e-01*_Complex_I, 7.1908e-01 + 1.2320e-01*_Complex_I, 8.3253e-01 + 3.2769e-01*_Complex_I, -9.4871e-02 + -9.0259e-01*_Complex_I, -9.6676e-02 + -4.9277e-01*_Complex_I, 4.8818e-01 + -2.7584e-01*_Complex_I, -9.8973e-02 + -1.0402e-01*_Complex_I, 2.0955e-02 + 9.4046e-01*_Complex_I, 1.3132e-01 + 7.3484e-01*_Complex_I, 1.3357e+00 + 3.0715e-01*_Complex_I, -3.3806e-01 + 3.2795e-01*_Complex_I, 1.4149e-01 + -1.3293e+00*_Complex_I, 1.4162e-02 + -6.8874e-01*_Complex_I, 1.3376e-01 + -9.5389e-02*_Complex_I, 2.5367e-02 + -2.8878e-01*_Complex_I, 1.3413e-01 + 1.1437e+00*_Complex_I, 2.3299e-01 + 5.3149e-01*_Complex_I, 4.7428e-01 + 1.2730e-01*_Complex_I, 1.1767e-01 + 3.3670e-01*_Complex_I, 4.1070e-01 + -1.3283e+00*_Complex_I, 3.7197e-01 + -8.8947e-01*_Complex_I, 2.5771e-01 + -2.8158e-01*_Complex_I, 3.6892e-01 + -4.8660e-01*_Complex_I, 3.8837e-01 + 1.1516e+00*_Complex_I, 3.7013e-01 + 7.3189e-01*_Complex_I, 2.3982e-01 + 1.2673e-01*_Complex_I, 4.7588e-01 + 5.2723e-01*_Complex_I, 2.6342e-01 + -1.1217e+00*_Complex_I, 2.4743e-01 + -6.8820e-01*_Complex_I, 3.5855e-01 + -7.8191e-02*_Complex_I, 1.4393e-01 + -4.8365e-01*_Complex_I, 2.7111e-01 + 1.3506e+00*_Complex_I, 2.6368e-01 + 9.3477e-01*_Complex_I, 3.5476e-01 + 3.1767e-01*_Complex_I, -1.0269e-01 + 3.2880e-01*_Complex_I,}; // optimal 256-QAM const float complex modem_arb256opt[256] = { -9.3121e-01 + -1.0845e+00*_Complex_I, -1.0165e+00 + -9.3103e-01*_Complex_I, -1.1864e+00 + -6.3650e-01*_Complex_I, -1.1012e+00 + -7.8304e-01*_Complex_I, -1.3617e+00 + -4.3833e-02*_Complex_I, -1.2644e+00 + -1.9022e-01*_Complex_I, -1.2686e+00 + -4.8780e-01*_Complex_I, -1.3534e+00 + -3.3726e-01*_Complex_I, -8.4260e-01 + 1.1480e+00*_Complex_I, -9.2614e-01 + 9.9761e-01*_Complex_I, -1.1955e+00 + 5.5467e-01*_Complex_I, -1.1148e+00 + 6.9890e-01*_Complex_I, -1.1792e+00 + -3.7010e-02*_Complex_I, -1.2648e+00 + 1.1118e-01*_Complex_I, -1.2769e+00 + 4.0872e-01*_Complex_I, -1.3599e+00 + 2.5518e-01*_Complex_I, -6.7924e-01 + -1.2278e+00*_Complex_I, -8.4406e-01 + -9.1876e-01*_Complex_I, -1.0044e+00 + -6.2843e-01*_Complex_I, -9.2155e-01 + -7.7299e-01*_Complex_I, -1.0806e+00 + 1.0494e-01*_Complex_I, -1.0866e+00 + -1.9152e-01*_Complex_I, -1.0854e+00 + -4.8371e-01*_Complex_I, -1.1661e+00 + -3.3876e-01*_Complex_I, -1.0146e+00 + 8.4545e-01*_Complex_I, -7.5625e-01 + 9.8074e-01*_Complex_I, -9.2315e-01 + 6.9214e-01*_Complex_I, -8.3445e-01 + 8.3483e-01*_Complex_I, -1.0046e+00 + -3.8507e-02*_Complex_I, -1.1695e+00 + 2.5672e-01*_Complex_I, -1.0054e+00 + 5.4855e-01*_Complex_I, -1.0894e+00 + 4.0650e-01*_Complex_I, -4.9806e-01 + -1.2285e+00*_Complex_I, -6.6615e-01 + -9.1531e-01*_Complex_I, -6.6471e-01 + -6.1531e-01*_Complex_I, -5.0291e-01 + -9.1017e-01*_Complex_I, -6.6983e-01 + -4.8903e-02*_Complex_I, -7.4988e-01 + -1.8703e-01*_Complex_I, -7.4628e-01 + -4.7626e-01*_Complex_I, -8.2246e-01 + -3.3201e-01*_Complex_I, -6.7081e-01 + 1.1403e+00*_Complex_I, -5.0407e-01 + 1.1300e+00*_Complex_I, -6.6636e-01 + 5.3994e-01*_Complex_I, -4.9992e-01 + 8.2622e-01*_Complex_I, -8.3007e-01 + -3.4761e-02*_Complex_I, -7.3978e-01 + 1.0568e-01*_Complex_I, -7.4366e-01 + 3.9573e-01*_Complex_I, -6.6403e-01 + 2.4968e-01*_Complex_I, -7.5405e-01 + -1.0716e+00*_Complex_I, -5.8636e-01 + -1.0663e+00*_Complex_I, -8.3409e-01 + -6.2296e-01*_Complex_I, -7.5222e-01 + -7.6536e-01*_Complex_I, -9.1403e-01 + 1.0898e-01*_Complex_I, -9.1712e-01 + -1.8842e-01*_Complex_I, -9.1470e-01 + -4.7918e-01*_Complex_I, -9.8965e-01 + -3.3463e-01*_Complex_I, -5.9594e-01 + 1.2959e+00*_Complex_I, -5.8407e-01 + 9.7847e-01*_Complex_I, -7.5480e-01 + 6.8214e-01*_Complex_I, -6.6815e-01 + 8.2880e-01*_Complex_I, -8.3654e-01 + 2.4948e-01*_Complex_I, -9.9781e-01 + 2.5965e-01*_Complex_I, -8.3730e-01 + 5.3876e-01*_Complex_I, -9.1612e-01 + 3.9942e-01*_Complex_I, -1.6318e-01 + -1.2127e+00*_Complex_I, 3.3430e-03 + -1.2073e+00*_Complex_I, -1.5729e-01 + -6.1725e-01*_Complex_I, 4.1148e-03 + -9.0838e-01*_Complex_I, 1.7582e-01 + -3.3603e-01*_Complex_I, 9.8785e-03 + -3.7206e-02*_Complex_I, -8.5107e-02 + -4.7781e-01*_Complex_I, -1.5814e-01 + -4.2120e-02*_Complex_I, -7.2012e-02 + 1.2831e+00*_Complex_I, 9.0714e-04 + 1.1297e+00*_Complex_I, -7.8182e-02 + 6.8626e-01*_Complex_I, -1.5437e-01 + 8.2912e-01*_Complex_I, 5.1610e-01 + -3.3653e-02*_Complex_I, 1.2961e+00 + 4.0304e-01*_Complex_I, -5.9161e-03 + 5.4276e-01*_Complex_I, -1.6148e-01 + 2.5858e-01*_Complex_I, -8.4651e-02 + -1.3668e+00*_Complex_I, -3.2532e-01 + -9.1229e-01*_Complex_I, -3.2442e-01 + -6.1566e-01*_Complex_I, -1.6208e-01 + -9.0614e-01*_Complex_I, 1.8048e-01 + -3.7457e-02*_Complex_I, 1.3866e+00 + -3.3074e-01*_Complex_I, -2.4797e-01 + -4.7456e-01*_Complex_I, -2.4267e-01 + -1.8754e-01*_Complex_I, -1.6601e-01 + 1.4313e+00*_Complex_I, -1.6374e-01 + 1.1268e+00*_Complex_I, -2.4284e-01 + 6.8228e-01*_Complex_I, -3.1958e-01 + 8.2714e-01*_Complex_I, 1.4029e+00 + -4.1466e-02*_Complex_I, -2.4744e-01 + 1.0415e-01*_Complex_I, -1.7024e-01 + 5.3942e-01*_Complex_I, -2.4815e-01 + 3.9378e-01*_Complex_I, -3.3086e-01 + -1.2116e+00*_Complex_I, -4.1344e-01 + -1.0631e+00*_Complex_I, -4.9938e-01 + -6.1504e-01*_Complex_I, -5.7571e-01 + -7.6257e-01*_Complex_I, -4.9789e-01 + -3.2872e-01*_Complex_I, -5.7916e-01 + -1.9183e-01*_Complex_I, -5.7533e-01 + -4.6997e-01*_Complex_I, -6.6353e-01 + -3.3083e-01*_Complex_I, -4.1537e-01 + 1.2917e+00*_Complex_I, -3.3797e-01 + 1.1288e+00*_Complex_I, -4.1372e-01 + 6.7949e-01*_Complex_I, -5.7762e-01 + 6.8425e-01*_Complex_I, -5.0299e-01 + -3.9519e-02*_Complex_I, -5.7735e-01 + 1.0080e-01*_Complex_I, -5.7869e-01 + 3.9486e-01*_Complex_I, -4.1708e-01 + 3.8814e-01*_Complex_I, -2.6216e-01 + -1.3722e+00*_Complex_I, -2.4777e-01 + -1.0554e+00*_Complex_I, -2.4828e-01 + -7.5682e-01*_Complex_I, -4.1106e-01 + -7.6293e-01*_Complex_I, -3.3539e-01 + -4.5041e-02*_Complex_I, -4.1183e-01 + -1.8648e-01*_Complex_I, -4.0960e-01 + -4.6924e-01*_Complex_I, -3.2757e-01 + -3.2493e-01*_Complex_I, -2.4811e-01 + 1.2791e+00*_Complex_I, -4.1293e-01 + 9.7796e-01*_Complex_I, -4.9363e-01 + 5.4125e-01*_Complex_I, -2.4841e-01 + 9.7484e-01*_Complex_I, -3.3291e-01 + 2.4287e-01*_Complex_I, -4.1270e-01 + 1.0610e-01*_Complex_I, -3.3149e-01 + 5.3493e-01*_Complex_I, -4.9570e-01 + 2.4793e-01*_Complex_I, 1.0268e+00 + -9.4120e-01*_Complex_I, 1.1117e+00 + -7.9063e-01*_Complex_I, 1.0229e+00 + -6.2590e-01*_Complex_I, 1.1972e+00 + -6.4225e-01*_Complex_I, 1.1800e+00 + -3.7594e-02*_Complex_I, 1.0994e+00 + -1.8428e-01*_Complex_I, 1.1013e+00 + -4.8132e-01*_Complex_I, 1.1761e+00 + -3.3277e-01*_Complex_I, 9.5265e-01 + 9.9923e-01*_Complex_I, 1.0339e+00 + 8.4543e-01*_Complex_I, 1.1967e+00 + 5.5722e-01*_Complex_I, 1.1136e+00 + 7.0186e-01*_Complex_I, 1.1048e+00 + 1.1370e-01*_Complex_I, 1.1933e+00 + 2.5489e-01*_Complex_I, 1.0283e+00 + 5.4096e-01*_Complex_I, 1.1081e+00 + 3.9628e-01*_Complex_I, 7.8700e-01 + -1.0692e+00*_Complex_I, 8.5334e-01 + -9.1694e-01*_Complex_I, 8.5637e-01 + -6.2050e-01*_Complex_I, 9.3281e-01 + -7.7176e-01*_Complex_I, 1.0137e+00 + -3.3408e-02*_Complex_I, 9.3260e-01 + -1.7917e-01*_Complex_I, 9.3071e-01 + -4.7454e-01*_Complex_I, 1.0048e+00 + -3.2937e-01*_Complex_I, 8.6318e-01 + 1.1482e+00*_Complex_I, 7.7447e-01 + 9.8650e-01*_Complex_I, 8.5413e-01 + 5.5129e-01*_Complex_I, 9.3949e-01 + 6.9420e-01*_Complex_I, 8.5475e-01 + -2.3510e-02*_Complex_I, 9.3037e-01 + 1.2129e-01*_Complex_I, 9.3010e-01 + 4.0514e-01*_Complex_I, 1.0095e+00 + 2.6363e-01*_Complex_I, 5.2780e-01 + -1.2149e+00*_Complex_I, 5.9973e-01 + -1.0535e+00*_Complex_I, 5.9400e-01 + -7.5805e-01*_Complex_I, 5.2055e-01 + -9.0495e-01*_Complex_I, 1.2793e+00 + 9.5945e-02*_Complex_I, 6.0607e-01 + -1.8528e-01*_Complex_I, 6.0178e-01 + -4.7516e-01*_Complex_I, 6.7818e-01 + -3.2877e-01*_Complex_I, 6.0752e-01 + 1.2941e+00*_Complex_I, 6.0140e-01 + 9.9091e-01*_Complex_I, 5.9529e-01 + 6.9382e-01*_Complex_I, 5.2016e-01 + 8.4000e-01*_Complex_I, 6.0208e-01 + 1.1391e-01*_Complex_I, 6.7047e-01 + 2.5780e-01*_Complex_I, 5.2294e-01 + 5.4883e-01*_Complex_I, 5.9654e-01 + 4.0163e-01*_Complex_I, 7.0156e-01 + -1.2190e+00*_Complex_I, 6.9013e-01 + -9.1191e-01*_Complex_I, 6.9013e-01 + -6.2098e-01*_Complex_I, 7.6463e-01 + -7.6594e-01*_Complex_I, 6.9136e-01 + -3.6954e-02*_Complex_I, 7.6789e-01 + -1.7954e-01*_Complex_I, 7.6457e-01 + -4.7424e-01*_Complex_I, 8.3961e-01 + -3.2637e-01*_Complex_I, 6.8917e-01 + 1.1431e+00*_Complex_I, 8.5163e-01 + 8.4194e-01*_Complex_I, 7.6086e-01 + 6.8960e-01*_Complex_I, 6.8618e-01 + 8.3840e-01*_Complex_I, 7.6026e-01 + 1.0911e-01*_Complex_I, 8.3319e-01 + 2.5542e-01*_Complex_I, 6.8351e-01 + 5.4604e-01*_Complex_I, 7.5901e-01 + 4.0203e-01*_Complex_I, 9.6338e-02 + -1.3604e+00*_Complex_I, -7.0831e-02 + -1.0602e+00*_Complex_I, -9.4577e-04 + -6.3305e-01*_Complex_I, -6.9734e-02 + -7.6470e-01*_Complex_I, 4.2835e-01 + -4.6668e-01*_Complex_I, 3.4710e-01 + -3.3413e-01*_Complex_I, -1.5430e-01 + -3.3941e-01*_Complex_I, 8.0032e-02 + -1.7572e-01*_Complex_I, 2.5905e-02 + 1.4320e+00*_Complex_I, -6.9530e-02 + 9.7883e-01*_Complex_I, 1.7048e-01 + 8.2571e-01*_Complex_I, 1.0068e-02 + 8.3542e-01*_Complex_I, 3.4137e-01 + 2.5976e-01*_Complex_I, 9.5063e-02 + 1.1412e-01*_Complex_I, -7.6478e-02 + 4.0262e-01*_Complex_I, 1.3861e+00 + 2.4822e-01*_Complex_I, 1.8256e-01 + -1.2079e+00*_Complex_I, 9.5999e-02 + -1.0579e+00*_Complex_I, 1.7231e-01 + -6.3492e-01*_Complex_I, 9.5184e-02 + -7.6915e-01*_Complex_I, 4.2346e-01 + -1.8043e-01*_Complex_I, 3.4732e-01 + -3.9482e-02*_Complex_I, 6.7179e-03 + -3.3361e-01*_Complex_I, 1.2869e+00 + -4.7883e-01*_Complex_I, 1.0396e-01 + 1.2834e+00*_Complex_I, 1.7477e-01 + 1.1309e+00*_Complex_I, 9.3443e-02 + 6.8396e-01*_Complex_I, 1.0164e-01 + 9.8006e-01*_Complex_I, 2.6248e-01 + 4.0262e-01*_Complex_I, 1.4300e-02 + 2.5562e-01*_Complex_I, 1.7725e-01 + 5.4449e-01*_Complex_I, 1.7520e-01 + 2.5568e-01*_Complex_I, 3.5711e-01 + -1.2043e+00*_Complex_I, 4.3106e-01 + -1.0550e+00*_Complex_I, 4.3130e-01 + -7.5874e-01*_Complex_I, 3.5671e-01 + -9.0533e-01*_Complex_I, 1.2810e+00 + -1.8054e-01*_Complex_I, 2.5776e-01 + -4.7036e-01*_Complex_I, 5.1032e-01 + -6.1269e-01*_Complex_I, 5.1825e-01 + -3.2616e-01*_Complex_I, 4.3563e-01 + 1.2900e+00*_Complex_I, 5.0429e-01 + 1.1325e+00*_Complex_I, 4.3124e-01 + 6.9057e-01*_Complex_I, 4.2828e-01 + 9.7727e-01*_Complex_I, 2.6878e-01 + 1.1645e-01*_Complex_I, 5.1065e-01 + 2.5785e-01*_Complex_I, 3.5648e-01 + 5.4453e-01*_Complex_I, 4.3802e-01 + 4.0358e-01*_Complex_I, 2.8096e-01 + -1.3583e+00*_Complex_I, 2.6017e-01 + -1.0511e+00*_Complex_I, 2.6553e-01 + -7.5915e-01*_Complex_I, 1.8554e-01 + -9.0436e-01*_Complex_I, 2.7459e-01 + -1.6584e-01*_Complex_I, 9.6288e-02 + -4.7108e-01*_Complex_I, 3.4524e-01 + -6.2309e-01*_Complex_I, -7.6534e-02 + -1.8689e-01*_Complex_I, 2.6953e-01 + 1.2917e+00*_Complex_I, 3.3760e-01 + 1.1286e+00*_Complex_I, 3.3928e-01 + 8.2592e-01*_Complex_I, 2.6659e-01 + 9.7456e-01*_Complex_I, 4.2936e-01 + 1.1261e-01*_Complex_I, 9.1148e-02 + 4.0330e-01*_Complex_I, 2.6333e-01 + 6.7210e-01*_Complex_I, -7.8413e-02 + 1.1615e-01*_Complex_I, }; liquid-dsp-1.3.1/src/modem/src/modem_ask.c000066400000000000000000000070161317124540100203530ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // modem_ask.c // // create an ask (amplitude-shift keying) modem object MODEM() MODEM(_create_ask)(unsigned int _bits_per_symbol) { MODEM() q = (MODEM()) malloc( sizeof(struct MODEM(_s)) ); MODEM(_init)(q, _bits_per_symbol); switch (q->M) { case 2: q->data.ask.alpha = ASK2_ALPHA; q->scheme = LIQUID_MODEM_ASK2; break; case 4: q->data.ask.alpha = ASK4_ALPHA; q->scheme = LIQUID_MODEM_ASK4; break; case 8: q->data.ask.alpha = ASK8_ALPHA; q->scheme = LIQUID_MODEM_ASK8; break; case 16: q->data.ask.alpha = ASK16_ALPHA; q->scheme = LIQUID_MODEM_ASK16; break; case 32: q->data.ask.alpha = ASK32_ALPHA; q->scheme = LIQUID_MODEM_ASK32; break; case 64: q->data.ask.alpha = ASK64_ALPHA; q->scheme = LIQUID_MODEM_ASK64; break; case 128: q->data.ask.alpha = ASK128_ALPHA; q->scheme = LIQUID_MODEM_ASK128; break; case 256: q->data.ask.alpha = ASK256_ALPHA; q->scheme = LIQUID_MODEM_ASK256; break; default: #if 0 // calculate alpha dynamically q->data.ask.alpha = expf(-0.70735 + 0.63653*q->m); #else fprintf(stderr,"error: modem_create_ask(), cannot support ASK with m > 8\n"); exit(1); #endif } unsigned int k; for (k=0; k<(q->m); k++) q->ref[k] = (1<data.ask.alpha; q->modulate_func = &MODEM(_modulate_ask); q->demodulate_func = &MODEM(_demodulate_ask); // initialize soft-demodulation look-up table if (q->m >= 2 && q->m < 8) MODEM(_demodsoft_gentab)(q, 2); // reset modem and return MODEM(_reset)(q); return q; } // modulate ASK void MODEM(_modulate_ask)(MODEM() _q, unsigned int _sym_in, TC * _y) { // 'encode' input symbol (actually gray decoding) _sym_in = gray_decode(_sym_in); // modulate symbol *_y = (2*(int)_sym_in - (int)(_q->M) + 1) * _q->data.ask.alpha; } // demodulate ASK void MODEM(_demodulate_ask)(MODEM() _q, TC _x, unsigned int * _sym_out) { // demodulate on linearly-spaced array unsigned int s; T res_i; MODEM(_demodulate_linear_array_ref)(crealf(_x), _q->m, _q->ref, &s, &res_i); // 'decode' output symbol (actually gray encoding) *_sym_out = gray_encode(s); // re-modulate symbol and store state MODEM(_modulate_ask)(_q, *_sym_out, &_q->x_hat); _q->r = _x; } liquid-dsp-1.3.1/src/modem/src/modem_bpsk.c000066400000000000000000000057701317124540100205410ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // modem_bpsk.c : specific BPSK modem // #include #include #include #include #include #include "liquid.internal.h" // create a bpsk (binary phase-shift keying) modem object MODEM() MODEM(_create_bpsk)() { MODEM() q = (MODEM()) malloc( sizeof(struct MODEM(_s)) ); q->scheme = LIQUID_MODEM_BPSK; MODEM(_init)(q, 1); q->modulate_func = &MODEM(_modulate_bpsk); q->demodulate_func = &MODEM(_demodulate_bpsk); // reset and return MODEM(_reset)(q); return q; } // modulate BPSK void MODEM(_modulate_bpsk)(MODEM() _q, unsigned int _sym_in, TC * _y) { // compute output sample directly from input *_y = _sym_in ? -1.0f : 1.0f; } // demodulate BPSK void MODEM(_demodulate_bpsk)(MODEM() _q, TC _x, unsigned int * _sym_out) { // slice directly to output symbol *_sym_out = (crealf(_x) > 0 ) ? 0 : 1; // re-modulate symbol and store state MODEM(_modulate_bpsk)(_q, *_sym_out, &_q->x_hat); _q->r = _x; } // demodulate BPSK (soft) void MODEM(_demodulate_soft_bpsk)(MODEM() _q, TC _x, unsigned int * _s, unsigned char * _soft_bits) { // gamma = 1/(2*sigma^2), approximate for constellation size T gamma = 4.0f; // approximate log-likelihood ratio T LLR = -2.0f * crealf(_x) * gamma; int soft_bit = LLR*16 + 127; if (soft_bit > 255) soft_bit = 255; if (soft_bit < 0) soft_bit = 0; _soft_bits[0] = (unsigned char) ( soft_bit ); // re-modulate symbol and store state unsigned int symbol_out = (crealf(_x) > 0 ) ? 0 : 1; MODEM(_modulate_bpsk)(_q, symbol_out, &_q->x_hat); _q->r = _x; *_s = symbol_out; } liquid-dsp-1.3.1/src/modem/src/modem_common.c000066400000000000000000000556401317124540100210730ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // modem_common.c : common utilities specific to precision // #include #include #include #include "liquid.internal.h" #define DEBUG_DEMODULATE_SOFT 0 // modem structure used for both modulation and demodulation // // The modem structure implements a variety of common modulation schemes, // including (differential) phase-shift keying, and (quadrature) amplitude // modulation. // // While the same modem structure may be used for both modulation and // demodulation for most schemes, it is important to use separate objects // for differential-mode modems (e.g. LIQUID_MODEM_DPSK) as the internal state // will change after each symbol. It is usually good practice to keep // separate instances of modulators and demodulators. struct MODEM(_s) { // common data modulation_scheme scheme; // modulation scheme unsigned int m; // bits per symbol (modulation depth) unsigned int M; // constellation size, M=2^m // Reference vector for demodulating linear arrays // // By storing these values in an array they do not need to be // calculated during run-time. This speeds up the demodulation by // approximately 8%. T ref[MAX_MOD_BITS_PER_SYMBOL]; // modulation TC * symbol_map; // complete symbol map int modulate_using_map; // modulate using map (look-up table) flag // demodulation TC r; // received state vector TC x_hat; // estimated symbol (demodulator) // common data structure shared between specific modem types union { // PSK modem struct { T d_phi; // half of phase between symbols T alpha; // scaling factor for phase symbols } psk; // DPSK modem struct { T d_phi; // half of phase between symbols T phi; // angle state for differential PSK T alpha; // scaling factor for phase symbols } dpsk; // ASK modem struct { T alpha; // scaling factor to ensure unity energy } ask; // QAM modem struct { unsigned int m_i; // bits per symbol, in-phase unsigned int m_q; // bits per symbol, quadrature unsigned int M_i; // in-phase dimension, M_i=2^{m_i} unsigned int M_q; // quadrature dimension, M_q=2^{m_q} T alpha; // scaling factor to ensure unity energy } qam; // APSK modem struct { unsigned int num_levels; // number of levels unsigned int p[8]; // number of symbols per level T r[8]; // radii of levels T r_slicer[8]; // slicer radii of levels T phi[8]; // phase offset of levels unsigned char * map; // symbol mapping (allocated) } apsk; // 'square' 32-QAM struct { TC * map; // 8-sample sub-map (first quadrant) } sqam32; // 'square' 128-QAM struct { TC * map; // 32-sample sub-map (first quadrant) } sqam128; } data; // modulate function pointer void (*modulate_func)(MODEM() _q, unsigned int _symbol_in, TC * _y); // demodulate function pointer void (*demodulate_func)(MODEM() _q, TC _x, unsigned int * _symbol_out); // soft demodulation //int demodulate_soft; // soft demodulation flag // neighbors array unsigned char * demod_soft_neighbors; // array of nearest neighbors unsigned int demod_soft_p; // number of neighbors in array }; // create digital modem of a specific scheme and bits/symbol MODEM() MODEM(_create)(modulation_scheme _scheme) { switch (_scheme) { // Phase-shift keying (PSK) case LIQUID_MODEM_PSK2: return MODEM(_create_psk)(1); case LIQUID_MODEM_PSK4: return MODEM(_create_psk)(2); case LIQUID_MODEM_PSK8: return MODEM(_create_psk)(3); case LIQUID_MODEM_PSK16: return MODEM(_create_psk)(4); case LIQUID_MODEM_PSK32: return MODEM(_create_psk)(5); case LIQUID_MODEM_PSK64: return MODEM(_create_psk)(6); case LIQUID_MODEM_PSK128: return MODEM(_create_psk)(7); case LIQUID_MODEM_PSK256: return MODEM(_create_psk)(8); // Differential phase-shift keying (DPSK) case LIQUID_MODEM_DPSK2: return MODEM(_create_dpsk)(1); case LIQUID_MODEM_DPSK4: return MODEM(_create_dpsk)(2); case LIQUID_MODEM_DPSK8: return MODEM(_create_dpsk)(3); case LIQUID_MODEM_DPSK16: return MODEM(_create_dpsk)(4); case LIQUID_MODEM_DPSK32: return MODEM(_create_dpsk)(5); case LIQUID_MODEM_DPSK64: return MODEM(_create_dpsk)(6); case LIQUID_MODEM_DPSK128: return MODEM(_create_dpsk)(7); case LIQUID_MODEM_DPSK256: return MODEM(_create_dpsk)(8); // amplitude-shift keying (ASK) case LIQUID_MODEM_ASK2: return MODEM(_create_ask)(1); case LIQUID_MODEM_ASK4: return MODEM(_create_ask)(2); case LIQUID_MODEM_ASK8: return MODEM(_create_ask)(3); case LIQUID_MODEM_ASK16: return MODEM(_create_ask)(4); case LIQUID_MODEM_ASK32: return MODEM(_create_ask)(5); case LIQUID_MODEM_ASK64: return MODEM(_create_ask)(6); case LIQUID_MODEM_ASK128: return MODEM(_create_ask)(7); case LIQUID_MODEM_ASK256: return MODEM(_create_ask)(8); // rectangular quadrature amplitude-shift keying (QAM) case LIQUID_MODEM_QAM4: return MODEM(_create_qam)(2); case LIQUID_MODEM_QAM8: return MODEM(_create_qam)(3); case LIQUID_MODEM_QAM16: return MODEM(_create_qam)(4); case LIQUID_MODEM_QAM32: return MODEM(_create_qam)(5); case LIQUID_MODEM_QAM64: return MODEM(_create_qam)(6); case LIQUID_MODEM_QAM128: return MODEM(_create_qam)(7); case LIQUID_MODEM_QAM256: return MODEM(_create_qam)(8); // amplitude phase-shift keying (APSK) case LIQUID_MODEM_APSK4: return MODEM(_create_apsk)(2); case LIQUID_MODEM_APSK8: return MODEM(_create_apsk)(3); case LIQUID_MODEM_APSK16: return MODEM(_create_apsk)(4); case LIQUID_MODEM_APSK32: return MODEM(_create_apsk)(5); case LIQUID_MODEM_APSK64: return MODEM(_create_apsk)(6); case LIQUID_MODEM_APSK128: return MODEM(_create_apsk)(7); case LIQUID_MODEM_APSK256: return MODEM(_create_apsk)(8); // specific modems case LIQUID_MODEM_BPSK: return MODEM(_create_bpsk)(); case LIQUID_MODEM_QPSK: return MODEM(_create_qpsk)(); case LIQUID_MODEM_OOK: return MODEM(_create_ook)(); case LIQUID_MODEM_SQAM32: return MODEM(_create_sqam32)(); case LIQUID_MODEM_SQAM128: return MODEM(_create_sqam128)(); case LIQUID_MODEM_V29: return MODEM(_create_V29)(); case LIQUID_MODEM_ARB16OPT: return MODEM(_create_arb16opt)(); case LIQUID_MODEM_ARB32OPT: return MODEM(_create_arb32opt)(); case LIQUID_MODEM_ARB64OPT: return MODEM(_create_arb64opt)(); case LIQUID_MODEM_ARB128OPT: return MODEM(_create_arb128opt)(); case LIQUID_MODEM_ARB256OPT: return MODEM(_create_arb256opt)(); case LIQUID_MODEM_ARB64VT: return MODEM(_create_arb64vt)(); // arbitrary modem case LIQUID_MODEM_ARB: fprintf(stderr,"error: modem_create(), cannot create arbitrary modem (LIQUID_MODEM_ARB) without specifying constellation\n"); exit(1); // unknown modulation scheme default: fprintf(stderr,"error: modem_create(), unknown/unsupported modulation scheme : %u\n", _scheme); exit(1); } // should never get to this point, but adding return statment // to keep compiler happy return NULL; } // recreate modulation scheme, re-allocating memory as necessary MODEM() MODEM(_recreate)(MODEM() _q, modulation_scheme _scheme) { // TODO : regenerate modem only when truly necessary if (_q->scheme != _scheme) { // destroy and re-create modem MODEM(_destroy)(_q); _q = MODEM(_create)(_scheme); } // return object return _q; } // destroy a modem object void MODEM(_destroy)(MODEM() _q) { // free symbol map if (_q->symbol_map != NULL) free(_q->symbol_map); // free soft-demodulation neighbors table if (_q->demod_soft_neighbors != NULL) free(_q->demod_soft_neighbors); // free memory in specific data types if (_q->scheme == LIQUID_MODEM_SQAM32) { free(_q->data.sqam32.map); } else if (_q->scheme == LIQUID_MODEM_SQAM128) { free(_q->data.sqam128.map); } else if (liquid_modem_is_apsk(_q->scheme)) { free(_q->data.apsk.map); } // free main object memory free(_q); } // print a modem object void MODEM(_print)(MODEM() _q) { printf("linear modem:\n"); printf(" scheme: %s\n", modulation_types[_q->scheme].name); printf(" bits/symbol: %u\n", _q->m); } // reset a modem object (only an issue with dpsk) void MODEM(_reset)(MODEM() _q) { _q->r = 1.0f; // received sample _q->x_hat = _q->r; // estimated symbol if ( liquid_modem_is_dpsk(_q->scheme) ) _q->data.dpsk.phi = 0.0f; // reset differential PSK phase state } // initialize a generic modem object void MODEM(_init)(MODEM() _q, unsigned int _bits_per_symbol) { if (_bits_per_symbol < 1 ) { fprintf(stderr,"error: modem_init(), modem must have at least 1 bit/symbol\n"); exit(1); } else if (_bits_per_symbol > MAX_MOD_BITS_PER_SYMBOL) { fprintf(stderr,"error: modem_init(), maximum number of bits per symbol exceeded\n"); exit(1); } // initialize common elements _q->symbol_map = NULL; // symbol map (LIQUID_MODEM_ARB only) _q->modulate_using_map=0; // modulate using map flag // common data _q->m = _bits_per_symbol; // bits/symbol _q->M = 1 << (_q->m); // constellation size (2^m) // set function pointers initially to NULL _q->modulate_func = NULL; _q->demodulate_func = NULL; // soft demodulation _q->demod_soft_neighbors = NULL; _q->demod_soft_p = 0; } // initialize symbol map for fast modulation void MODEM(_init_map)(MODEM() _q) { // validate input if (_q->symbol_map == NULL) { fprintf(stderr,"error: modem_init_map(), symbol map array has not been allocated\n"); exit(1); } else if (_q->M == 0 || _q->M > (1<modulate_func == NULL) { fprintf(stderr,"error: modem_init_map(), modulation function has not been initialized\n"); exit(1); } unsigned int i; for (i=0; i<_q->M; i++) _q->modulate_func(_q, i, &_q->symbol_map[i]); } // Generate random symbol unsigned int MODEM(_gen_rand_sym)(MODEM() _q) { return rand() % (_q->M); } // Get modem depth (bits/symbol) unsigned int MODEM(_get_bps)(MODEM() _q) { return _q->m; } // get modulation scheme modulation_scheme MODEM(_get_scheme)(MODEM() _q) { return _q->scheme; } // generic modulatio function // _q : modem object // _symbol_in : input symbol // _y : output sample void MODEM(_modulate)(MODEM() _q, unsigned int _symbol_in, TC * _y) { // validate input if (_symbol_in >= _q->M) { fprintf(stderr,"error: modem_modulate(), input symbol exceeds constellation size\n"); exit(1); } if (_q->modulate_using_map) { // modulate simply using map (look-up table) MODEM(_modulate_map)(_q, _symbol_in, _y); } else { // invoke method specific to scheme (calculate symbol on the fly) _q->modulate_func(_q, _symbol_in, _y); } } // modulate using symbol map (look-up table) void MODEM(_modulate_map)(MODEM() _q, unsigned int _symbol_in, TC * _y) { if (_symbol_in >= _q->M) { fprintf(stderr,"error: modem_modulate_table(), input symbol exceeds maximum\n"); exit(1); } else if (_q == NULL) { fprintf(stderr,"error: modem_modulate_table(), symbol table not initialized\n"); exit(1); } // map sample directly to output *_y = _q->symbol_map[_symbol_in]; } // generic demodulation void MODEM(_demodulate)(MODEM() _q, TC x, unsigned int *symbol_out) { // invoke method specific to scheme (calculate symbol on the fly) _q->demodulate_func(_q, x, symbol_out); } // generic soft demodulation void MODEM(_demodulate_soft)(MODEM() _q, TC _x, unsigned int * _s, unsigned char * _soft_bits) { // switch scheme switch (_q->scheme) { case LIQUID_MODEM_ARB: MODEM(_demodulate_soft_arb)( _q,_x,_s,_soft_bits); return; case LIQUID_MODEM_BPSK: MODEM(_demodulate_soft_bpsk)(_q,_x,_s,_soft_bits); return; case LIQUID_MODEM_QPSK: MODEM(_demodulate_soft_qpsk)(_q,_x,_s,_soft_bits); return; default:; } // check if... if (_q->demod_soft_neighbors != NULL && _q->demod_soft_p != 0) { // demodulate using approximate log-likelihood method with // look-up table for nearest neighbors MODEM(_demodulate_soft_table)(_q, _x, _s, _soft_bits); return; } // for now demodulate normally and simply copy the // hard-demodulated bits unsigned int symbol_out; _q->demodulate_func(_q, _x, &symbol_out); *_s = symbol_out; // unpack soft bits liquid_unpack_soft_bits(symbol_out, _q->m, _soft_bits); } #if DEBUG_DEMODULATE_SOFT // print a string of bits to the standard output void print_bitstring_demod_soft(unsigned int _x, unsigned int _n) { unsigned int i; for (i=0; i<_n; i++) printf("%1u", (_x >> (_n-i-1)) & 1); } #endif // generic soft demodulation using look-up table... // _q : demodulator object // _r : received sample // _s : hard demodulator output // _soft_bits : soft bit ouput (approximate log-likelihood ratio) void MODEM(_demodulate_soft_table)(MODEM() _q, TC _r, unsigned int * _s, unsigned char * _soft_bits) { // run hard demodulation; this will store re-modulated sample // as internal variable x_hat unsigned int s; MODEM(_demodulate)(_q, _r, &s); unsigned int bps = MODEM(_get_bps)(_q); // gamma = 1/(2*sigma^2), approximate for constellation size T gamma = 1.2f*_q->M; // set and initialize minimum bit values unsigned int i; unsigned int k; T dmin_0[bps]; T dmin_1[bps]; for (k=0; kdemod_soft_neighbors; unsigned int p = _q->demod_soft_p; // check hard demodulation d = crealf( (_r-_q->x_hat)*conjf(_r-_q->x_hat) ); for (k=0; k> (bps-k-1)) & 0x01; if (bit) dmin_1[k] = d; else dmin_0[k] = d; } // parse all 'nearest neighbors' and find minimum distance for each bit for (i=0; imodulate_using_map) x_hat = _q->symbol_map[ softab[s*p + i] ]; else MODEM(_modulate)(_q, softab[s*p+i], &x_hat); // compute magnitude squared of Euclidean distance //d = crealf( (_r-x_hat)*conjf(_r-x_hat) ); // (same as above, but faster) TC e = _r - x_hat; d = crealf(e)*crealf(e) + cimagf(e)*cimagf(e); // look at each bit in 'nearest neighbor' and update minimum for (k=0; k> (bps-k-1)) & 0x01; if ( bit ) { if (d < dmin_1[k]) dmin_1[k] = d; } else { if (d < dmin_0[k]) dmin_0[k] = d; } } } // make soft bit assignments for (k=0; k 255) soft_bit = 255; if (soft_bit < 0) soft_bit = 0; _soft_bits[k] = (unsigned char)soft_bit; } // set hard output symbol *_s = s; } // get demodulator's estimated transmit sample void MODEM(_get_demodulator_sample)(MODEM() _q, TC * _x_hat) { *_x_hat = _q->x_hat; } // get demodulator phase error T MODEM(_get_demodulator_phase_error)(MODEM() _q) { return cimagf(_q->r*conjf(_q->x_hat)); } // get error vector magnitude T MODEM(_get_demodulator_evm)(MODEM() _q) { return cabsf(_q->x_hat - _q->r); } // Demodulate a linear symbol constellation using dynamic threshold calculation // _v : input value // _m : bits per symbol // _alpha : scaling factor // _s : demodulated symbol // _res : residual void MODEM(_demodulate_linear_array)(T _v, unsigned int _m, T _alpha, unsigned int * _s, T * _res) { unsigned int s=0; unsigned int i, k = _m; T ref=0.0f; for (i=0; i<_m; i++) { s <<= 1; s |= (_v > 0) ? 1 : 0; ref = _alpha * (1<<(k-1)); _v += (_v < 0) ? ref : -ref; k--; } *_s = s; *_res = _v; } // Demodulate a linear symbol constellation using refereneced lookup table // _v : input value // _m : bits per symbol // _ref : array of thresholds // _s : demodulated symbol // _res : residual void MODEM(_demodulate_linear_array_ref)(T _v, unsigned int _m, T * _ref, unsigned int * _s, T * _res) { // initialize loop counter register unsigned int i; // initialize demodulated symbol register unsigned int s=0; for (i=0; i<_m; i++) { // prepare symbol for next demodulated bit s <<= 1; // compare received value to zero if ( _v > 0 ) { // shift '1' into symbol, subtract reference s |= 1; _v -= _ref[_m-i-1]; } else { // shift '0' into symbol, add reference s |= 0; _v += _ref[_m-i-1]; } } // return demodulated symbol *_s = s; // return residual *_res = _v; } // generate soft demodulation look-up table void MODEM(_demodsoft_gentab)(MODEM() _q, unsigned int _p) { // validate input: ensure number of nearest symbols is not too large if (_p > (_q->M-1)) { fprintf(stderr,"error: modem_demodsoft_gentab(), requesting too many neighbors\n"); exit(1); } // allocate internal memory _q->demod_soft_p = _p; _q->demod_soft_neighbors = (unsigned char*)malloc(_q->M*_p*sizeof(unsigned char)); unsigned int i; unsigned int j; unsigned int k; // generate constellation // TODO : enforce full constellation for modulation unsigned int M = _q->M; // constellation size TC c[M]; // constellation for (i=0; idemod_soft_neighbors[i*_p + k] = M; } int symbol_valid; for (i=0; idemod_soft_neighbors[i*_p + l] == j ) symbol_valid = 0; } // compute distance T d = cabsf( c[i] - c[j] ); if ( d < dmin && symbol_valid ) { dmin = d; _q->demod_soft_neighbors[i*_p + k] = j; } } } } #if DEBUG_DEMODULATE_SOFT // // print results // unsigned int bps = _q->m; for (i=0; idemod_soft_neighbors[i*_p + k],bps); if (_q->demod_soft_neighbors[i*_p + k] < M) printf("(%6.4f)", cabsf( c[i]-c[_q->demod_soft_neighbors[i*_p+k]] )); else printf(" "); } printf("\n"); } // print c-type array printf("\n"); printf("// %s%u soft demodulation nearest neighbors (p=%u)\n", modulation_types[_q->scheme].name, M, _p); printf("const unsigned char %s%u_demod_soft_neighbors[%u] = {\n", modulation_types[_q->scheme].name, M, _p*M); printf(" "); for (i=0; idemod_soft_neighbors[i*_p+k]); if (k != _p-1) printf(","); } if (i != M-1) { printf(", // "); print_bitstring_demod_soft(i,bps); printf("\n "); } else { printf("}; // "); print_bitstring_demod_soft(i,bps); printf("\n\n"); } } #endif } liquid-dsp-1.3.1/src/modem/src/modem_dpsk.c000066400000000000000000000075431317124540100205430ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // modem_dpsk.c // // create a dpsk (differential phase-shift keying) modem object MODEM() MODEM(_create_dpsk)(unsigned int _bits_per_symbol) { MODEM() q = (MODEM()) malloc( sizeof(struct MODEM(_s)) ); switch (_bits_per_symbol) { case 1: q->scheme = LIQUID_MODEM_DPSK2; break; case 2: q->scheme = LIQUID_MODEM_DPSK4; break; case 3: q->scheme = LIQUID_MODEM_DPSK8; break; case 4: q->scheme = LIQUID_MODEM_DPSK16; break; case 5: q->scheme = LIQUID_MODEM_DPSK32; break; case 6: q->scheme = LIQUID_MODEM_DPSK64; break; case 7: q->scheme = LIQUID_MODEM_DPSK128; break; case 8: q->scheme = LIQUID_MODEM_DPSK256; break; default: fprintf(stderr,"error: modem_create_dpsk(), cannot support DPSK with m > 8\n"); exit(1); } MODEM(_init)(q, _bits_per_symbol); q->data.dpsk.alpha = M_PI/(T)(q->M); q->data.dpsk.phi = 0.0f; unsigned int k; for (k=0; k<(q->m); k++) q->ref[k] = (1<data.dpsk.alpha; q->data.dpsk.d_phi = M_PI*(1.0f - 1.0f/(T)(q->M)); q->modulate_func = &MODEM(_modulate_dpsk); q->demodulate_func = &MODEM(_demodulate_dpsk); // reset and return MODEM(_reset)(q); return q; } // modulate DPSK void MODEM(_modulate_dpsk)(MODEM() _q, unsigned int _sym_in, TC * _y) { // 'encode' input symbol (actually gray decoding) _sym_in = gray_decode(_sym_in); // compute phase difference between this symbol and the previous _q->data.dpsk.phi += _sym_in * 2 * _q->data.dpsk.alpha; // limit phase _q->data.dpsk.phi -= (_q->data.dpsk.phi > 2*M_PI) ? 2*M_PI : 0.0f; // compute output sample *_y = liquid_cexpjf(_q->data.dpsk.phi); // save symbol state _q->r = *_y; } void MODEM(_demodulate_dpsk)(MODEM() _q, TC _x, unsigned int * _sym_out) { // compute angle difference T theta = cargf(_x); T d_theta = cargf(_x) - _q->data.dpsk.phi; _q->data.dpsk.phi = theta; // subtract phase offset, ensuring phase is in [-pi,pi) d_theta -= _q->data.dpsk.d_phi; if (d_theta > M_PI) d_theta -= 2*M_PI; else if (d_theta < -M_PI) d_theta += 2*M_PI; // demodulate on linearly-spaced array unsigned int s; // demodulated symbol T demod_phase_error; // demodulation phase error MODEM(_demodulate_linear_array_ref)(d_theta, _q->m, _q->ref, &s, &demod_phase_error); // 'decode' output symbol (actually gray encoding) *_sym_out = gray_encode(s); // re-modulate symbol (accounting for differential rotation) // and store state _q->x_hat = liquid_cexpjf(theta - demod_phase_error); _q->r = _x; } liquid-dsp-1.3.1/src/modem/src/modem_ook.c000066400000000000000000000043531317124540100203660ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // modem_ook.c // #include #include #include #include #include #include "liquid.internal.h" // create an ook (on/off keying) modem object MODEM() MODEM(_create_ook)() { MODEM() q = (MODEM()) malloc( sizeof(struct MODEM(_s)) ); q->scheme = LIQUID_MODEM_OOK; MODEM(_init)(q, 1); q->modulate_func = &MODEM(_modulate_ook); q->demodulate_func = &MODEM(_demodulate_ook); // reset and return MODEM(_reset)(q); return q; } // modulate symbol using on/off keying void MODEM(_modulate_ook)(MODEM() _q, unsigned int _sym_in, float complex * _y) { // compute output sample directly from input *_y = _sym_in ? 0.0f : M_SQRT2; } // demodulate OOK void MODEM(_demodulate_ook)(MODEM() _q, float complex _x, unsigned int * _sym_out) { // slice directly to output symbol *_sym_out = (crealf(_x) > M_SQRT1_2 ) ? 0 : 1; // re-modulate symbol and store state MODEM(_modulate_ook)(_q, *_sym_out, &_q->x_hat); _q->r = _x; } liquid-dsp-1.3.1/src/modem/src/modem_psk.c000066400000000000000000000074651317124540100204020ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // modem_psk.c // // create a psk (phase-shift keying) modem object MODEM() MODEM(_create_psk)(unsigned int _bits_per_symbol) { MODEM() q = (MODEM()) malloc( sizeof(struct MODEM(_s)) ); switch (_bits_per_symbol) { case 1: q->scheme = LIQUID_MODEM_PSK2; break; case 2: q->scheme = LIQUID_MODEM_PSK4; break; case 3: q->scheme = LIQUID_MODEM_PSK8; break; case 4: q->scheme = LIQUID_MODEM_PSK16; break; case 5: q->scheme = LIQUID_MODEM_PSK32; break; case 6: q->scheme = LIQUID_MODEM_PSK64; break; case 7: q->scheme = LIQUID_MODEM_PSK128; break; case 8: q->scheme = LIQUID_MODEM_PSK256; break; default: fprintf(stderr,"error: modem_create_psk(), cannot support PSK with m > 8\n"); exit(1); } // initialize basic modem structure MODEM(_init)(q, _bits_per_symbol); // compute alpha q->data.psk.alpha = M_PI/(T)(q->M); // initialize demodulation array reference unsigned int k; for (k=0; k<(q->m); k++) q->ref[k] = (1<data.psk.alpha; // compute phase offset (half of phase difference between symbols) q->data.psk.d_phi = M_PI*(1.0f - 1.0f/(T)(q->M)); // set modulation/demodulation functions q->modulate_func = &MODEM(_modulate_psk); q->demodulate_func = &MODEM(_demodulate_psk); // initialize symbol map q->symbol_map = (TC*)malloc(q->M*sizeof(TC)); MODEM(_init_map)(q); q->modulate_using_map = 1; // initialize soft-demodulation look-up table if (q->m >= 3) MODEM(_demodsoft_gentab)(q, 2); // reset and return MODEM(_reset)(q); return q; } // modulate PSK void MODEM(_modulate_psk)(MODEM() _q, unsigned int _sym_in, TC * _y) { // 'encode' input symbol (actually gray decoding) _sym_in = gray_decode(_sym_in); // compute output sample *_y = liquid_cexpjf(_sym_in * 2 * _q->data.psk.alpha ); } // demodulate PSK void MODEM(_demodulate_psk)(MODEM() _q, TC _x, unsigned int * _sym_out) { // compute angle and subtract phase offset, ensuring phase is in [-pi,pi) T theta = cargf(_x); theta -= _q->data.psk.d_phi; if (theta < -M_PI) theta += 2*M_PI; // demodulate on linearly-spaced array unsigned int s; // demodulated symbol T demod_phase_error; // demodulation phase error MODEM(_demodulate_linear_array_ref)(theta, _q->m, _q->ref, &s, &demod_phase_error); // 'decode' output symbol (actually gray encoding) *_sym_out = gray_encode(s); // re-modulate symbol and store state MODEM(_modulate_psk)(_q, *_sym_out, &_q->x_hat); _q->r = _x; } liquid-dsp-1.3.1/src/modem/src/modem_qam.c000066400000000000000000000123221317124540100203470ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // modem_qam.c // #include // create a qam (quaternary amplitude-shift keying) modem object MODEM() MODEM(_create_qam)(unsigned int _bits_per_symbol) { if (_bits_per_symbol < 1 ) { fprintf(stderr,"error: modem_create_qam(), modem must have at least 2 bits/symbol\n"); exit(1); } MODEM() q = (MODEM()) malloc( sizeof(struct MODEM(_s)) ); MODEM(_init)(q, _bits_per_symbol); if (q->m % 2) { // rectangular qam q->data.qam.m_i = (q->m + 1) >> 1; q->data.qam.m_q = (q->m - 1) >> 1; } else { // square qam q->data.qam.m_i = q->m >> 1; q->data.qam.m_q = q->m >> 1; } q->data.qam.M_i = 1 << (q->data.qam.m_i); q->data.qam.M_q = 1 << (q->data.qam.m_q); assert(q->data.qam.m_i + q->data.qam.m_q == q->m); assert(q->data.qam.M_i * q->data.qam.M_q == q->M); switch (q->M) { case 4: q->data.qam.alpha = RQAM4_ALPHA; q->scheme = LIQUID_MODEM_QAM4; break; case 8: q->data.qam.alpha = RQAM8_ALPHA; q->scheme = LIQUID_MODEM_QAM8; break; case 16: q->data.qam.alpha = RQAM16_ALPHA; q->scheme = LIQUID_MODEM_QAM16; break; case 32: q->data.qam.alpha = RQAM32_ALPHA; q->scheme = LIQUID_MODEM_QAM32; break; case 64: q->data.qam.alpha = RQAM64_ALPHA; q->scheme = LIQUID_MODEM_QAM64; break; case 128: q->data.qam.alpha = RQAM128_ALPHA; q->scheme = LIQUID_MODEM_QAM128; break; case 256: q->data.qam.alpha = RQAM256_ALPHA; q->scheme = LIQUID_MODEM_QAM256; break; #if 0 case 512: q->data.qam.alpha = RQAM512_ALPHA; break; case 1024: q->data.qam.alpha = RQAM1024_ALPHA; break; case 2048: q->data.qam.alpha = RQAM2048_ALPHA; break; case 4096: q->data.qam.alpha = RQAM4096_ALPHA; break; default: // calculate alpha dynamically // NOTE: this is only an approximation q->data.qam.alpha = sqrtf(2.0f / (T)(q->M) ); #else default: fprintf(stderr,"error: modem_create_qam(), cannot support QAM with m > 8\n"); exit(1); #endif } unsigned int k; for (k=0; k<(q->m); k++) q->ref[k] = (1<data.qam.alpha; q->modulate_func = &MODEM(_modulate_qam); q->demodulate_func = &MODEM(_demodulate_qam); // initialize symbol map q->symbol_map = (TC*)malloc(q->M*sizeof(TC)); MODEM(_init_map)(q); q->modulate_using_map = 1; // initialize soft-demodulation look-up table if (q->m == 3) MODEM(_demodsoft_gentab)(q, 3); else if (q->m >= 4) MODEM(_demodsoft_gentab)(q, 4); // reset and return MODEM(_reset)(q); return q; } // modulate QAM void MODEM(_modulate_qam)(MODEM() _q, unsigned int _sym_in, TC * _y) { unsigned int s_i; // in-phase symbol unsigned int s_q; // quadrature symbol s_i = _sym_in >> _q->data.qam.m_q; s_q = _sym_in & ( (1<<_q->data.qam.m_q)-1 ); // 'encode' symbols (actually gray decoding) s_i = gray_decode(s_i); s_q = gray_decode(s_q); // compute output sample *_y = (2*(int)s_i - (int)(_q->data.qam.M_i) + 1) * _q->data.qam.alpha + (2*(int)s_q - (int)(_q->data.qam.M_q) + 1) * _q->data.qam.alpha * _Complex_I; } // demodulate QAM void MODEM(_demodulate_qam)(MODEM() _q, TC _x, unsigned int * _sym_out) { // demodulate in-phase component on linearly-spaced array unsigned int s_i; // in-phase symbol T res_i; // in-phase residual MODEM(_demodulate_linear_array_ref)(crealf(_x), _q->data.qam.m_i, _q->ref, &s_i, &res_i); // demodulate quadrature component on linearly-spaced array unsigned int s_q; // quadrature symbol T res_q; // quadrature residual MODEM(_demodulate_linear_array_ref)(cimagf(_x), _q->data.qam.m_q, _q->ref, &s_q, &res_q); // 'decode' output symbol (actually gray encoding) s_i = gray_encode(s_i); s_q = gray_encode(s_q); *_sym_out = ( s_i << _q->data.qam.m_q ) + s_q; // re-modulate symbol (subtract residual) and store state _q->x_hat = _x - (res_i + _Complex_I*res_q); _q->r = _x; } liquid-dsp-1.3.1/src/modem/src/modem_qpsk.c000066400000000000000000000065771317124540100205660ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // modem_qpsk.c // #include #include #include #include #include #include "liquid.internal.h" // create a qpsk (quaternary phase-shift keying) modem object MODEM() MODEM(_create_qpsk)() { MODEM() q = (MODEM()) malloc( sizeof(struct MODEM(_s)) ); q->scheme = LIQUID_MODEM_QPSK; MODEM(_init)(q, 2); q->modulate_func = &MODEM(_modulate_qpsk); q->demodulate_func = &MODEM(_demodulate_qpsk); // reset and return MODEM(_reset)(q); return q; } // modulate QPSK void MODEM(_modulate_qpsk)(MODEM() _q, unsigned int _sym_in, TC * _y) { // compute output sample directly from input *_y = (_sym_in & 0x01 ? -M_SQRT1_2 : M_SQRT1_2) + (_sym_in & 0x02 ? -M_SQRT1_2 : M_SQRT1_2)*_Complex_I; } // demodulate QPSK void MODEM(_demodulate_qpsk)(MODEM() _q, TC _x, unsigned int * _sym_out) { // slice directly to output symbol *_sym_out = (crealf(_x) > 0 ? 0 : 1) + (cimagf(_x) > 0 ? 0 : 2); // re-modulate symbol and store state MODEM(_modulate_qpsk)(_q, *_sym_out, &_q->x_hat); _q->r = _x; } // demodulate QPSK (soft) void MODEM(_demodulate_soft_qpsk)(MODEM() _q, TC _x, unsigned int * _s, unsigned char * _soft_bits) { // gamma = 1/(2*sigma^2), approximate for constellation size T gamma = 5.8f; // approximate log-likelihood ratios T LLR; int soft_bit; // compute soft value for first bit LLR = -2.0f * cimagf(_x) * gamma; soft_bit = LLR*16 + 127; if (soft_bit > 255) soft_bit = 255; if (soft_bit < 0) soft_bit = 0; _soft_bits[0] = (unsigned char) ( soft_bit ); // compute soft value for first bit LLR = -2.0f * crealf(_x) * gamma; soft_bit = LLR*16 + 127; if (soft_bit > 255) soft_bit = 255; if (soft_bit < 0) soft_bit = 0; _soft_bits[1] = (unsigned char) ( soft_bit ); // re-modulate symbol and store state *_s = (crealf(_x) > 0 ? 0 : 1) + (cimagf(_x) > 0 ? 0 : 2); MODEM(_modulate_qpsk)(_q, *_s, &_q->x_hat); _q->r = _x; } liquid-dsp-1.3.1/src/modem/src/modem_sqam128.c000066400000000000000000000075251317124540100207760ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // modem_sqam128.c // // create a 'square' 128-QAM modem object MODEM() MODEM(_create_sqam128)() { MODEM() q = (MODEM()) malloc( sizeof(struct MODEM(_s)) ); q->scheme = LIQUID_MODEM_SQAM128; MODEM(_init)(q, 7); // allocate memory for 32-point symbol map q->data.sqam128.map = (TC*) malloc( 32*sizeof(TC) ); #if T == float memmove(q->data.sqam128.map, modem_arb_sqam128, 32*sizeof(TC)); #endif // set modulation, demodulation functions q->modulate_func = &MODEM(_modulate_sqam128); q->demodulate_func = &MODEM(_demodulate_sqam128); // reset and return MODEM(_reset)(q); return q; } // modulate symbol with 'square' 128-QAM void MODEM(_modulate_sqam128)(MODEM() _q, unsigned int _sym_in, TC * _y) { // strip off most-significant two bits (quadrant) unsigned int quad = (_sym_in >> 5) & 0x03; // strip off least-significant 5 bits unsigned int s = _sym_in & 0x1f; TC p = _q->data.sqam128.map[s]; switch (quad) { case 0: *_y = p; return; case 1: *_y = conjf(p); return; case 2: *_y = -conjf(p); return; case 3: *_y = -p; return; default: // should never get to this point fprintf(stderr,"error: modem_modulate_sqam128(), logic error\n"); exit(1); } } // demodulate 'square' 128-QAM void MODEM(_demodulate_sqam128)(MODEM() _q, TC _x, unsigned int * _sym_out) { // determine quadrant and de-rotate to first quadrant // 10 | 00 // ---+--- // 11 | 01 unsigned int quad = 2*(crealf(_x) < 0.0f) + (cimagf(_x) < 0.0f); TC x_prime = _x; switch (quad) { case 0: x_prime = _x; break; case 1: x_prime = conjf(_x); break; case 2: x_prime = -conjf(_x); break; case 3: x_prime = -_x; break; default: // should never get to this point fprintf(stderr,"error: modem_demodulate_sqam128(), logic error\n"); exit(1); } //printf(" x = %12.8f +j*%12.8f, quad = %1u, r = %12.8f + j*%12.8f\n", // crealf(_x), cimagf(_x), quad, crealf(r), cimagf(r)); assert(crealf(x_prime) >= 0.0f); assert(cimagf(x_prime) >= 0.0f); // find symbol in map closest to x_prime T dmin = 0.0f; T d = 0.0f; unsigned int i; for (i=0; i<32; i++) { d = cabsf(x_prime - _q->data.sqam128.map[i]); if (i==0 || d < dmin) { dmin = d; *_sym_out = i; } } // add quadrant bits *_sym_out |= (quad << 5); // re-modulate symbol and store state MODEM(_modulate_sqam128)(_q, *_sym_out, &_q->x_hat); _q->r = _x; } liquid-dsp-1.3.1/src/modem/src/modem_sqam32.c000066400000000000000000000074721317124540100207110ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // modem_sqam32.c // // create a 'square' 32-QAM modem object MODEM() MODEM(_create_sqam32)() { MODEM() q = (MODEM()) malloc( sizeof(struct MODEM(_s)) ); q->scheme = LIQUID_MODEM_SQAM32; MODEM(_init)(q, 5); // allocate memory for 8-point symbol map q->data.sqam32.map = (TC*) malloc( 8*sizeof(TC) ); #if T == float memmove(q->data.sqam32.map, modem_arb_sqam32, 8*sizeof(TC)); #endif // set modulation, demodulation functions q->modulate_func = &MODEM(_modulate_sqam32); q->demodulate_func = &MODEM(_demodulate_sqam32); // reset and return MODEM(_reset)(q); return q; } // modulate symbol with 'square' 32-QAM void MODEM(_modulate_sqam32)(MODEM() _q, unsigned int _sym_in, TC * _y) { // strip off most-significant two bits (quadrant) unsigned int quad = (_sym_in >> 3) & 0x03; // strip off least-significant 3 bits unsigned int s = _sym_in & 0x07; TC p = _q->data.sqam32.map[s]; switch (quad) { case 0: *_y = p; return; case 1: *_y = conjf(p); return; case 2: *_y = -conjf(p); return; case 3: *_y = -p; return; default: // should never get to this point fprintf(stderr,"error: modem_modulate_sqam32(), logic error\n"); exit(1); } } // demodulate 'square' 32-QAM void MODEM(_demodulate_sqam32)(MODEM() _q, TC _x, unsigned int * _sym_out) { // determine quadrant and de-rotate to first quadrant // 10 | 00 // ---+--- // 11 | 01 unsigned int quad = 2*(crealf(_x) < 0.0f) + (cimagf(_x) < 0.0f); TC x_prime = _x; switch (quad) { case 0: x_prime = _x; break; case 1: x_prime = conjf(_x); break; case 2: x_prime = -conjf(_x); break; case 3: x_prime = -_x; break; default: // should never get to this point fprintf(stderr,"error: modem_demodulate_sqam32(), logic error\n"); exit(1); } //printf(" x = %12.8f +j*%12.8f, quad = %1u, r = %12.8f + j*%12.8f\n", // crealf(_x), cimagf(_x), quad, crealf(r), cimagf(r)); assert(crealf(x_prime) >= 0.0f); assert(cimagf(x_prime) >= 0.0f); // find symbol in map closest to x_prime T dmin = 0.0f; T d = 0.0f; unsigned int i; for (i=0; i<8; i++) { d = cabsf(x_prime - _q->data.sqam32.map[i]); if (i==0 || d < dmin) { dmin = d; *_sym_out = i; } } // add quadrant bits *_sym_out |= (quad << 3); // re-modulate symbol and store state MODEM(_modulate_sqam32)(_q, *_sym_out, &_q->x_hat); _q->r = _x; } liquid-dsp-1.3.1/src/modem/src/modem_utilities.c000066400000000000000000000253151317124540100216120ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // modem_utilities.c : common utilities not specific to precision // #include #include #include #include "liquid.internal.h" // full modulation type descriptor const struct modulation_type_s modulation_types[LIQUID_MODEM_NUM_SCHEMES] = { // name fullname scheme bps // unknown {"unknown", "unkown", LIQUID_MODEM_UNKNOWN, 0}, // phase-shift keying {"psk2", "phase-shift keying (2)", LIQUID_MODEM_PSK2, 1}, {"psk4", "phase-shift keying (4)", LIQUID_MODEM_PSK4, 2}, {"psk8", "phase-shift keying (8)", LIQUID_MODEM_PSK8, 3}, {"psk16", "phase-shift keying (16)", LIQUID_MODEM_PSK16, 4}, {"psk32", "phase-shift keying (32)", LIQUID_MODEM_PSK32, 5}, {"psk64", "phase-shift keying (64)", LIQUID_MODEM_PSK64, 6}, {"psk128", "phase-shift keying (128)", LIQUID_MODEM_PSK128, 7}, {"psk256", "phase-shift keying (256)", LIQUID_MODEM_PSK256, 8}, // differential phase-shift keying {"dpsk2", "differential phase-shift keying (2)", LIQUID_MODEM_DPSK2, 1}, {"dpsk4", "differential phase-shift keying (4)", LIQUID_MODEM_DPSK4, 2}, {"dpsk8", "differential phase-shift keying (8)", LIQUID_MODEM_DPSK8, 3}, {"dpsk16", "differential phase-shift keying (16)", LIQUID_MODEM_DPSK16, 4}, {"dpsk32", "differential phase-shift keying (32)", LIQUID_MODEM_DPSK32, 5}, {"dpsk64", "differential phase-shift keying (64)", LIQUID_MODEM_DPSK64, 6}, {"dpsk128", "differential phase-shift keying (128)", LIQUID_MODEM_DPSK128, 7}, {"dpsk256", "differential phase-shift keying (256)", LIQUID_MODEM_DPSK256, 8}, // amplitude-shift keying {"ask2", "amplitude-shift keying (2)", LIQUID_MODEM_ASK2, 1}, {"ask4", "amplitude-shift keying (4)", LIQUID_MODEM_ASK4, 2}, {"ask8", "amplitude-shift keying (8)", LIQUID_MODEM_ASK8, 3}, {"ask16", "amplitude-shift keying (16)", LIQUID_MODEM_ASK16, 4}, {"ask32", "amplitude-shift keying (32)", LIQUID_MODEM_ASK32, 5}, {"ask64", "amplitude-shift keying (64)", LIQUID_MODEM_ASK64, 6}, {"ask128", "amplitude-shift keying (128)", LIQUID_MODEM_ASK128, 7}, {"ask256", "amplitude-shift keying (256)", LIQUID_MODEM_ASK256, 8}, // quadrature amplitude-shift keying {"qam4", "quadrature amplitude-shift keying (4)", LIQUID_MODEM_QAM4, 2}, {"qam8", "quadrature amplitude-shift keying (8)", LIQUID_MODEM_QAM8, 3}, {"qam16", "quadrature amplitude-shift keying (16)", LIQUID_MODEM_QAM16, 4}, {"qam32", "quadrature amplitude-shift keying (32)", LIQUID_MODEM_QAM32, 5}, {"qam64", "quadrature amplitude-shift keying (64)", LIQUID_MODEM_QAM64, 6}, {"qam128", "quadrature amplitude-shift keying (128)", LIQUID_MODEM_QAM128, 7}, {"qam256", "quadrature amplitude-shift keying (256)", LIQUID_MODEM_QAM256, 8}, // amplitude/phase-shift keying {"apsk4", "amplitude/phase-shift keying (4)", LIQUID_MODEM_APSK4, 2}, {"apsk8", "amplitude/phase-shift keying (8)", LIQUID_MODEM_APSK8, 3}, {"apsk16", "amplitude/phase-shift keying (16)", LIQUID_MODEM_APSK16, 4}, {"apsk32", "amplitude/phase-shift keying (32)", LIQUID_MODEM_APSK32, 5}, {"apsk64", "amplitude/phase-shift keying (64)", LIQUID_MODEM_APSK64, 6}, {"apsk128", "amplitude/phase-shift keying (128)", LIQUID_MODEM_APSK128, 7}, {"apsk256", "amplitude/phase-shift keying (256)", LIQUID_MODEM_APSK256, 8}, // specific modem types {"bpsk", "binary phase-shift keying", LIQUID_MODEM_BPSK, 1}, {"qpsk", "quaternary phase-shift keying", LIQUID_MODEM_QPSK, 2}, {"ook", "ook (on/off keying)", LIQUID_MODEM_OOK, 1}, {"sqam32", "'square' 32-QAM", LIQUID_MODEM_SQAM32, 5}, {"sqam128", "'square' 128-QAM", LIQUID_MODEM_SQAM128, 7}, {"V29", "V.29", LIQUID_MODEM_V29, 4}, {"arb16opt", "arb16opt (optimal 16-qam)", LIQUID_MODEM_ARB16OPT, 4}, {"arb32opt", "arb32opt (optimal 32-qam)", LIQUID_MODEM_ARB32OPT, 5}, {"arb64opt", "arb64opt (optimal 64-qam)", LIQUID_MODEM_ARB64OPT, 6}, {"arb128opt", "arb128opt (optimal 128-qam)", LIQUID_MODEM_ARB128OPT, 7}, {"arb256opt", "arb256opt (optimal 256-qam)", LIQUID_MODEM_ARB256OPT, 8}, {"arb64vt", "arb64vt (64-qam vt logo)", LIQUID_MODEM_ARB64VT, 6}, // arbitrary modem type {"arb", "arbitrary constellation", LIQUID_MODEM_ARB, 0}, }; modulation_scheme liquid_getopt_str2mod(const char * _str) { // compare each string to short name unsigned int i; for (i=0; i 48 && i != LIQUID_MODEM_NUM_SCHEMES-1) { len = 10; printf("\n "); } } printf("\n"); } // query basic modulation types int liquid_modem_is_psk(modulation_scheme _ms) { switch (_ms) { // Phase-shift keying (PSK) case LIQUID_MODEM_PSK2: case LIQUID_MODEM_PSK4: case LIQUID_MODEM_PSK8: case LIQUID_MODEM_PSK16: case LIQUID_MODEM_PSK32: case LIQUID_MODEM_PSK64: case LIQUID_MODEM_PSK128: case LIQUID_MODEM_PSK256: return 1; default: return 0; } return 0; } int liquid_modem_is_dpsk(modulation_scheme _ms) { switch (_ms) { // Differential phase-shift keying (DPSK) case LIQUID_MODEM_DPSK2: case LIQUID_MODEM_DPSK4: case LIQUID_MODEM_DPSK8: case LIQUID_MODEM_DPSK16: case LIQUID_MODEM_DPSK32: case LIQUID_MODEM_DPSK64: case LIQUID_MODEM_DPSK128: case LIQUID_MODEM_DPSK256: return 1; default: return 0; } return 0; } int liquid_modem_is_ask(modulation_scheme _ms) { switch (_ms) { // amplitude-shift keying (ASK) case LIQUID_MODEM_ASK2: case LIQUID_MODEM_ASK4: case LIQUID_MODEM_ASK8: case LIQUID_MODEM_ASK16: case LIQUID_MODEM_ASK32: case LIQUID_MODEM_ASK64: case LIQUID_MODEM_ASK128: case LIQUID_MODEM_ASK256: return 1; default: return 0; } return 0; } int liquid_modem_is_qam(modulation_scheme _ms) { switch (_ms) { // rectangular quadrature amplitude-shift keying (QAM) case LIQUID_MODEM_QAM4: case LIQUID_MODEM_QAM8: case LIQUID_MODEM_QAM16: case LIQUID_MODEM_QAM32: case LIQUID_MODEM_QAM64: case LIQUID_MODEM_QAM128: case LIQUID_MODEM_QAM256: return 1; default: return 0; } return 0; } int liquid_modem_is_apsk(modulation_scheme _ms) { switch (_ms) { // amplitude phase-shift keying (APSK) case LIQUID_MODEM_APSK4: case LIQUID_MODEM_APSK8: case LIQUID_MODEM_APSK16: case LIQUID_MODEM_APSK32: case LIQUID_MODEM_APSK64: case LIQUID_MODEM_APSK128: case LIQUID_MODEM_APSK256: return 1; default: return 0; } return 0; } // gray encoding unsigned int gray_encode(unsigned int symbol_in) { return symbol_in ^ (symbol_in >> 1); } // gray decoding unsigned int gray_decode(unsigned int symbol_in) { unsigned int mask = symbol_in; unsigned int symbol_out = symbol_in; unsigned int i; // Run loop in blocks of 4 to reduce number of comparisons. Running // loop more times than MAX_MOD_BITS_PER_SYMBOL will not result in // decoding errors. for (i=0; i> 1); symbol_out ^= (mask >> 2); symbol_out ^= (mask >> 3); symbol_out ^= (mask >> 4); mask >>= 4; } return symbol_out; } // pack soft bits into symbol // _soft_bits : soft input bits [size: _bps x 1] // _bps : bits per symbol // _sym_out : output symbol, value in [0,2^_bps) void liquid_pack_soft_bits(unsigned char * _soft_bits, unsigned int _bps, unsigned int * _sym_out) { // validate input if (_bps > MAX_MOD_BITS_PER_SYMBOL) { fprintf(stderr,"error: liquid_unpack_soft_bits(), bits/symbol exceeds maximum (%u)\n", MAX_MOD_BITS_PER_SYMBOL); exit(1); } unsigned int i; unsigned int s=0; for (i=0; i<_bps; i++) { s <<= 1; s |= _soft_bits[i] > LIQUID_SOFTBIT_ERASURE ? 1 : 0; } *_sym_out = s; } // unpack soft bits into symbol // _sym_in : input symbol, value in [0,2^_bps) // _bps : bits per symbol // _soft_bits : soft output bits [size: _bps x 1] void liquid_unpack_soft_bits(unsigned int _sym_in, unsigned int _bps, unsigned char * _soft_bits) { // validate input if (_bps > MAX_MOD_BITS_PER_SYMBOL) { fprintf(stderr,"error: liquid_unpack_soft_bits(), bits/symbol exceeds maximum (%u)\n", MAX_MOD_BITS_PER_SYMBOL); exit(1); } unsigned int i; for (i=0; i<_bps; i++) _soft_bits[i] = ((_sym_in >> (_bps-i-1)) & 0x0001) ? LIQUID_SOFTBIT_1 : LIQUID_SOFTBIT_0; } liquid-dsp-1.3.1/src/modem/src/modemf.c000066400000000000000000000041741317124540100176650ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // modemf.c : linear modem API, floating-point (single precision) // #include #include #include "liquid.internal.h" // Macro definitions #define MODEM(name) LIQUID_CONCAT(modem,name) #define FREQMOD(name) LIQUID_CONCAT(freqmod,name) #define FREQDEM(name) LIQUID_CONCAT(freqdem,name) #define T float /* primitive type */ #define TC float complex /* primitive type (complex) */ #define PRINTVAL_T(X,F) PRINTVAL_FLOAT(X,F) #define PRINTVAL_TC(X,F) PRINTVAL_CFLOAT(X,F) // common source must come first (object definition) #include "modem_common.c" // generic modem specifications #include "modem_psk.c" #include "modem_dpsk.c" #include "modem_ask.c" #include "modem_qam.c" #include "modem_apsk.c" // specific modems #include "modem_bpsk.c" #include "modem_qpsk.c" #include "modem_ook.c" #include "modem_sqam32.c" #include "modem_sqam128.c" // arbitary modems #include "modem_arb.c" // analog modems #include "freqmod.c" #include "freqdem.c" liquid-dsp-1.3.1/src/modem/tests/000077500000000000000000000000001317124540100166175ustar00rootroot00000000000000liquid-dsp-1.3.1/src/modem/tests/cpfskmodem_autotest.c000066400000000000000000000134521317124540100230500ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.h" // Help function to keep code base small void cpfskmodem_test_mod_demod(unsigned int _bps, float _h, unsigned int _k, unsigned int _m, float _beta, int _filter_type) { // create modulator/demodulator pair cpfskmod mod = cpfskmod_create(_bps, _h, _k, _m, _beta, _filter_type); cpfskdem dem = cpfskdem_create(_bps, _h, _k, _m, _beta, _filter_type); // derived values unsigned int delay = cpfskmod_get_delay(mod) + cpfskdem_get_delay(dem); //unsigned int M = 1 << _m; // constellation size unsigned int num_symbols = 80 + delay; // number of symbols to test msequence ms = msequence_create_default(7); float complex buf[_k]; // sample buffer unsigned int sym_in [num_symbols]; // symbol buffer unsigned int sym_out[num_symbols]; // symbol buffer // modulate, demodulate, count errors unsigned int i; for (i=0; i= delay) { // print results if (liquid_autotest_verbose) { printf(" %3u : input = %2u, output = %2u %s\n", i, sym_in[i-delay], sym_out[i], (sym_in[i-delay] == sym_out[i]) ? "" : "*"); } // check result CONTEND_EQUALITY(sym_in[i-delay], sym_out[i]); } } // clean it up msequence_destroy(ms); cpfskmod_destroy(mod); cpfskdem_destroy(dem); } // // AUTOTESTS: check different modulation indices // // square pulse shape void autotest_cpfskmodem_bps1_h0p5000_k4_m3_square() { cpfskmodem_test_mod_demod( 1, 0.5000f, 4, 3, 0.25f, LIQUID_CPFSK_SQUARE ); } void autotest_cpfskmodem_bps1_h0p0250_k4_m3_square() { cpfskmodem_test_mod_demod( 1, 0.2500f, 4, 3, 0.25f, LIQUID_CPFSK_SQUARE ); } void autotest_cpfskmodem_bps1_h0p1250_k4_m3_square() { cpfskmodem_test_mod_demod( 1, 0.1250f, 4, 3, 0.25f, LIQUID_CPFSK_SQUARE ); } void autotest_cpfskmodem_bps1_h0p0625_k4_m3_square() { cpfskmodem_test_mod_demod( 1, 0.0625f, 4, 3, 0.25f, LIQUID_CPFSK_SQUARE ); } // raised-cosine pulse shape (full) void autotest_cpfskmodem_bps1_h0p5000_k4_m3_rcosfull() { cpfskmodem_test_mod_demod( 1, 0.5000f, 4, 3, 0.25f, LIQUID_CPFSK_RCOS_FULL ); } void autotest_cpfskmodem_bps1_h0p0250_k4_m3_rcosfull() { cpfskmodem_test_mod_demod( 1, 0.2500f, 4, 3, 0.25f, LIQUID_CPFSK_RCOS_FULL ); } void autotest_cpfskmodem_bps1_h0p1250_k4_m3_rcosfull() { cpfskmodem_test_mod_demod( 1, 0.1250f, 4, 3, 0.25f, LIQUID_CPFSK_RCOS_FULL ); } void autotest_cpfskmodem_bps1_h0p0625_k4_m3_rcosfull() { cpfskmodem_test_mod_demod( 1, 0.0625f, 4, 3, 0.25f, LIQUID_CPFSK_RCOS_FULL ); } // raised-cosine pulse shape (partial) void autotest_cpfskmodem_bps1_h0p5000_k4_m3_rcospart() { cpfskmodem_test_mod_demod( 1, 0.5000f, 4, 3, 0.25f, LIQUID_CPFSK_RCOS_PARTIAL ); } void autotest_cpfskmodem_bps1_h0p0250_k4_m3_rcospart() { cpfskmodem_test_mod_demod( 1, 0.2500f, 4, 3, 0.25f, LIQUID_CPFSK_RCOS_PARTIAL ); } void autotest_cpfskmodem_bps1_h0p1250_k4_m3_rcospart() { cpfskmodem_test_mod_demod( 1, 0.1250f, 4, 3, 0.25f, LIQUID_CPFSK_RCOS_PARTIAL ); } void autotest_cpfskmodem_bps1_h0p0625_k4_m3_rcospart() { cpfskmodem_test_mod_demod( 1, 0.0625f, 4, 3, 0.25f, LIQUID_CPFSK_RCOS_PARTIAL ); } // Gauss minimum-shift keying void autotest_cpfskmodem_bps1_h0p5000_k4_m3_gmsk() { cpfskmodem_test_mod_demod( 1, 0.5000f, 4, 3, 0.25f, LIQUID_CPFSK_GMSK ); } void autotest_cpfskmodem_bps1_h0p0250_k4_m3_gmsk() { cpfskmodem_test_mod_demod( 1, 0.2500f, 4, 3, 0.25f, LIQUID_CPFSK_GMSK ); } void autotest_cpfskmodem_bps1_h0p1250_k4_m3_gmsk() { cpfskmodem_test_mod_demod( 1, 0.1250f, 4, 3, 0.25f, LIQUID_CPFSK_GMSK ); } void autotest_cpfskmodem_bps1_h0p0625_k4_m3_gmsk() { cpfskmodem_test_mod_demod( 1, 0.0625f, 4, 3, 0.25f, LIQUID_CPFSK_GMSK ); } // // AUTOTESTS: check different bits per symbol // // square pulse shape void autotest_cpfskmodem_bps2_h0p0250_k4_m3_square() { cpfskmodem_test_mod_demod( 2, 0.2500f, 4, 3, 0.25f, LIQUID_CPFSK_SQUARE ); } void autotest_cpfskmodem_bps3_h0p1250_k4_m3_square() { cpfskmodem_test_mod_demod( 3, 0.1250f, 4, 3, 0.25f, LIQUID_CPFSK_SQUARE ); } void autotest_cpfskmodem_bps4_h0p0625_k4_m3_square() { cpfskmodem_test_mod_demod( 4, 0.0625f, 4, 3, 0.25f, LIQUID_CPFSK_SQUARE ); } liquid-dsp-1.3.1/src/modem/tests/freqmodem_autotest.c000066400000000000000000000050301317124540100226700ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.h" // Help function to keep code base small // _kf : modulation factor void freqmodem_test(float _kf) { // options unsigned int num_samples = 1024; float tol = 5e-2f; unsigned int i; // create mod/demod objects freqmod mod = freqmod_create(_kf); // modulator freqdem dem = freqdem_create(_kf); // demodulator // allocate arrays float m[num_samples]; // message signal float complex r[num_samples]; // received signal (complex baseband) float y[num_samples]; // demodulator output // generate message signal (sum of sines) for (i=0; i #include "autotest/autotest.h" #include "liquid.h" // Helper function to keep code base small void modem_test_demodstats(modulation_scheme _ms) { // generate mod/demod modem mod = modem_create(_ms); modem demod = modem_create(_ms); // run the test unsigned int i, s, M = 1 << modem_get_bps(mod); float complex x; float complex x_hat; // rotated symbol float demodstats; float phi = 0.01f; for (i=0; i 0.0f); } // repeat with negative phase error for (i=0; i #include "liquid.h" #define FIRPFBCH2_EXECUTE_BENCH_API(NUM_CHANNELS,M,TYPE) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { firpfbch2_crcf_execute_bench(_start, _finish, _num_iterations, NUM_CHANNELS, M, TYPE); } // Helper function to keep code base small void firpfbch2_crcf_execute_bench(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations, unsigned int _num_channels, unsigned int _m, int _type) { // initialize channelizer float As = 60.0f; firpfbch2_crcf q = firpfbch2_crcf_create_kaiser(_type,_num_channels,_m,As); unsigned long int i; float complex x[_num_channels]; float complex y[_num_channels]; for (i=0; i<_num_channels; i++) x[i] = 1.0f + _Complex_I*1.0f; // scale number of iterations to keep execution time // relatively linear *_num_iterations /= _num_channels; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { firpfbch2_crcf_execute(q, x, y); firpfbch2_crcf_execute(q, x, y); firpfbch2_crcf_execute(q, x, y); firpfbch2_crcf_execute(q, x, y); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; firpfbch2_crcf_destroy(q); } // analysis void benchmark_firpfbch2_crcf_a4 FIRPFBCH2_EXECUTE_BENCH_API(4, 2, LIQUID_ANALYZER) void benchmark_firpfbch2_crcf_a16 FIRPFBCH2_EXECUTE_BENCH_API(16, 2, LIQUID_ANALYZER) void benchmark_firpfbch2_crcf_a64 FIRPFBCH2_EXECUTE_BENCH_API(64, 2, LIQUID_ANALYZER) void benchmark_firpfbch2_crcf_a256 FIRPFBCH2_EXECUTE_BENCH_API(256, 2, LIQUID_ANALYZER) void benchmark_firpfbch2_crcf_a512 FIRPFBCH2_EXECUTE_BENCH_API(512, 2, LIQUID_ANALYZER) void benchmark_firpfbch2_crcf_a1024 FIRPFBCH2_EXECUTE_BENCH_API(1024, 2, LIQUID_ANALYZER) // synthesis void benchmark_firpfbch2_crcf_s4 FIRPFBCH2_EXECUTE_BENCH_API(4, 2, LIQUID_SYNTHESIZER) void benchmark_firpfbch2_crcf_s16 FIRPFBCH2_EXECUTE_BENCH_API(16, 2, LIQUID_SYNTHESIZER) void benchmark_firpfbch2_crcf_s64 FIRPFBCH2_EXECUTE_BENCH_API(64, 2, LIQUID_SYNTHESIZER) void benchmark_firpfbch2_crcf_s256 FIRPFBCH2_EXECUTE_BENCH_API(256, 2, LIQUID_SYNTHESIZER) void benchmark_firpfbch2_crcf_s512 FIRPFBCH2_EXECUTE_BENCH_API(512, 2, LIQUID_SYNTHESIZER) void benchmark_firpfbch2_crcf_s1024 FIRPFBCH2_EXECUTE_BENCH_API(1024, 2, LIQUID_SYNTHESIZER) liquid-dsp-1.3.1/src/multichannel/bench/firpfbch_crcf_benchmark.c000066400000000000000000000066141317124540100250630ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" #define FIRPFBCH_EXECUTE_BENCH_API(NUM_CHANNELS,M,TYPE) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { firpfbch_crcf_execute_bench(_start, _finish, _num_iterations, NUM_CHANNELS, M, TYPE); } // Helper function to keep code base small void firpfbch_crcf_execute_bench( struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _num_channels, unsigned int _m, int _type) { // initialize channelizer float As = 60.0f; firpfbch_crcf c = firpfbch_crcf_create_kaiser(_type,_num_channels,_m,As); unsigned long int i; float complex x[_num_channels]; float complex y[_num_channels]; for (i=0; i<_num_channels; i++) x[i] = 1.0f + _Complex_I*1.0f; // scale number of iterations to keep execution time // relatively linear *_num_iterations /= _num_channels; // start trials getrusage(RUSAGE_SELF, _start); if (_type == LIQUID_SYNTHESIZER) { for (i=0; i<(*_num_iterations); i++) { firpfbch_crcf_synthesizer_execute(c,x,y); firpfbch_crcf_synthesizer_execute(c,x,y); firpfbch_crcf_synthesizer_execute(c,x,y); firpfbch_crcf_synthesizer_execute(c,x,y); } } else { for (i=0; i<(*_num_iterations); i++) { firpfbch_crcf_analyzer_execute(c,x,y); firpfbch_crcf_analyzer_execute(c,x,y); firpfbch_crcf_analyzer_execute(c,x,y); firpfbch_crcf_analyzer_execute(c,x,y); } } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; firpfbch_crcf_destroy(c); } // void benchmark_firpfbch_crcf_a4 FIRPFBCH_EXECUTE_BENCH_API(4, 2, LIQUID_ANALYZER) void benchmark_firpfbch_crcf_a16 FIRPFBCH_EXECUTE_BENCH_API(16, 2, LIQUID_ANALYZER) void benchmark_firpfbch_crcf_a64 FIRPFBCH_EXECUTE_BENCH_API(64, 2, LIQUID_ANALYZER) void benchmark_firpfbch_crcf_a256 FIRPFBCH_EXECUTE_BENCH_API(256, 2, LIQUID_ANALYZER) void benchmark_firpfbch_crcf_a512 FIRPFBCH_EXECUTE_BENCH_API(512, 2, LIQUID_ANALYZER) void benchmark_firpfbch_crcf_a1024 FIRPFBCH_EXECUTE_BENCH_API(1024, 2, LIQUID_ANALYZER) liquid-dsp-1.3.1/src/multichannel/bench/ofdmframesync_acquire_benchmark.c000066400000000000000000000070421317124540100266450ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include #include "liquid.h" #define OFDMFRAMESYNC_ACQUIRE_BENCH_API(M,CP_LEN) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { ofdmframesync_acquire_bench(_start, _finish, _num_iterations, M, CP_LEN); } // Helper function to keep code base small void ofdmframesync_acquire_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _num_subcarriers, unsigned int _cp_len) { // options unsigned int M = _num_subcarriers; unsigned int cp_len = _cp_len; unsigned int taper_len = 0; // derived values unsigned int num_samples = 3*(M + cp_len); // create synthesizer/analyzer objects ofdmframegen fg = ofdmframegen_create(M, cp_len, taper_len, NULL); //ofdmframegen_print(fg); ofdmframesync fs = ofdmframesync_create(M,cp_len,taper_len,NULL,NULL,NULL); unsigned int i; float complex y[num_samples]; // frame samples // assemble full frame unsigned int n=0; // write first S0 symbol ofdmframegen_write_S0a(fg, &y[n]); n += M + cp_len; // write second S0 symbol ofdmframegen_write_S0b(fg, &y[n]); n += M + cp_len; // write S1 symbol ofdmframegen_write_S1( fg, &y[n]); n += M + cp_len; assert(n == num_samples); // add noise for (i=0; i #include #include #include #include #include #include "liquid.h" #define OFDMFRAMESYNC_RXSYMBOL_BENCH_API(M,CP_LEN) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { ofdmframesync_rxsymbol_bench(_start, _finish, _num_iterations, M, CP_LEN); } // Helper function to keep code base small void ofdmframesync_rxsymbol_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _num_subcarriers, unsigned int _cp_len) { // options modulation_scheme ms = LIQUID_MODEM_QPSK; unsigned int M = _num_subcarriers; unsigned int cp_len = _cp_len; unsigned int taper_len = 0; // create synthesizer/analyzer objects ofdmframegen fg = ofdmframegen_create(M, cp_len, taper_len, NULL); //ofdmframegen_print(fg); modem mod = modem_create(ms); ofdmframesync fs = ofdmframesync_create(M,cp_len,taper_len,NULL,NULL,NULL); unsigned int i; float complex X[M]; // channelized symbol float complex x[M+cp_len]; // time-domain symbol // synchronize short sequence (first) ofdmframegen_write_S0a(fg, x); ofdmframesync_execute(fs, x, M+cp_len); // synchronize short sequence (second) ofdmframegen_write_S0b(fg, x); ofdmframesync_execute(fs, x, M+cp_len); // synchronize long sequence ofdmframegen_write_S1(fg, x); ofdmframesync_execute(fs, x, M+cp_len); // modulate data symbols (use same symbol, ignore pilot phase) unsigned int s; for (i=0; i Re{-} -->| | X[1] ----+----------->jIm{-} -->| | X[2] ------+---------> Re{-} -->| | {x0} | | | . | firpfbch |---------->(+)---> | | | . | [c0] | | | | | . | | | X[M-1] --------------+->jIm{-} -->| | | | | | | +-----------+ | | | | | | | | | | {X1} +-----------+ | +------------->jIm{-} -->| | | +-----------> Re{-} -->| | | +--------->jIm{-} | | {x1} | . | | firpfbch |--[z^-M/2]--+ . | | [c1] | {x1_prime} . | | | +-> Re{-} -->| | +-----------+ ## ## Analysis channelizer ## +-----------+ {X0} | | --> Re{-} -->(+)--------------> X[0] | | -->jIm{-} ---->(+)------------> X[1] {x0} | | --> Re{-} ------>(+)----------> X[2] --+--[z^-M] ----> | firpfbch | . | | | . | {x0_prime} | [c0] | . | | | . | | | . | | | . | | | -->jIm{-}----------------(+)--> X[M-1] | +-----------+ | | | | | | | | | | +-----------+ {X1} | | | . . . | | | | -->jIm{-} ----+ | | | | | | --> Re{-} ------+ | | | {x1} | | -->jIm{-} --------+ | +--[z^-M/2] --> | firpfbch | . . | {x1_prime} | [c1] | . . | | | . . | | | --> Re{-} ----------------+ +-----------+ liquid-dsp-1.3.1/src/multichannel/readme.ofdm.txt000066400000000000000000000125641317124540100217710ustar00rootroot00000000000000========================================================================= OFDM framing structure ========================================================================= signal preamble payload ^ |<-------------------->|<---------------------------------->| | | | | | +----+----+----+--+----+--+----+--+----+--+----+-//-+--+----+ | | | | |//| |//| |//| |//| | |//| | | | | | |//| |//| |//| |//| | |//| | | | S0 | S0 | .. |//| S1 |//| P0 |//| P1 |//| P2 | .. |//| Px | | | | | |//| |//| |//| |//| | |//| | |_______| | | |//| |//| |//| |//| | |//| | +-----------------------------------------------------------------------> time spectral null ^ pilot subcarrier / | / *----*----* *----*----+---*----*----*----*----*----* | | | | | | | | | ... | ___/ \________/ | \___ +-------------------------------+--------------------------------+ freq -Fs/2 0 +Fs/2 Overview: The ofdmframe family of objects (generator and synchronizer) realize a simple way to load data onto an OFDM physical layer system. OFDM has several benefits over traditional 'narrowband' communications systems. These objects allow the user to abstractly specify the number of subcarriers, their assignment (null/pilot/data), forward error-correction and modulation scheme. Furthermore, the framing structure includes a provision for a brief user-defined header which can be used for source/destination address, packet identifier, etc. Operational description: The structure of the frame consists of three main components: the preamble, the header, and the payload. Preamble The preamble consists of two types of phasing symbols: the S0 and S1 sequences. The S0 symbols are necessary for coarse carrier frequency and timing offsets while the S1 sequence is used for fine timing acquisition and equalizer gain estimation. The transmitter generates multiple S0 symbols (minimally 2, but usually 3 or more) and just a single S1 symbol. This aligns the receiver's timing to that of the transmitter, signalling the start of the header. OFDM frame gen/sync parameters (must match on both TX and RX side): M : Total number of subcarriers p* : subcarrier allocation cplen : cyclic prefix length (samples) M0 : number of null subcarriers Mp : number of pilot subcarriers Md : number of data subcarriers num_S0 : number of S0 symbols num_S1 : number of S1 symbols (must be 1, non-negotiable) Notes: * The length of each data symbol is equal to the number of subcarriers plus the cyclic prefix length (e.g. if N=64 and cplen=16, each data symbol is 80 samples long) with the exception of the S0 training symbols which are simply the number of subcarriers. * The S0 symbols do NOT have a cyclic prefix; this is necessary to preserve continuity between symbols. Unlike 802.11a (and derivative protocols) in which a fixed cyclic prefix has been designed into the system, the flexibility of liquid-dsp's OFDM framing structure requires that no prefix is added to maintain temporal continuity. Details: section num samples Description/purpose S0 M*num_S0 Initial preamble for coarse carrier frequency, phase, and timing offset estimates S1 M+cplen Secondary preamble for timing disambiguation and equalization payload M+cplen payload symbols ========================================================================= Synchronizer: Description of Operation ========================================================================= signal FFT input ^ |<---------------------------------------->| | | | | +------------+------------------------------------------+------- | |////////////| |////// | |// //| |// | |// cyclic //| OFDM |// ... | |// prefix //| symbol |// | |// //| |// |_______|////////////| |////// +------------------+-+------------------------------------------+-------> | | | time | +- true start of symbol | | +- start of +- timing backoff (e.g. 2 samples) next symbol Talking points: * FFT input backoff by one or two samples to ensure no overlap with next symbol liquid-dsp-1.3.1/src/multichannel/src/000077500000000000000000000000001317124540100176265ustar00rootroot00000000000000liquid-dsp-1.3.1/src/multichannel/src/firpfbch.c000066400000000000000000000316401317124540100215610ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firpfbch.c // // finite impulse response polyphase filterbank channelizer // #include #include #include #include #include "liquid.internal.h" // firpfbch object structure definition struct FIRPFBCH(_s) { int type; // synthesis/analysis unsigned int num_channels; // number of channels unsigned int p; // filter length (symbols) // filter unsigned int h_len; // filter length TC * h; // filter coefficients // create separate bank of dotprod and window objects DOTPROD() * dp; // dot product object array WINDOW() * w; // window buffer object array unsigned int filter_index; // running filter index (analysis) // fft plan FFT_PLAN fft; // fft|ifft object TO * x; // fft|ifft transform input array TO * X; // fft|ifft transform output array }; // // forward declaration of internal methods // void FIRPFBCH(_analyzer_push)(FIRPFBCH() _q, TI _x); void FIRPFBCH(_analyzer_run)(FIRPFBCH() _q, unsigned int _k, TO * _X); // create FIR polyphase filterbank channelizer object // _type : channelizer type (LIQUID_ANALYZER | LIQUID_SYNTHESIZER) // _M : number of channels // _p : filter length (symbols) // _h : filter coefficients, [size: _M*_p x 1] FIRPFBCH() FIRPFBCH(_create)(int _type, unsigned int _M, unsigned int _p, TC * _h) { // validate input if (_type != LIQUID_ANALYZER && _type != LIQUID_SYNTHESIZER) { fprintf(stderr,"error: firpfbch_%s_create(), invalid type %d\n", EXTENSION_FULL, _type); exit(1); } else if (_M == 0) { fprintf(stderr,"error: firpfbch_%s_create(), number of channels must be greater than 0\n", EXTENSION_FULL); exit(1); } else if (_p == 0) { fprintf(stderr,"error: firpfbch_%s_create(), invalid filter size (must be greater than 0)\n", EXTENSION_FULL); exit(1); } // create main object FIRPFBCH() q = (FIRPFBCH()) malloc(sizeof(struct FIRPFBCH(_s))); // set user-defined properties q->type = _type; q->num_channels = _M; q->p = _p; // derived values q->h_len = q->num_channels * q->p; // create bank of filters q->dp = (DOTPROD()*) malloc((q->num_channels)*sizeof(DOTPROD())); q->w = (WINDOW()*) malloc((q->num_channels)*sizeof(WINDOW())); // copy filter coefficients q->h = (TC*) malloc((q->h_len)*sizeof(TC)); unsigned int i; for (i=0; ih_len; i++) q->h[i] = _h[i]; // generate bank of sub-samped filters unsigned int n; unsigned int h_sub_len = q->p; TC h_sub[h_sub_len]; for (i=0; inum_channels; i++) { // sub-sample prototype filter, loading coefficients in reverse order for (n=0; nh[i + n*(q->num_channels)]; } // create window buffer and dotprod object (coefficients // loaded in reverse order) q->dp[i] = DOTPROD(_create)(h_sub,h_sub_len); q->w[i] = WINDOW(_create)(h_sub_len); } // allocate memory for buffers // TODO : use fftw_malloc if HAVE_FFTW3_H q->x = (T*) malloc((q->num_channels)*sizeof(T)); q->X = (T*) malloc((q->num_channels)*sizeof(T)); // create fft plan if (q->type == LIQUID_ANALYZER) q->fft = FFT_CREATE_PLAN(q->num_channels, q->X, q->x, FFT_DIR_FORWARD, FFT_METHOD); else q->fft = FFT_CREATE_PLAN(q->num_channels, q->X, q->x, FFT_DIR_BACKWARD, FFT_METHOD); // reset filterbank object FIRPFBCH(_reset)(q); // return filterbank object return q; } // create FIR polyphase filterbank channelizer object with // prototype filter based on windowed Kaiser design // _type : channelizer type (LIQUID_ANALYZER | LIQUID_SYNTHESIZER) // _M : number of channels // _m : filter delay (symbols) // _As : stop-band attentuation [dB] FIRPFBCH() FIRPFBCH(_create_kaiser)(int _type, unsigned int _M, unsigned int _m, float _As) { // validate input if (_M == 0) { fprintf(stderr,"error: firpfbch_%s_create_kaiser(), number of channels must be greater than 0\n", EXTENSION_FULL); exit(1); } else if (_m == 0) { fprintf(stderr,"error: firpfbch_%s_create_kaiser(), invalid filter size (must be greater than 0)\n", EXTENSION_FULL); exit(1); } _As = fabsf(_As); // design filter unsigned int h_len = 2*_M*_m + 1; float h[h_len]; float fc = 0.5f / (float)_M; // TODO : check this value liquid_firdes_kaiser(h_len, fc, _As, 0.0f, h); // copy coefficients to type-specfic array TC hc[h_len]; unsigned int i; for (i=0; inum_channels; i++) { DOTPROD(_destroy)(_q->dp[i]); WINDOW(_destroy)(_q->w[i]); } free(_q->dp); free(_q->w); // free transform object FFT_DESTROY_PLAN(_q->fft); // free additional arrays free(_q->h); free(_q->x); free(_q->X); // free main object memory free(_q); } // clear/reset firpfbch object internals void FIRPFBCH(_reset)(FIRPFBCH() _q) { unsigned int i; for (i=0; i<_q->num_channels; i++) { WINDOW(_reset)(_q->w[i]); _q->x[i] = 0; _q->X[i] = 0; } _q->filter_index = _q->num_channels-1; } // print firpfbch object void FIRPFBCH(_print)(FIRPFBCH() _q) { unsigned int i; printf("firpfbch (%s) [%u channels]:\n", _q->type == LIQUID_ANALYZER ? "analyzer" : "synthesizer", _q->num_channels); for (i=0; i<_q->h_len; i++) printf(" h[%3u] = %12.8f + %12.8f*j\n", i, crealf(_q->h[i]), cimagf(_q->h[i])); } // // SYNTHESIZER // // execute filterbank as synthesizer on block of samples // _q : filterbank channelizer object // _x : channelized input, [size: num_channels x 1] // _y : output time series, [size: num_channels x 1] void FIRPFBCH(_synthesizer_execute)(FIRPFBCH() _q, TI * _x, TO * _y) { unsigned int i; // copy channelized symbols to transform input memmove(_q->X, _x, _q->num_channels*sizeof(TI)); // execute inverse DFT, store result in buffer 'x' FFT_EXECUTE(_q->fft); // push samples into filter bank and execute T * r; // read pointer for (i=0; i<_q->num_channels; i++) { WINDOW(_push)(_q->w[i], _q->x[i]); WINDOW(_read)(_q->w[i], &r); DOTPROD(_execute)(_q->dp[i], r, &_y[i]); // normalize by DFT scaling factor //_y[i] /= (float) (_q->num_channels); } } // // ANALYZER // // execute filterbank as analyzer on block of samples // _q : filterbank channelizer object // _x : input time series, [size: num_channels x 1] // _y : channelized output, [size: num_channels x 1] void FIRPFBCH(_analyzer_execute)(FIRPFBCH() _q, TI * _x, TO * _y) { unsigned int i; // push samples into buffers for (i=0; i<_q->num_channels; i++) FIRPFBCH(_analyzer_push)(_q, _x[i]); // execute analysis filters on the given input starting // with filterbank at index zero FIRPFBCH(_analyzer_run)(_q, 0, _y); } // // internal methods // // push single sample into analysis filterbank, updating index // counter appropriately // _q : filterbank channelizer object // _x : input sample void FIRPFBCH(_analyzer_push)(FIRPFBCH() _q, TI _x) { // push sample into filter WINDOW(_push)(_q->w[_q->filter_index], _x); // decrement filter index _q->filter_index = (_q->filter_index + _q->num_channels - 1) % _q->num_channels; } // run filterbank analyzer dot products, DFT // _q : filterbank channelizer object // _k : filterbank alignment index // _y : output array, [size: num_channels x 1] void FIRPFBCH(_analyzer_run)(FIRPFBCH() _q, unsigned int _k, TO * _y) { unsigned int i; // execute filter outputs, reversing order of output (not // sure why this is necessary) T * r; // read pointer unsigned int index; for (i=0; i<_q->num_channels; i++) { // compute appropriate index index = (i+_k) % _q->num_channels; // read buffer at specified index WINDOW(_read)(_q->w[index], &r); // compute dot product DOTPROD(_execute)(_q->dp[i], r, &_q->X[_q->num_channels-i-1]); } // execute DFT, store result in buffer 'x' FFT_EXECUTE(_q->fft); // move to output array memmove(_y, _q->x, _q->num_channels*sizeof(TO)); } liquid-dsp-1.3.1/src/multichannel/src/firpfbch2.c000066400000000000000000000271201317124540100216410ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // firpfbch2.c // // finite impulse response polyphase filterbank channelizer with output // rate 2 Fs / M // #include #include #include #include // firpfbch2 object structure definition struct FIRPFBCH2(_s) { int type; // synthesis/analysis unsigned int M; // number of channels unsigned int M2; // number of channels/2 unsigned int m; // filter semi-length // filter unsigned int h_len; // prototype filter length: 2*M*m // create separate bank of dotprod and window objects DOTPROD() * dp; // dot product object array // inverse FFT plan FFT_PLAN ifft; // inverse FFT object TO * X; // IFFT input array [size: M x 1] TO * x; // IFFT output array [size: M x 1] // common data structures shared between analysis and // synthesis algorithms WINDOW() * w0; // window buffer object array WINDOW() * w1; // window buffer object array (synthesizer only) int flag; // flag indicating filter/buffer alignment }; // create firpfbch2 object // _type : channelizer type (e.g. LIQUID_ANALYZER) // _M : number of channels (must be even) // _m : prototype filter semi-lenth, length=2*M*m // _h : prototype filter coefficient array // _h_len : number of coefficients FIRPFBCH2() FIRPFBCH2(_create)(int _type, unsigned int _M, unsigned int _m, TC * _h) { // validate input if (_type != LIQUID_ANALYZER && _type != LIQUID_SYNTHESIZER) { fprintf(stderr,"error: firpfbch2_%s_create(), invalid type %d\n", EXTENSION_FULL, _type); exit(1); } else if (_M < 2 || _M % 2) { fprintf(stderr,"error: firpfbch2_%s_create(), number of channels must be greater than 2 and even\n", EXTENSION_FULL); exit(1); } else if (_m < 1) { fprintf(stderr,"error: firpfbch2_%s_create(), filter semi-length must be at least 1\n", EXTENSION_FULL); exit(1); } // create object FIRPFBCH2() q = (FIRPFBCH2()) malloc(sizeof(struct FIRPFBCH2(_s))); // set input parameters q->type = _type; // channelizer type (e.g. LIQUID_ANALYZER) q->M = _M; // number of channels q->m = _m; // prototype filter semi-length // compute derived values q->h_len = 2*q->M*q->m; // prototype filter length q->M2 = q->M / 2; // number of channels / 2 // generate bank of sub-samped filters q->dp = (DOTPROD()*) malloc((q->M)*sizeof(DOTPROD())); unsigned int i; unsigned int n; unsigned int h_sub_len = 2 * q->m; TC h_sub[h_sub_len]; for (i=0; iM; i++) { // sub-sample prototype filter, loading coefficients // in reverse order for (n=0; nM)]; // create dotprod object q->dp[i] = DOTPROD(_create)(h_sub,h_sub_len); } // create FFT plan (inverse transform) // TODO : use fftw_malloc if HAVE_FFTW3_H q->X = (T*) malloc((q->M)*sizeof(T)); // IFFT input q->x = (T*) malloc((q->M)*sizeof(T)); // IFFT output q->ifft = FFT_CREATE_PLAN(q->M, q->X, q->x, FFT_DIR_BACKWARD, FFT_METHOD); // create buffer objects q->w0 = (WINDOW()*) malloc((q->M)*sizeof(WINDOW())); q->w1 = (WINDOW()*) malloc((q->M)*sizeof(WINDOW())); for (i=0; iM; i++) { q->w0[i] = WINDOW(_create)(h_sub_len); q->w1[i] = WINDOW(_create)(h_sub_len); } // reset filterbank object and return FIRPFBCH2(_reset)(q); return q; } // create firpfbch2 object using Kaiser window prototype // _type : channelizer type (e.g. LIQUID_ANALYZER) // _M : number of channels (must be even) // _m : prototype filter semi-lenth, length=2*M*m+1 // _As : filter stop-band attenuation [dB] FIRPFBCH2() FIRPFBCH2(_create_kaiser)(int _type, unsigned int _M, unsigned int _m, float _As) { // validate input if (_type != LIQUID_ANALYZER && _type != LIQUID_SYNTHESIZER) { fprintf(stderr,"error: firpfbch2_%s_create_kaiser(), invalid type %d\n", EXTENSION_FULL, _type); exit(1); } else if (_M < 2 || _M % 2) { fprintf(stderr,"error: firpfbch2_%s_create_kaiser(), number of channels must be greater than 2 and even\n", EXTENSION_FULL); exit(1); } else if (_m < 1) { fprintf(stderr,"error: firpfbch2_%s_create_kaiser(), filter semi-length must be at least 1\n", EXTENSION_FULL); exit(1); } // design prototype filter unsigned int h_len = 2*_M*_m+1; float * hf = (float*)malloc(h_len*sizeof(float)); // filter cut-off frequency (analyzer has twice the // bandwidth of the synthesizer) float fc = (_type == LIQUID_ANALYZER) ? 1.0f/(float)_M : 0.5f/(float)_M; // compute filter coefficients (floating point precision) liquid_firdes_kaiser(h_len, fc, _As, 0.0f, hf); // normalize to unit average and scale by number of channels float hf_sum = 0.0f; unsigned int i; for (i=0; iM; i++) DOTPROD(_destroy)(_q->dp[i]); free(_q->dp); // free transform object and arrays FFT_DESTROY_PLAN(_q->ifft); free(_q->X); free(_q->x); // free window objects (buffers) for (i=0; i<_q->M; i++) { WINDOW(_destroy)(_q->w0[i]); WINDOW(_destroy)(_q->w1[i]); } free(_q->w0); free(_q->w1); // free main object memory free(_q); } // reset firpfbch2 object internals void FIRPFBCH2(_reset)(FIRPFBCH2() _q) { unsigned int i; // clear window buffers for (i=0; i<_q->M; i++) { WINDOW(_reset)(_q->w0[i]); WINDOW(_reset)(_q->w1[i]); } // reset filter/buffer alignment flag _q->flag = 0; } // print firpfbch2 object internals void FIRPFBCH2(_print)(FIRPFBCH2() _q) { printf("firpfbch2_%s:\n", EXTENSION_FULL); printf(" channels : %u\n", _q->M); printf(" h_len : %u\n", _q->h_len); printf(" semi-length : %u\n", _q->m); // TODO: print filter coefficients... unsigned int i; for (i=0; i<_q->M; i++) DOTPROD(_print)(_q->dp[i]); } // execute filterbank channelizer (analyzer) // _x : channelizer input, [size: M/2 x 1] // _y : channelizer output, [size: M x 1] void FIRPFBCH2(_execute_analyzer)(FIRPFBCH2() _q, TI * _x, TO * _y) { unsigned int i; // load buffers in blocks of num_channels/2 starting // in the middle of the filter bank and moving in the // negative direction unsigned int base_index = _q->flag ? _q->M : _q->M2; for (i=0; i<_q->M2; i++) { // push sample into buffer at filter index WINDOW(_push)(_q->w0[base_index-i-1], _x[i]); } // execute filter outputs unsigned int offset = _q->flag ? _q->M2 : 0; TI * r; // buffer read pointer for (i=0; i<_q->M; i++) { // compute buffer index unsigned int buffer_index = (offset+i)%(_q->M); // read buffer at index WINDOW(_read)(_q->w0[buffer_index], &r); // run dot product storing result in IFFT input buffer DOTPROD(_execute)(_q->dp[i], r, &_q->X[buffer_index]); } // execute IFFT, store result in buffer 'x' FFT_EXECUTE(_q->ifft); // scale result by 1/num_channels (C transform) for (i=0; i<_q->M; i++) _y[i] = _q->x[i] / (float)(_q->M); // update flag _q->flag = 1 - _q->flag; } // execute filterbank channelizer (synthesizer) // _x : channelizer input, [size: M x 1] // _y : channelizer output, [size: M/2 x 1] void FIRPFBCH2(_execute_synthesizer)(FIRPFBCH2() _q, TI * _x, TO * _y) { unsigned int i; // copy input array to internal IFFT input buffer memmove(_q->X, _x, _q->M * sizeof(TI)); // execute IFFT, store result in buffer 'x' FFT_EXECUTE(_q->ifft); // TODO: ignore this scaling // scale result by 1/num_channels (C transform) for (i=0; i<_q->M; i++) _q->x[i] *= 1.0f / (float)(_q->M); // scale result by num_channels/2 for (i=0; i<_q->M; i++) _q->x[i] *= (float)(_q->M2); // push samples into appropriate buffer WINDOW() * buffer = (_q->flag == 0 ? _q->w1 : _q->w0); for (i=0; i<_q->M; i++) WINDOW(_push)(buffer[i], _q->x[i]); // compute filter outputs TO * r0, * r1; // buffer read pointers TO y0, y1; // dotprod outputs for (i=0; i<_q->M2; i++) { // buffer index unsigned int b = (_q->flag == 0) ? i : i+_q->M2; // read buffer with index offset WINDOW(_read)(_q->w0[b], &r0); WINDOW(_read)(_q->w1[b], &r1); // swap buffer outputs on alternating runs TO * p0 = _q->flag ? r0 : r1; TO * p1 = _q->flag ? r1 : r0; // run dot products DOTPROD(_execute)(_q->dp[i], p0, &y0); DOTPROD(_execute)(_q->dp[i+_q->M2], p1, &y1); // save output _y[i] = y0 + y1; } _q->flag = 1 - _q->flag; } // execute filterbank channelizer // LIQUID_ANALYZER: input: M/2, output: M // LIQUID_SYNTHESIZER: input: M, output: M/2 // _x : channelizer input // _y : channelizer output void FIRPFBCH2(_execute)(FIRPFBCH2() _q, TI * _x, TO * _y) { switch (_q->type) { case LIQUID_ANALYZER: FIRPFBCH2(_execute_analyzer)(_q, _x, _y); return; case LIQUID_SYNTHESIZER: FIRPFBCH2(_execute_synthesizer)(_q, _x, _y); return; default: fprintf(stderr,"error: firpfbch2_%s_execute(), invalid type\n", EXTENSION_FULL); exit(1); } } liquid-dsp-1.3.1/src/multichannel/src/firpfbch_cccf.c000066400000000000000000000037361317124540100225440ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // multichannel API: complex floating-point // #include "liquid.internal.h" // naming extensions (useful for print statements) #define EXTENSION_SHORT "f" #define EXTENSION_FULL "cccf" // #define FIRPFBCH(name) LIQUID_CONCAT(firpfbch_cccf,name) #define T float complex // general #define TO float complex // output #define TC float complex // coefficients #define TI float complex // input #define WINDOW(name) LIQUID_CONCAT(windowcf,name) #define DOTPROD(name) LIQUID_CONCAT(dotprod_cccf,name) #define TO_COMPLEX 1 #define TC_COMPLEX 1 #define TI_COMPLEX 1 #define PRINTVAL_TO(X,F) PRINTVAL_CFLOAT(X,F) #define PRINTVAL_TC(X,F) PRINTVAL_CFLOAT(X,F) #define PRINTVAL_TI(X,F) PRINTVAL_CFLOAT(X,F) // source files #include "firpfbch.c" liquid-dsp-1.3.1/src/multichannel/src/firpfbch_crcf.c000066400000000000000000000042321317124540100225530ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // multichannel API: complex floating-point // #include "liquid.internal.h" // naming extensions (useful for print statements) #define EXTENSION_SHORT "f" #define EXTENSION_FULL "crcf" // #define FIRPFBCH(name) LIQUID_CONCAT(firpfbch_crcf,name) #define FIRPFBCH2(name) LIQUID_CONCAT(firpfbch2_crcf,name) #define T float complex // general #define TO float complex // output #define TC float // coefficients #define TI float complex // input #define WINDOW(name) LIQUID_CONCAT(windowcf,name) #define DOTPROD(name) LIQUID_CONCAT(dotprod_crcf,name) #define TO_COMPLEX 1 #define TC_COMPLEX 0 #define TI_COMPLEX 1 #define PRINTVAL_TO(X,F) PRINTVAL_CFLOAT(X,F) #define PRINTVAL_TC(X,F) PRINTVAL_FLOAT(X,F) #define PRINTVAL_TI(X,F) PRINTVAL_CFLOAT(X,F) // source files #include "firpfbch.c" // maximally-decimated polyphase filterbank #include "firpfbch2.c" // polyphase filterbank w/ output rate 2 Fs / M liquid-dsp-1.3.1/src/multichannel/src/firpfbch_old.c000066400000000000000000000225421317124540100224200ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // // #include #include #include #include "liquid.internal.h" #define DEBUG_FIRPFBCH_PRINT 0 #define FIRFILT(name) LIQUID_CONCAT(firfilt_crcf,name) #define DOTPROD(name) LIQUID_CONCAT(dotprod_crcf,name) #define WINDOW(name) LIQUID_CONCAT(windowcf,name) struct firpfbch_s { unsigned int num_channels; unsigned int m; float beta; float dt; float complex * x; // time-domain buffer float complex * X; // freq-domain buffer // run|state buffers float complex * X_prime; // freq-domain buffer (analysis // filter bank) // filter unsigned int h_len; float * h; unsigned int filter_index; // create separate bank of dotprod and window objects DOTPROD() * dp; WINDOW() * w; // fft plan FFT_PLAN fft; int nyquist; // nyquist/root-nyquist //int type; // synthesis/analysis }; firpfbch firpfbch_create(unsigned int _num_channels, unsigned int _m, float _beta, float _dt, int _nyquist, int _gradient) { firpfbch c = (firpfbch) malloc(sizeof(struct firpfbch_s)); c->num_channels = _num_channels; c->m = _m; c->beta = _beta; c->dt = _dt; c->nyquist = _nyquist; // validate inputs if (_m < 1) { printf("error: firpfbch_create(), invalid filter delay (must be greater than 0)\n"); exit(1); } // create bank of filters c->dp = (DOTPROD()*) malloc((c->num_channels)*sizeof(DOTPROD())); c->w = (WINDOW()*) malloc((c->num_channels)*sizeof(WINDOW())); // design filter // TODO: use filter prototype object c->h_len = 2*(c->m)*(c->num_channels); c->h = (float*) malloc((c->h_len+1)*sizeof(float)); if (c->nyquist == FIRPFBCH_NYQUIST) { float fc = 0.5f/(float)(c->num_channels); // cutoff frequency liquid_firdes_kaiser(c->h_len+1, fc, c->beta, 0.0f, c->h); } else if (c->nyquist == FIRPFBCH_ROOTNYQUIST) { design_rkaiser_filter(c->num_channels, c->m, c->beta, c->dt, c->h); } else { printf("error: firpfbch_create(), unsupported nyquist flag: %d\n", _nyquist); exit(1); } unsigned int i; if (_gradient) { float dh[c->h_len]; for (i=0; ih_len; i++) { if (i==0) { dh[i] = c->h[i+1] - c->h[c->h_len-1]; } else if (i==c->h_len-1) { dh[i] = c->h[0] - c->h[i-1]; } else { dh[i] = c->h[i+1] - c->h[i-1]; } } memmove(c->h, dh, (c->h_len)*sizeof(float)); } // generate bank of sub-samped filters unsigned int n; unsigned int h_sub_len = 2*(c->m); // length of each sub-sampled filter float h_sub[h_sub_len]; for (i=0; inum_channels; i++) { // sub-sample prototype filter, loading coefficients in reverse order for (n=0; nh[i + n*(c->num_channels)]; } // create window buffer and dotprod object (coefficients // loaded in reverse order) c->dp[i] = DOTPROD(_create)(h_sub,h_sub_len); c->w[i] = WINDOW(_create)(h_sub_len); #if DEBUG_FIRPFBCH_PRINT printf("h_sub[%u] :\n", i); for (n=0; nh_len+1; i++) printf("h(%4u) = %12.4e;\n", i+1, c->h[i]); #endif // allocate memory for buffers // TODO : use fftw_malloc if HAVE_FFTW3_H c->x = (float complex*) malloc((c->num_channels)*sizeof(float complex)); c->X = (float complex*) malloc((c->num_channels)*sizeof(float complex)); c->X_prime = (float complex*) malloc((c->num_channels)*sizeof(float complex)); firpfbch_clear(c); // create fft plan c->fft = FFT_CREATE_PLAN(c->num_channels, c->X, c->x, FFT_DIR_BACKWARD, FFT_METHOD); return c; } void firpfbch_destroy(firpfbch _c) { unsigned int i; for (i=0; i<_c->num_channels; i++) { DOTPROD(_destroy)(_c->dp[i]); WINDOW(_destroy)(_c->w[i]); } free(_c->dp); free(_c->w); FFT_DESTROY_PLAN(_c->fft); free(_c->h); free(_c->x); free(_c->X); free(_c->X_prime); free(_c); } void firpfbch_clear(firpfbch _c) { unsigned int i; for (i=0; i<_c->num_channels; i++) { WINDOW(_clear)(_c->w[i]); _c->x[i] = 0; _c->X[i] = 0; _c->X_prime[i] = 0; } _c->filter_index = 0; } void firpfbch_print(firpfbch _c) { printf("firpfbch: [%u channels]\n", _c->num_channels); unsigned int i; for (i=0; i<_c->num_channels; i++) { DOTPROD(_print)(_c->dp[i]); } } void firpfbch_get_filter_taps(firpfbch _c, float * _h) { memmove(_h, _c->h, (_c->h_len)*sizeof(float)); } // // SYNTHESIZER // void firpfbch_synthesizer_execute(firpfbch _c, float complex * _x, float complex * _y) { unsigned int i; // copy samples into ifft input buffer _c->X memmove(_c->X, _x, (_c->num_channels)*sizeof(float complex)); // execute inverse fft, store in buffer _c->x FFT_EXECUTE(_c->fft); // push samples into filter bank and execute, putting // samples into output buffer _y float complex * r; for (i=0; i<_c->num_channels; i++) { WINDOW(_push)(_c->w[i], _c->x[i]); WINDOW(_read)(_c->w[i], &r); DOTPROD(_execute)(_c->dp[i], r, &(_y[i])); // invoke scaling factor _y[i] /= (float)(_c->num_channels); } } // // ANALYZER // void firpfbch_analyzer_execute(firpfbch _c, float complex * _x, float complex * _y) { unsigned int i; for (i=0; i<_c->num_channels; i++) firpfbch_analyzer_push(_c,_x[i]); // run the analysis filters on the given input firpfbch_analyzer_run(_c,_y); // save the run state : IDFT input X -> X_prime firpfbch_analyzer_saverunstate(_c); } void firpfbch_analyzer_push(firpfbch _c, float complex _x) { // push sample into the buffer at filter_index WINDOW(_push)(_c->w[_c->filter_index], _x); // decrement filter index _c->filter_index = (_c->filter_index+_c->num_channels-1) % _c->num_channels; } void firpfbch_analyzer_run(firpfbch _c, float complex * _y) { // NOTE: The analyzer is different from the synthesizer in // that the invocation of the commutator results in a // delay from the first input sample to the resulting // partitions. As a result, the inverse DFT is // invoked after the first filter is run, after which // the remaining filters are executed. // restore saved IDFT input state X from X_prime memmove(_c->X, _c->X_prime, (_c->num_channels)*sizeof(float complex)); unsigned int i, b; unsigned int k = _c->filter_index; // push first value and compute output float complex * r; WINDOW(_read)(_c->w[k], &r); DOTPROD(_execute)(_c->dp[0], r, &(_c->X[0])); // execute inverse fft, store in buffer _c->x FFT_EXECUTE(_c->fft); // copy results to output buffer memmove(_y, _c->x, (_c->num_channels)*sizeof(float complex)); // push remaining samples into filter bank and execute in // *reverse* order, putting result into the inverse DFT // input buffer _c->X //for (i=1; i<_c->num_channels; i++) { // NOTE : the filter window buffers have already been loaded // in the proper reverse order, so there is no need // to execute the dot products in any particular order, // so long as they are aligned with the proper input // buffer. for (i=1; i<_c->num_channels; i++) { b = (k+i) % _c->num_channels; WINDOW(_read)(_c->w[b], &r); DOTPROD(_execute)(_c->dp[i], r, &(_c->X[i])); } } // save the run state of the filter bank by dumping the // IDFT input buffer X into the temporary buffer X_prime void firpfbch_analyzer_saverunstate(firpfbch _c) { memmove(_c->X_prime, _c->X, (_c->num_channels)*sizeof(float complex)); } // clear the run state of the filter bank void firpfbch_analyzer_clearrunstate(firpfbch _c) { unsigned int i; for (i=0; i<_c->num_channels; i++) _c->X_prime[i] = 0; } liquid-dsp-1.3.1/src/multichannel/src/ofdmframe.common.c000066400000000000000000000237351317124540100232330ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // ofdmframe data, methods common to both generator/synchronizer // objects // - physical layer convergence procedure (PLCP) // #include #include #include #include "liquid.internal.h" // generate short sequence symbols // _p : subcarrier allocation array // _M : total number of subcarriers // _S0 : output symbol (freq) // _s0 : output symbol (time) // _M_S0 : total number of enabled subcarriers in S0 void ofdmframe_init_S0(unsigned char * _p, unsigned int _M, float complex * _S0, float complex * _s0, unsigned int * _M_S0) { unsigned int i; // compute m-sequence length unsigned int m = liquid_nextpow2(_M); if (m < 4) m = 4; else if (m > 8) m = 8; // generate m-sequence generator object msequence ms = msequence_create_default(m); unsigned int s; unsigned int M_S0 = 0; // short sequence for (i=0; i<_M; i++) { // generate symbol //s = msequence_generate_symbol(ms,1); s = msequence_generate_symbol(ms,3) & 0x01; if (_p[i] == OFDMFRAME_SCTYPE_NULL) { // NULL subcarrier _S0[i] = 0.0f; } else { if ( (i%2) == 0 ) { // even subcarrer _S0[i] = s ? 1.0f : -1.0f; M_S0++; } else { // odd subcarrer (ignore) _S0[i] = 0.0f; } } } // destroy objects msequence_destroy(ms); // ensure at least one subcarrier was enabled if (M_S0 == 0) { fprintf(stderr,"error: ofdmframe_init_S0(), no subcarriers enabled; check allocation\n"); exit(1); } // set return value(s) *_M_S0 = M_S0; // run inverse fft to get time-domain sequence fft_run(_M, _S0, _s0, LIQUID_FFT_BACKWARD, 0); // normalize time-domain sequence level float g = 1.0f / sqrtf(M_S0); for (i=0; i<_M; i++) _s0[i] *= g; } // generate long sequence symbols // _p : subcarrier allocation array // _M : total number of subcarriers // _S1 : output symbol (freq) // _s1 : output symbol (time) // _M_S1 : total number of enabled subcarriers in S1 void ofdmframe_init_S1(unsigned char * _p, unsigned int _M, float complex * _S1, float complex * _s1, unsigned int * _M_S1) { unsigned int i; // compute m-sequence length unsigned int m = liquid_nextpow2(_M); if (m < 4) m = 4; else if (m > 8) m = 8; // increase m such that the resulting S1 sequence will // differ significantly from S0 with the same subcarrier // allocation array m++; // generate m-sequence generator object msequence ms = msequence_create_default(m); unsigned int s; unsigned int M_S1 = 0; // long sequence for (i=0; i<_M; i++) { // generate symbol //s = msequence_generate_symbol(ms,1); s = msequence_generate_symbol(ms,3) & 0x01; if (_p[i] == OFDMFRAME_SCTYPE_NULL) { // NULL subcarrier _S1[i] = 0.0f; } else { _S1[i] = s ? 1.0f : -1.0f; M_S1++; } } // destroy objects msequence_destroy(ms); // ensure at least one subcarrier was enabled if (M_S1 == 0) { fprintf(stderr,"error: ofdmframe_init_S1(), no subcarriers enabled; check allocation\n"); exit(1); } // set return value(s) *_M_S1 = M_S1; // run inverse fft to get time-domain sequence fft_run(_M, _S1, _s1, LIQUID_FFT_BACKWARD, 0); // normalize time-domain sequence level float g = 1.0f / sqrtf(M_S1); for (i=0; i<_M; i++) _s1[i] *= g; } // initialize default subcarrier allocation // _M : number of subcarriers // _p : output subcarrier allocation array, [size: _M x 1] // // key: '.' (null), 'P' (pilot), '+' (data) // .+++P+++++++P.........P+++++++P+++ // void ofdmframe_init_default_sctype(unsigned int _M, unsigned char * _p) { // validate input if (_M < 6) { fprintf(stderr,"warning: ofdmframe_init_default_sctype(), less than 6 subcarriers\n"); } unsigned int i; unsigned int M2 = _M/2; // compute guard band unsigned int G = _M / 10; if (G < 2) G = 2; // designate pilot spacing unsigned int P = (_M > 34) ? 8 : 4; unsigned int P2 = P/2; // initialize as NULL for (i=0; i<_M; i++) _p[i] = OFDMFRAME_SCTYPE_NULL; // upper band for (i=1; i 0.5f) { fprintf(stderr,"error: ofdmframe_init_sctype_range(), lower frequency edge must be in [-0.5,0.5]\n"); exit(1); } else if (_f1 < -0.5f || _f1 > 0.5f) { fprintf(stderr,"error: ofdmframe_init_sctype_range(), upper frequency edge must be in [-0.5,0.5]\n"); exit(1); } else if (_f0 >= _f1) { fprintf(stderr,"error: ofdmframe_init_sctype_range(), lower frequency edge must be below upper edge\n"); exit(1); } // get relative edges int M0 = (int)((_f0 + 0.5f) * _M); // lower subcarrier index int M1 = (int)((_f1 + 0.5f) * _M); // upper subcarrier index int Mp = M1 - M0; if (Mp > (int)_M) { Mp = (int)_M; } else if (Mp < 6) { fprintf(stderr,"warning: ofdmframe_init_sctype_range(), less than 6 subcarriers (effectively)\n"); exit(1); } // designate pilot spacing unsigned int P = (Mp > 34) ? 8 : 4; // upper band int i; for (i=0; i<(int)_M; i++) { // shift unsigned int k = ((unsigned int)i + _M/2) % _M; if (i < M0 || i > M1) { // guard band _p[k] = OFDMFRAME_SCTYPE_NULL; } else if ( (k%P)==0 ) { _p[k] = OFDMFRAME_SCTYPE_PILOT; } else { _p[k] = OFDMFRAME_SCTYPE_DATA; } } } // validate subcarrier type (count number of null, pilot, and data // subcarriers in the allocation) // _p : subcarrier allocation array, [size: _M x 1] // _M : number of subcarriers // _M_null : output number of null subcarriers // _M_pilot : output number of pilot subcarriers // _M_data : output number of data subcarriers void ofdmframe_validate_sctype(unsigned char * _p, unsigned int _M, unsigned int * _M_null, unsigned int * _M_pilot, unsigned int * _M_data) { // clear counters unsigned int M_null = 0; unsigned int M_pilot = 0; unsigned int M_data = 0; unsigned int i; for (i=0; i<_M; i++) { // update appropriate counters if (_p[i] == OFDMFRAME_SCTYPE_NULL) M_null++; else if (_p[i] == OFDMFRAME_SCTYPE_PILOT) M_pilot++; else if (_p[i] == OFDMFRAME_SCTYPE_DATA) M_data++; else { fprintf(stderr,"error: ofdmframe_validate_sctype(), invalid subcarrier type (%u)\n", _p[i]); exit(1); } } // set outputs *_M_null = M_null; *_M_pilot = M_pilot; *_M_data = M_data; } // print subcarrier allocation to screen // // key: '.' (null), 'P' (pilot), '+' (data) // .+++P+++++++P.........P+++++++P+++ // void ofdmframe_print_sctype(unsigned char * _p, unsigned int _M) { unsigned int i; printf("["); for (i=0; i<_M; i++) { unsigned int k = (i + _M/2) % _M; switch (_p[k]) { case OFDMFRAME_SCTYPE_NULL: printf("."); break; case OFDMFRAME_SCTYPE_PILOT: printf("|"); break; case OFDMFRAME_SCTYPE_DATA: printf("+"); break; default: fprintf(stderr,"error: ofdmframe_print_default_sctype(), invalid subcarrier type\n"); exit(1); } } printf("]\n"); } liquid-dsp-1.3.1/src/multichannel/src/ofdmframegen.c000066400000000000000000000300051317124540100224220ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // ofdmframegen.c // // OFDM frame generator // #include #include #include #include #include #include "liquid.internal.h" #if HAVE_FFTW3_H # include #endif #define DEBUG_OFDMFRAMEGEN 1 struct ofdmframegen_s { unsigned int M; // number of subcarriers unsigned int cp_len; // cyclic prefix length unsigned char * p; // subcarrier allocation (null, pilot, data) // tapering/trasition unsigned int taper_len; // number of samples in tapering window/overlap float * taper; // tapering window float complex *postfix; // overlapping symbol buffer // constants unsigned int M_null; // number of null subcarriers unsigned int M_pilot; // number of pilot subcarriers unsigned int M_data; // number of data subcarriers unsigned int M_S0; // number of enabled subcarriers in S0 unsigned int M_S1; // number of enabled subcarriers in S1 // scaling factors float g_data; // // transform object FFT_PLAN ifft; // ifft object float complex * X; // frequency-domain buffer float complex * x; // time-domain buffer // PLCP short float complex * S0; // short sequence (frequency) float complex * s0; // short sequence (time) // PLCP long float complex * S1; // long sequence (frequency) float complex * s1; // long sequence (time) // pilot sequence msequence ms_pilot; }; // create OFDM framing generator object // _M : number of subcarriers, >10 typical // _cp_len : cyclic prefix length // _taper_len : taper length (OFDM symbol overlap) // _p : subcarrier allocation (null, pilot, data), [size: _M x 1] ofdmframegen ofdmframegen_create(unsigned int _M, unsigned int _cp_len, unsigned int _taper_len, unsigned char * _p) { // validate input if (_M < 2) { fprintf(stderr,"error: ofdmframegen_create(), number of subcarriers must be at least 2\n"); exit(1); } else if (_M % 2) { fprintf(stderr,"error: ofdmframegen_create(), number of subcarriers must be even\n"); exit(1); } else if (_cp_len > _M) { fprintf(stderr,"error: ofdmframegen_create(), cyclic prefix cannot exceed symbol length\n"); exit(1); } else if (_taper_len > _cp_len) { fprintf(stderr,"error: ofdmframegen_create(), taper length cannot exceed cyclic prefix\n"); exit(1); } ofdmframegen q = (ofdmframegen) malloc(sizeof(struct ofdmframegen_s)); q->M = _M; q->cp_len = _cp_len; q->taper_len = _taper_len; // allocate memory for subcarrier allocation IDs q->p = (unsigned char*) malloc((q->M)*sizeof(unsigned char)); if (_p == NULL) { // initialize default subcarrier allocation ofdmframe_init_default_sctype(q->M, q->p); } else { // copy user-defined subcarrier allocation memmove(q->p, _p, q->M*sizeof(unsigned char)); } // validate and count subcarrier allocation ofdmframe_validate_sctype(q->p, q->M, &q->M_null, &q->M_pilot, &q->M_data); if ( (q->M_pilot + q->M_data) == 0) { fprintf(stderr,"error: ofdmframegen_create(), must have at least one enabled subcarrier\n"); exit(1); } else if (q->M_data == 0) { fprintf(stderr,"error: ofdmframegen_create(), must have at least one data subcarriers\n"); exit(1); } else if (q->M_pilot < 2) { fprintf(stderr,"error: ofdmframegen_create(), must have at least two pilot subcarriers\n"); exit(1); } unsigned int i; // allocate memory for transform objects q->X = (float complex*) malloc((q->M)*sizeof(float complex)); q->x = (float complex*) malloc((q->M)*sizeof(float complex)); q->ifft = FFT_CREATE_PLAN(q->M, q->X, q->x, FFT_DIR_BACKWARD, FFT_METHOD); // allocate memory for PLCP arrays q->S0 = (float complex*) malloc((q->M)*sizeof(float complex)); q->s0 = (float complex*) malloc((q->M)*sizeof(float complex)); q->S1 = (float complex*) malloc((q->M)*sizeof(float complex)); q->s1 = (float complex*) malloc((q->M)*sizeof(float complex)); ofdmframe_init_S0(q->p, q->M, q->S0, q->s0, &q->M_S0); ofdmframe_init_S1(q->p, q->M, q->S1, q->s1, &q->M_S1); // create tapering window and transition buffer q->taper = (float*) malloc(q->taper_len * sizeof(float)); q->postfix = (float complex*) malloc(q->taper_len * sizeof(float complex)); for (i=0; itaper_len; i++) { float t = ((float)i + 0.5f) / (float)(q->taper_len); float g = sinf(M_PI_2*t); q->taper[i] = g*g; } #if 0 // validate window symmetry for (i=0; itaper_len; i++) { printf(" taper[%2u] = %12.8f (%12.8f)\n", i, q->taper[i], q->taper[i] + q->taper[q->taper_len - i - 1]); } #endif // compute scaling factor q->g_data = 1.0f / sqrtf(q->M_pilot + q->M_data); // set pilot sequence q->ms_pilot = msequence_create_default(8); return q; } // free transform object memory void ofdmframegen_destroy(ofdmframegen _q) { // free subcarrier type array memory free(_q->p); // free transform array memory free(_q->X); free(_q->x); FFT_DESTROY_PLAN(_q->ifft); // free tapering window and transition buffer free(_q->taper); free(_q->postfix); // free PLCP memory arrays free(_q->S0); free(_q->s0); free(_q->S1); free(_q->s1); // free pilot msequence object memory msequence_destroy(_q->ms_pilot); // free main object memory free(_q); } void ofdmframegen_print(ofdmframegen _q) { printf("ofdmframegen:\n"); printf(" num subcarriers : %-u\n", _q->M); printf(" - NULL : %-u\n", _q->M_null); printf(" - pilot : %-u\n", _q->M_pilot); printf(" - data : %-u\n", _q->M_data); printf(" cyclic prefix len : %-u\n", _q->cp_len); printf(" taper len : %-u\n", _q->taper_len); printf(" "); ofdmframe_print_sctype(_q->p, _q->M); } void ofdmframegen_reset(ofdmframegen _q) { msequence_reset(_q->ms_pilot); // clear internal postfix buffer unsigned int i; for (i=0; i<_q->taper_len; i++) _q->postfix[i] = 0.0f; } // write first PLCP short sequence 'symbol' to buffer // // |<- 2*cp->|<- M ->|<- M ->| // | | | | // +-----+-------------------+-------------------+ // / | | | // / ..s0 | s0 | s0 | // / | | | // +---------+-------------------+-------------------+-----> time // | | | // |<- s0[a] ->|<- s0[b] ->| // | M + cp_len | M + cp_len | // void ofdmframegen_write_S0a(ofdmframegen _q, float complex * _y) { unsigned int i; unsigned int k; for (i=0; i<_q->M + _q->cp_len; i++) { k = (i + _q->M - 2*_q->cp_len) % _q->M; _y[i] = _q->s0[k]; } // apply tapering window for (i=0; i<_q->taper_len; i++) _y[i] *= _q->taper[i]; } void ofdmframegen_write_S0b(ofdmframegen _q, float complex * _y) { unsigned int i; unsigned int k; for (i=0; i<_q->M + _q->cp_len; i++) { k = (i + _q->M - _q->cp_len) % _q->M; _y[i] = _q->s0[k]; } // copy postfix (first 'taper_len' samples of s0 symbol) memmove(_q->postfix, _q->s0, _q->taper_len*sizeof(float complex)); } void ofdmframegen_write_S1(ofdmframegen _q, float complex * _y) { // copy S1 symbol to output, adding cyclic prefix and tapering window memmove(_q->x, _q->s1, (_q->M)*sizeof(float complex)); ofdmframegen_gensymbol(_q, _y); } // write OFDM symbol // _q : framing generator object // _x : input symbols, [size: _M x 1] // _y : output samples, [size: _M x 1] void ofdmframegen_writesymbol(ofdmframegen _q, float complex * _x, float complex * _y) { // move frequency data to internal buffer unsigned int i; unsigned int k; int sctype; for (i=0; i<_q->M; i++) { // start at mid-point (effective fftshift) k = (i + _q->M/2) % _q->M; sctype = _q->p[k]; if (sctype==OFDMFRAME_SCTYPE_NULL) { // disabled subcarrier _q->X[k] = 0.0f; } else if (sctype==OFDMFRAME_SCTYPE_PILOT) { // pilot subcarrier _q->X[k] = (msequence_advance(_q->ms_pilot) ? 1.0f : -1.0f) * _q->g_data; } else { // data subcarrier _q->X[k] = _x[k] * _q->g_data; } //printf("X[%3u] = %12.8f + j*%12.8f;\n",i+1,crealf(_q->X[i]),cimagf(_q->X[i])); } // execute transform FFT_EXECUTE(_q->ifft); // copy result to output, adding cyclic prefix and tapering window ofdmframegen_gensymbol(_q, _y); } // write tail to output void ofdmframegen_writetail(ofdmframegen _q, float complex * _buffer) { // write tail to output, applying tapering window unsigned int i; for (i=0; i<_q->taper_len; i++) _buffer[i] = _q->postfix[i] * _q->taper[_q->taper_len-i-1]; } // // internal methods // // generate symbol (add cyclic prefix/postfix, overlap) // // ->| |<- taper_len // + +-----+-------------------+ // \ / | | // X | symbol | // / \ | | // +---+-----+-------------------+----> time // | | | // |<- cp ->|<- M ->| // // _q->x : input time-domain symbol [size: _q->M x 1] // _q->postfix : input: post-fix from previous symbol [size: _q->taper_len x 1] // output: post-fix from this new symbol // _q->taper : tapering window // _q->taper_len : tapering window length // // _buffer : output sample buffer [size: (_q->M + _q->cp_len) x 1] void ofdmframegen_gensymbol(ofdmframegen _q, float complex * _buffer) { // copy input symbol with cyclic prefix to output symbol memmove( &_buffer[0], &_q->x[_q->M-_q->cp_len], _q->cp_len*sizeof(float complex)); memmove( &_buffer[_q->cp_len], &_q->x[ 0], _q->M * sizeof(float complex)); // apply tapering window to over-lapping regions unsigned int i; for (i=0; i<_q->taper_len; i++) { _buffer[i] *= _q->taper[i]; _buffer[i] += _q->postfix[i] * _q->taper[_q->taper_len-i-1]; } // copy post-fix to output (first 'taper_len' samples of input symbol) memmove(_q->postfix, _q->x, _q->taper_len*sizeof(float complex)); } liquid-dsp-1.3.1/src/multichannel/src/ofdmframesync.c000066400000000000000000001213451317124540100226350ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // ofdmframesync.c // // OFDM frame synchronizer // #include #include #include #include #include #include "liquid.internal.h" #define DEBUG_OFDMFRAMESYNC 1 #define DEBUG_OFDMFRAMESYNC_PRINT 0 #define DEBUG_OFDMFRAMESYNC_FILENAME "ofdmframesync_internal_debug.m" #define DEBUG_OFDMFRAMESYNC_BUFFER_LEN (2048) #define OFDMFRAMESYNC_ENABLE_SQUELCH 0 struct ofdmframesync_s { unsigned int M; // number of subcarriers unsigned int M2; // number of subcarriers (divided by 2) unsigned int cp_len; // cyclic prefix length unsigned char * p; // subcarrier allocation (null, pilot, data) // constants unsigned int M_null; // number of null subcarriers unsigned int M_pilot; // number of pilot subcarriers unsigned int M_data; // number of data subcarriers unsigned int M_S0; // number of enabled subcarriers in S0 unsigned int M_S1; // number of enabled subcarriers in S1 // scaling factors float g_data; // data symbols gain float g_S0; // S0 training symbols gain float g_S1; // S1 training symbols gain // transform object FFT_PLAN fft; // ifft object float complex * X; // frequency-domain buffer float complex * x; // time-domain buffer windowcf input_buffer; // input sequence buffer // PLCP sequences float complex * S0; // short sequence (freq) float complex * s0; // short sequence (time) float complex * S1; // long sequence (freq) float complex * s1; // long sequence (time) // gain float g0; // nominal gain (coarse initial estimate) float complex * G0; // complex subcarrier gain estimate, S0[0] float complex * G1; // complex subcarrier gain estimate, S0[1] float complex * G; // complex subcarrier gain estimate float complex * B; // subcarrier phase rotation due to backoff float complex * R; // // receiver state enum { OFDMFRAMESYNC_STATE_SEEKPLCP=0, // seek initial PLCP OFDMFRAMESYNC_STATE_PLCPSHORT0, // seek first PLCP short sequence OFDMFRAMESYNC_STATE_PLCPSHORT1, // seek second PLCP short sequence OFDMFRAMESYNC_STATE_PLCPLONG, // seek PLCP long sequence OFDMFRAMESYNC_STATE_RXSYMBOLS // receive payload symbols } state; // synchronizer objects nco_crcf nco_rx; // numerically-controlled oscillator msequence ms_pilot; // pilot sequence generator float phi_prime; // ... float p1_prime; // filtered pilot phase slope #if OFDMFRAMESYNC_ENABLE_SQUELCH // coarse signal detection float squelch_threshold; int squelch_enabled; #endif // timing unsigned int timer; // input sample timer unsigned int num_symbols; // symbol counter unsigned int backoff; // sample timing backoff float complex s_hat_0; // first S0 symbol metrics estimate float complex s_hat_1; // second S0 symbol metrics estimate // detection thresholds float plcp_detect_thresh; // plcp detection threshold, nominally 0.35 float plcp_sync_thresh; // long symbol threshold, nominally 0.30 // callback ofdmframesync_callback callback; void * userdata; #if DEBUG_OFDMFRAMESYNC int debug_enabled; int debug_objects_created; windowcf debug_x; windowf debug_rssi; windowcf debug_framesyms; float complex * G_hat; // complex subcarrier gain estimate, S1 float * px; // pilot x-value float * py; // pilot y-value float p_phase[2]; // pilot polyfit windowf debug_pilot_0; // pilot polyfit history, p[0] windowf debug_pilot_1; // pilot polyfit history, p[1] #endif }; // create OFDM framing synchronizer object // _M : number of subcarriers, >10 typical // _cp_len : cyclic prefix length // _taper_len : taper length (OFDM symbol overlap) // _p : subcarrier allocation (null, pilot, data), [size: _M x 1] // _callback : user-defined callback function // _userdata : user-defined data pointer ofdmframesync ofdmframesync_create(unsigned int _M, unsigned int _cp_len, unsigned int _taper_len, unsigned char * _p, ofdmframesync_callback _callback, void * _userdata) { ofdmframesync q = (ofdmframesync) malloc(sizeof(struct ofdmframesync_s)); // validate input if (_M < 8) { fprintf(stderr,"warning: ofdmframesync_create(), less than 8 subcarriers\n"); } else if (_M % 2) { fprintf(stderr,"error: ofdmframesync_create(), number of subcarriers must be even\n"); exit(1); } else if (_cp_len > _M) { fprintf(stderr,"error: ofdmframesync_create(), cyclic prefix length cannot exceed number of subcarriers\n"); exit(1); } q->M = _M; q->cp_len = _cp_len; // derived values q->M2 = _M/2; // subcarrier allocation q->p = (unsigned char*) malloc((q->M)*sizeof(unsigned char)); if (_p == NULL) { ofdmframe_init_default_sctype(q->M, q->p); } else { memmove(q->p, _p, q->M*sizeof(unsigned char)); } // validate and count subcarrier allocation ofdmframe_validate_sctype(q->p, q->M, &q->M_null, &q->M_pilot, &q->M_data); if ( (q->M_pilot + q->M_data) == 0) { fprintf(stderr,"error: ofdmframesync_create(), must have at least one enabled subcarrier\n"); exit(1); } else if (q->M_data == 0) { fprintf(stderr,"error: ofdmframesync_create(), must have at least one data subcarriers\n"); exit(1); } else if (q->M_pilot < 2) { fprintf(stderr,"error: ofdmframesync_create(), must have at least two pilot subcarriers\n"); exit(1); } // create transform object q->X = (float complex*) malloc((q->M)*sizeof(float complex)); q->x = (float complex*) malloc((q->M)*sizeof(float complex)); q->fft = FFT_CREATE_PLAN(q->M, q->x, q->X, FFT_DIR_FORWARD, FFT_METHOD); // create input buffer the length of the transform q->input_buffer = windowcf_create(q->M + q->cp_len); // allocate memory for PLCP arrays q->S0 = (float complex*) malloc((q->M)*sizeof(float complex)); q->s0 = (float complex*) malloc((q->M)*sizeof(float complex)); q->S1 = (float complex*) malloc((q->M)*sizeof(float complex)); q->s1 = (float complex*) malloc((q->M)*sizeof(float complex)); ofdmframe_init_S0(q->p, q->M, q->S0, q->s0, &q->M_S0); ofdmframe_init_S1(q->p, q->M, q->S1, q->s1, &q->M_S1); // compute scaling factor q->g_data = sqrtf(q->M) / sqrtf(q->M_pilot + q->M_data); q->g_S0 = sqrtf(q->M) / sqrtf(q->M_S0); q->g_S1 = sqrtf(q->M) / sqrtf(q->M_S1); // gain q->g0 = 1.0f; q->G0 = (float complex*) malloc((q->M)*sizeof(float complex)); q->G1 = (float complex*) malloc((q->M)*sizeof(float complex)); q->G = (float complex*) malloc((q->M)*sizeof(float complex)); q->B = (float complex*) malloc((q->M)*sizeof(float complex)); q->R = (float complex*) malloc((q->M)*sizeof(float complex)); #if 1 memset(q->G0, 0x00, q->M*sizeof(float complex)); memset(q->G1, 0x00, q->M*sizeof(float complex)); memset(q->G , 0x00, q->M*sizeof(float complex)); memset(q->B, 0x00, q->M*sizeof(float complex)); #endif // timing backoff q->backoff = q->cp_len < 2 ? q->cp_len : 2; float phi = (float)(q->backoff)*2.0f*M_PI/(float)(q->M); unsigned int i; for (i=0; iM; i++) q->B[i] = liquid_cexpjf(i*phi); // set callback data q->callback = _callback; q->userdata = _userdata; // // synchronizer objects // // numerically-controlled oscillator q->nco_rx = nco_crcf_create(LIQUID_NCO); // set pilot sequence q->ms_pilot = msequence_create_default(8); #if OFDMFRAMESYNC_ENABLE_SQUELCH // coarse detection q->squelch_threshold = -25.0f; q->squelch_enabled = 0; #endif // reset object ofdmframesync_reset(q); #if DEBUG_OFDMFRAMESYNC q->debug_enabled = 0; q->debug_objects_created = 0; q->debug_x = NULL; q->debug_rssi = NULL; q->debug_framesyms =NULL; q->G_hat = NULL; q->px = NULL; q->py = NULL; q->debug_pilot_0 = NULL; q->debug_pilot_1 = NULL; #endif // return object return q; } void ofdmframesync_destroy(ofdmframesync _q) { #if DEBUG_OFDMFRAMESYNC // destroy debugging objects if (_q->debug_x != NULL) windowcf_destroy(_q->debug_x); if (_q->debug_rssi != NULL) windowf_destroy(_q->debug_rssi); if (_q->debug_framesyms != NULL) windowcf_destroy(_q->debug_framesyms); if (_q->G_hat != NULL) free(_q->G_hat); if (_q->px != NULL) free(_q->px); if (_q->py != NULL) free(_q->py); if (_q->debug_pilot_0 != NULL) windowf_destroy(_q->debug_pilot_0); if (_q->debug_pilot_1 != NULL) windowf_destroy(_q->debug_pilot_1); #endif // free subcarrier type array memory free(_q->p); // free transform object windowcf_destroy(_q->input_buffer); free(_q->X); free(_q->x); FFT_DESTROY_PLAN(_q->fft); // clean up PLCP arrays free(_q->S0); free(_q->s0); free(_q->S1); free(_q->s1); // free gain arrays free(_q->G0); free(_q->G1); free(_q->G); free(_q->B); free(_q->R); // destroy synchronizer objects nco_crcf_destroy(_q->nco_rx); // numerically-controlled oscillator msequence_destroy(_q->ms_pilot); // free main object memory free(_q); } void ofdmframesync_print(ofdmframesync _q) { printf("ofdmframesync:\n"); printf(" num subcarriers : %-u\n", _q->M); printf(" cyclic prefix len : %-u\n", _q->cp_len); //printf(" taper len : %-u\n", _q->taper_len); } void ofdmframesync_reset(ofdmframesync _q) { #if 0 // reset gain parameters unsigned int i; for (i=0; i<_q->M; i++) _q->G[i] = 1.0f; #endif // reset synchronizer objects nco_crcf_reset(_q->nco_rx); msequence_reset(_q->ms_pilot); // reset timers _q->timer = 0; _q->num_symbols = 0; _q->s_hat_0 = 0.0f; _q->s_hat_1 = 0.0f; _q->phi_prime = 0.0f; _q->p1_prime = 0.0f; // set thresholds (increase for small number of subcarriers) _q->plcp_detect_thresh = (_q->M > 44) ? 0.35f : 0.35f + 0.01f*(44 - _q->M); _q->plcp_sync_thresh = (_q->M > 44) ? 0.30f : 0.30f + 0.01f*(44 - _q->M); // reset state _q->state = OFDMFRAMESYNC_STATE_SEEKPLCP; } int ofdmframesync_is_frame_open(ofdmframesync _q) { return (_q->state == OFDMFRAMESYNC_STATE_SEEKPLCP) ? 0 : 1; } void ofdmframesync_execute(ofdmframesync _q, float complex * _x, unsigned int _n) { unsigned int i; float complex x; for (i=0; i<_n; i++) { x = _x[i]; // correct for carrier frequency offset if (_q->state != OFDMFRAMESYNC_STATE_SEEKPLCP) { nco_crcf_mix_down(_q->nco_rx, x, &x); nco_crcf_step(_q->nco_rx); } // save input sample to buffer windowcf_push(_q->input_buffer,x); #if DEBUG_OFDMFRAMESYNC if (_q->debug_enabled) { windowcf_push(_q->debug_x, x); windowf_push(_q->debug_rssi, crealf(x)*crealf(x) + cimagf(x)*cimagf(x)); } #endif switch (_q->state) { case OFDMFRAMESYNC_STATE_SEEKPLCP: ofdmframesync_execute_seekplcp(_q); break; case OFDMFRAMESYNC_STATE_PLCPSHORT0: ofdmframesync_execute_S0a(_q); break; case OFDMFRAMESYNC_STATE_PLCPSHORT1: ofdmframesync_execute_S0b(_q); break; case OFDMFRAMESYNC_STATE_PLCPLONG: ofdmframesync_execute_S1(_q); break; case OFDMFRAMESYNC_STATE_RXSYMBOLS: ofdmframesync_execute_rxsymbols(_q); break; default:; } } // for (i=0; i<_n; i++) } // ofdmframesync_execute() // get receiver RSSI float ofdmframesync_get_rssi(ofdmframesync _q) { return -10.0f*log10(_q->g0); } // get receiver carrier frequency offset estimate float ofdmframesync_get_cfo(ofdmframesync _q) { return nco_crcf_get_frequency(_q->nco_rx); } // // internal methods // // frame detection void ofdmframesync_execute_seekplcp(ofdmframesync _q) { _q->timer++; if (_q->timer < _q->M) return; // reset timer _q->timer = 0; // float complex * rc; windowcf_read(_q->input_buffer, &rc); // estimate gain unsigned int i; float g = 0.0f; for (i=_q->cp_len; i<_q->M + _q->cp_len; i++) { // compute |rc[i]|^2 efficiently g += crealf(rc[i])*crealf(rc[i]) + cimagf(rc[i])*cimagf(rc[i]); } g = (float)(_q->M) / g; #if OFDMFRAMESYNC_ENABLE_SQUELCH // TODO : squelch here if ( -10*log10f( sqrtf(g) ) < _q->squelch_threshold && _q->squelch_enabled) { printf("squelch\n"); return; } #endif // estimate S0 gain ofdmframesync_estimate_gain_S0(_q, &rc[_q->cp_len], _q->G0); float complex s_hat; ofdmframesync_S0_metrics(_q, _q->G0, &s_hat); s_hat *= g; float tau_hat = cargf(s_hat) * (float)(_q->M2) / (2*M_PI); #if DEBUG_OFDMFRAMESYNC_PRINT printf(" - gain=%12.3f, rssi=%12.8f, s_hat=%12.4f <%12.8f>, tau_hat=%8.3f\n", sqrt(g), -10*log10(g), cabsf(s_hat), cargf(s_hat), tau_hat); #endif // save gain (permits dynamic invocation of get_rssi() method) _q->g0 = g; // if (cabsf(s_hat) > _q->plcp_detect_thresh) { int dt = (int)roundf(tau_hat); // set timer appropriately... _q->timer = (_q->M + dt) % (_q->M2); _q->timer += _q->M; // add delay to help ensure good S0 estimate _q->state = OFDMFRAMESYNC_STATE_PLCPSHORT0; #if DEBUG_OFDMFRAMESYNC_PRINT printf("********** frame detected! ************\n"); printf(" s_hat : %12.8f <%12.8f>\n", cabsf(s_hat), cargf(s_hat)); printf(" tau_hat : %12.8f\n", tau_hat); printf(" dt : %12d\n", dt); printf(" timer : %12u\n", _q->timer); #endif //printf("exiting prematurely\n"); //ofdmframesync_destroy(_q); //exit(1); } } // frame detection void ofdmframesync_execute_S0a(ofdmframesync _q) { //printf("t : %u\n", _q->timer); _q->timer++; if (_q->timer < _q->M2) return; // reset timer _q->timer = 0; // float complex * rc; windowcf_read(_q->input_buffer, &rc); // TODO : re-estimate nominal gain // estimate S0 gain ofdmframesync_estimate_gain_S0(_q, &rc[_q->cp_len], _q->G0); float complex s_hat; ofdmframesync_S0_metrics(_q, _q->G0, &s_hat); s_hat *= _q->g0; _q->s_hat_0 = s_hat; #if DEBUG_OFDMFRAMESYNC_PRINT float tau_hat = cargf(s_hat) * (float)(_q->M2) / (2*M_PI); printf("********** S0[0] received ************\n"); printf(" s_hat : %12.8f <%12.8f>\n", cabsf(s_hat), cargf(s_hat)); printf(" tau_hat : %12.8f\n", tau_hat); #endif #if 0 // TODO : also check for phase of s_hat (should be small) if (cabsf(s_hat) < 0.3f) { // false alarm #if DEBUG_OFDMFRAMESYNC_PRINT printf("false alarm S0[0]\n"); #endif ofdmframesync_reset(_q); return; } #endif _q->state = OFDMFRAMESYNC_STATE_PLCPSHORT1; } // frame detection void ofdmframesync_execute_S0b(ofdmframesync _q) { //printf("t = %u\n", _q->timer); _q->timer++; if (_q->timer < _q->M2) return; // reset timer _q->timer = _q->M + _q->cp_len - _q->backoff; // float complex * rc; windowcf_read(_q->input_buffer, &rc); // estimate S0 gain ofdmframesync_estimate_gain_S0(_q, &rc[_q->cp_len], _q->G1); float complex s_hat; ofdmframesync_S0_metrics(_q, _q->G1, &s_hat); s_hat *= _q->g0; _q->s_hat_1 = s_hat; #if DEBUG_OFDMFRAMESYNC_PRINT float tau_hat = cargf(s_hat) * (float)(_q->M2) / (2*M_PI); printf("********** S0[1] received ************\n"); printf(" s_hat : %12.8f <%12.8f>\n", cabsf(s_hat), cargf(s_hat)); printf(" tau_hat : %12.8f\n", tau_hat); // new timing offset estimate tau_hat = cargf(_q->s_hat_0 + _q->s_hat_1) * (float)(_q->M2) / (2*M_PI); printf(" tau_hat * : %12.8f\n", tau_hat); printf("**********\n"); #endif // re-adjust timer accordingly float tau_prime = cargf(_q->s_hat_0 + _q->s_hat_1) * (float)(_q->M2) / (2*M_PI); _q->timer -= (int)roundf(tau_prime); #if 0 if (cabsf(s_hat) < 0.3f) { #if DEBUG_OFDMFRAMESYNC_PRINT printf("false alarm S0[1]\n"); #endif // false alarm ofdmframesync_reset(_q); return; } #endif float complex g_hat = 0.0f; unsigned int i; for (i=0; i<_q->M; i++) g_hat += _q->G1[i] * conjf(_q->G0[i]); #if 0 // compute carrier frequency offset estimate using freq. domain method float nu_hat = 2.0f * cargf(g_hat) / (float)(_q->M); #else // compute carrier frequency offset estimate using ML method float complex t0 = 0.0f; for (i=0; i<_q->M2; i++) { t0 += conjf(rc[i]) * _q->s0[i] * rc[i+_q->M2] * conjf(_q->s0[i+_q->M2]); } float nu_hat = cargf(t0) / (float)(_q->M2); #endif #if DEBUG_OFDMFRAMESYNC_PRINT printf(" nu_hat : %12.8f\n", nu_hat); #endif // set NCO frequency nco_crcf_set_frequency(_q->nco_rx, nu_hat); _q->state = OFDMFRAMESYNC_STATE_PLCPLONG; } void ofdmframesync_execute_S1(ofdmframesync _q) { _q->timer--; if (_q->timer > 0) return; // increment number of symbols observed _q->num_symbols++; // run fft float complex * rc; windowcf_read(_q->input_buffer, &rc); // estimate S1 gain // TODO : add backoff in gain estimation ofdmframesync_estimate_gain_S1(_q, &rc[_q->cp_len], _q->G); // compute detector output float complex g_hat = 0.0f; unsigned int i; for (i=0; i<_q->M; i++) { //g_hat += _q->G[(i+1+_q->M)%_q->M]*conjf(_q->G[(i+_q->M)%_q->M]); g_hat += _q->G[(i+1)%_q->M]*conjf(_q->G[i]); } g_hat /= _q->M_S1; // normalize output g_hat *= _q->g0; // rotate by complex phasor relative to timing backoff g_hat *= liquid_cexpjf((float)(_q->backoff)*2.0f*M_PI/(float)(_q->M)); #if DEBUG_OFDMFRAMESYNC_PRINT printf(" g_hat : %12.4f <%12.8f>\n", cabsf(g_hat), cargf(g_hat)); #endif // check conditions for g_hat: // 1. magnitude should be large (near unity) when aligned // 2. phase should be very near zero (time aligned) if (cabsf(g_hat) > _q->plcp_sync_thresh && fabsf(cargf(g_hat)) < 0.1f*M_PI ) { //printf(" acquisition\n"); _q->state = OFDMFRAMESYNC_STATE_RXSYMBOLS; // reset timer _q->timer = _q->M + _q->cp_len + _q->backoff; _q->num_symbols = 0; // normalize gain by subcarriers, apply timing backoff correction float g = (float)(_q->M) / sqrtf(_q->M_pilot + _q->M_data); for (i=0; i<_q->M; i++) { _q->G[i] *= g; // gain due to relative subcarrier allocation _q->G[i] *= _q->B[i]; // timing backoff correction } #if 0 // TODO : choose number of taps more appropriately //unsigned int ntaps = _q->M / 4; unsigned int ntaps = (_q->M < 8) ? 2 : 8; // FIXME : this is by far the most computationally complex part of synchronization ofdmframesync_estimate_eqgain(_q, ntaps); #else unsigned int poly_order = 4; if (poly_order >= _q->M_pilot + _q->M_data) poly_order = _q->M_pilot + _q->M_data - 1; ofdmframesync_estimate_eqgain_poly(_q, poly_order); #endif #if 1 // compute composite gain unsigned int i; for (i=0; i<_q->M; i++) _q->R[i] = _q->B[i] / _q->G[i]; #endif return; #if 0 printf("exiting prematurely\n"); ofdmframesync_destroy(_q); exit(1); #endif } // check if we are stuck searching for the S1 symbol if (_q->num_symbols == 16) { #if DEBUG_OFDMFRAMESYNC_PRINT printf("could not find S1 symbol. bailing...\n"); #endif ofdmframesync_reset(_q); } // 'reset' timer (wait another half symbol) _q->timer = _q->M2; } void ofdmframesync_execute_rxsymbols(ofdmframesync _q) { // wait for timeout _q->timer--; if (_q->timer == 0) { // run fft float complex * rc; windowcf_read(_q->input_buffer, &rc); memmove(_q->x, &rc[_q->cp_len-_q->backoff], (_q->M)*sizeof(float complex)); FFT_EXECUTE(_q->fft); // recover symbol in internal _q->X buffer ofdmframesync_rxsymbol(_q); #if DEBUG_OFDMFRAMESYNC if (_q->debug_enabled) { unsigned int i; for (i=0; i<_q->M; i++) { if (_q->p[i] == OFDMFRAME_SCTYPE_DATA) windowcf_push(_q->debug_framesyms, _q->X[i]); } } #endif // invoke callback if (_q->callback != NULL) { int retval = _q->callback(_q->X, _q->p, _q->M, _q->userdata); if (retval != 0) ofdmframesync_reset(_q); } // reset timer _q->timer = _q->M + _q->cp_len; } } // compute S0 metrics void ofdmframesync_S0_metrics(ofdmframesync _q, float complex * _G, float complex * _s_hat) { // timing, carrier offset correction unsigned int i; float complex s_hat = 0.0f; // compute timing estimate, accumulate phase difference across // gains on subsequent pilot subcarriers (note that all the odd // subcarriers are NULL) for (i=0; i<_q->M; i+=2) { s_hat += _G[(i+2)%_q->M]*conjf(_G[i]); } s_hat /= _q->M_S0; // normalize output // set output values *_s_hat = s_hat; } // estimate short sequence gain // _q : ofdmframesync object // _x : input array (time), [size: M x 1] // _G : output gain (freq) void ofdmframesync_estimate_gain_S0(ofdmframesync _q, float complex * _x, float complex * _G) { // move input array into fft input buffer memmove(_q->x, _x, (_q->M)*sizeof(float complex)); // compute fft, storing result into _q->X FFT_EXECUTE(_q->fft); // compute gain, ignoring NULL subcarriers unsigned int i; float gain = sqrtf(_q->M_S0) / (float)(_q->M); for (i=0; i<_q->M; i++) { if (_q->p[i] != OFDMFRAME_SCTYPE_NULL && (i%2)==0) { // NOTE : if cabsf(_q->S0[i]) == 0 then we can multiply by conjugate // rather than compute division //_G[i] = _q->X[i] / _q->S0[i]; _G[i] = _q->X[i] * conjf(_q->S0[i]); } else { _G[i] = 0.0f; } // normalize gain _G[i] *= gain; } } // estimate long sequence gain // _q : ofdmframesync object // _x : input array (time), [size: M x 1] // _G : output gain (freq) void ofdmframesync_estimate_gain_S1(ofdmframesync _q, float complex * _x, float complex * _G) { // move input array into fft input buffer memmove(_q->x, _x, (_q->M)*sizeof(float complex)); // compute fft, storing result into _q->X FFT_EXECUTE(_q->fft); // compute gain, ignoring NULL subcarriers unsigned int i; float gain = sqrtf(_q->M_S1) / (float)(_q->M); for (i=0; i<_q->M; i++) { if (_q->p[i] != OFDMFRAME_SCTYPE_NULL) { // NOTE : if cabsf(_q->S1[i]) == 0 then we can multiply by conjugate // rather than compute division //_G[i] = _q->X[i] / _q->S1[i]; _G[i] = _q->X[i] * conjf(_q->S1[i]); } else { _G[i] = 0.0f; } // normalize gain _G[i] *= gain; } } // estimate complex equalizer gain from G0 and G1 // _q : ofdmframesync object // _ntaps : number of time-domain taps for smoothing void ofdmframesync_estimate_eqgain(ofdmframesync _q, unsigned int _ntaps) { #if DEBUG_OFDMFRAMESYNC if (_q->debug_enabled) { // copy pre-smoothed gain memmove(_q->G_hat, _q->G, _q->M*sizeof(float complex)); } #endif // validate input if (_ntaps == 0 || _ntaps > _q->M) { fprintf(stderr, "error: ofdmframesync_estimate_eqgain(), ntaps must be in [1,M]\n"); exit(1); } unsigned int i; // generate smoothing window (fft of temporal window) for (i=0; i<_q->M; i++) _q->x[i] = (i < _ntaps) ? 1.0f : 0.0f; FFT_EXECUTE(_q->fft); memmove(_q->G0, _q->G, _q->M*sizeof(float complex)); // smooth complex equalizer gains for (i=0; i<_q->M; i++) { // set gain to zero for null subcarriers if (_q->p[i] == OFDMFRAME_SCTYPE_NULL) { _q->G[i] = 0.0f; continue; } float complex w; float complex w0 = 0.0f; float complex G_hat = 0.0f; unsigned int j; for (j=0; j<_q->M; j++) { if (_q->p[j] == OFDMFRAME_SCTYPE_NULL) continue; // select window sample from array w = _q->X[(i + _q->M - j) % _q->M]; // accumulate gain //G_hat += w * 0.5f * (_q->G0[j] + _q->G1[j]); G_hat += w * _q->G0[j]; w0 += w; } // eliminate divide-by-zero issues if (cabsf(w0) < 1e-4f) { fprintf(stderr,"error: ofdmframesync_estimate_eqgain(), weighting factor is zero\n"); w0 = 1.0f; } _q->G[i] = G_hat / w0; } } // estimate complex equalizer gain from G0 and G1 using polynomial fit // _q : ofdmframesync object // _order : polynomial order void ofdmframesync_estimate_eqgain_poly(ofdmframesync _q, unsigned int _order) { #if DEBUG_OFDMFRAMESYNC if (_q->debug_enabled) { // copy pre-smoothed gain memmove(_q->G_hat, _q->G, _q->M*sizeof(float complex)); } #endif // polynomial interpolation unsigned int i; unsigned int N = _q->M_pilot + _q->M_data; if (_order > N-1) _order = N-1; if (_order > 10) _order = 10; float x_freq[N]; float y_abs[N]; float y_arg[N]; float p_abs[_order+1]; float p_arg[_order+1]; unsigned int n=0; unsigned int k; for (i=0; i<_q->M; i++) { // start at mid-point (effective fftshift) k = (i + _q->M2) % _q->M; if (_q->p[k] != OFDMFRAME_SCTYPE_NULL) { if (n == N) { fprintf(stderr, "error: ofdmframesync_estimate_eqgain_poly(), pilot subcarrier mismatch\n"); exit(1); } // store resulting... x_freq[n] = (k > _q->M2) ? (float)k - (float)(_q->M) : (float)k; x_freq[n] = x_freq[n] / (float)(_q->M); y_abs[n] = cabsf(_q->G[k]); y_arg[n] = cargf(_q->G[k]); // update counter n++; } } if (n != N) { fprintf(stderr, "error: ofdmframesync_estimate_eqgain_poly(), pilot subcarrier mismatch\n"); exit(1); } // try to unwrap phase for (i=1; i M_PI) y_arg[i] -= 2*M_PI; while ((y_arg[i] - y_arg[i-1]) < -M_PI) y_arg[i] += 2*M_PI; } // fit to polynomial polyf_fit(x_freq, y_abs, N, p_abs, _order+1); polyf_fit(x_freq, y_arg, N, p_arg, _order+1); // compute subcarrier gain for (i=0; i<_q->M; i++) { float freq = (i > _q->M2) ? (float)i - (float)(_q->M) : (float)i; freq = freq / (float)(_q->M); float A = polyf_val(p_abs, _order+1, freq); float theta = polyf_val(p_arg, _order+1, freq); _q->G[i] = (_q->p[i] == OFDMFRAME_SCTYPE_NULL) ? 0.0f : A * liquid_cexpjf(theta); } #if 0 for (i=0; iM; i++) _q->X[i] *= _q->R[i]; // polynomial curve-fit float x_phase[_q->M_pilot]; float y_phase[_q->M_pilot]; float p_phase[2]; unsigned int n=0; unsigned int k; float complex pilot = 1.0f; for (i=0; i<_q->M; i++) { // start at mid-point (effective fftshift) k = (i + _q->M2) % _q->M; if (_q->p[k]==OFDMFRAME_SCTYPE_PILOT) { if (n == _q->M_pilot) { fprintf(stderr,"warning: ofdmframesync_rxsymbol(), pilot subcarrier mismatch\n"); return; } pilot = (msequence_advance(_q->ms_pilot) ? 1.0f : -1.0f); #if 0 printf("pilot[%3u] = %12.4e + j*%12.4e (expected %12.4e + j*%12.4e)\n", k, crealf(_q->X[k]), cimagf(_q->X[k]), crealf(pilot), cimagf(pilot)); #endif // store resulting... x_phase[n] = (k > _q->M2) ? (float)k - (float)(_q->M) : (float)k; y_phase[n] = cargf(_q->X[k]*conjf(pilot)); // update counter n++; } } if (n != _q->M_pilot) { fprintf(stderr,"warning: ofdmframesync_rxsymbol(), pilot subcarrier mismatch\n"); return; } // try to unwrap phase for (i=1; i<_q->M_pilot; i++) { while ((y_phase[i] - y_phase[i-1]) > M_PI) y_phase[i] -= 2*M_PI; while ((y_phase[i] - y_phase[i-1]) < -M_PI) y_phase[i] += 2*M_PI; } // fit phase to 1st-order polynomial (2 coefficients) polyf_fit(x_phase, y_phase, _q->M_pilot, p_phase, 2); // filter slope estimate (timing offset) float alpha = 0.3f; p_phase[1] = alpha*p_phase[1] + (1-alpha)*_q->p1_prime; _q->p1_prime = p_phase[1]; #if DEBUG_OFDMFRAMESYNC if (_q->debug_enabled) { // save pilots memmove(_q->px, x_phase, _q->M_pilot*sizeof(float)); memmove(_q->py, y_phase, _q->M_pilot*sizeof(float)); // NOTE : swapping values for octave _q->p_phase[0] = p_phase[1]; _q->p_phase[1] = p_phase[0]; windowf_push(_q->debug_pilot_0, p_phase[0]); windowf_push(_q->debug_pilot_1, p_phase[1]); } #endif // compensate for phase offset // TODO : find more computationally efficient way to do this for (i=0; i<_q->M; i++) { // only apply to data/pilot subcarriers if (_q->p[i] == OFDMFRAME_SCTYPE_NULL) { _q->X[i] = 0.0f; } else { float fx = (i > _q->M2) ? (float)i - (float)(_q->M) : (float)i; float theta = polyf_val(p_phase, 2, fx); _q->X[i] *= liquid_cexpjf(-theta); } } // adjust NCO frequency based on differential phase if (_q->num_symbols > 0) { // compute phase error (unwrapped) float dphi_prime = p_phase[0] - _q->phi_prime; while (dphi_prime > M_PI) dphi_prime -= M_2_PI; while (dphi_prime < -M_PI) dphi_prime += M_2_PI; // adjust NCO proportionally to phase error nco_crcf_adjust_frequency(_q->nco_rx, 1e-3f*dphi_prime); } // set internal phase state _q->phi_prime = p_phase[0]; //printf("%3u : theta : %12.8f, nco freq: %12.8f\n", _q->num_symbols, p_phase[0], nco_crcf_get_frequency(_q->nco_rx)); // increment symbol counter _q->num_symbols++; #if 0 for (i=0; i<_q->M_pilot; i++) printf("x_phase(%3u) = %12.8f; y_phase(%3u) = %12.8f;\n", i+1, x_phase[i], i+1, y_phase[i]); printf("poly : p0=%12.8f, p1=%12.8f\n", p_phase[0], p_phase[1]); #endif } // enable debugging void ofdmframesync_debug_enable(ofdmframesync _q) { // create debugging objects if necessary #if DEBUG_OFDMFRAMESYNC if (_q->debug_objects_created) return; _q->debug_x = windowcf_create(DEBUG_OFDMFRAMESYNC_BUFFER_LEN); _q->debug_rssi = windowf_create(DEBUG_OFDMFRAMESYNC_BUFFER_LEN); _q->debug_framesyms = windowcf_create(DEBUG_OFDMFRAMESYNC_BUFFER_LEN); _q->G_hat = (float complex*) malloc((_q->M)*sizeof(float complex)); _q->px = (float*) malloc((_q->M_pilot)*sizeof(float)); _q->py = (float*) malloc((_q->M_pilot)*sizeof(float)); _q->debug_pilot_0 = windowf_create(DEBUG_OFDMFRAMESYNC_BUFFER_LEN); _q->debug_pilot_1 = windowf_create(DEBUG_OFDMFRAMESYNC_BUFFER_LEN); _q->debug_enabled = 1; _q->debug_objects_created = 1; #else fprintf(stderr,"ofdmframesync_debug_enable(): compile-time debugging disabled\n"); #endif } void ofdmframesync_debug_disable(ofdmframesync _q) { // disable debugging #if DEBUG_OFDMFRAMESYNC _q->debug_enabled = 0; #else fprintf(stderr,"ofdmframesync_debug_disable(): compile-time debugging disabled\n"); #endif } void ofdmframesync_debug_print(ofdmframesync _q, const char * _filename) { #if DEBUG_OFDMFRAMESYNC if (!_q->debug_objects_created) { fprintf(stderr,"error: ofdmframe_debug_print(), debugging objects don't exist; enable debugging first\n"); return; } FILE * fid = fopen(_filename,"w"); if (!fid) { fprintf(stderr,"error: ofdmframe_debug_print(), could not open '%s' for writing\n", _filename); return; } fprintf(fid,"%% %s : auto-generated file\n", DEBUG_OFDMFRAMESYNC_FILENAME); fprintf(fid,"close all;\n"); fprintf(fid,"clear all;\n"); fprintf(fid,"n = %u;\n", DEBUG_OFDMFRAMESYNC_BUFFER_LEN); fprintf(fid,"M = %u;\n", _q->M); fprintf(fid,"M_null = %u;\n", _q->M_null); fprintf(fid,"M_pilot = %u;\n", _q->M_pilot); fprintf(fid,"M_data = %u;\n", _q->M_data); unsigned int i; float complex * rc; float * r; // save subcarrier allocation fprintf(fid,"p = zeros(1,M);\n"); for (i=0; i<_q->M; i++) fprintf(fid,"p(%4u) = %d;\n", i+1, _q->p[i]); fprintf(fid,"i_null = find(p==%d);\n", OFDMFRAME_SCTYPE_NULL); fprintf(fid,"i_pilot = find(p==%d);\n", OFDMFRAME_SCTYPE_PILOT); fprintf(fid,"i_data = find(p==%d);\n", OFDMFRAME_SCTYPE_DATA); // short, long, training sequences for (i=0; i<_q->M; i++) { fprintf(fid,"S0(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->S0[i]), cimagf(_q->S0[i])); fprintf(fid,"S1(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->S1[i]), cimagf(_q->S1[i])); } fprintf(fid,"x = zeros(1,n);\n"); windowcf_read(_q->debug_x, &rc); for (i=0; iM; i++) fprintf(fid,"s1(%3u) = %12.4e + j*%12.4e;\n", i+1, crealf(_q->s1[i]), cimagf(_q->s1[i])); // write agc_rssi fprintf(fid,"\n\n"); fprintf(fid,"agc_rssi = zeros(1,%u);\n", DEBUG_OFDMFRAMESYNC_BUFFER_LEN); windowf_read(_q->debug_rssi, &r); for (i=0; iM; i++) { fprintf(fid,"S0(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(_q->S0[i]), cimagf(_q->S0[i])); fprintf(fid,"S1(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(_q->S1[i]), cimagf(_q->S1[i])); } // write gain arrays fprintf(fid,"\n\n"); fprintf(fid,"G0 = zeros(1,M);\n"); fprintf(fid,"G1 = zeros(1,M);\n"); fprintf(fid,"G_hat = zeros(1,M);\n"); fprintf(fid,"G = zeros(1,M);\n"); for (i=0; i<_q->M; i++) { fprintf(fid,"G0(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(_q->G0[i]), cimagf(_q->G0[i])); fprintf(fid,"G1(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(_q->G1[i]), cimagf(_q->G1[i])); fprintf(fid,"G_hat(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(_q->G_hat[i]),cimagf(_q->G_hat[i])); fprintf(fid,"G(%3u) = %12.8f + j*%12.8f;\n", i+1, crealf(_q->G[i]), cimagf(_q->G[i])); } fprintf(fid,"f = [0:(M-1)];\n"); fprintf(fid,"figure;\n"); fprintf(fid,"subplot(2,1,1);\n"); fprintf(fid," plot(f, fftshift(abs(G_hat)),'sb',...\n"); fprintf(fid," f, fftshift(abs(G)),'-k','LineWidth',2);\n"); fprintf(fid," grid on;\n"); fprintf(fid," xlabel('subcarrier index');\n"); fprintf(fid," ylabel('gain estimate (mag)');\n"); fprintf(fid,"subplot(2,1,2);\n"); fprintf(fid," plot(f, fftshift(arg(G_hat).*[abs(G0) > 1e-3]),'sb',...\n"); fprintf(fid," f, fftshift(arg(G)),'-k','LineWidth',2);\n"); fprintf(fid," grid on;\n"); fprintf(fid," xlabel('subcarrier index');\n"); fprintf(fid," ylabel('gain estimate (phase)');\n"); // write pilot response fprintf(fid,"\n\n"); fprintf(fid,"px = zeros(1,M_pilot);\n"); fprintf(fid,"py = zeros(1,M_pilot);\n"); for (i=0; i<_q->M_pilot; i++) { fprintf(fid,"px(%3u) = %12.8f;\n", i+1, _q->px[i]); fprintf(fid,"py(%3u) = %12.8f;\n", i+1, _q->py[i]); } fprintf(fid,"p_phase(1) = %12.8f;\n", _q->p_phase[0]); fprintf(fid,"p_phase(2) = %12.8f;\n", _q->p_phase[1]); // save pilot history fprintf(fid,"p0 = zeros(1,M);\n"); windowf_read(_q->debug_pilot_0, &r); for (i=0; idebug_pilot_1, &r); for (i=0; idebug_framesyms, &rc); for (i=0; i #include "autotest/autotest.h" #include "liquid.h" // Helper function to keep code base small void firpfbch2_crcf_runtest(unsigned int _M, unsigned int _m, float _As) { float tol = 1e-3f; unsigned int i; // derived values unsigned int num_symbols = 8*_m; // number of symbols unsigned int num_samples = _M * num_symbols; // allocate arrays float complex x[num_samples]; float complex y[num_samples]; // generate pseudo-random sequence unsigned int s = 1; // seed unsigned int p = 524287; // large prime number unsigned int g = 1031; // another large prime number for (i=0; i #include "autotest/autotest.h" #include "liquid.h" // // AUTOTEST: validate analysis correctness // void autotest_firpfbch_crcf_analysis() { float tol = 1e-4f; // error tolerance unsigned int num_channels=4; // number of channels unsigned int p=5; // filter length (symbols) unsigned int num_symbols=40; // number of symbols // derived values unsigned int num_samples = num_channels * num_symbols; unsigned int i; unsigned int j; // generate filter // NOTE : these coefficients can be random; the purpose of this // exercise is to demonstrate mathematical equivalence. // For the sake of consistency, use pseudo-random values // chosen from m-sequences unsigned int h_len = p*num_channels; float h[h_len]; msequence ms = msequence_create_default(6); for (i=0; i #include "autotest/autotest.h" #include "liquid.h" // // AUTOTEST: validate synthesis correctness // void autotest_firpfbch_crcf_synthesis() { // options float tol = 1e-4f; // error tolerance unsigned int num_channels=4; // number of channels unsigned int p=5; // filter length (symbols) unsigned int num_symbols=40; // number of symbols // derived values unsigned int num_samples = num_channels * num_symbols; unsigned int i; unsigned int j; // generate filter // NOTE : these coefficients can be random; the purpose of this // exercise is to demonstrate mathematical equivalence. // For the sake of consistency, use pseudo-random values // chosen from m-sequences unsigned int h_len = p*num_channels; float h[h_len]; msequence ms = msequence_create_default(6); for (i=0; i #include #include #include #include #include #include "autotest/autotest.h" #include "liquid.h" // internal callback // _X : subcarrier symbols // _p : subcarrier allocation // _M : number of subcarriers // _userdata : user-defined data structure int ofdmframesync_autotest_callback(float complex * _X, unsigned char * _p, unsigned int _M, void * _userdata) { printf("******** callback invoked!\n"); // type cast _userdata as complex float array float complex * X = (float complex *)_userdata; // copy values and return memmove(X, _X, _M*sizeof(float complex)); // return return 0; } // Helper function to keep code base small // _num_subcarriers : number of subcarriers // _cp_len : cyclic prefix lenght // _taper_len : taper length void ofdmframesync_acquire_test(unsigned int _num_subcarriers, unsigned int _cp_len, unsigned int _taper_len) { // options unsigned int M = _num_subcarriers; // number of subcarriers unsigned int cp_len = _cp_len; // cyclic prefix lenght unsigned int taper_len = _taper_len; // taper length float tol = 1e-2f; // error tolerance // float dphi = 1.0f / (float)M; // carrier frequency offset // subcarrier allocation (initialize to default) unsigned char p[M]; ofdmframe_init_default_sctype(M, p); // derived values unsigned int num_samples = (3 + 1)*(M + cp_len); // create synthesizer/analyzer objects ofdmframegen fg = ofdmframegen_create(M, cp_len, taper_len, p); //ofdmframegen_print(fg); float complex X[M]; // original data sequence float complex X_test[M]; // recovered data sequence ofdmframesync fs = ofdmframesync_create(M,cp_len,taper_len,p,ofdmframesync_autotest_callback,(void*)X_test); unsigned int i; float complex y[num_samples]; // frame samples // assemble full frame unsigned int n=0; // write first S0 symbol ofdmframegen_write_S0a(fg, &y[n]); n += M + cp_len; // write second S0 symbol ofdmframegen_write_S0b(fg, &y[n]); n += M + cp_len; // write S1 symbol ofdmframegen_write_S1( fg, &y[n]); n += M + cp_len; // generate data symbol (random) for (i=0; i #include #include "liquid.h" void benchmark_nco_sincos(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { float s, c; nco_crcf p = nco_crcf_create(LIQUID_NCO); nco_crcf_set_phase(p, 0.0f); nco_crcf_set_frequency(p, 0.1f); unsigned int i; // increase number of iterations for NCO *_num_iterations *= 100; getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { nco_crcf_sincos(p, &s, &c); nco_crcf_step(p); } getrusage(RUSAGE_SELF, _finish); nco_crcf_destroy(p); } void benchmark_nco_mix_up(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { float complex x[16], y[16]; memset(x, 0, 16*sizeof(float complex)); nco_crcf p = nco_crcf_create(LIQUID_NCO); nco_crcf_set_phase(p, 0.0f); nco_crcf_set_frequency(p, 0.1f); unsigned int i, j; getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { for (j=0; j<16; j++) { nco_crcf_mix_up(p, x[j], &y[j]); nco_crcf_step(p); } } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 16; nco_crcf_destroy(p); } void benchmark_nco_mix_block_up(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { float complex x[16], y[16]; memset(x, 0, 16*sizeof(float complex)); nco_crcf p = nco_crcf_create(LIQUID_NCO); nco_crcf_set_phase(p, 0.0f); nco_crcf_set_frequency(p, 0.1f); unsigned int i; getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { nco_crcf_mix_block_up(p, x, y, 16); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 16; nco_crcf_destroy(p); } liquid-dsp-1.3.1/src/nco/bench/vco_benchmark.c000066400000000000000000000057171317124540100211710ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "liquid.h" void benchmark_vco_sincos(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { float s, c; nco_crcf p = nco_crcf_create(LIQUID_VCO); nco_crcf_set_phase(p, 0.0f); nco_crcf_set_frequency(p, 0.1f); unsigned int i; getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { nco_crcf_sincos(p, &s, &c); nco_crcf_step(p); } getrusage(RUSAGE_SELF, _finish); nco_crcf_destroy(p); } void benchmark_vco_mix_up(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { float complex x[16], y[16]; memset(x, 0, 16*sizeof(float complex)); nco_crcf p = nco_crcf_create(LIQUID_VCO); nco_crcf_set_phase(p, 0.0f); nco_crcf_set_frequency(p, 0.1f); unsigned int i, j; getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { for (j=0; j<16; j++) { nco_crcf_mix_up(p, x[j], &y[j]); nco_crcf_step(p); } } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 16; nco_crcf_destroy(p); } void benchmark_vco_mix_block_up(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { float complex x[16], y[16]; memset(x, 0, 16*sizeof(float complex)); nco_crcf p = nco_crcf_create(LIQUID_VCO); nco_crcf_set_phase(p, 0.0f); nco_crcf_set_frequency(p, 0.1f); unsigned int i; getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { nco_crcf_mix_block_up(p, x, y, 16); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 16; nco_crcf_destroy(p); } liquid-dsp-1.3.1/src/nco/src/000077500000000000000000000000001317124540100157225ustar00rootroot00000000000000liquid-dsp-1.3.1/src/nco/src/nco.c000066400000000000000000000230471317124540100166530ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Numerically-controlled oscillator (nco) with internal phase-locked // loop (pll) implementation // #include #include #include #include #define NCO_PLL_BANDWIDTH_DEFAULT (0.1) #define NCO_PLL_GAIN_DEFAULT (1000) #define LIQUID_DEBUG_NCO (0) struct NCO(_s) { liquid_ncotype type; T theta; // NCO phase T d_theta; // NCO frequency T sintab[256]; // sine table unsigned int index; // table index T sine; T cosine; void (*compute_sincos)(NCO() _q); // phase-locked loop T alpha; T beta; }; // create nco/vco object NCO() NCO(_create)(liquid_ncotype _type) { NCO() q = (NCO()) malloc(sizeof(struct NCO(_s))); q->type = _type; // initialize sine table unsigned int i; for (i=0; i<256; i++) q->sintab[i] = SIN(2.0f*M_PI*(float)(i)/256.0f); // set default pll bandwidth NCO(_pll_set_bandwidth)(q, NCO_PLL_BANDWIDTH_DEFAULT); // set internal method if (q->type == LIQUID_NCO) { q->compute_sincos = &NCO(_compute_sincos_nco); } else if (q->type == LIQUID_VCO) { q->compute_sincos = &NCO(_compute_sincos_vco); } else { fprintf(stderr,"error: NCO(_create)(), unknown type : %u\n", q->type); exit(1); } // reset object and return NCO(_reset)(q); return q; } // destroy nco object void NCO(_destroy)(NCO() _q) { free(_q); } // reset internal state of nco object void NCO(_reset)(NCO() _q) { _q->theta = 0; _q->d_theta = 0; // reset sine table index _q->index = 0; // set internal sine, cosine values _q->sine = 0; _q->cosine = 1; // reset pll filter state NCO(_pll_reset)(_q); } // set frequency of nco object void NCO(_set_frequency)(NCO() _q, T _f) { _q->d_theta = _f; } // adjust frequency of nco object void NCO(_adjust_frequency)(NCO() _q, T _df) { _q->d_theta += _df; } // set phase of nco object, constraining phase void NCO(_set_phase)(NCO() _q, T _phi) { _q->theta = _phi; NCO(_constrain_phase)(_q); } // adjust phase of nco object, constraining phase void NCO(_adjust_phase)(NCO() _q, T _dphi) { _q->theta += _dphi; NCO(_constrain_phase)(_q); } // increment internal phase of nco object void NCO(_step)(NCO() _q) { _q->theta += _q->d_theta; NCO(_constrain_phase)(_q); } // get phase T NCO(_get_phase)(NCO() _q) { return _q->theta; } // ge frequency T NCO(_get_frequency)(NCO() _q) { return _q->d_theta; } // TODO : compute sine, cosine internally T NCO(_sin)(NCO() _q) { // compute internal sin, cos _q->compute_sincos(_q); // return resulting cosine component return _q->sine; } T NCO(_cos)(NCO() _q) { // compute internal sin, cos _q->compute_sincos(_q); // return resulting cosine component return _q->cosine; } // compute sin, cos of internal phase void NCO(_sincos)(NCO() _q, T* _s, T* _c) { // compute sine, cosine internally, calling implementation- // specific function (nco, vco) _q->compute_sincos(_q); // return result *_s = _q->sine; *_c = _q->cosine; } // compute complex exponential of internal phase void NCO(_cexpf)(NCO() _q, TC * _y) { // compute sine, cosine internally, calling implementation- // specific function (nco, vco) _q->compute_sincos(_q); // set _y[0] to [cos(theta) + _Complex_I*sin(theta)] *_y = _q->cosine + _Complex_I*(_q->sine); } // pll methods // reset pll state, retaining base frequency void NCO(_pll_reset)(NCO() _q) { } // set pll bandwidth void NCO(_pll_set_bandwidth)(NCO() _q, T _bandwidth) { // validate input if (_bandwidth < 0.0f) { fprintf(stderr,"error: nco_pll_set_bandwidth(), bandwidth must be positive\n"); exit(1); } _q->alpha = _bandwidth; // frequency proportion _q->beta = sqrtf(_q->alpha); // phase proportion } // advance pll phase // _q : nco object // _dphi : phase error void NCO(_pll_step)(NCO() _q, T _dphi) { // increase frequency proportional to error NCO(_adjust_frequency)(_q, _dphi*_q->alpha); // increase phase proportional to error NCO(_adjust_phase)(_q, _dphi*_q->beta); // constrain frequency //NCO(_constrain_frequency)(_q); } // mixing functions // Rotate input vector up by NCO angle, y = x exp{+j theta} // _q : nco object // _x : input sample // _y : output sample void NCO(_mix_up)(NCO() _q, TC _x, TC *_y) { // compute sine, cosine internally, calling implementation- // specific function (nco, vco) _q->compute_sincos(_q); // multiply _x by [cos(theta) + _Complex_I*sin(theta)] *_y = _x * (_q->cosine + _Complex_I*(_q->sine)); } // Rotate input vector down by NCO angle, y = x exp{-j theta} // _q : nco object // _x : input sample // _y : output sample void NCO(_mix_down)(NCO() _q, TC _x, TC *_y) { // compute sine, cosine internally _q->compute_sincos(_q); // multiply _x by [cos(-theta) + _Complex_I*sin(-theta)] *_y = _x * (_q->cosine - _Complex_I*(_q->sine)); } // Rotate input vector array up by NCO angle: // y(t) = x(t) exp{+j (f*t + theta)} // TODO : implement NCO/VCO-specific versions // _q : nco object // _x : input array [size: _n x 1] // _y : output sample [size: _n x 1] // _n : number of input, output samples void NCO(_mix_block_up)(NCO() _q, TC *_x, TC *_y, unsigned int _n) { unsigned int i; // FIXME: this method should be more efficient but is causing occasional // errors so instead favor slower but more reliable algorithm #if 0 T theta = _q->theta; T d_theta = _q->d_theta; for (i=0; i<_n; i++) { // multiply _x[i] by [cos(theta) + _Complex_I*sin(theta)] _y[i] = _x[i] * liquid_cexpjf(theta); theta += d_theta; } NCO(_set_phase)(_q, theta); #else for (i=0; i<_n; i++) { // mix single sample up NCO(_mix_up)(_q, _x[i], &_y[i]); // step NCO phase NCO(_step)(_q); } #endif } // Rotate input vector array down by NCO angle: // y(t) = x(t) exp{-j (f*t + theta)} // TODO : implement NCO/VCO-specific versions // _q : nco object // _x : input array [size: _n x 1] // _y : output sample [size: _n x 1] // _n : number of input, output samples void NCO(_mix_block_down)(NCO() _q, TC *_x, TC *_y, unsigned int _n) { unsigned int i; // FIXME: this method should be more efficient but is causing occasional // errors so instead favor slower but more reliable algorithm #if 0 T theta = _q->theta; T d_theta = _q->d_theta; for (i=0; i<_n; i++) { // multiply _x[i] by [cos(-theta) + _Complex_I*sin(-theta)] _y[i] = _x[i] * liquid_cexpjf(-theta); theta += d_theta; } NCO(_set_phase)(_q, theta); #else for (i=0; i<_n; i++) { // mix single sample down NCO(_mix_down)(_q, _x[i], &_y[i]); // step NCO phase NCO(_step)(_q); } #endif } // // internal methods // // constrain frequency of NCO object to be in (-pi,pi) void NCO(_constrain_frequency)(NCO() _q) { if (_q->d_theta > M_PI) _q->d_theta -= 2*M_PI; else if (_q->d_theta < -M_PI) _q->d_theta += 2*M_PI; } // constrain phase of NCO object to be in (-pi,pi) void NCO(_constrain_phase)(NCO() _q) { if (_q->theta > M_PI) _q->theta -= 2*M_PI; else if (_q->theta < -M_PI) _q->theta += 2*M_PI; } // compute sin, cos of internal phase of nco void NCO(_compute_sincos_nco)(NCO() _q) { // assume phase is constrained to be in (-pi,pi) // compute index // NOTE : 40.743665 ~ 256 / (2*pi) // NOTE : add 512 to ensure positive value, add 0.5 for rounding precision // TODO : move away from floating-point specific code _q->index = ((unsigned int)((_q->theta)*40.743665f + 512.0f + 0.5f))&0xff; assert(_q->index < 256); _q->sine = _q->sintab[_q->index]; _q->cosine = _q->sintab[(_q->index+64)&0xff]; } // compute sin, cos of internal phase of vco void NCO(_compute_sincos_vco)(NCO() _q) { _q->sine = SIN(_q->theta); _q->cosine = COS(_q->theta); } liquid-dsp-1.3.1/src/nco/src/nco.utilities.c000066400000000000000000000042031317124540100206560ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // nco.utilities.c // // Numerically-controlled oscillator (nco) utilities // #include #include #include // unwrap phase of array (basic) void liquid_unwrap_phase(float * _theta, unsigned int _n) { unsigned int i; for (i=1; i<_n; i++) { while ( (_theta[i] - _theta[i-1]) > M_PI ) _theta[i] -= 2*M_PI; while ( (_theta[i] - _theta[i-1]) < -M_PI ) _theta[i] += 2*M_PI; } } // unwrap phase of array (advanced) void liquid_unwrap_phase2(float * _theta, unsigned int _n) { fprintf(stderr,"warning: liquid_unwrap_phase2() has not yet been tested!\n"); unsigned int i; // make an initial estimate of phase difference float dphi = 0.0f; for (i=1; i<_n; i++) dphi += _theta[i] - _theta[i-1]; dphi /= (float)(_n-1); for (i=1; i<_n; i++) { while ( (_theta[i] - _theta[i-1]) > M_PI+dphi ) _theta[i] -= 2*M_PI; while ( (_theta[i] - _theta[i-1]) < -M_PI+dphi ) _theta[i] += 2*M_PI; } } liquid-dsp-1.3.1/src/nco/src/nco_crcf.c000066400000000000000000000026101317124540100176410ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // numerically-controlled oscillator (nco) API, floating point precision // #include "liquid.internal.h" #define NCO(name) LIQUID_CONCAT(nco_crcf,name) #define T float #define TC float complex #define SIN sinf #define COS cosf #include "nco.c" liquid-dsp-1.3.1/src/nco/tests/000077500000000000000000000000001317124540100162755ustar00rootroot00000000000000liquid-dsp-1.3.1/src/nco/tests/data/000077500000000000000000000000001317124540100172065ustar00rootroot00000000000000liquid-dsp-1.3.1/src/nco/tests/data/nco_sincos_fsqrt1_2.c000066400000000000000000000333431317124540100232360ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest nco sincos data for f=0.707106781187 // #include float complex nco_sincos_fsqrt1_2[256] = { 1.000000000000 + _Complex_I* 0.000000000000, 0.760244597076 + _Complex_I* 0.649636939080, 0.155943694765 + _Complex_I* 0.987765945993, -0.523133894289 + _Complex_I* 0.852250508152, -0.951363128126 + _Complex_I* 0.308071742363, -0.923403461740 + _Complex_I* -0.383830752866, -0.452661857292 + _Complex_I* -0.891682254479, 0.235135999123 + _Complex_I* -0.971962479686, 0.810183603115 + _Complex_I* -0.586176193003, 0.996739414692 + _Complex_I* 0.080687912355, 0.705347906308 + _Complex_I* 0.708861291838, 0.075734454968 + _Complex_I* 0.997128022037, -0.590194485905 + _Complex_I* 0.807261090854, -0.973118793234 + _Complex_I* 0.230303743466, -0.889422123833 + _Complex_I* -0.457086737542, -0.379237935093 + _Complex_I* -0.925299188688, 0.312794941512 + _Complex_I* -0.949820680215, 0.854839263647 + _Complex_I* -0.518892891961, 0.986978921600 + _Complex_I* 0.160849645067, 0.645851521500 + _Complex_I* 0.763463039168, -0.004968662133 + _Complex_I* 0.999987656122, -0.653406318582 + _Complex_I* 0.757007386250, -0.988528584662 + _Complex_I* 0.151033894564, -0.849640712505 + _Complex_I* -0.527361981615, -0.303340937614 + _Complex_I* -0.952882089016, 0.388414094720 + _Complex_I* -0.921484938034, 0.893920371491 + _Complex_I* -0.448225801838, 0.970782170565 + _Complex_I* 0.239962449800, 0.582143428727 + _Complex_I* 0.813086113761, -0.085639377739 + _Complex_I* 0.996326200087, -0.712357177173 + _Complex_I* 0.701817107322, -0.997492012529 + _Complex_I* 0.070779127866, -0.804318649129 + _Complex_I* -0.594198208230, -0.225465802126 + _Complex_I* -0.974251082664, 0.461500333346 + _Complex_I* -0.887140035351, 0.927172072075 + _Complex_I* -0.374635754786, 0.948254783364 + _Complex_I* 0.317510418456, 0.514639079331 + _Complex_I* 0.857406915079, -0.165751624352 + _Complex_I* 0.986167530912, -0.766662633072 + _Complex_I* 0.642050159295, -0.999950624793 + _Complex_I* -0.009937201600, -0.753751486611 + _Complex_I* -0.657159566948, -0.146120365674 + _Complex_I* -0.989266818778, 0.531577049558 + _Complex_I* -0.847009941136, 0.954377525386 + _Complex_I* -0.298602644058, 0.919543664932 + _Complex_I* 0.392987847501, 0.443778680694 + _Complex_I* 0.896136419616, -0.244782976343 + _Complex_I* 0.969577895010, -0.815968551135 + _Complex_I* 0.578096292635, -0.995888388425 + _Complex_I* -0.090588728879, -0.698268982046 + _Complex_I* -0.715835476008, -0.065822053387 + _Complex_I* -0.997831377181, 0.598187261134 + _Complex_I* -0.801356350581, 0.975359320021 + _Complex_I* -0.220622294542, 0.884836045372 + _Complex_I* 0.465902535742, 0.370024325563 + _Complex_I* 0.929022065665, -0.322218056780 + _Complex_I* 0.946665476229, -0.859953399058 + _Complex_I* 0.510372561418, -0.985331793961 + _Complex_I* -0.170649511602, -0.638232946313 + _Complex_I* -0.769843299796, 0.014905495740 + _Complex_I* -0.999888906928, 0.660896591520 + _Complex_I* -0.750476978539, 0.989980630117 + _Complex_I* -0.141203229401, 0.844358258992 + _Complex_I* 0.535778994056, 0.293856978673 + _Complex_I* 0.955849400316, -0.397551898294 + _Complex_I* 0.917579690361, -0.898330344143 + _Complex_I* 0.439320603650, -0.968349682754 + _Complex_I* -0.249597459743, -0.574034884644 + _Complex_I* -0.818830844077, 0.095535843587 + _Complex_I* -0.995425990514, 0.719296102472 + _Complex_I* -0.694703618076, 0.998146107617 + _Complex_I* -0.060863353909, 0.798374268344 + _Complex_I* 0.602161546138, 0.215773340288 + _Complex_I* 0.976443477945, -0.470293236050 + _Complex_I* 0.882510210777, -0.930849123784 + _Complex_I* 0.365403761270, -0.945052798049 + _Complex_I* -0.326917740264, -0.506093443552 + _Complex_I* -0.862478652718, 0.175543185898 + _Complex_I* -0.984471731379, 0.773004960816 + _Complex_I* -0.634399976792, 0.999802504049 + _Complex_I* 0.019873421897, 0.747183942875 + _Complex_I* 0.664617300038, 0.136282607136 + _Complex_I* 0.990670001056, -0.539967711374 + _Complex_I* 0.841685731538, -0.957297677470 + _Complex_I* 0.289104058618, -0.915593062806 + _Complex_I* -0.402106134423, -0.434851680767 + _Complex_I* -0.900502090911, 0.254405781142 + _Complex_I* -0.967097564117, 0.821672921923 + _Complex_I* -0.569959305019, 0.994939017768 + _Complex_I* 0.100480599729, 0.691121103433 + _Complex_I* 0.722738971129, 0.055903151852 + _Complex_I* 0.998436196065, -0.606120965124 + _Complex_I* 0.795372476037, -0.977503529671 + _Complex_I* 0.210919059075, -0.880162588986 + _Complex_I* -0.474672325874, -0.360774175978 + _Complex_I* -0.932653201328, 0.331609352882 + _Complex_I* -0.943416788636, 0.864982613715 + _Complex_I* -0.501801831374, 0.983587364400 + _Complex_I* 0.180432526426, 0.630551345359 + _Complex_I* 0.776147538079, -0.024840857424 + _Complex_I* 0.999691418290, -0.668321600646 + _Complex_I* 0.743872460917, -0.991334914576 + _Complex_I* 0.131358620360, -0.838992424751 + _Complex_I* -0.544143098100, -0.284344001234 + _Complex_I* -0.958722321093, 0.406650443454 + _Complex_I* -0.913583831314, 0.902651606302 + _Complex_I* -0.430372022371, 0.965821570012 + _Complex_I* 0.259207821834, 0.565869654379 + _Complex_I* 0.824494714509, -0.105422875231 + _Complex_I* 0.994427482212, -0.726163996983 + _Complex_I* 0.687521526561, -0.998701635364 + _Complex_I* 0.050941569671, -0.792351047769 + _Complex_I* -0.610065420344, -0.206059570743 + _Complex_I* -0.978539449029, 0.479039697103 + _Complex_I* -0.877793237955, 0.934434253757 + _Complex_I* -0.356135683981, 0.941757488380 + _Complex_I* 0.336292778810, 0.497497830836 + _Complex_I* 0.867465220233, -0.185317412481 + _Complex_I* 0.982678714856, -0.779270954001 + _Complex_I* 0.626687147028, -0.999555652393 + _Complex_I* -0.029807679686, -0.740542614416 + _Complex_I* -0.672009401894, -0.126431390635 + _Complex_I* -0.991975354261, 0.548305051154 + _Complex_I* -0.836278405125, 0.960123296014 + _Complex_I* -0.279576924033, 0.911552045487 + _Complex_I* 0.411184713198, 0.425881739056 + _Complex_I* 0.904778837252, -0.264003463266 + _Complex_I* 0.964521731940, -0.827296152171 + _Complex_I* 0.561766033686, -0.993891396472 + _Complex_I* -0.110362548078, -0.683904976326 + _Complex_I* -0.729571095478, -0.045978729857 + _Complex_I* -0.998942418962, 0.613994814417 + _Complex_I* -0.789310058132, 0.979551210443 + _Complex_I* -0.201194995263, 0.875402216180 + _Complex_I* 0.483395241917, 0.351488399794 + _Complex_I* 0.936192237102, -0.340967902424 + _Complex_I* 0.940074938245, -0.869926410981 + _Complex_I* 0.493181548192, -0.981745805180 + _Complex_I* -0.190197723464, -0.622807477199 + _Complex_I* -0.782375131472, 0.034773766063 + _Complex_I* -0.999395209711, 0.675680612738 + _Complex_I* -0.737194485581, 0.992591304302 + _Complex_I* -0.121501039602, 0.833543739662 + _Complex_I* 0.552453467788, 0.274802944706 + _Complex_I* 0.961500567644, -0.415708831715 + _Complex_I* 0.909497755486, -0.906883731242 + _Complex_I* 0.421380941677, -0.963198081990 + _Complex_I* -0.268792587045, -0.557648544251 + _Complex_I* -0.830077165747, 0.115299496322 + _Complex_I* -0.993330773785, 0.732960182500 + _Complex_I* -0.680271542011, 0.999158540912 + _Complex_I* -0.041014754931, 0.786249582201 + _Complex_I* 0.617909050337, 0.196325452731 + _Complex_I* 0.980538788937, -0.487738852787 + _Complex_I* 0.872989582688, -0.937927107962 + _Complex_I* 0.346832438147, -0.938369179770 + _Complex_I* -0.345634608305, -0.488853090003 + _Complex_I* -0.872366125199, 0.195073338893 + _Complex_I* -0.980788658404, 0.785459993857 + _Complex_I* -0.618912431650, 0.999210094204 + _Complex_I* 0.039738993954, 0.733828157068 + _Complex_I* 0.679335142543, 0.116567688981 + _Complex_I* 0.993182749491, -0.556588245585 + _Complex_I* 0.830788495874, -0.962854101984 + _Complex_I* 0.270022181112, -0.907421012027 + _Complex_I* -0.420222687313, -0.416869741348 + _Complex_I* -0.908966236308, 0.273575074938 + _Complex_I* -0.961850652842, 0.832837686581 + _Complex_I* -0.553517287725, 0.992745627990 + _Complex_I* 0.120233598080, 0.676621313319 + _Complex_I* 0.736331174379, 0.036049767444 + _Complex_I* 0.999349995881, -0.621808031469 + _Complex_I* 0.783169695533, -0.981502160129 + _Complex_I* 0.191451063363, -0.870555397043 + _Complex_I* -0.492070422480, -0.342167913985 + _Complex_I* -0.939638823506, 0.350292781243 + _Complex_I* -0.936640255065, 0.874784302655 + _Complex_I* -0.484512563128, 0.979807298156 + _Complex_I* 0.199944138398, 0.615002106542 + _Complex_I* 0.788525464997, -0.044703240778 + _Complex_I* 0.999000310442, -0.682972901089 + _Complex_I* 0.730443711985, -0.993749675226 + _Complex_I* 0.111631460566, -0.828012741783 + _Complex_I* -0.560709282467, -0.265234751275 + _Complex_I* -0.964183865617, 0.424726168556 + _Complex_I* -0.905321866379, 0.911026301038 + _Complex_I* -0.412348249441, 0.960479477760 + _Complex_I* 0.278350808877, 0.549372366100 + _Complex_I* 0.835577646521, -0.125164731540 + _Complex_I* 0.992135973533, -0.739683987895 + _Complex_I* 0.672954380365, -0.999516779141 + _Complex_I* 0.031083889968, -0.780070474162 + _Complex_I* -0.625691661556, -0.186571947499 + _Complex_I* -0.982441300235, 0.496389844059 + _Complex_I* -0.868099719338, 0.941327341476 + _Complex_I* -0.337494942465, 0.934888206815 + _Complex_I* 0.354942306239, 0.480160074725 + _Complex_I* 0.877180883649, -0.204810001732 + _Complex_I* 0.978801748665, -0.791571469213 + _Complex_I* 0.611076598413, -0.998765863605 + _Complex_I* -0.049666383980, -0.727041233885 + _Complex_I* -0.686593798567, -0.106692476220 + _Complex_I* -0.994292067512, 0.564816476695 + _Complex_I* -0.825216545916, 0.965489825714 + _Complex_I* -0.260440773388, 0.903200370366 + _Complex_I* 0.429219164264, 0.407816577581 + _Complex_I* 0.913063874573, -0.283119670959 + _Complex_I* 0.959084590595, -0.838296977925 + _Complex_I* 0.545213881703, -0.991501825466 + _Complex_I* -0.130092774964, -0.669270833677 + _Complex_I* -0.743018540273, -0.026117245101 + _Complex_I* -0.999658886575, 0.629559844720 + _Complex_I* -0.776951994602, 0.983356186070 + _Complex_I* -0.181688225591, 0.865622610200 + _Complex_I* 0.500697010886, 0.332813638953 + _Complex_I* 0.942992620187, -0.359583068506 + _Complex_I* 0.933113078273, -0.879555809016 + _Complex_I* 0.475795732248, -0.977772034756 + _Complex_I* -0.209670808766, -0.607136004174 + _Complex_I* -0.794597931306, 0.054628301030 + _Complex_I* -0.998506759480, 0.690197745585 + _Complex_I* -0.723620806770, 0.994809912959 + _Complex_I* -0.101750857877, 0.822399977304 + _Complex_I* 0.568909726873, 0.255640365802 + _Complex_I* 0.966771950034, -0.433701563513 + _Complex_I* 0.901056576363, -0.915078906610 + _Complex_I* 0.403274837644, -0.957666025784 + _Complex_I* -0.287881543451, -0.541041937199 + _Complex_I* -0.840995613658, 0.135017606689 + _Complex_I* -0.990843199444, 0.746334749190 + _Complex_I* -0.665570764195, 0.999776314675 + _Complex_I* -0.021149955457, 0.773814333841 + _Complex_I* 0.633412485465, 0.176800018209 + _Complex_I* 0.984246795047, -0.504991816627 + _Complex_I* 0.863124130783, -0.944634618526 + _Complex_I* 0.328124119019, -0.931314913263 + _Complex_I* -0.364214953474, -0.471419643442 + _Complex_I* -0.881909020125, 0.214526439499 + _Complex_I* -0.976718181850, 0.797604776560 + _Complex_I* -0.603180421109, 0.998223004463 + _Complex_I* 0.059588869430, 0.720182515080 + _Complex_I* 0.693784653169, 0.096806727533 + _Complex_I* 0.995303198781, -0.572988931946 + _Complex_I* 0.819563105482, -0.968030206924 + _Complex_I* 0.250833647030, -0.898890537295 + _Complex_I* -0.438173255644, -0.398723141757 + _Complex_I* -0.917071347403, 0.292636308795 + _Complex_I* -0.956223818347, 0.843673487096 + _Complex_I* -0.536856635585, 0.990160111727 + _Complex_I* 0.139939105133, 0.661854263264 + _Complex_I* 0.749632532778, 0.016182143669 + _Complex_I* 0.999869060541, -0.637249488677 + _Complex_I* 0.770657569340, -0.985113105181 + _Complex_I* 0.171907446032, -0.860604342767 + _Complex_I* -0.509274155254, -0.323426498437 + _Complex_I* -0.946253295957}; liquid-dsp-1.3.1/src/nco/tests/data/nco_sincos_fsqrt1_3.c000066400000000000000000000333431317124540100232370ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest nco sincos data for f=0.577350269190 // #include float complex nco_sincos_fsqrt1_3[256] = { 1.000000000000 + _Complex_I* 0.000000000000, 0.837911827695 + _Complex_I* 0.545805614673, 0.404192461982 + _Complex_I* 0.914673960314, -0.160556538575 + _Complex_I* 0.987026644990, -0.673256907353 + _Complex_I* 0.739408639861, -0.967703312923 + _Complex_I* 0.252091844688, -0.948443195842 + _Complex_I* -0.316947163201, -0.621720230463 + _Complex_I* -0.783239398290, -0.093450273402 + _Complex_I* -0.995623948286, 0.465114051693 + _Complex_I* -0.885250766121, 0.872899403683 + _Complex_I* -0.487900226531, 0.997711417775 + _Complex_I* 0.067616025029, 0.799088991477 + _Complex_I* 0.601212760759, 0.341420816904 + _Complex_I* 0.939910541373, -0.226927910067 + _Complex_I* 0.973911558424, -0.721711976662 + _Complex_I* 0.692193486492, -0.982534092802 + _Complex_I* 0.186082660346, -0.924841898283 + _Complex_I* -0.380351762426, -0.567337837836 + _Complex_I* -0.823485141190, -0.025916270960 + _Complex_I* -0.999664117041, 0.523906737901 + _Complex_I* -0.851775633592, 0.903891575553 + _Complex_I* -0.427761638818, 0.990856146318 + _Complex_I* 0.134922560393, 0.756608593536 + _Complex_I* 0.653868057170, 0.277086432600 + _Complex_I* 0.960844997317, -0.292260595196 + _Complex_I* 0.956338718496, -0.766863651569 + _Complex_I* 0.641810049705, -0.992867652562 + _Complex_I* 0.119221745066, -0.897007447265 + _Complex_I* -0.442015429086, -0.510358646627 + _Complex_I* -0.859961657176, 0.041736354516 + _Complex_I* -0.999128658738, 0.580301416814 + _Complex_I* -0.814401783915, 0.930746487037 + _Complex_I* -0.365665115738, 0.979465563334 + _Complex_I* 0.201611533010, 0.710665073638 + _Complex_I* 0.703530491955, 0.211483778128 + _Complex_I* 0.977381507697, -0.356255555520 + _Complex_I* 0.934388558985, -0.808505265432 + _Complex_I* 0.588488942775, -0.998656693799 + _Complex_I* 0.051815132253, -0.865067245650 + _Complex_I* -0.501655918438, -0.451043459964 + _Complex_I* -0.892501987238, 0.109197945833 + _Complex_I* -0.994020024258, 0.634039960711 + _Complex_I* -0.773300283345, 0.953341218789 + _Complex_I* -0.301894883291, 0.963591805394 + _Complex_I* 0.267377696485, 0.661468722830 + _Complex_I* 0.749972751984, 0.144913127625 + _Complex_I* 0.989444382187, -0.418619875580 + _Complex_I* 0.908161549379, -0.846446217737 + _Complex_I* 0.532474225177, -0.999874719120 + _Complex_I* -0.015828646941, -0.829167488991 + _Complex_I* -0.559000246154, -0.389663773211 + _Complex_I* -0.920957188933, 0.176159720196 + _Complex_I* -0.984361596661, 0.684876399442 + _Complex_I* -0.728659260209, 0.971572351007 + _Complex_I* -0.236742828316, 0.943307529299 + _Complex_I* 0.331920028273, 0.609244720899 + _Complex_I* 0.792982263393, 0.077679185906 + _Complex_I* 0.996978407026, -0.479068103627 + _Complex_I* 0.877777735015, -0.880512846507 + _Complex_I* 0.474022285486, -0.996516153423 + _Complex_I* -0.083399975816, -0.789472496379 + _Complex_I* -0.613785937817, -0.326500531288 + _Complex_I* -0.945197018123, 0.242315182549 + _Complex_I* -0.970197584158, 0.732578046264 + _Complex_I* -0.680683043811, 0.985356436799 + _Complex_I* -0.170507162484, 0.918705579515 + _Complex_I* 0.394943107508, 0.554232105691 + _Complex_I* 0.832362164578, 0.010089693778 + _Complex_I* 0.999949097744, -0.537323558182 + _Complex_I* 0.843376187607, -0.910549223177 + _Complex_I* 0.413400667841, -0.988596369416 + _Complex_I* -0.150589569286, -0.746163958323 + _Complex_I* -0.665762230305, -0.261842842740 + _Complex_I* -0.965110525124, 0.307361528464 + _Complex_I* -0.951592817764, 0.776926562896 + _Complex_I* -0.629591229184, 0.994630384139 + _Complex_I* -0.103491057329, 0.889898563214 + _Complex_I* 0.456158467191, 0.496682678992 + _Complex_I* 0.867932207254, -0.057545980537 + _Complex_I* 0.998342857001, -0.593119594448 + _Complex_I* 0.805114368697, -0.936417866314 + _Complex_I* 0.350886847356, -0.976151617251 + _Complex_I* -0.217089889533, -0.699440105123 + _Complex_I* -0.714691219581, -0.195986656442 + _Complex_I* -0.980606562540, 0.371001030117 + _Complex_I* -0.928632454555, 0.817718958886 + _Complex_I* -0.575617671966, 0.999351744645 + _Complex_I* -0.036001256586, 0.857018334845 + _Complex_I* 0.515285914556, 0.436859853992 + _Complex_I* 0.899529581487, -0.124918257436 + _Complex_I* 0.992167036824, -0.646200824792 + _Complex_I* 0.763167408920, -0.958000370884 + _Complex_I* 0.286766960067, -0.959238858607 + _Complex_I* -0.282596553655, -0.649514799540 + _Complex_I* -0.760348949614, -0.129233406987 + _Complex_I* -0.991614202459, 0.432942399044 + _Complex_I* -0.901421587888, 0.854768520727 + _Complex_I* -0.519009418002, 0.999498907872 + _Complex_I* 0.031653327829, 0.820215392622 + _Complex_I* 0.572054813550, 0.375037449599 + _Complex_I* 0.927009660898, -0.191718762927 + _Complex_I* 0.981449904958, -0.696324287694 + _Complex_I* 0.717727306410, -0.975197950213 + _Complex_I* 0.221334493244, -0.937935505961 + _Complex_I* -0.346809726878, -0.596616557906 + _Complex_I* -0.802526437466, -0.061888634976 + _Complex_I* -0.998083061103, 0.492902119414 + _Complex_I* -0.870084766375, 0.887905666482 + _Complex_I* -0.460025572582, 0.995071200231 + _Complex_I* 0.099163029757, 0.779658189663 + _Complex_I* 0.626205323590, 0.311498437124 + _Complex_I* 0.950246664645, -0.257641740113 + _Complex_I* 0.966240515478, -0.743260559821 + _Complex_I* 0.669002047989, -0.987931888154 + _Complex_I* 0.154888942047, -0.912339068261 + _Complex_I* -0.409435494949, -0.540987504175 + _Complex_I* -0.841030629839, 0.005739411495 + _Complex_I* -0.999983529442, 0.550605745726 + _Complex_I* -0.834765423801, 0.916978721986 + _Complex_I* -0.398936114465, 0.986088888068 + _Complex_I* 0.166218846191, 0.735532362955 + _Complex_I* 0.677489588884, 0.246533645077 + _Complex_I* 0.969134233141, -0.322385448685 + _Complex_I* 0.946608484262, -0.786794806137 + _Complex_I* 0.617214657178, -0.996143899378 + _Complex_I* 0.087734438690, -0.882566704612 + _Complex_I* -0.470187209428, -0.482882261671 + _Complex_I* -0.875685286712, 0.073341187736 + _Complex_I* -0.997306908720, 0.605789158993 + _Complex_I* -0.795625222606, 0.941854615084 + _Complex_I* -0.336020660147, 0.972593084902 + _Complex_I* 0.232513851631, 0.688039883664 + _Complex_I* 0.725672872917, 0.180440427994 + _Complex_I* 0.983585914877, -0.385653546043 + _Complex_I* 0.922643670343, -0.826727763238 + _Complex_I* 0.562602173380, -0.999796396159 + _Complex_I* 0.020178360380, -0.848754688019 + _Complex_I* -0.528786799727, -0.422566787646 + _Complex_I* -0.906331788022, 0.140607269299 + _Complex_I* -0.990065450271, 0.658199775658 + _Complex_I* -0.752843313927, 0.962419484720 + _Complex_I* -0.271567184010, 0.954645563245 + _Complex_I* 0.297744602936, 0.637398132678 + _Complex_I* 0.770534632874, 0.113521305399 + _Complex_I* 0.993535562132, -0.447156443700 + _Complex_I* 0.894455764618, -0.862876651411 + _Complex_I* 0.505414566915, -0.998872660419 + _Complex_I* -0.047470077604, -0.811057781641 + _Complex_I* -0.584966045886, -0.360317155943 + _Complex_I* -0.932829859692, 0.207229768268 + _Complex_I* -0.978292299440, 0.707597703708 + _Complex_I* -0.706615517595, 0.978579202106 + _Complex_I* -0.205870700212, 0.932328471853 + _Complex_I* 0.361612528228, 0.583838905619 + _Complex_I* 0.811869529102, 0.046082577121 + _Complex_I* 0.998937633732, -0.506612632779 + _Complex_I* 0.862173787765, -0.895076011251 + _Complex_I* 0.445913594861, -0.993376920248 + _Complex_I* -0.114901237236, -0.769648530419 + _Complex_I* -0.638467806255, -0.296418293364 + _Complex_I* -0.955058215691, 0.272903742509 + _Complex_I* -0.962041343875, 0.753756840705 + _Complex_I* -0.657153425837, 0.990259801557 + _Complex_I* -0.139231912364, 0.905743959725 + _Complex_I* 0.423825293512, 0.527607351878 + _Complex_I* 0.849488364985, -0.021567078691 + _Complex_I* 0.999767403508, -0.563749972526 + _Complex_I* 0.825945499701, -0.923178460993 + _Complex_I* 0.384371602954, -0.983334330553 + _Complex_I* -0.181806475010, -0.724716471305 + _Complex_I* -0.689047194479, -0.231162675510 + _Complex_I* -0.972915113178, 0.337328591442 + _Complex_I* -0.941386966872, 0.796465908688 + _Complex_I* -0.604683434781, 0.997407819049 + _Complex_I* -0.071955837157, 0.875013708545 + _Complex_I* 0.484098140730, 0.468960852521 + _Complex_I* 0.883218952923, -0.089118018438 + _Complex_I* 0.996021073467, -0.618306935941 + _Complex_I* 0.785936723259, -0.947055371103 + _Complex_I* 0.321070279011, -0.968790857919 + _Complex_I* -0.247879554650, -0.676467265722 + _Complex_I* -0.736472700381, -0.164848988076 + _Complex_I* -0.986318818197, 0.400209431938 + _Complex_I* -0.916423706911, 0.835529421227 + _Complex_I* -0.549445708204, 0.999990536929 + _Complex_I* -0.004350408249, 0.840278375725 + _Complex_I* 0.542155191149, 0.408167842223 + _Complex_I* 0.912906902469, -0.156261050358 + _Complex_I* 0.987715791177, -0.670033806829 + _Complex_I* 0.742330585188, -0.966597453037 + _Complex_I* 0.256299363601, -0.949813070210 + _Complex_I* -0.312818048805, -0.625121758220 + _Complex_I* -0.780527249621, -0.097780759713 + _Complex_I* -0.995207979786, 0.461258448050 + _Complex_I* -0.887265824938, 0.870768578204 + _Complex_I* -0.491693078264, 0.997996133675 + _Complex_I* 0.063274933192, 0.801696950596 + _Complex_I* 0.597730708100, 0.345506580588 + _Complex_I* 0.938416326995, -0.222688849754 + _Complex_I* 0.974889571282, -0.718693822797 + _Complex_I* 0.695326677953, -0.981715259472 + _Complex_I* 0.190355323855, -0.926487831883 + _Complex_I* -0.376324723307, -0.570914965629 + _Complex_I* -0.821009197281, -0.030264972734 + _Complex_I* -0.999541910790, 0.520196208392 + _Complex_I* -0.854046781374, 0.902022084201 + _Complex_I* -0.431689888246, 0.991433737996 + _Complex_I* 0.130610654858, 0.759446026685 + _Complex_I* 0.650570313304, 0.281263878515 + _Complex_I* 0.959630465670, -0.288097365664 + _Complex_I* 0.957601121500, -0.764064258949 + _Complex_I* 0.645140146167, -0.992339593722 + _Complex_I* 0.123539996488, -0.898921906390 + _Complex_I* -0.438108897665, -0.514095001354 + _Complex_I* -0.857733250832, 0.037389342002 + _Complex_I* -0.999300774094, 0.576752945141 + _Complex_I* -0.816918625244, 0.929146886781 + _Complex_I* -0.369710782619, 0.980333387059 + _Complex_I* 0.197348550079, 0.713718993420 + _Complex_I* 0.700432151198, 0.215733785416 + _Complex_I* 0.976452217894, -0.352187212553 + _Complex_I* 0.935929573907, -0.805937447338 + _Complex_I* 0.592000701839, -0.998421826461 + _Complex_I* 0.056159206242, -0.867241467503 + _Complex_I* -0.497887775551, -0.454921939715 + _Complex_I* -0.890531318240, 0.104872519572 + _Complex_I* -0.994485673420, 0.630669788815 + _Complex_I* -0.776051298225, 0.952018831263 + _Complex_I* -0.306039449941, 0.964745888993 + _Complex_I* 0.263183148531, 0.664725150952 + _Complex_I* 0.747087995950, 0.149216243304 + _Complex_I* 0.988804587739, -0.414665040654 + _Complex_I* 0.909974122742, -0.844121727495 + _Complex_I* 0.536151572944, -0.999934118311 + _Complex_I* -0.011478633927, -0.831591521802 + _Complex_I* -0.555387739211, -0.393666625547 + _Complex_I* -0.919253277356, 0.171875678373 + _Complex_I* -0.985118648277, 0.681699953151 + _Complex_I* -0.731631856793, 0.970533228996 + _Complex_I* -0.240967324373, 0.944742590342 + _Complex_I* 0.327813114433, 0.612688752154 + _Complex_I* 0.790324296086, 0.082015713908 + _Complex_I* 0.996631036378, -0.475244878672 + _Complex_I* 0.879853570372, -0.878442323690 + _Complex_I* 0.477848390130, -0.996869547263 + _Complex_I* -0.079063934501, -0.792135244952 + _Complex_I* -0.610345601856, -0.330609434495 + _Complex_I* -0.943767663052, 0.238092133930 + _Complex_I* -0.971242573079, 0.729609864697 + _Complex_I* -0.683863616035, 0.984605336535 + _Complex_I* -0.174792251734, 0.920415049492 + _Complex_I* 0.390942625801, 0.557847976181 + _Complex_I* 0.829943151952, 0.014439785103 + _Complex_I* 0.999895740868, -0.533649442727 + _Complex_I* 0.845705783519, -0.908742144910 + _Complex_I* 0.417358016653}; liquid-dsp-1.3.1/src/nco/tests/data/nco_sincos_fsqrt1_5.c000066400000000000000000000333431317124540100232410ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest nco sincos data for f=0.447213595500 // #include float complex nco_sincos_fsqrt1_5[256] = { 1.000000000000 + _Complex_I* 0.000000000000, 0.901655595150 + _Complex_I* 0.432454838954, 0.625965624531 + _Complex_I* 0.779850650385, 0.227155220309 + _Complex_I* 0.973858565648, -0.216334073812 + _Complex_I* 0.976319398818, -0.617272876457 + _Complex_I* 0.786749131547, -0.896801011772 + _Complex_I* 0.442434114060, -0.999938423544 + _Complex_I* 0.011097257308, -0.906399137016 + _Complex_I* -0.422422305775, -0.634581283115 + _Complex_I* -0.772856128345, -0.237948391981 + _Complex_I* -0.971277798961, 0.205486285143 + _Complex_I* -0.978659995411, 0.608504109432 + _Complex_I* -0.793550722263, 0.891835984739 + _Complex_I* -0.452358902117, 0.999753701760 + _Complex_I* -0.022193147956, 0.911031053190 + _Complex_I* 0.412337750060, 0.643118791167 + _Complex_I* 0.765766426822, 0.248712259614 + _Complex_I* 0.968577416584, -0.194613190240 + _Complex_I* 0.980880067177, -0.599660403354 + _Complex_I* 0.800254584898, -0.886761125508 + _Complex_I* 0.462227980858, -0.999445857398 + _Complex_I* 0.033286305454, -0.915550773236 + _Complex_I* -0.402202413750, -0.651577097268 + _Complex_I* -0.758582418934, -0.259445497609 + _Complex_I* -0.965757751080, 0.183716128155 + _Complex_I* -0.982979340706, 0.590742847351 + _Complex_I* -0.806859893850, 0.881577059062 + _Complex_I* -0.472040134878, 0.999014928368 + _Complex_I* -0.044375363646, 0.919957740540 + _Complex_I* 0.392017545042, 0.659955159752 + _Complex_I* 0.751304989413, 0.270146784136 + _Complex_I* 0.962819149696, -0.172796440895 + _Complex_I* 0.984957557468, -0.581752539647 + _Complex_I* 0.813365835657, -0.876284423835 + _Complex_I* 0.481794155781, -0.998460967741 + _Complex_I* 0.055458956883, -0.924251412370 + _Complex_I* -0.381784398231, -0.668251946836 + _Complex_I* -0.743935034495, -0.280814801300 + _Complex_I* -0.959761974331, 0.161855473250 + _Complex_I* -0.986814473839, 0.572690587423 + _Complex_I* -0.819771609094, 0.870883871630 + _Complex_I* -0.491488842330, 0.997784043738 + _Complex_I* -0.066535720188, 0.928431259947 + _Complex_I* 0.371504233561, 0.676466436748 + _Complex_I* 0.736473461812, 0.291448235303 + _Complex_I* 0.956586601484, -0.150894572633 + _Complex_I* 0.988549861135, -0.563558106687 + _Complex_I* 0.826076425270, -0.865376067540 + _Complex_I* 0.501123000598, -0.996984239726 + _Complex_I* 0.077604289425, -0.932496768511 + _Complex_I* -0.361178317063, -0.684597617848 + _Complex_I* -0.728921190278, -0.302045776608 + _Complex_I* -0.953293422212, 0.139915088909 + _Complex_I* -0.990163505637, 0.554356222129 + _Complex_I* -0.832279507730, 0.859761689869 + _Complex_I* -0.510695444109, 0.996061654203 + _Complex_I* -0.088663301468, 0.936447437384 + _Complex_I* 0.350807920403, 0.692644488759 + _Complex_I* 0.721279149977, 0.312606120095 + _Complex_I* 0.949882842080, -0.128918374235 + _Complex_I* 0.991655208621, -0.545086066988 + _Complex_I* 0.838380092545, -0.854041430042 + _Complex_I* 0.520204993990, -0.995016400786 + _Complex_I* 0.099711394367, -0.940282780028 + _Complex_I* -0.340394320727, -0.700606058485 + _Complex_I* -0.713548282049, -0.323127965229 + _Complex_I* -0.946355281111, 0.117905782887 + _Complex_I* -0.993024786378, 0.535748782911 + _Complex_I* -0.844377428410, 0.848215992526 + _Complex_I* -0.529650479111, 0.993848608203 + _Complex_I* -0.110747207518, 0.944002324110 + _Complex_I* 0.329938800499, 0.708481346534 + _Complex_I* 0.705729538572, 0.333610016214 + _Complex_I* 0.942711173733, -0.106878671100 + _Complex_I* 0.994272070242, -0.526345519812 + _Complex_I* 0.850270776737, -0.842286094742 + _Complex_I* 0.539030736233, -0.992558420270 + _Complex_I* 0.121769381828, -0.947605611558 + _Complex_I* -0.319442647347, -0.716269383043 + _Complex_I* -0.697823882448, -0.344050982153 + _Complex_I* -0.938950968730, 0.095838396892 + _Complex_I* -0.995396906606, 0.516877435730 + _Complex_I* -0.856059411743, 0.836252466973 + _Complex_I* -0.548344610151, 0.991145995878 + _Complex_I* -0.132776559884, 0.951092198616 + _Complex_I* 0.308907153903, 0.723969208892 + _Complex_I* 0.689832287281, 0.354449577213 + _Complex_I* 0.935075129181, -0.084786319907 + _Complex_I* 0.996399156943, -0.507345696686 + _Complex_I* 0.861742620539, -0.830115852277 + _Complex_I* 0.557590953834, -0.989611508971 + _Complex_I* 0.143767386120, -0.954461655900 + _Complex_I* -0.298333617644, -0.731579875826 + _Complex_I* -0.681755737260, -0.364804520775 + _Complex_I* -0.931084132408, 0.073723801240 + _Complex_I* -0.997278697823, 0.497751476543 + _Complex_I* -0.867319703223, 0.823877006398 + _Complex_I* -0.566768628568, 0.987955148526 + _Complex_I* -0.154740506984, 0.957713568453 + _Complex_I* 0.287723340731, 0.739100446567 + _Complex_I* 0.673595227035, 0.375114537598 + _Complex_I* 0.926978469913, -0.062652203273 + _Complex_I* 0.998035420927, -0.488095956857 + _Complex_I* 0.872789972960, -0.817536697667 + _Complex_I* 0.575876504094, -0.986177118527 + _Complex_I* 0.165694571104, -0.960847535791 + _Complex_I* -0.277077629851, -0.746529994937 + _Complex_I* -0.665351761596, -0.385378357974 + _Complex_I* -0.922758647321, 0.051572889504 + _Complex_I* -0.998669233064, 0.478380326732 + _Complex_I* -0.878152756072, 0.811095706911 + _Complex_I* -0.584913458753, 0.984277637946 + _Complex_I* -0.176628229455, 0.963863171958 + _Complex_I* 0.266397796054, 0.753867605965 + _Complex_I* 0.657026356151, 0.395594717883 + _Complex_I* 0.918425184315, -0.040487224383 + _Complex_I* 0.999180056177, -0.468605782677 + _Complex_I* 0.883407392114, -0.804554827358 + _Complex_I* 0.593878379616, -0.982256940707 + _Complex_I* 0.187540135525, -0.966760105569 + _Complex_I* -0.255685154594, -0.761112376002 + _Complex_I* -0.648620035997, -0.405762359151 + _Complex_I* -0.913978614573, 0.029396573143 + _Complex_I* -0.999567827357, 0.458773528456 + _Complex_I* -0.888553233964, 0.797914864535 + _Complex_I* -0.602770162628, 0.980115275667 + _Complex_I* -0.198428945482, 0.969537979859 + _Complex_I* 0.244941024761, 0.768263412834 + _Complex_I* 0.640133836397, 0.415880029602 + _Complex_I* 0.909419485704, -0.018302301629 + _Complex_I* 0.999832498849, -0.448884774939 + _Complex_I* 0.893589647897, -0.791176636173 + _Complex_I* 0.611587712739, -0.977852906576 + _Complex_I* 0.209293318336, -0.972196452723 + _Complex_I* -0.234166729729, -0.775319835790 + _Complex_I* -0.631568802452, -0.425946483218 + _Complex_I* -0.904748359177, 0.007205776134 + _Complex_I* -0.999974038058, 0.438940739955 + _Complex_I* -0.898516013662, 0.784340972106 + _Complex_I* -0.620329944043, 0.975470112054 + _Complex_I* -0.220131916109, 0.974735196764 + _Complex_I* 0.223363596382, 0.782280775851 + _Complex_I* 0.622925988970, 0.435960480284 + _Complex_I* 0.899965810257, 0.003891636774 + _Complex_I* 0.999992427553, -0.428942648141 + _Complex_I* 0.903331724565, -0.777408714164 + _Complex_I* 0.628995779908, -0.972967185547 + _Complex_I* 0.230943403995, -0.977153899328 + _Complex_I* -0.212532955158, -0.789145375757 + _Complex_I* -0.614206460339, -0.445920787547 + _Complex_I* -0.895072427926, -0.014988570415 + _Complex_I* -0.999887665069, 0.418891730791 + _Complex_I* -0.908036187536, 0.770380716075 + _Complex_I* -0.637584153112, 0.970344435298 + _Complex_I* -0.241726450529, 0.979452262544 + _Complex_I* 0.201676139882, 0.795912790112 + _Complex_I* 0.605411290394, 0.455826178368 + _Complex_I* 0.890068814820, 0.026083658170 + _Complex_I* 0.999659763508, -0.408789225705 + _Complex_I* 0.912628823207, -0.763257843359 + _Complex_I* 0.646094005971, -0.967602184308 + _Complex_I* 0.252479727747, -0.981630003362 + _Complex_I* -0.190794487601, -0.802582185490 + _Complex_I* -0.596541562286, -0.465675432867 + _Complex_I* -0.884955587148, -0.037175533647 + _Complex_I* -0.999308750936, 0.398636377036 + _Complex_I* -0.917109065981, 0.756040973217 + _Complex_I* -0.654524290472, 0.964740770291 + _Complex_I* -0.263201911351, 0.983686853588 + _Complex_I* 0.179889338425, 0.809152740535 + _Complex_I* 0.587598368348, 0.475467338081 + _Complex_I* 0.879733374619, 0.048262830849 + _Complex_I* 0.998834670583, -0.388434435136 + _Complex_I* 0.921476364103, -0.748730994427 + _Complex_I* 0.662873968401, -0.961760545639 + _Complex_I* 0.273891680873, -0.985622559913 + _Complex_I* -0.168962035352, -0.815623646064 + _Complex_I* -0.578582809960, -0.485200688108 + _Complex_I* -0.874402820364, -0.059344184342 + _Complex_I* -0.998237580832, 0.378184656405 + _Complex_I* -0.925730179728, 0.741328807236 + _Complex_I* -0.671142011471, 0.958661877377 + _Complex_I* -0.284547719838, 0.987436883951 + _Complex_I* 0.158013924113, 0.821994105167 + _Complex_I* 0.569495997414, 0.494874284257 + _Complex_I* 0.868964580855, 0.070418229426 + _Complex_I* 0.997517555216, -0.367888303132 + _Complex_I* 0.929869988987, -0.733835323245 + _Complex_I* 0.679327401448, -0.955445147112 + _Complex_I* 0.295168715922, -0.989129602261 + _Complex_I* -0.147046352999, -0.828263333302 + _Complex_I* -0.560339049779, -0.504486935198 + _Complex_I* -0.863419325829, -0.081483602301 + _Complex_I* -0.996674682410, 0.357546643343 + _Complex_I* -0.933895282049, 0.726251465296 + _Complex_I* -0.687429130278, 0.952110750997 + _Complex_I* -0.305753361120, 0.990700506382 + _Complex_I* 0.136060672699, 0.834430558397 + _Complex_I* 0.551113094758, 0.514037457104 + _Complex_I* 0.857767738198, 0.092538940232 + _Complex_I* 0.995709066214, -0.347160950645 + _Complex_I* 0.937805563189, -0.718578167365 + _Complex_I* 0.695446200210, -0.948659099670 + _Complex_I* 0.316300351901, -0.992149402850 + _Complex_I* -0.125058236130, -0.840495020939 + _Complex_I* -0.541819268554, -0.523524673801 + _Complex_I* -0.852010513974, -0.103582881724 + _Complex_I* -0.994620825548, 0.336732504064 + _Complex_I* -0.941600350842, 0.710816374441 + _Complex_I* -0.703377623917, 0.945090618214 + _Complex_I* -0.326808389373, 0.993476113231 + _Complex_I* 0.114040398276, 0.846455974072 + _Complex_I* 0.532458715731, 0.532947416909 + _Complex_I* 0.846148362174, 0.114614066682 + _Complex_I* 0.993410094432, -0.326262587896 + _Complex_I* 0.945279177672, -0.702967042411 + _Complex_I* 0.711222424621, -0.941405746096 + _Complex_I* 0.337276179440, -0.994680474136 + _Complex_I* -0.103008516015, -0.852312683688 + _Complex_I* -0.523032589066, -0.542304525992 + _Complex_I* -0.840182004740, -0.125631136584 + _Complex_I* -0.992077021970, 0.315752491540 + _Complex_I* -0.948841590618, 0.695031137943 + _Complex_I* -0.718979636214, 0.937604937119 + _Complex_I* -0.347702432964, 0.995762337245 + _Complex_I* 0.091963947955, 0.858064428515 + _Complex_I* 0.513542049416, 0.551594848693 + _Complex_I* 0.834112176446, 0.136632734646 + _Complex_I* 0.990621772334, -0.305203509345 + _Complex_I* 0.952287150960, -0.687009638366 + _Complex_I* 0.726648303371, -0.933688659365 + _Complex_I* 0.358085865921, -0.996721569324 + _Complex_I* -0.080908054267, -0.863710500209 + _Complex_I* -0.503988265566, -0.560817240883 + _Complex_I* -0.827939624808, -0.147617505989 + _Complex_I* -0.989044524744, 0.294616940449 + _Complex_I* -0.955615434367, 0.678903531553 + _Complex_I* -0.734227481674, 0.929657395135 + _Complex_I* -0.368425199561, 0.997558052238 + _Complex_I* 0.069842196517, 0.869250203441 + _Complex_I* 0.494372414095, 0.569970566797 + _Complex_I* 0.821665109996, 0.158584097806 + _Complex_I* 0.987345473440, -0.283994088620 + _Complex_I* 0.958826030951, -0.670713815793 + _Complex_I* 0.741716237725, -0.925511640889 + _Complex_I* 0.378719160565, -0.998271682975 + _Complex_I* -0.058767737497, -0.874682855979 + _Complex_I* -0.484695679221, -0.579053699176 + _Complex_I* -0.815289404733, -0.169531159530 + _Complex_I* -0.985524827667, 0.273336262091 + _Complex_I* -0.961918545318, 0.662441499674 + _Complex_I* -0.749113649261, 0.921251907190 + _Complex_I* -0.388966481202, 0.998862373647 + _Complex_I* 0.047686041058, 0.880007788778 + _Complex_I* 0.474959252664, 0.588065519407 + _Complex_I* 0.808813294206}; liquid-dsp-1.3.1/src/nco/tests/data/nco_sincos_fsqrt1_7.c000066400000000000000000000333431317124540100232430ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // autotest nco sincos data for f=0.377964473009 // #include float complex nco_sincos_fsqrt1_7[256] = { 1.000000000000 + _Complex_I* 0.000000000000, 0.929417729782 + _Complex_I* 0.369029380357, 0.727634632866 + _Complex_I* 0.685964897829, 0.423135327397 + _Complex_I* 0.906066495743, 0.058904317893 + _Complex_I* 0.998263633182, -0.313641892575 + _Complex_I* 0.949541343608, -0.641912989417 + _Complex_I* 0.766777486640, -0.879568734108 + _Complex_I* 0.475771838153, -0.993060562667 + _Complex_I* 0.117604076781, -0.966367453272 + _Complex_I* -0.257165210044, -0.803257526443 + _Complex_I* -0.595631888176, -0.526756120043 + _Complex_I* -0.850016464545, -0.175895428035 + _Complex_I* -0.984408857333, 0.199795461237 + _Complex_I* -0.979837626175, 0.547282316042 + _Complex_I* -0.836948066817, 0.817512314214 + _Complex_I* -0.575911118237, 0.972338562249 + _Complex_I* -0.233575941320, 0.989905083997 + _Complex_I* 0.141731876011, 0.867732109487 + _Complex_I* 0.497032178200, 0.623066130519 + _Complex_I* 0.782169161371, 0.290445307576 + _Complex_I* 0.956891594334, -0.083176093733 + _Complex_I* 0.996534865136, -0.445055979995 + _Complex_I* 0.895502749673, -0.744109743372 + _Complex_I* 0.668057400093, -0.938121596793 + _Complex_I* 0.346306034644, -0.999703946129 + _Complex_I* -0.024331463036, -0.920163547338 + _Complex_I* -0.391534220918, -0.710728684262 + _Complex_I* -0.703466230439, -0.400964133096 + _Complex_I* -0.916093752828, -0.034597664351 + _Complex_I* -0.999401321603, 0.336652767782 + _Complex_I* -0.941628862103, 0.660379766665 + _Complex_I* -0.750931797023, 0.890884559273 + _Complex_I* -0.454229789917, 0.995628042491 + _Complex_I* -0.093406643266, 0.959824150645 + _Complex_I* 0.280602209256, 0.788527123674 + _Complex_I* 0.614999979863, 0.505918027668 + _Complex_I* 0.862581560944, 0.151891245788 + _Complex_I* 0.988397212386, -0.223577193999 + _Complex_I* 0.974686225574, -0.567484461944 + _Complex_I* 0.823384105659, -0.831283046614 + _Complex_I* 0.555849346867, -0.977733942036 + _Complex_I* 0.209848370473, -0.986163474863 + _Complex_I* -0.165775754701, -0.855381693965 + _Complex_I* -0.517998221646, -0.603850349342 + _Complex_I* -0.797097707687, -0.267076747662 + _Complex_I* -0.963675262139, 0.107398620363 + _Complex_I* -0.994216041082, 0.466713111501 + _Complex_I* -0.884408769491, 0.760144260739 + _Complex_I* -0.649754340398, 0.946269994744 + _Complex_I* -0.323377638447, 0.998815959813 + _Complex_I* 0.048648519224, 0.910364528935 + _Complex_I* 0.413807231035, 0.693401907701 + _Complex_I* 0.720551035248, 0.378555524829 + _Complex_I* 0.925578583709, 0.010270525265 + _Complex_I* 0.999947256764, -0.359464308278 + _Complex_I* 0.933158834858, -0.678455527940 + _Complex_I* 0.734641474875, -0.901672884794 + _Complex_I* 0.432418788707, -0.997606003243 + _Complex_I* 0.069153902954, -0.952712528707 + _Complex_I* -0.303873061728, -0.773329827890 + _Complex_I* -0.634003925300, -0.484780377312 + _Complex_I* -0.874635916123, -0.127797127559 + _Complex_I* -0.991800329798, 0.247226544974 + _Complex_I* -0.968957705713, 0.587350595903 + _Complex_I* -0.809332612399, 0.844561569887 + _Complex_I* -0.535458452795, 0.982550397988 + _Complex_I* -0.185996546781, 0.981837950701 + _Complex_I* 0.189721476283, 0.842524800322 + _Complex_I* 0.538657554336, 0.584277023699 + _Complex_I* 0.811554286279, 0.243550049538 + _Complex_I* 0.969888330361, -0.131557555439 + _Complex_I* 0.991308534013, -0.488093898561 + _Complex_I* 0.872791124031, -0.775728690804 + _Complex_I* 0.631066556129, -0.953858098906 + _Complex_I* 0.300257767846, -0.997336566835 + _Complex_I* -0.072936770247, -0.900026476647 + _Complex_I* -0.435835222687, -0.675664562503 + _Complex_I* -0.737209196211, -0.355922770904 + _Complex_I* -0.934515372346, 0.014062695080 + _Complex_I* -0.999901115414, 0.382063007175 + _Complex_I* -0.924136277044, 0.696129570446 + _Complex_I* -0.717916165824, 0.911927322820 + _Complex_I* -0.410351748984, 0.998993273758 + _Complex_I* -0.044860216082, 0.945036798307 + _Complex_I* 0.326963988607, 0.757674637528 + _Complex_I* 0.652632472106, 0.463355684742 + _Complex_I* 0.886172392606, 0.103627339662 + _Complex_I* 0.994616194557, -0.270729511199 + _Complex_I* 0.962655458493, -0.606868955028 + _Complex_I* 0.794801907033, -0.857340021717 + _Complex_I* 0.514750509629, -0.986785078242 + _Complex_I* 0.162034593094, -0.976931072688 + _Complex_I* -0.213554862310, -0.829169041221 + _Complex_I* -0.558997943718, -0.564357743106 + _Complex_I* -0.825530337296, -0.219879143544 + _Complex_I* -0.975527120194, 0.155638594267 + _Complex_I* -0.987814065487, 0.509185681445 + _Complex_I* -0.860656692190, 0.790853805905 + _Complex_I* -0.612005112466, 0.960881416303 + _Complex_I* -0.276960112297, 0.995266643155 + _Complex_I* 0.097181834844, 0.889155511714 + _Complex_I* 0.457605152930, 0.657527151087 + _Complex_I* 0.753430849902, 0.333079272352 + _Complex_I* 0.942898827197, -0.038387588793 + _Complex_I* 0.999262924873, -0.404435483608 + _Complex_I* 0.914566530985, -0.713391429243 + _Complex_I* 0.700765773053, -0.921641801618 + _Complex_I* 0.388041736814, -0.999789032622 + _Complex_I* 0.020539967128, -0.936801504302 + _Complex_I* -0.349861317578, -0.741570822148 + _Complex_I* -0.670874590172, -0.441656635685 + _Complex_I* -0.897184159555, -0.079396193214 + _Complex_I* -0.996843139367, 0.294072176383 + _Complex_I* -0.955783215524, 0.626027982347 + _Complex_I* -0.779800593305, 0.869610835882 + _Complex_I* -0.493737778701, 0.990435475412 + _Complex_I* -0.137976697470, 0.971445746224 + _Complex_I* 0.237261800850, 0.815322324712 + _Complex_I* 0.579007346089, 0.544104301925 + _Complex_I* 0.839017585410, 0.196078045407 + _Complex_I* 0.980588292868, -0.179627478280 + _Complex_I* 0.983734704606, -0.529975971546 + _Complex_I* 0.848012658858, -0.805510650347 + _Complex_I* 0.592581295839, -0.967335788375 + _Complex_I* 0.253498466521, -0.992607414390 + _Complex_I* -0.121369357324, -0.877758070920 + _Complex_I* -0.479104131619, -0.639000412754 + _Complex_I* -0.769206391354, -0.310038554984 + _Complex_I* -0.950723984353, 0.062689752919 + _Complex_I* -0.998033063019, 0.426568490660 + _Complex_I* -0.904455263004, 0.730230883453 + _Complex_I* -0.683200451443, 0.930810569171 + _Complex_I* -0.365501962128, 0.999992808660 + _Complex_I* 0.003792443700, 0.928011522874 + _Complex_I* 0.372551490955, 0.725027916943 + _Complex_I* 0.688719478201, 0.419696078314 + _Complex_I* 0.907664696817, 0.055118035666 + _Complex_I* 0.998479845638, -0.317240719156 + _Complex_I* 0.948345045914, -0.644816333651 + _Complex_I* 0.764337553609, -0.881366746740 + _Complex_I* 0.472432701811, -0.993499428070 + _Complex_I* 0.113837104776, -0.965385219214 + _Complex_I* -0.260828254841, -0.800992849544 + _Complex_I* -0.598673913729, -0.523528692375 + _Complex_I* -0.852008044716, -0.172160847942 + _Complex_I* -0.985068851622, 0.203510003471 + _Complex_I* -0.979072866791, 0.550452458771 + _Complex_I* -0.834866510667, 0.819690545696 + _Complex_I* -0.572806607239, 0.973217393439 + _Complex_I* -0.229886722341, 0.989360455092 + _Complex_I* 0.145485016068, 0.865840902777 + _Complex_I* 0.500319429044, 0.620095317331 + _Complex_I* 0.784526479747, 0.286814261387 + _Complex_I* 0.957986210477, -0.086954797956 + _Complex_I* 0.996212258062, -0.448448923206 + _Complex_I* 0.893808460060, -0.746637962304 + _Complex_I* 0.665230601556, -0.939428196580 + _Complex_I* 0.342745770900, -0.999604481214 + _Complex_I* -0.028122608992, -0.918672058640 + _Complex_I* -0.395021073709, -0.708055717096 + _Complex_I* -0.706156570094, -0.397487015646 + _Complex_I* -0.917607798786, -0.030807242302 + _Complex_I* -0.999525344262, 0.340221421243 + _Complex_I* -0.940345353861, 0.663222884212 + _Complex_I* -0.748421943731, 0.892600793524 + _Complex_I* -0.450847893862, 0.995975122026 + _Complex_I* -0.089630108250, 0.958753080142 + _Complex_I* 0.284240270403, 0.786189100308 + _Complex_I* 0.617986001910, 0.502643097433 + _Complex_I* 0.864494023463, 0.148141712706 + _Complex_I* 0.988966143483, -0.227272028815 + _Complex_I* 0.973831312353, -0.570603018834 + _Complex_I* 0.821226031551, -0.833385095928 + _Complex_I* 0.552692755412, -0.978522748949 + _Complex_I* 0.206138860453, -0.985527687809 + _Complex_I* -0.169514532008, -0.853411063532 + _Complex_I* -0.521238483461, -0.600823058669 + _Complex_I* -0.799382043938, -0.263420142846 + _Complex_I* -0.964681205551, 0.111168356384 + _Complex_I* -0.993801588114, 0.470063825674 + _Complex_I* -0.882632426207, 0.762602951037 + _Complex_I* -0.646866863481, 0.947489581282 + _Complex_I* -0.319786637248, 0.998624280217 + _Complex_I* 0.052436122669, 0.908788641568 + _Complex_I* 0.417256761428, 0.690664271978 + _Complex_I* 0.723175541216, 0.375042597839 + _Complex_I* 0.927007578074, 0.006478207732 + _Complex_I* 0.999979016192, -0.363000675592 + _Complex_I* 0.931788876044, -0.681236735369 + _Complex_I* 0.732063187426, -0.903306324468 + _Complex_I* 0.428996135385, -0.997861091402 + _Complex_I* 0.065370041044, -0.951553255949 + _Complex_I* -0.307483985100, -0.770919842419 + _Complex_I* -0.636932175796, -0.481459883622 + _Complex_I* -0.876468128606, -0.124034861615 + _Complex_I* -0.992277860835, 0.250899484630 + _Complex_I* -0.968013144855, 0.590415720432 + _Complex_I* -0.807099298145, 0.846586192393 + _Complex_I* -0.532251649927, 0.983248713565 + _Complex_I* -0.182268942150, 0.981111381953 + _Complex_I* 0.193443677081, 0.840475912991 + _Complex_I* 0.541848908537, 0.581195048024 + _Complex_I* 0.813764287833, 0.239870051199 + _Complex_I* 0.970805005414, -0.135316091168 + _Complex_I* 0.990802480554, -0.491400399711 + _Complex_I* 0.870933778863, -0.778116396659 + _Complex_I* 0.628120110528, -0.954989950067 + _Complex_I* 0.296638155453, -0.997052786053 + _Complex_I* -0.076718588513, -0.898367123706 + _Complex_I* -0.439245388188, -0.672863879197 + _Complex_I* -0.739766314502, -0.352376114406 + _Complex_I* -0.935858468998, 0.017854662635 + _Complex_I* -0.999840592806, 0.385564994432 + _Complex_I* -0.922680678821, 0.698847220981 + _Complex_I* -0.715270970841, 0.913477000745 + _Complex_I* -0.406890364975, 0.999156219501 + _Complex_I* -0.041071267730, 0.943790009707 + _Complex_I* 0.330545636150, 0.755194116925 + _Complex_I* 0.655501217209, 0.459991593687 + _Complex_I* 0.887923270186, 0.099854568522 + _Complex_I* 0.995002042784, -0.274378380919 + _Complex_I* 0.961621809281, -0.609878832312 + _Complex_I* 0.792494674997, -0.859286018620 + _Complex_I* 0.511495394119, -0.987392489006 + _Complex_I* 0.158291100995, -0.976114152452 + _Complex_I* -0.217258282656, -0.827043110154 + _Complex_I* -0.562138500679, -0.561222907291 + _Complex_I* -0.827664695593, -0.216177930638 + _Complex_I* -0.976353984119, 0.159383704246 + _Complex_I* -0.987216711174, 0.512446011768 + _Complex_I* -0.858719444885, 0.793169113539 + _Complex_I* -0.609001442796, 0.961924861910 + _Complex_I* -0.273314031909, 0.994890929216 + _Complex_I* 0.100955628686, 0.887413675715 + _Complex_I* 0.460973934354, 0.654665078505 + _Complex_I* 0.755919066426, 0.329500986349 + _Complex_I* 0.944155230878, -0.042176961119 + _Complex_I* 0.999110156064, -0.407901017253 + _Complex_I* 0.913026155224, -0.716043913743 + _Complex_I* 0.698055236776, -0.923106800218 + _Complex_I* 0.384543671630, -0.999859739467 + _Complex_I* 0.016748175800, -0.935467938094 + _Complex_I* -0.353411568569, -0.739021235147 + _Complex_I* -0.673682131277, -0.438250939168 + _Complex_I* -0.898852665523, -0.075615150766 + _Complex_I* -0.997137076321, 0.297694815644 + _Complex_I* -0.954661089989, 0.628980830213 + _Complex_I* -0.777420809616, 0.871477054943 + _Complex_I* -0.490436277929, 0.990951621711 + _Complex_I* -0.134219534454, 0.970538958206 + _Complex_I* 0.240944247919, 0.813120608690 + _Complex_I* 0.582095246264, 0.540918462130 + _Complex_I* 0.841075036680, 0.192357809450 + _Complex_I* 0.981324856071, -0.183356945000 + _Complex_I* 0.983046403137, -0.533188200573 + _Complex_I* 0.845996656476}; liquid-dsp-1.3.1/src/nco/tests/gen_nco_data.m000066400000000000000000000045351317124540100210630ustar00rootroot00000000000000% generate nco data for autotests % options p = 7; % base frequency integer f = 1/sqrt(p); % frequency n = 256; % number of points % compute sincos data v = exp(j*[0:(n-1)]*f); % print results basename = ['nco_sincos_fsqrt1_' num2str(p)]; filename = ['data/' basename '.c']; fid = fopen(filename,'w'); fprintf(fid,'/* Copyright (c) 2007 - 2015 Joseph Gaeddert\n'); fprintf(fid,' *\n'); fprintf(fid,' * Permission is hereby granted, free of charge, to any person obtaining a copy\n'); fprintf(fid,' * of this software and associated documentation files (the "Software"), to deal\n'); fprintf(fid,' * in the Software without restriction, including without limitation the rights\n'); fprintf(fid,' * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n'); fprintf(fid,' * copies of the Software, and to permit persons to whom the Software is\n'); fprintf(fid,' * furnished to do so, subject to the following conditions:\n'); fprintf(fid,' * \n'); fprintf(fid,' * The above copyright notice and this permission notice shall be included in\n'); fprintf(fid,' * all copies or substantial portions of the Software.\n'); fprintf(fid,' *\n'); fprintf(fid,' * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n'); fprintf(fid,' * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n'); fprintf(fid,' * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n'); fprintf(fid,' * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n'); fprintf(fid,' * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n'); fprintf(fid,' * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n'); fprintf(fid,' * THE SOFTWARE.\n'); fprintf(fid,' */\n'); fprintf(fid,'\n'); fprintf(fid,'//\n'); fprintf(fid,'// autotest nco sincos data for f=%.12f\n', f); fprintf(fid,'//\n'); fprintf(fid,'\n'); fprintf(fid,'#include \n'); fprintf(fid,'\n'); fprintf(fid,'float complex %s[%u] = {\n', basename, n); for i=1:n, %fprintf(fid,' {%16.12f, %16.12f}', real(v(i)), imag(v(i))); fprintf(fid,' %16.12f + _Complex_I*%16.12f', real(v(i)), imag(v(i))); if i==n, fprintf(fid,'};\n'); else, fprintf(fid,',\n'); end; end; fprintf(fid,'\n'); fclose(fid); printf('results written to %s\n', filename); liquid-dsp-1.3.1/src/nco/tests/nco_crcf_frequency_autotest.c000066400000000000000000000075771317124540100242460ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "autotest/autotest.h" #include "liquid.h" // declare external arrays extern float complex nco_sincos_fsqrt1_2[]; extern float complex nco_sincos_fsqrt1_3[]; extern float complex nco_sincos_fsqrt1_5[]; extern float complex nco_sincos_fsqrt1_7[]; // autotest helper function // _type : NCO type (e.g. LIQUID_NCO) // _phase : initial phase // _frequency : initial frequency // _sincos : external sin/cosine data // _num_samples: number of samples to test // _tol : error tolerance void nco_crcf_frequency_test(int _type, float _phase, float _frequency, float complex * _sincos, unsigned int _num_samples, float _tol) { // create object nco_crcf nco = nco_crcf_create(_type); // set phase and frequency nco_crcf_set_phase(nco, _phase); nco_crcf_set_frequency(nco, _frequency); // run trials unsigned int i; for (i=0; i<_num_samples; i++) { // compute complex output float complex y_test; nco_crcf_cexpf(nco, &y_test); // compare to expected output float complex y = _sincos[i]; // run tests CONTEND_DELTA( crealf(y_test), crealf(y), _tol ); CONTEND_DELTA( cimagf(y_test), cimagf(y), _tol ); // step oscillator nco_crcf_step(nco); } // destroy object nco_crcf_destroy(nco); } // test floating point precision nco phase void autotest_nco_crcf_frequency() { // error tolerance (higher for NCO) float tol = 0.04f; // test frequencies with irrational values nco_crcf_frequency_test(LIQUID_NCO, 0.0f, 0.707106781186547, nco_sincos_fsqrt1_2, 256, tol); // 1/sqrt(2) nco_crcf_frequency_test(LIQUID_NCO, 0.0f, 0.577350269189626, nco_sincos_fsqrt1_3, 256, tol); // 1/sqrt(3) nco_crcf_frequency_test(LIQUID_NCO, 0.0f, 0.447213595499958, nco_sincos_fsqrt1_5, 256, tol); // 1/sqrt(5) nco_crcf_frequency_test(LIQUID_NCO, 0.0f, 0.377964473009227, nco_sincos_fsqrt1_7, 256, tol); // 1/sqrt(7) } // test floating point precision vco phase void autotest_vco_crcf_frequency() { // error tolerance float tol = 0.0001f; // test frequencies with irrational values nco_crcf_frequency_test(LIQUID_VCO, 0.0f, 0.707106781186547, nco_sincos_fsqrt1_2, 256, tol); // 1/sqrt(2) nco_crcf_frequency_test(LIQUID_VCO, 0.0f, 0.577350269189626, nco_sincos_fsqrt1_3, 256, tol); // 1/sqrt(3) nco_crcf_frequency_test(LIQUID_VCO, 0.0f, 0.447213595499958, nco_sincos_fsqrt1_5, 256, tol); // 1/sqrt(5) nco_crcf_frequency_test(LIQUID_VCO, 0.0f, 0.377964473009227, nco_sincos_fsqrt1_7, 256, tol); // 1/sqrt(7) } liquid-dsp-1.3.1/src/nco/tests/nco_crcf_phase_autotest.c000066400000000000000000000225531317124540100233340ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "autotest/autotest.h" #include "liquid.h" // autotest helper function // _theta : input phase // _cos : expected output: cos(_theta) // _sin : expected output: sin(_theta) // _type : NCO type (e.g. LIQUID_NCO) // _tol : error tolerance void nco_crcf_phase_test(float _theta, float _cos, float _sin, int _type, float _tol) { // create object nco_crcf nco = nco_crcf_create(_type); // set phase nco_crcf_set_phase(nco, _theta); // compute cosine and sine outputs float c = nco_crcf_cos(nco); float s = nco_crcf_sin(nco); // run tests CONTEND_DELTA( c, _cos, _tol ); CONTEND_DELTA( s, _sin, _tol ); // destroy object nco_crcf_destroy(nco); } // test floating point precision nco phase void autotest_nco_crcf_phase() { // error tolerance (higher for NCO) float tol = 0.02f; nco_crcf_phase_test(-6.283185307f, 1.000000000f, 0.000000000f, LIQUID_NCO, tol); nco_crcf_phase_test(-6.195739393f, 0.996179042f, 0.087334510f, LIQUID_NCO, tol); nco_crcf_phase_test(-5.951041106f, 0.945345356f, 0.326070787f, LIQUID_NCO, tol); nco_crcf_phase_test(-5.131745978f, 0.407173250f, 0.913350943f, LIQUID_NCO, tol); nco_crcf_phase_test(-4.748043551f, 0.035647016f, 0.999364443f, LIQUID_NCO, tol); nco_crcf_phase_test(-3.041191113f, -0.994963998f, -0.100232943f, LIQUID_NCO, tol); nco_crcf_phase_test(-1.947799864f, -0.368136099f, -0.929771914f, LIQUID_NCO, tol); nco_crcf_phase_test(-1.143752030f, 0.414182352f, -0.910193924f, LIQUID_NCO, tol); nco_crcf_phase_test(-1.029377689f, 0.515352252f, -0.856978446f, LIQUID_NCO, tol); nco_crcf_phase_test(-0.174356887f, 0.984838307f, -0.173474811f, LIQUID_NCO, tol); nco_crcf_phase_test(-0.114520496f, 0.993449692f, -0.114270338f, LIQUID_NCO, tol); nco_crcf_phase_test( 0.000000000f, 1.000000000f, 0.000000000f, LIQUID_NCO, tol); nco_crcf_phase_test( 1.436080000f, 0.134309213f, 0.990939471f, LIQUID_NCO, tol); nco_crcf_phase_test( 2.016119855f, -0.430749878f, 0.902471353f, LIQUID_NCO, tol); nco_crcf_phase_test( 2.996498473f, -0.989492293f, 0.144585621f, LIQUID_NCO, tol); nco_crcf_phase_test( 3.403689755f, -0.965848729f, -0.259106603f, LIQUID_NCO, tol); nco_crcf_phase_test( 3.591162483f, -0.900634128f, -0.434578148f, LIQUID_NCO, tol); nco_crcf_phase_test( 5.111428476f, 0.388533479f, -0.921434607f, LIQUID_NCO, tol); nco_crcf_phase_test( 5.727585681f, 0.849584319f, -0.527452828f, LIQUID_NCO, tol); nco_crcf_phase_test( 6.283185307f, 1.000000000f, -0.000000000f, LIQUID_NCO, tol); } // test floating point precision vco phase void autotest_vco_crcf_phase() { // error tolerance float tol = 0.0001f; nco_crcf_phase_test(-6.283185307f, 1.000000000f, 0.000000000f, LIQUID_VCO, tol); nco_crcf_phase_test(-6.195739393f, 0.996179042f, 0.087334510f, LIQUID_VCO, tol); nco_crcf_phase_test(-5.951041106f, 0.945345356f, 0.326070787f, LIQUID_VCO, tol); nco_crcf_phase_test(-5.131745978f, 0.407173250f, 0.913350943f, LIQUID_VCO, tol); nco_crcf_phase_test(-4.748043551f, 0.035647016f, 0.999364443f, LIQUID_VCO, tol); nco_crcf_phase_test(-3.041191113f, -0.994963998f, -0.100232943f, LIQUID_VCO, tol); nco_crcf_phase_test(-1.947799864f, -0.368136099f, -0.929771914f, LIQUID_VCO, tol); nco_crcf_phase_test(-1.143752030f, 0.414182352f, -0.910193924f, LIQUID_VCO, tol); nco_crcf_phase_test(-1.029377689f, 0.515352252f, -0.856978446f, LIQUID_VCO, tol); nco_crcf_phase_test(-0.174356887f, 0.984838307f, -0.173474811f, LIQUID_VCO, tol); nco_crcf_phase_test(-0.114520496f, 0.993449692f, -0.114270338f, LIQUID_VCO, tol); nco_crcf_phase_test( 0.000000000f, 1.000000000f, 0.000000000f, LIQUID_VCO, tol); nco_crcf_phase_test( 1.436080000f, 0.134309213f, 0.990939471f, LIQUID_VCO, tol); nco_crcf_phase_test( 2.016119855f, -0.430749878f, 0.902471353f, LIQUID_VCO, tol); nco_crcf_phase_test( 2.996498473f, -0.989492293f, 0.144585621f, LIQUID_VCO, tol); nco_crcf_phase_test( 3.403689755f, -0.965848729f, -0.259106603f, LIQUID_VCO, tol); nco_crcf_phase_test( 3.591162483f, -0.900634128f, -0.434578148f, LIQUID_VCO, tol); nco_crcf_phase_test( 5.111428476f, 0.388533479f, -0.921434607f, LIQUID_VCO, tol); nco_crcf_phase_test( 5.727585681f, 0.849584319f, -0.527452828f, LIQUID_VCO, tol); nco_crcf_phase_test( 6.283185307f, 1.000000000f, -0.000000000f, LIQUID_VCO, tol); } // // test floating point precision nco // void autotest_nco_basic() { nco_crcf p = nco_crcf_create(LIQUID_NCO); unsigned int i; // loop index float s, c; // sine/cosine result float tol=1e-4f; // error tolerance float f=0.0f; // frequency to test nco_crcf_set_phase( p, 0.0f); CONTEND_DELTA( nco_crcf_cos(p), 1.0f, tol ); CONTEND_DELTA( nco_crcf_sin(p), 0.0f, tol ); nco_crcf_sincos(p, &s, &c); CONTEND_DELTA( s, 0.0f, tol ); CONTEND_DELTA( c, 1.0f, tol ); nco_crcf_set_phase(p, M_PI/2); CONTEND_DELTA( nco_crcf_cos(p), 0.0f, tol ); CONTEND_DELTA( nco_crcf_sin(p), 1.0f, tol ); nco_crcf_sincos(p, &s, &c); CONTEND_DELTA( s, 1.0f, tol ); CONTEND_DELTA( c, 0.0f, tol ); // cycle through one full period in 64 steps nco_crcf_set_phase(p, 0.0f); f = 2.0f * M_PI / 64.0f; nco_crcf_set_frequency(p, f); for (i=0; i<128; i++) { nco_crcf_sincos(p, &s, &c); CONTEND_DELTA( s, sinf(i*f), tol ); CONTEND_DELTA( c, cosf(i*f), tol ); nco_crcf_step(p); } // double frequency: cycle through one full period in 32 steps nco_crcf_set_phase(p, 0.0f); f = 2.0f * M_PI / 32.0f; nco_crcf_set_frequency(p, f); for (i=0; i<128; i++) { nco_crcf_sincos(p, &s, &c); CONTEND_DELTA( s, sinf(i*f), tol ); CONTEND_DELTA( c, cosf(i*f), tol ); nco_crcf_step(p); } // destroy NCO object nco_crcf_destroy(p); } // // test nco mixing // void autotest_nco_mixing() { // frequency, phase float f = 0.1f; float phi = M_PI; // error tolerance (high for NCO) float tol = 0.05f; // initialize nco object nco_crcf p = nco_crcf_create(LIQUID_NCO); nco_crcf_set_frequency(p, f); nco_crcf_set_phase(p, phi); unsigned int i; float nco_i, nco_q; for (i=0; i<64; i++) { // generate sin/cos nco_crcf_sincos(p, &nco_q, &nco_i); // mix back to zero phase complex float nco_cplx_in = nco_i + _Complex_I*nco_q; complex float nco_cplx_out; nco_crcf_mix_down(p, nco_cplx_in, &nco_cplx_out); // assert mixer output is correct CONTEND_DELTA(crealf(nco_cplx_out), 1.0f, tol); CONTEND_DELTA(cimagf(nco_cplx_out), 0.0f, tol); //printf("%3u : %12.8f + j*%12.8f\n", i, crealf(nco_cplx_out), cimagf(nco_cplx_out)); // step nco nco_crcf_step(p); } // destroy NCO object nco_crcf_destroy(p); } // // test nco block mixing // void autotest_nco_block_mixing() { // frequency, phase float f = 0.1f; float phi = M_PI; // error tolerance (high for NCO) float tol = 0.05f; unsigned int i; // number of samples unsigned int num_samples = 1024; // store samples float complex * x = (float complex*)malloc(num_samples*sizeof(float complex)); float complex * y = (float complex*)malloc(num_samples*sizeof(float complex)); // generate complex sin/cos for (i=0; i 0) { unsigned int n = 7 < num_remaining ? 7 : num_remaining; nco_crcf_mix_block_down(p, &x[i], &y[i], n); i += n; num_remaining -= n; } // assert mixer output is correct for (i=0; i #include "autotest/autotest.h" #include "liquid.h" // // test phase-locked loop // _type : NCO type (e.g. LIQUID_NCO) // _phase_offset : initial phase offset // _freq_offset : initial frequency offset // _pll_bandwidth : bandwidth of phase-locked loop // _num_iterations : number of iterations to run // _tol : error tolerance void nco_crcf_pll_test(int _type, float _phase_offset, float _freq_offset, float _pll_bandwidth, unsigned int _num_iterations, float _tol) { // objects nco_crcf nco_tx = nco_crcf_create(_type); nco_crcf nco_rx = nco_crcf_create(_type); // initialize objects nco_crcf_set_phase(nco_tx, _phase_offset); nco_crcf_set_frequency(nco_tx, _freq_offset); nco_crcf_pll_set_bandwidth(nco_rx, _pll_bandwidth); // run loop unsigned int i; float phase_error; float complex r, v; for (i=0; i<_num_iterations; i++) { // received complex signal nco_crcf_cexpf(nco_tx,&r); nco_crcf_cexpf(nco_rx,&v); // error estimation phase_error = cargf(r*conjf(v)); // update pll nco_crcf_pll_step(nco_rx, phase_error); // update nco objects nco_crcf_step(nco_tx); nco_crcf_step(nco_rx); } // ensure phase of oscillators is locked float nco_tx_phase = nco_crcf_get_phase(nco_tx); float nco_rx_phase = nco_crcf_get_phase(nco_rx); CONTEND_DELTA(nco_tx_phase, nco_rx_phase, _tol); // ensure frequency of oscillators is locked float nco_tx_freq = nco_crcf_get_frequency(nco_tx); float nco_rx_freq = nco_crcf_get_frequency(nco_rx); CONTEND_DELTA(nco_tx_freq, nco_rx_freq, _tol); if (liquid_autotest_verbose) { printf(" phase error : %12.4e, frequency error : %12.4e\n", cargf( cexpf(_Complex_I*(nco_tx_phase-nco_rx_phase)) ), nco_tx_freq-nco_rx_freq); } // clean it up nco_crcf_destroy(nco_tx); nco_crcf_destroy(nco_rx); } // // AUTOTEST: test frequency and phase offsets // void autotest_vco_crcf_pll_phase() { float tol = 0.01f; // test various phase offsets nco_crcf_pll_test(LIQUID_NCO, -M_PI/1.1f, 0.0f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_NCO, -M_PI/2.0f, 0.0f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_NCO, -M_PI/4.0f, 0.0f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_NCO, -M_PI/8.0f, 0.0f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_NCO, M_PI/8.0f, 0.0f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_NCO, M_PI/4.0f, 0.0f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_NCO, M_PI/2.0f, 0.0f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_NCO, M_PI/1.1f, 0.0f, 0.1f, 256, tol); // test various frequency offsets nco_crcf_pll_test(LIQUID_NCO, 0.0f, -1.6f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_NCO, 0.0f, -0.8f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_NCO, 0.0f, -0.4f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_NCO, 0.0f, -0.2f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_NCO, 0.0f, 0.2f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_NCO, 0.0f, 0.4f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_NCO, 0.0f, 0.8f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_NCO, 0.0f, 1.6f, 0.1f, 256, tol); } // // AUTOTEST: test frequency and phase offsets // void autotest_nco_crcf_pll_phase() { float tol = 1e-4f; // test various phase offsets nco_crcf_pll_test(LIQUID_VCO, -M_PI/1.1f, 0.0f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_VCO, -M_PI/2.0f, 0.0f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_VCO, -M_PI/4.0f, 0.0f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_VCO, -M_PI/8.0f, 0.0f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_VCO, M_PI/8.0f, 0.0f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_VCO, M_PI/4.0f, 0.0f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_VCO, M_PI/2.0f, 0.0f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_VCO, M_PI/1.1f, 0.0f, 0.1f, 256, tol); // test various frequency offsets nco_crcf_pll_test(LIQUID_VCO, 0.0f, -1.6f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_VCO, 0.0f, -0.8f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_VCO, 0.0f, -0.4f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_VCO, 0.0f, -0.2f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_VCO, 0.0f, 0.2f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_VCO, 0.0f, 0.4f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_VCO, 0.0f, 0.8f, 0.1f, 256, tol); nco_crcf_pll_test(LIQUID_VCO, 0.0f, 1.6f, 0.1f, 256, tol); } liquid-dsp-1.3.1/src/nco/tests/unwrap_phase_autotest.c000066400000000000000000000040661317124540100230730ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "autotest/autotest.h" #include "liquid.h" // // AUTOTEST: regular phase-unwrapping // void autotest_nco_unwrap_phase() { unsigned int n=32; // number of steps float tol = 1e-6f; // error tolerance // initialize data arrays float phi[n]; // original array float theta[n]; // wrapped array float phi_hat[n]; // unwrapped array float phi0 = 3.0f; // initial phase float dphi = 0.1f; // phase step unsigned int i; for (i=0; i M_PI) theta[i] -= 2*M_PI; while (theta[i] < -M_PI) theta[i] += 2*M_PI; // initialize output phi_hat[i] = theta[i]; } // unwrap phase liquid_unwrap_phase(phi_hat, n); // compare input to output for (i=0; i #include #include #include #include "liquid.internal.h" #define LIQUID_CHROMOSOME_MAX_SIZE (32) // create chromosome with varying bits/trait // _bits_per_trait : array of bits/trait [size: _num_traits x 1] // _num_traits : number of traits in this chromosome chromosome chromosome_create(unsigned int * _bits_per_trait, unsigned int _num_traits) { chromosome q; q = (chromosome) malloc( sizeof(struct chromosome_s) ); q->num_traits = _num_traits; // validate input if (q->num_traits < 1) { fprintf(stderr,"error: chromosome_create(), must have at least one trait\n"); exit(1); } // initialize internal arrays q->bits_per_trait = (unsigned int *) malloc(q->num_traits*sizeof(unsigned int)); q->max_value = (unsigned long*) malloc(q->num_traits*sizeof(unsigned long)); q->traits = (unsigned long*) malloc(q->num_traits*sizeof(unsigned long)); // copy/initialize values unsigned int i; q->num_bits = 0; for (i=0; inum_traits; i++) { q->bits_per_trait[i] = _bits_per_trait[i]; if (q->bits_per_trait[i] > LIQUID_CHROMOSOME_MAX_SIZE) { fprintf(stderr,"error: chromosome_create(), bits/trait cannot exceed %u\n", LIQUID_CHROMOSOME_MAX_SIZE); exit(1); } q->max_value[i] = 1 << q->bits_per_trait[i]; q->traits[i] = 0; q->num_bits += q->bits_per_trait[i]; } return q; } // create basic chromosome // _num_traits : number of traits in this chromosome // _bits_per_trait : number of bits/trait for all traits chromosome chromosome_create_basic(unsigned int _num_traits, unsigned int _bits_per_trait) { // validate input if (_num_traits == 0) { fprintf(stderr,"error: chromosome_create_basic(), must have at least one trait\n"); exit(1); } unsigned int * bpt = (unsigned int *) malloc(_num_traits*sizeof(unsigned int)); unsigned int i; for (i=0; i<_num_traits; i++) bpt[i] = _bits_per_trait; // create chromosome chromosome q = chromosome_create(bpt, _num_traits); // free bits/trait array free(bpt); return q; } // create chromosome cloning a parent chromosome chromosome_create_clone(chromosome _parent) { // create chromosome chromosome q = chromosome_create(_parent->bits_per_trait, _parent->num_traits); // copy internal values chromosome_copy(_parent, q); return q; } // copy chromosome void chromosome_copy(chromosome _parent, chromosome _child) { // copy internal values unsigned int i; for (i=0; i<_parent->num_traits; i++) _child->traits[i] = _parent->traits[i]; } void chromosome_destroy(chromosome _q) { free(_q->bits_per_trait); free(_q->max_value); free(_q->traits); free(_q); } unsigned int chromosome_get_num_traits(chromosome _q) { return _q->num_traits; } void chromosome_print(chromosome _q) { unsigned int i,j; printf("chromosome: "); // print one bit at a time for (i=0; i<_q->num_traits; i++) { for (j=0; j<_q->bits_per_trait[i]; j++) { unsigned int bit = (_q->traits[i] >> (_q->bits_per_trait[i]-j-1) ) & 1; printf("%c", bit ? '1' : '0'); } if (i != _q->num_traits-1) printf("."); } printf("\n"); } void chromosome_printf(chromosome _q) { unsigned int i; printf("chromosome: "); for (i=0; i<_q->num_traits; i++) printf("%6.3f", chromosome_valuef(_q,i)); printf("\n"); } // clear chromosome (set traits to zero) void chromosome_reset(chromosome _q) { unsigned int i; for (i=0; i<_q->num_traits; i++) _q->traits[i] = 0; } // initialize chromosome on integer values void chromosome_init(chromosome _c, unsigned int * _v) { unsigned int i; for (i=0; i<_c->num_traits; i++) { if (_v[i] >= _c->max_value[i]) { fprintf(stderr,"error: chromosome_init(), value exceeds maximum\n"); exit(1); } _c->traits[i] = _v[i]; } } // initialize chromosome on floating-point values void chromosome_initf(chromosome _c, float * _v) { unsigned int i; for (i=0; i<_c->num_traits; i++) { if (_v[i] > 1.0f || _v[i] < 0.0f) { fprintf(stderr,"error: chromosome_initf(), value must be in [0,1]\n"); exit(1); } // quantize sample unsigned int N = 1 << _c->bits_per_trait[i]; _c->traits[i] = (unsigned int) floorf( _v[i] * N ); } } // mutate bit at _index void chromosome_mutate(chromosome _q, unsigned int _index) { if (_index >= _q->num_bits) { fprintf(stderr,"error: chromosome_mutate(), maximum index exceeded\n"); exit(1); } // search for unsigned int i; unsigned int t=0; for (i=0; i<_q->num_traits; i++) { unsigned int b = _q->bits_per_trait[i]; if (t == _index) { _q->traits[i] ^= (unsigned long)(1 << (b-1)); return; } else if (t > _index) { _q->traits[i-1] ^= (unsigned long)(1 << (t-_index-1)); return; } else { t += b; } } _q->traits[i-1] ^= (unsigned long)(1 << (t-_index-1)); } // crossover parent chromosomes and store in child // _p1 : first parent chromosome // _p2 : second parent chromosome // _q : child chromosome // _threshold : crossover point void chromosome_crossover(chromosome _p1, chromosome _p2, chromosome _q, unsigned int _threshold) { if (_threshold > _q->num_bits) { fprintf(stderr,"error: chromosome_crossover(), maximum index exceeded\n"); exit(1); } // TODO : validate input on all properties of _p1, _p2, and _q // find crossover point unsigned int i; unsigned int t=0; for (i=0; i<_q->num_traits; i++) { if (t >= _threshold) break; else t += _q->bits_per_trait[i]; // child gets first parent's traits up until // threshold is reached _q->traits[i] = _p1->traits[i]; } #if 0 printf(" crossover point : %u\n", i); printf(" accumulator : %u\n", t); printf(" remainder : %u\n", t - _threshold); #endif // determine if trait is split unsigned int rem = t - _threshold; if (rem > 0) { // split trait on remainder unsigned int b = _q->bits_per_trait[i-1]; unsigned int mask1 = ((1 << (b-rem)) - 1) << rem; unsigned int mask2 = ((1 << rem ) - 1); _q->traits[i-1] = (_p1->traits[i-1] & mask1) | (_p2->traits[i-1] & mask2); #if 0 printf(" b : %u\n", b); printf(" mask1 : %.8x\n", mask1); printf(" mask2 : %.8x\n", mask2); #endif } // finish crossover for ( ; i<_q->num_traits; i++) { // child gets second parent's traits beyond threshold _q->traits[i] = _p2->traits[i]; } } void chromosome_init_random(chromosome _q) { unsigned int i; for (i=0; i<_q->num_traits; i++) _q->traits[i] = rand() & (_q->max_value[i]-1); } float chromosome_valuef(chromosome _q, unsigned int _index) { if (_index > _q->num_traits) { fprintf(stderr,"error: chromosome_valuef(), trait index exceeded\n"); exit(1); } return (float) (_q->traits[_index]) / (float)(_q->max_value[_index] - 1); } unsigned int chromosome_value(chromosome _q, unsigned int _index) { if (_index > _q->num_traits) { fprintf(stderr,"error: chromosome_value(), trait index exceeded\n"); exit(1); } return _q->traits[_index]; } liquid-dsp-1.3.1/src/optim/src/gasearch.c000066400000000000000000000301161317124540100202150ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // gasearch.c // #include #include #include #include #include "liquid.internal.h" #define LIQUID_GA_SEARCH_MAX_POPULATION_SIZE (1024) #define LIQUID_GA_SEARCH_MAX_CHROMOSOME_SIZE (32) #define LIQUID_DEBUG_GA_SEARCH 0 // Create a simple gasearch object; parameters are specified internally // _utility : chromosome fitness utility function // _userdata : user data, void pointer passed to _utility() callback // _parent : initial population parent chromosome, governs precision, etc. // _minmax : search direction gasearch gasearch_create(gasearch_utility _utility, void * _userdata, chromosome _parent, int _minmax) { return gasearch_create_advanced(_utility, _userdata, _parent, _minmax, 16, // population size 0.02f); // mutation rate } // Create a gasearch object, specifying search parameters // _utility : chromosome fitness utility function // _userdata : user data, void pointer passed to _utility() callback // _parent : initial population parent chromosome, governs precision, etc. // _minmax : search direction // _population_size : number of chromosomes in population // _mutation_rate : probability of mutating chromosomes gasearch gasearch_create_advanced(gasearch_utility _utility, void * _userdata, chromosome _parent, int _minmax, unsigned int _population_size, float _mutation_rate) { gasearch ga; ga = (gasearch) malloc( sizeof(struct gasearch_s) ); if (_population_size > LIQUID_GA_SEARCH_MAX_POPULATION_SIZE) { fprintf(stderr,"error: gasearch_create(), population size exceeds maximum\n"); exit(1); } else if (_mutation_rate < 0.0f || _mutation_rate > 1.0f) { fprintf(stderr,"error: gasearch_create(), mutation rate must be in [0,1]\n"); exit(1); } // initialize public values ga->userdata = _userdata; ga->num_parameters = _parent->num_traits; ga->population_size = _population_size; ga->mutation_rate = _mutation_rate; ga->get_utility = _utility; ga->minimize = ( _minmax==LIQUID_OPTIM_MINIMIZE ) ? 1 : 0; ga->bits_per_chromosome = _parent->num_bits; // initialize selection size be be 25% of population, minimum of 2 ga->selection_size = ( ga->population_size >> 2 ) < 2 ? 2 : ga->population_size >> 2; // allocate internal arrays ga->population = (chromosome*) malloc( sizeof(chromosome)*(ga->population_size) ); ga->utility = (float*) calloc( sizeof(float), ga->population_size ); // create optimum chromosome (clone) ga->c = chromosome_create_clone(_parent); //printf("num_parameters: %d\n", ga->num_parameters); //printf("population_size: %d\n", ga->population_size); //printf("\nbits_per_chromosome: %d\n", ga->bits_per_chromosome); // create population unsigned int i; for (i=0; ipopulation_size; i++) ga->population[i] = chromosome_create_clone(_parent); // initialize population to random, preserving first chromosome for (i=1; ipopulation_size; i++) chromosome_init_random( ga->population[i] ); // evaluate population gasearch_evaluate(ga); // rank chromosomes gasearch_rank(ga); // set global utility optimum ga->utility_opt = ga->utility[0]; // return object return ga; } // destroy a gasearch object void gasearch_destroy(gasearch _g) { unsigned int i; for (i=0; i<_g->population_size; i++) chromosome_destroy( _g->population[i] ); free(_g->population); // destroy optimum chromosome chromosome_destroy(_g->c); free(_g->utility); free(_g); } // print search parameter internals void gasearch_print(gasearch _g) { printf("ga search :\n"); printf(" num traits : %u\n", _g->num_parameters); printf(" bits/chromosome : %u\n", _g->bits_per_chromosome); printf(" population size : %u\n", _g->population_size); printf(" selection size : %u\n", _g->selection_size); printf(" mutation rate : %12.8f\n", _g->mutation_rate); printf("population:\n"); unsigned int i; for (i=0; i<_g->population_size; i++) { printf("%4u: [%8.4f] ", i, _g->utility[i]); chromosome_printf( _g->population[i] ); } } // set population/selection size // _q : ga search object // _population_size : new population size (number of chromosomes) // _selection_size : selection size (number of parents for new generation) void gasearch_set_population_size(gasearch _g, unsigned int _population_size, unsigned int _selection_size) { // validate input if (_population_size < 2) { fprintf(stderr,"error: gasearch_set_population_size(), population must be at least 2\n"); exit(1); } else if (_selection_size == 0) { fprintf(stderr,"error: gasearch_set_population_size(), selection size must be greater than zero\n"); exit(1); } else if (_selection_size >= _population_size) { fprintf(stderr,"error: gasearch_set_population_size(), selection size must be less than population\n"); exit(1); } // re-size arrays _g->population = (chromosome*) realloc( _g->population, _population_size*sizeof(chromosome) ); _g->utility = (float*) realloc( _g->utility, _population_size*sizeof(float) ); // initialize new chromosomes (copies) if (_population_size > _g->population_size) { unsigned int i; unsigned int k = _g->population_size-1; // least optimal for (i=_g->population_size; i<_population_size; i++) { // clone chromosome, copying internal values _g->population[i] = chromosome_create_clone(_g->population[k]); // copy utility _g->utility[i] = _g->utility[k]; } } // set internal variables _g->population_size = _population_size; _g->selection_size = _selection_size; } // set mutation rate void gasearch_set_mutation_rate(gasearch _g, float _mutation_rate) { if (_mutation_rate < 0.0f || _mutation_rate > 1.0f) { fprintf(stderr,"error: gasearch_set_mutation_rate(), mutation rate must be in [0,1]\n"); exit(1); } _g->mutation_rate = _mutation_rate; } // Execute the search // _g : ga search object // _max_iterations : maximum number of iterations to run before bailing // _tarutility : target utility float gasearch_run(gasearch _g, unsigned int _max_iterations, float _tarutility) { unsigned int i=0; do { i++; gasearch_evolve(_g); } while ( optim_threshold_switch(_g->utility[0], _tarutility, _g->minimize) && i < _max_iterations); // return optimum utility return _g->utility_opt; } // iterate over one evolution of the search algorithm void gasearch_evolve(gasearch _g) { // Inject random chromosome at end chromosome_init_random(_g->population[_g->population_size-1]); // Crossover gasearch_crossover(_g); // Mutation gasearch_mutate(_g); // Evaluation gasearch_evaluate(_g); // Rank gasearch_rank(_g); if ( optim_threshold_switch(_g->utility_opt, _g->utility[0], _g->minimize) ) { // update optimum _g->utility_opt = _g->utility[0]; // copy optimum chromosome chromosome_copy(_g->population[0], _g->c); #if LIQUID_DEBUG_GA_SEARCH printf(" utility: %0.2E", _g->utility_opt); chromosome_printf(_g->c); #endif } } // get optimal chromosome // _g : ga search object // _c : output optimal chromosome // _utility_opt : fitness of _c void gasearch_getopt(gasearch _g, chromosome _c, float * _utility_opt) { // copy optimum chromosome chromosome_copy(_g->c, _c); // copy optimum utility *_utility_opt = _g->utility_opt; } // evaluate fitness of entire population void gasearch_evaluate(gasearch _g) { unsigned int i; for (i=0; i<_g->population_size; i++) _g->utility[i] = _g->get_utility(_g->userdata, _g->population[i]); } // crossover population void gasearch_crossover(gasearch _g) { chromosome p1, p2; // parental chromosomes chromosome c; // child chromosome unsigned int threshold; unsigned int i; for (i=_g->selection_size; i<_g->population_size; i++) { // ensure fittest member is used at least once as parent p1 = (i==_g->selection_size) ? _g->population[0] : _g->population[rand() % _g->selection_size]; p2 = _g->population[rand() % _g->selection_size]; threshold = rand() % _g->bits_per_chromosome; c = _g->population[i]; //printf(" gasearch_crossover, p1: %d, p2: %d, c: %d\n", p1, p2, c); chromosome_crossover(p1, p2, c, threshold); } } // mutate population void gasearch_mutate(gasearch _g) { unsigned int i; unsigned int index; // mutate all but first (best) chromosome //for (i=_g->selection_size; i<_g->population_size; i++) { for (i=1; i<_g->population_size; i++) { // generate random number and mutate if within mutation_rate range unsigned int num_mutations = 0; // force at least one mutation (otherwise nothing has changed) while ( randf() < _g->mutation_rate || num_mutations == 0) { // generate random mutation index index = rand() % _g->bits_per_chromosome; // mutate chromosome at index chromosome_mutate( _g->population[i], index ); // num_mutations++; if (num_mutations == _g->bits_per_chromosome) break; } } } // rank population by fitness void gasearch_rank(gasearch _g) { unsigned int i, j; float u_tmp; // temporary utility placeholder chromosome c_tmp; // temporary chromosome placeholder (pointer) for (i=0; i<_g->population_size; i++) { for (j=_g->population_size-1; j>i; j--) { if ( optim_threshold_switch(_g->utility[j], _g->utility[j-1], !(_g->minimize)) ) { // swap chromosome pointers c_tmp = _g->population[j]; _g->population[j] = _g->population[j-1]; _g->population[j-1] = c_tmp; // swap utility values u_tmp = _g->utility[j]; _g->utility[j] = _g->utility[j-1]; _g->utility[j-1] = u_tmp; } } } } liquid-dsp-1.3.1/src/optim/src/gradsearch.c000066400000000000000000000246401317124540100205500ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "liquid.internal.h" // gradient search algorithm (steepest descent) object struct gradsearch_s { float * v; // vector to optimize (externally allocated) unsigned int num_parameters;// ... float u; // utility at current position // properties float delta; // gradient approximation step size float alpha; // line search step size float * p; // gradient estimate float pnorm; // L2-norm of gradient estimate utility_function utility; // utility function pointer void * userdata; // object to optimize (user data) int direction; // search direction (minimize/maximimze utility) }; // create a gradient search object // _userdata : user data object pointer // _v : array of parameters to optimize // _num_parameters : array length (number of parameters to optimize) // _u : utility function pointer // _direction : search direction (e.g. LIQUID_OPTIM_MAXIMIZE) gradsearch gradsearch_create(void * _userdata, float * _v, unsigned int _num_parameters, utility_function _utility, int _direction) { gradsearch q = (gradsearch) malloc( sizeof(struct gradsearch_s) ); // set user-defined properties q->userdata = _userdata; q->v = _v; q->num_parameters = _num_parameters; q->utility = _utility; q->direction = _direction; // set internal properties // TODO : make these user-configurable properties q->delta = 1e-6f; // gradient approximation step size q->alpha = q->delta; // line search step size // allocate array for gradient estimate q->p = (float*) malloc(q->num_parameters*sizeof(float)); q->pnorm = 0.0f; q->u = 0.0f; return q; } void gradsearch_destroy(gradsearch _q) { // free gradient estimate array free(_q->p); // free main object memory free(_q); } // print status void gradsearch_print(gradsearch _q) { //printf("gradient search:\n"); printf("u=%12.4e ", _q->u); // utility #if 0 // enable more verbose output printf("|p|=%7.1e ", _q->pnorm); // norm(p) printf("del=%7.1e ", _q->delta); // delta #endif printf("step=%7.1e ", _q->alpha); // alpha (step size) unsigned int i; printf("{"); for (i=0; i<_q->num_parameters; i++) printf("%8.4f", _q->v[i]); printf("}\n"); } float gradsearch_step(gradsearch _q) { unsigned int i; // ensure norm(p) > 0, otherwise increase delta unsigned int n=20; for (i=0; iutility, _q->userdata, _q->v, _q->num_parameters, _q->delta, _q->p); // normalize gradient vector _q->pnorm = gradsearch_norm(_q->p, _q->num_parameters); if (_q->pnorm > 0.0f) { // try to keep delta about 1e-4 * pnorm if (1e-4f*_q->pnorm < _q->delta) _q->delta *= 0.90f; else if ( 1e-5f*_q->pnorm > _q->delta) _q->delta *= 1.10f; break; } else { // step size is too small to approximate gradient _q->delta *= 10.0f; } } if (i == n) { fprintf(stderr,"warning: gradsearch_step(), function ill-conditioned\n"); return _q->utility(_q->userdata, _q->v, _q->num_parameters); } // run line search _q->alpha = gradsearch_linesearch(_q->utility, _q->userdata, _q->direction, _q->num_parameters, _q->v, _q->p, _q->delta); // step in the negative direction of the gradient float dir = _q->direction == LIQUID_OPTIM_MINIMIZE ? 1.0f : -1.0f; for (i=0; i<_q->num_parameters; i++) _q->v[i] = _q->v[i] - dir*_q->alpha*_q->p[i]; // evaluate utility at current position _q->u = _q->utility(_q->userdata, _q->v, _q->num_parameters); // return utility return _q->u; } // batch execution of gradient search : run many steps and stop // when criteria are met float gradsearch_execute(gradsearch _q, unsigned int _max_iterations, float _target_utility) { int continue_running = 1; unsigned int num_iterations = 0; float u = 0.0f; while (continue_running) { // increment number of iterations num_iterations++; // step gradient search algorithm u = gradsearch_step(_q); // check exit criteria (any one of the following) // * maximum number of iterations met // * maximize utility and target exceeded // * minimize utility and target exceeded if ( (num_iterations >= _max_iterations ) || (_q->direction == LIQUID_OPTIM_MINIMIZE && u < _target_utility) || (_q->direction == LIQUID_OPTIM_MAXIMIZE && u > _target_utility) ) { continue_running = 0; } } // return final utility return u; } // // internal (generic functions) // // compute the gradient of a function at a particular point // _utility : user-defined function // _userdata : user-defined data object // _x : operating point, [size: _n x 1] // _n : dimensionality of search // _delta : step value for which to compute gradient // _gradient : resulting gradient void gradsearch_gradient(utility_function _utility, void * _userdata, float * _x, unsigned int _n, float _delta, float * _gradient) { // operating point for evaluation float x_prime[_n]; float u_prime; // evaluate function at current operating point float u0 = _utility(_userdata, _x, _n); unsigned int i; for (i=0; i<_n; i++) { // copy operating point memmove(x_prime, _x, _n*sizeof(float)); // increment test vector by delta along dimension 'i' x_prime[i] += _delta; // evaluate new utility u_prime = _utility(_userdata, x_prime, _n); // compute gradient estimate _gradient[i] = (u_prime - u0) / _delta; } } // execute line search; loosely solve: // // min|max phi(alpha) := f(_x - alpha*_p) // // and return best guess at alpha that achieves this // // _utility : user-defined function // _userdata : user-defined data object // _direction : search direction (e.g. LIQUID_OPTIM_MINIMIZE) // _n : dimensionality of search // _x : operating point, [size: _n x 1] // _p : normalized gradient, [size: _n x 1] // _alpha : initial step size float gradsearch_linesearch(utility_function _utility, void * _userdata, int _direction, unsigned int _n, float * _x, float * _p, float _alpha) { // evaluate utility at base point float u0 = _utility(_userdata, _x, _n); // initialize step size estimate float alpha = _alpha; // step direction float dir = _direction == LIQUID_OPTIM_MINIMIZE ? 1.0f : -1.0f; // test vector, TODO : dynamic allocation? float x_prime[_n]; // run line search int continue_running = 1; unsigned int num_iterations = 0; while (continue_running) { // increment iteration counter num_iterations++; // update evaluation point unsigned int i; for (i=0; i<_n; i++) x_prime[i] = _x[i] - dir*alpha*_p[i]; // compute utility for line search step float uls = _utility(_userdata, x_prime, _n); //printf(" linesearch %6u : alpha=%12.6f, u0=%12.8f, uls=%12.8f\n", num_iterations, alpha, u0, uls); // check exit criteria if ( (_direction == LIQUID_OPTIM_MINIMIZE && uls > u0) || (_direction == LIQUID_OPTIM_MAXIMIZE && uls < u0) ) { // compared this utility to previous; went too far. // backtrack step size and stop line search alpha *= 0.5f; continue_running = 0; } else if ( num_iterations >= 20 ) { // maximum number of iterations met: stop line search continue_running = 0; } else { // save new best estimate, increase step size, and continue u0 = uls; alpha *= 2.0f; } } return alpha; } // normalize vector, returning its l2-norm float gradsearch_norm(float * _v, unsigned int _n) { float vnorm = 0.0f; unsigned int i; for (i=0; i<_n; i++) vnorm += _v[i]*_v[i]; vnorm = sqrtf(vnorm); for (i=0; i<_n; i++) _v[i] /= vnorm; return vnorm; } liquid-dsp-1.3.1/src/optim/src/optim.common.c000066400000000000000000000046011317124540100210570ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // optim.common.c // #include #include #include "liquid.internal.h" // optimization threshold switch // _u0 : first utility // _u1 : second utility // _minimize : minimize flag // // returns: // (_u0 > _u1) if (_minimize == 1) // (_u0 < _u1) otherwise int optim_threshold_switch(float _u0, float _u1, int _minimize) { return _minimize ? _u0 > _u1 : _u0 < _u1; } // sort values by index // _v : input values [size: _len x 1] // _rank : output rank array (indices) [size: _len x 1] // _len : length of input array // _descending : descending/ascending void optim_sort(float *_v, unsigned int * _rank, unsigned int _len, int _descending) { unsigned int i, j, tmp_index; for (i=0; i<_len; i++) _rank[i] = i; for (i=0; i<_len; i++) { for (j=_len-1; j>i; j--) { //if (_v[_rank[j]]>_v[_rank[j-1]]) { if ( optim_threshold_switch(_v[_rank[j]], _v[_rank[j-1]], _descending) ) { // swap elements tmp_index = _rank[j]; _rank[j] = _rank[j-1]; _rank[j-1] = tmp_index; } } } } liquid-dsp-1.3.1/src/optim/src/optim.h000066400000000000000000000037551317124540100176060ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Optimization // #ifndef __LIQUID_OPTIM_H__ #define __LIQUID_OPTIM_H__ // optim pattern set (struct) struct optim_ps_s { float *x, *y; unsigned int nx, ny, np; unsigned int na; // num allocated }; typedef struct optim_ps_s * optim_ps; optim_ps optim_ps_create(unsigned int _nx, unsigned int _ny); void optim_ps_destroy(optim_ps _ps); void optim_ps_print(optim_ps _ps); void optim_ps_append_pattern(optim_ps _ps, float *_x, float *_y); void optim_ps_append_patterns(optim_ps _ps, float *_x, float *_y, unsigned int _np); void optim_ps_delete_pattern(optim_ps _ps, unsigned int _i); void optim_ps_clear(optim_ps _ps); void optim_ps_access(optim_ps _ps, unsigned int _i, float **_x, float **_y); typedef void(*optim_target_function)(float *_x, float *_y, void *_p); typedef float(*optim_obj_function)(optim_ps _ps, void *_p, optim_target_function _f); #endif // __LIQUID_OPTIM_H__ liquid-dsp-1.3.1/src/optim/src/qnsearch.c000066400000000000000000000200031317124540100202360ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include "liquid.internal.h" #define LIQUID_qnsearch_GAMMA_MIN 0.000001 qnsearch qnsearch_create(void * _userdata, float * _v, unsigned int _num_parameters, utility_function _u, int _minmax) { qnsearch q = (qnsearch) malloc( sizeof(struct qnsearch_s) ); // initialize public values q->delta = 1e-6f; //_delta; q->gamma = 1e-3f; //_gamma; q->dgamma = 0.99f; q->gamma_hat = q->gamma; q->userdata = _userdata; q->v = _v; q->num_parameters = _num_parameters; q->get_utility = _u; q->minimize = ( _minmax == LIQUID_OPTIM_MINIMIZE ) ? 1 : 0; // initialize internal memory arrays q->B = (float*) calloc( q->num_parameters*q->num_parameters, sizeof(float)); q->H = (float*) calloc( q->num_parameters*q->num_parameters, sizeof(float)); q->p = (float*) calloc( q->num_parameters, sizeof(float) ); q->gradient = (float*) calloc( q->num_parameters, sizeof(float) ); q->gradient0= (float*) calloc( q->num_parameters, sizeof(float) ); q->v_prime = (float*) calloc( q->num_parameters, sizeof(float) ); q->dv = (float*) calloc( q->num_parameters, sizeof(float) ); q->utility = q->get_utility(q->userdata, q->v, q->num_parameters); qnsearch_reset(q); return q; } void qnsearch_destroy(qnsearch _q) { free(_q->B); free(_q->H); free(_q->p); free(_q->gradient); free(_q->gradient0); free(_q->v_prime); free(_q->dv); free(_q); } void qnsearch_print(qnsearch _q) { printf("[%.3f] ", _q->utility); unsigned int i; for (i=0; i<_q->num_parameters; i++) printf("%.3f ", _q->v[i]); printf("\n"); } void qnsearch_reset(qnsearch _q) { _q->gamma_hat = _q->gamma; // set B to identity matrix unsigned int i,j,n=0; for (i=0; i<_q->num_parameters; i++) { for (j=0; j<_q->num_parameters; j++) { _q->B[n++] = (i==j) ? 1.0f : 0.0f; } } _q->utility = _q->get_utility(_q->userdata, _q->v, _q->num_parameters); } void qnsearch_step(qnsearch _q) { unsigned int i; unsigned int n = _q->num_parameters; // compute normalized gradient vector qnsearch_compute_gradient(_q); //qnsearch_normalize_gradient(_q); // TODO : perform line search to find optimal gamma // compute search direction #if 0 matrixf_mul(_q->B, n, n, _q->gradient, n, 1, _q->p, n, 1); for (i=0; i<_q->num_parameters; i++) _q->p[i] = -_q->p[i]; #else qnsearch_compute_Hessian(_q); matrixf_inv(_q->H, n, n); matrixf_mul(_q->H, n, n, _q->gradient, n, 1, _q->p, n, 1); #endif // compute step vector for (i=0; i<_q->num_parameters; i++) _q->dv[i] = -_q->gamma_hat * _q->p[i]; // apply change for (i=0; i<_q->num_parameters; i++) { _q->v[i] += _q->dv[i]; } // TODO update inverse Hessian approximation // store previous gradient memmove(_q->gradient0, _q->gradient, (_q->num_parameters)*sizeof(float)); // update utility float u_prime = _q->get_utility(_q->userdata, _q->v, _q->num_parameters); if (u_prime > _q->utility) { _q->gamma_hat *= 0.99f; } else { _q->gamma_hat *= 1.001f; } _q->utility = u_prime; } float qnsearch_run(qnsearch _q, unsigned int _max_iterations, float _target_utility) { unsigned int i=0; do { i++; qnsearch_step(_q); _q->utility = _q->get_utility(_q->userdata, _q->v, _q->num_parameters); } while ( optim_threshold_switch(_q->utility, _target_utility, _q->minimize) && i < _max_iterations); return _q->utility; } // // internal // // compute gradient void qnsearch_compute_gradient(qnsearch _q) { unsigned int i; float f_prime; // reset v_prime memmove(_q->v_prime, _q->v, (_q->num_parameters)*sizeof(float)); for (i=0; i<_q->num_parameters; i++) { _q->v_prime[i] += _q->delta; f_prime = _q->get_utility(_q->userdata, _q->v_prime, _q->num_parameters); _q->v_prime[i] -= _q->delta; _q->gradient[i] = (f_prime - _q->utility) / _q->delta; } } // normalize gradient vector to unity void qnsearch_normalize_gradient(qnsearch _q) { // normalize gradient float sig = 0.0f; unsigned int i; for (i=0; i<_q->num_parameters; i++) sig += _q->gradient[i] * _q->gradient[i]; sig = 1.0f / sqrtf(sig/(float)(_q->num_parameters)); for (i=0; i<_q->num_parameters; i++) _q->gradient[i] *= sig; } // compute Hessian void qnsearch_compute_Hessian(qnsearch _q) { unsigned int i, j; unsigned int n = _q->num_parameters; float f00, f01, f10, f11; float f0, f1, f2; float m0, m1; float delta = 1e-2f; // reset v_prime memmove(_q->v_prime, _q->v, (_q->num_parameters)*sizeof(float)); for (i=0; i<_q->num_parameters; i++) { //for (j=0; j<_q->num_parameters; j++) { for (j=0; j<=i; j++) { if (i==j) { _q->v_prime[i] = _q->v[i] - delta; f0 = _q->get_utility(_q->userdata, _q->v_prime, _q->num_parameters); _q->v_prime[i] = _q->v[i]; f1 = _q->get_utility(_q->userdata, _q->v_prime, _q->num_parameters); _q->v_prime[i] = _q->v[i] + delta; f2 = _q->get_utility(_q->userdata, _q->v_prime, _q->num_parameters); m0 = (f1 - f0) / delta; m1 = (f2 - f1) / delta; matrix_access(_q->H, n, n, i, j) = (m1 - m0) / delta; } else { // 0 0 _q->v_prime[i] = _q->v[i] - delta; _q->v_prime[j] = _q->v[j] - delta; f00 = _q->get_utility(_q->userdata, _q->v_prime, _q->num_parameters); // 0 1 _q->v_prime[i] = _q->v[i] - delta; _q->v_prime[j] = _q->v[j] + delta; f01 = _q->get_utility(_q->userdata, _q->v_prime, _q->num_parameters); // 1 0 _q->v_prime[i] = _q->v[i] + delta; _q->v_prime[j] = _q->v[j] - delta; f10 = _q->get_utility(_q->userdata, _q->v_prime, _q->num_parameters); // 1 1 _q->v_prime[i] = _q->v[i] + delta; _q->v_prime[j] = _q->v[j] + delta; f11 = _q->get_utility(_q->userdata, _q->v_prime, _q->num_parameters); // compute second partial derivative m0 = (f01 - f00) / (2.0f*delta); m1 = (f11 - f10) / (2.0f*delta); matrix_access(_q->H, n, n, i, j) = (m1 - m0) / (2.0f*delta); matrix_access(_q->H, n, n, j, i) = (m1 - m0) / (2.0f*delta); } } } //matrixf_print(_q->H, n, n); //exit(1); } liquid-dsp-1.3.1/src/optim/src/utilities.c000066400000000000000000000103401317124540100204500ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // utilities.c : n-dimensional utility functions // #include #include #include #include "liquid.internal.h" // n-dimensional Rosenbrock utility function, minimum at _v = {1,1,1...} float liquid_rosenbrock(void * _userdata, float * _v, unsigned int _n) { if (_n == 0) { fprintf(stderr,"error: liquid_rosenbrock(), input vector length cannot be zero\n"); exit(1); } else if (_n == 1) { return (1.0f-_v[0])*(1.0f-_v[0]); } float u=0.0f; unsigned int i; for (i=0; i<_n-1; i++) u += powf(1-_v[i],2) + 100*powf( _v[i+1] - powf(_v[i],2), 2); return u; } // n-dimensional inverse Gauss utility function (minimum at _v = {1,1,1...} // _userdata : user-defined data structure (convenience) // _v : input vector [size: _n x 1] // _n : input vector size float liquid_invgauss(void * _userdata, float * _v, unsigned int _n) { if (_n == 0) { fprintf(stderr,"error: liquid_invgauss(), input vector length cannot be zero\n"); exit(1); } float t = 0.0f; float sigma = 1.0f; unsigned int i; for (i=0; i<_n; i++) { t += (_v[i]-1.0f)*(_v[i]-1.0f) / (sigma*sigma); // increase variance along this dimension sigma *= 1.5f; } return 1 - expf(-t); } // n-dimensional multimodal utility function (minimum at _v = {0,0,0...} // _userdata : user-defined data structure (convenience) // _v : input vector [size: _n x 1] // _n : input vector size float liquid_multimodal(void * _userdata, float * _v, unsigned int _n) { if (_n == 0) { fprintf(stderr,"error: liquid_multimodal(), input vector length cannot be zero\n"); exit(1); } float t0 = 1.0f; float t1 = 0.0f; float sigma = 4.0f; unsigned int i; for (i=0; i<_n; i++) { t0 *= 0.5f + 0.5f*cosf(2*M_PI*_v[i]); t1 += _v[i]*_v[i] / (sigma*sigma); } //t0 = powf(t0, 1.0f / (float)_n); return 1.0f - t0*expf(-t1); } // n-dimensional spiral utility function (minimum at _v = {0,0,0...} // _userdata : user-defined data structure (convenience) // _v : input vector [size: _n x 1] // _n : input vector size float liquid_spiral(void * _userdata, float * _v, unsigned int _n) { if (_n == 0) { fprintf(stderr,"error: liquid_rosenbrock(), input vector length cannot be zero\n"); exit(1); } else if (_n == 1) { return _v[0]*_v[0]; } // n is at least 2 float r_hat = sqrtf(_v[0]*_v[0] + _v[1]*_v[1]); float theta_hat = atan2f(_v[1], _v[0]); float delta = theta_hat - r_hat * 10; while (delta > M_PI) delta -= 2*M_PI; while (delta < -M_PI) delta += 2*M_PI; delta = delta / M_PI; float u = 1 - delta*delta*expf(-r_hat*r_hat/10); // additional error... unsigned int i; for (i=2; i<_n; i++) u += _v[i]*_v[i]; return u; } liquid-dsp-1.3.1/src/optim/tests/000077500000000000000000000000001317124540100166465ustar00rootroot00000000000000liquid-dsp-1.3.1/src/optim/tests/gradsearch_autotest.c000066400000000000000000000117271317124540100230550ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.h" #include #include #include #include #include #include "liquid.h" // // AUTOTEST: Find minimum of Rosenbrock function, should be [1 1 1 ...] // void autotest_gradsearch_rosenbrock() { float tol = 1e-2f; // error tolerance unsigned int num_parameters = 6; // dimensionality of search (minimum 2) unsigned int num_iterations = 4000; // number of iterations to run // initialize vector for optimization float v_opt[num_parameters]; unsigned int i; for (i=0; i #include "liquid.h" // void benchmark_compress_mulaw( struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { unsigned long int i; float x = -0.1f; float mu = 255.0f; float y = 0.0f; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { y += compress_mulaw(x,mu); y -= compress_mulaw(x,mu); x += compress_mulaw(y,mu); x -= compress_mulaw(y,mu); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; } // void benchmark_expand_mulaw( struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { unsigned long int i; float x = 0.0f; float mu = 255.0f; float y = 0.75f; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { x += expand_mulaw(y,mu); x -= expand_mulaw(y,mu); y += expand_mulaw(x,mu); y -= expand_mulaw(x,mu); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; } liquid-dsp-1.3.1/src/quantization/bench/quantizer_benchmark.c000066400000000000000000000045341317124540100243670ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // void benchmark_quantize_adc(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations) { unsigned long int i; unsigned int q = 0; unsigned int num_bits=8; float x=-0.1f; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { q ^= quantize_adc(x,num_bits); q ^= quantize_adc(x,num_bits); q ^= quantize_adc(x,num_bits); q ^= quantize_adc(x,num_bits); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; } // void benchmark_quantize_dac(struct rusage * _start, struct rusage * _finish, unsigned long int * _num_iterations) { unsigned long int i; unsigned int q=0x0f; unsigned int num_bits=8; float x = 0; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { x += quantize_dac(q,num_bits); x += quantize_dac(q,num_bits); x += quantize_dac(q,num_bits); x += quantize_dac(q,num_bits); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; } liquid-dsp-1.3.1/src/quantization/src/000077500000000000000000000000001317124540100176715ustar00rootroot00000000000000liquid-dsp-1.3.1/src/quantization/src/compand.c000066400000000000000000000047041317124540100214630ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // // #include #include #include #include "liquid.internal.h" #define LIQUID_VALIDATE_INPUT float compress_mulaw(float _x, float _mu) { #ifdef LIQUID_VALIDATE_INPUT if ( _mu <= 0.0f ) { printf("error: compress_mulaw(), mu out of range\n"); exit(1); } #endif float y = logf(1 + _mu*fabsf(_x)) / logf(1 + _mu); return copysignf(y, _x); } float expand_mulaw(float _y, float _mu) { #ifdef LIQUID_VALIDATE_INPUT if ( _mu <= 0.0f ) { printf("error: expand_mulaw(), mu out of range\n"); exit(1); } #endif float x = (1/_mu)*( powf(1+_mu,fabsf(_y)) - 1); return copysign(x, _y); } void compress_cf_mulaw(float complex _x, float _mu, float complex * _y) { #ifdef LIQUID_VALIDATE_INPUT if ( _mu <= 0.0f ) { printf("error: compress_mulaw(), mu out of range\n"); exit(1); } #endif *_y = cexpf(_Complex_I*cargf(_x)) * logf(1 + _mu*cabsf(_x)) / logf(1 + _mu); } void expand_cf_mulaw(float complex _y, float _mu, float complex * _x) { #ifdef LIQUID_VALIDATE_INPUT if ( _mu <= 0.0f ) { printf("error: expand_mulaw(), mu out of range\n"); exit(1); } #endif *_x = cexpf(_Complex_I*cargf(_y)) * (1/_mu)*( powf(1+_mu,cabsf(_y)) - 1); } /* float compress_alaw(float _x, float _a) { } float expand_alaw(float _x, float _a) { } */ liquid-dsp-1.3.1/src/quantization/src/quantizer.c000066400000000000000000000056621317124540100220700ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // structured quantizer // #include #include struct QUANTIZER(_s) { int ctype; // compander type unsigned int n; // number of bits // table? }; // create quantizer object // _ctype : compander type (e.g. LIQUID_COMPANDER_LINEAR) // _range : maximum absolute input // _num_bits : number of bits per sample QUANTIZER() QUANTIZER(_create)(liquid_compander_type _ctype, float _range, unsigned int _num_bits) { // validate input if (_num_bits == 0) { fprintf(stderr,"error: quantizer_create(), must have at least one bit/sample\n"); exit(1); } // create quantizer object QUANTIZER() q = (QUANTIZER()) malloc(sizeof(struct QUANTIZER(_s))); // initialize values q->ctype = _ctype; q->n = _num_bits; // return object return q; } void QUANTIZER(_destroy)(QUANTIZER() _q) { // free main object memory free(_q); } void QUANTIZER(_print)(QUANTIZER() _q) { printf("quantizer:\n"); printf(" compander : "); switch(_q->ctype) { case LIQUID_COMPANDER_NONE: printf("none\n"); break; case LIQUID_COMPANDER_LINEAR: printf("linear\n"); break; case LIQUID_COMPANDER_MULAW: printf("mu-law\n"); break; case LIQUID_COMPANDER_ALAW: printf("A-law\n"); break; default: printf("unknown\n"); } printf(" num bits : %u\n", _q->n); } void QUANTIZER(_execute_adc)(QUANTIZER() _q, T _x, unsigned int * _sample) { #if T_COMPLEX #else #endif *_sample = 0; } void QUANTIZER(_execute_dac)(QUANTIZER() _q, unsigned int _sample, T * _x) { #if T_COMPLEX #else #endif *_x = 0.0; } liquid-dsp-1.3.1/src/quantization/src/quantizer.inline.c000066400000000000000000000045251317124540100233420ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // // #include #include #include #include "liquid.internal.h" #define LIQUID_VALIDATE_INPUT #define QUANTIZER_MAX_BITS 32 // inline quantizer: 'analog' signal in [-1, 1] unsigned int quantize_adc(float _x, unsigned int _num_bits) { #ifdef LIQUID_VALIDATE_INPUT if (_num_bits > QUANTIZER_MAX_BITS) { printf("error: quantize_adc(), maximum bits exceeded\n"); exit(1); } #endif if (_num_bits == 0) return 0; unsigned int n = _num_bits-1; // unsigned int N = 1<= N) r = N-1; // if negative set MSB to 1 if (neg) r |= N; return r; } float quantize_dac(unsigned int _s, unsigned int _num_bits) { #ifdef LIQUID_VALIDATE_INPUT if (_num_bits > QUANTIZER_MAX_BITS) { printf("error: quantize_dac(), maximum bits exceeded\n"); exit(1); } #endif if (_num_bits == 0) return 0.0f; unsigned int n = _num_bits-1; // unsigned int N = 1< %8.4f -> %8.4f\n", x, y, x_hat); CONTEND_DELTA(x,x_hat,tol); x += dx; x = (x > 1.0f) ? 1.0f : x; } } void autotest_compand_cfloat() { float complex x = -0.707f - 0.707f*_Complex_I; float mu=255.0f; unsigned int n=30; float complex dx = 2*(0.707f +0.707f* _Complex_I)/(float)(n); float complex y; float complex z; float tol = 1e-6f; unsigned int i; for (i=0; i ", crealf(x), cimagf(x)); printf("%8.4f +j%8.4f > ", crealf(y), cimagf(y)); printf("%8.4f +j%8.4f\n", crealf(z), cimagf(z)); } CONTEND_DELTA(crealf(x),crealf(z),tol); CONTEND_DELTA(cimagf(x),cimagf(z),tol); x += dx; //x = (x > 1.0f) ? 1.0f : x; } } liquid-dsp-1.3.1/src/quantization/tests/quantize_autotest.c000066400000000000000000000035771317124540100242140ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.internal.h" void autotest_quantize_float_n8() { float x = -1.0f; unsigned int num_steps=30; unsigned int num_bits=8; float dx = 2/(float)(num_steps); unsigned int q; float x_hat; float tol = 1.0f / (float)(1<>num_bits, 0); x_hat = quantize_dac(q,num_bits); if (liquid_autotest_verbose) printf("%8.4f > 0x%2.2x > %8.4f\n", x, q, x_hat); // ensure original value is recovered withing tolerance CONTEND_DELTA(x,x_hat,tol); x += dx; x = (x > 1.0f) ? 1.0f : x; } } liquid-dsp-1.3.1/src/random/000077500000000000000000000000001317124540100156345ustar00rootroot00000000000000liquid-dsp-1.3.1/src/random/bench/000077500000000000000000000000001317124540100167135ustar00rootroot00000000000000liquid-dsp-1.3.1/src/random/bench/random_benchmark.c000066400000000000000000000103301317124540100223460ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // // BENCHMARK: uniform // void benchmark_random_uniform(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { // normalize number of iterations *_num_iterations *= 10; float x = 0.0f; unsigned long int i; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { x += randf(); x += randf(); x += randf(); x += randf(); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; } // // BENCHMARK: normal // void benchmark_random_normal(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { // normalize number of iterations *_num_iterations *= 1; float x = 0.0f; unsigned long int i; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { x += randnf(); x += randnf(); x += randnf(); x += randnf(); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; } // // BENCHMARK: complex normal // void benchmark_random_complex_normal(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { // normalize number of iterations *_num_iterations /= 2; float complex x = 0.0f; unsigned long int i; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { crandnf(&x); crandnf(&x); crandnf(&x); crandnf(&x); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; } // // BENCHMARK: Weibull // void benchmark_random_weibull(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { // normalize number of iterations *_num_iterations *= 2; float x=0.0f; float alpha=1.0f; float beta=2.0f; float gamma=6.0f; unsigned long int i; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { x += randweibf(alpha,beta,gamma); x += randweibf(alpha,beta,gamma); x += randweibf(alpha,beta,gamma); x += randweibf(alpha,beta,gamma); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; } // // BENCHMARK: Rice-K // void benchmark_random_ricek(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations) { // normalize number of iterations *_num_iterations /= 3; float x = 0.0f; float K=2.0f; float omega=1.0f; unsigned long int i; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { x += randricekf(K,omega); x += randricekf(K,omega); x += randricekf(K,omega); x += randricekf(K,omega); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; } liquid-dsp-1.3.1/src/random/src/000077500000000000000000000000001317124540100164235ustar00rootroot00000000000000liquid-dsp-1.3.1/src/random/src/rand.c000066400000000000000000000032221317124540100175120ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Uniform random number generator definitions // #include #include #include #include "liquid.internal.h" // uniform random number generator float randf() { return randf_inline(); } // uniform random number probability distribution function float randf_pdf(float _x) { return (_x < 0.0f || _x > 1.0f) ? 0.0f : 1.0f; } // uniform random number cumulative distribution function float randf_cdf(float _x) { if (_x < 0.0f) return 0.0f; else if (_x > 1.0f) return 1.0f; return _x; } liquid-dsp-1.3.1/src/random/src/randexp.c000066400000000000000000000045201317124540100202310ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Exponential distribution // #include #include #include #include "liquid.internal.h" // Exponential float randexpf(float _lambda) { // validate input if (_lambda <= 0) { fprintf(stderr,"error: randexpf(), lambda must be greater than zero\n"); return 0.0f; } // compute a non-zero uniform random variable in (0,1] float u; do { u = randf(); } while (u==0.0f); // perform variable transformation return -logf( u ) / _lambda; } // Exponential random number probability distribution function float randexpf_pdf(float _x, float _lambda) { // validate input if (_lambda <= 0) { fprintf(stderr,"error: randexpf(), lambda must be greater than zero\n"); return 0.0f; } if (_x < 0.0f) return 0.0f; return _lambda * expf(-_lambda*_x); } // Exponential random number cumulative distribution function float randexpf_cdf(float _x, float _lambda) { // validate input if (_lambda <= 0) { fprintf(stderr,"error: randexpf(), lambda must be greater than zero\n"); return 0.0f; } if (_x < 0.0f) return 0.0f; return 1.0f - expf(-_lambda*_x); } liquid-dsp-1.3.1/src/random/src/randgamma.c000066400000000000000000000111541317124540100205200ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Gamma distribution // #include #include #include #include "liquid.internal.h" float randgammaf(float _alpha, float _beta) { // validate input if (_alpha <= 0.0f) { fprintf(stderr,"error: randgammaf(), alpha must be greater than zero\n"); exit(1); } else if (_beta <= 0.0f) { fprintf(stderr,"error: randgammaf(), beta must be greater than zero\n"); exit(1); } unsigned int n = (unsigned int) floorf(_alpha); // residual float delta = _alpha - (float)n; // generate x' ~ Gamma(n,1) float x_n = 0.0f; unsigned int i; for (i=0; i 0 // b = beta, b > 0 // Gamma(z) = regular gamma function // x >= 0 float randgammaf_pdf(float _x, float _alpha, float _beta) { // validate input if (_alpha <= 0.0f) { fprintf(stderr,"error: randgammaf_pdf(), alpha must be greater than zero\n"); exit(1); } else if (_beta <= 0.0f) { fprintf(stderr,"error: randgammaf_pdf(), beta must be greater than zero\n"); exit(1); } if (_x <= 0.0f) return 0.0f; float t0 = powf(_x, _alpha-1.0f); float t1 = expf(-_x / _beta); float t2 = liquid_gammaf(_alpha); float t3 = powf(_beta, _alpha); return (t0*t1)/(t2*t3); } // Gamma distribution cumulative distribution function // F(x) = gamma(a,x/b) / Gamma(a) // where // a = alpha, alpha > 0 // b = beta, beta > 0 // gamma(a,z) = lower incomplete gamma function // Gamma(z) = regular gamma function // float randgammaf_cdf(float _x, float _alpha, float _beta) { // validate input if (_alpha <= 0.0f) { fprintf(stderr,"error: randgammaf_cdf(), alpha must be greater than zero\n"); exit(1); } else if (_beta <= 0.0f) { fprintf(stderr,"error: randgammaf_cdf(), beta must be greater than zero\n"); exit(1); } if (_x <= 0.0f) return 0.0f; return liquid_lowergammaf(_alpha, _x/_beta) / liquid_gammaf(_alpha); } // // internal methods // // generate x ~ Gamma(delta,1) float randgammaf_delta(float _delta) { // validate input if ( _delta < 0.0f || _delta >= 1.0f ) { fprintf(stderr,"error: randgammaf_delta(), delta must be in [0,1)\n"); exit(1); } // initialization float delta_inv = 1.0f / _delta; float e = expf(1.0f); float v0 = e / (e + _delta); float V0 = 0.0f; float V1 = 0.0f; float V2 = 0.0f; unsigned int m = 1; float xi = 0.0f; float eta = 0.0f; while (1) { // step 2 V0 = randf(); V1 = randf(); V2 = randf(); if (V2 <= v0) { // step 4 xi = powf(V1, delta_inv); eta = V0 * powf(xi, _delta - 1.0f); } else { // step 5 xi = 1.0f - logf(V1); eta = V0 * expf(-xi); } // step 6 if ( eta > powf(xi,_delta-1.0f)*expf(-xi) ) { m++; } else { break; } } // xi ~ Gamma(delta,1) return xi; } liquid-dsp-1.3.1/src/random/src/randn.c000066400000000000000000000052431317124540100176750ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // // #include #include #include #include "liquid.internal.h" // Gauss float randnf() { // generate two uniform random numbers float u1, u2; // ensure u1 does not equal zero do { u1 = randf(); } while (u1 == 0.0f); u2 = randf(); return sqrtf(-2*logf(u1)) * sinf(2*M_PI*u2); //return sqrtf(-2*logf(u1)) * cosf(2*M_PI*u2); } void awgn(float *_x, float _nstd) { *_x += randnf()*_nstd; } // Complex Gauss void crandnf(float complex * _y) { // generate two uniform random numbers float u1, u2; // ensure u1 does not equal zero do { u1 = randf(); } while (u1 == 0.0f); u2 = randf(); *_y = sqrtf(-2*logf(u1)) * cexpf(_Complex_I*2*M_PI*u2); } // Internal complex Gauss (inline) float complex icrandnf() { float complex y; crandnf(&y); return y; } void cawgn(float complex *_x, float _nstd) { *_x += icrandnf()*_nstd*0.707106781186547f; } // Gauss random number probability distribution function float randnf_pdf(float _x, float _eta, float _sig) { // validate input if (_sig <= 0.0f) { fprintf(stderr,"error: randnf_pdf(), standard deviation must be greater than zero\n"); exit(1); } float t = _x - _eta; float s2 = _sig * _sig; return expf(-t*t/(2.0f*s2)) / sqrtf(2.0f*M_PI*s2); } // Gauss random number cumulative distribution function float randnf_cdf(float _x, float _eta, float _sig) { return 0.5 + 0.5*erff( M_SQRT1_2*(_x-_eta)/_sig ); } liquid-dsp-1.3.1/src/random/src/randnakm.c000066400000000000000000000065741317124540100203760ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Nakagami-m distribution // #include #include #include #include "liquid.internal.h" float randnakmf(float _m, float _omega) { // validate input if (_m < 0.5f) { fprintf(stderr,"error: randnakmf(), m cannot be less than 0.5\n"); exit(1); } else if (_omega <= 0.0f) { fprintf(stderr,"error: randnakmf(), omega must be greater than zero\n"); exit(1); } // generate Gamma random variable float alpha = _m; float beta = _omega / _m; float x = randgammaf(alpha,beta); // sqrt(x) ~ Nakagami(m,omega) return sqrtf(x); } // Nakagami-m distribution probability distribution function // Nakagami-m // f(x) = (2/Gamma(m)) (m/omega)^m x^(2m-1) exp{-(m/omega)x^2} // where // m : shape parameter, m >= 0.5 // omega : spread parameter, omega > 0 // Gamma(z): regular complete gamma function // x >= 0 float randnakmf_pdf(float _x, float _m, float _omega) { // validate input if (_m < 0.5f) { fprintf(stderr,"error: randnakmf_pdf(), m cannot be less than 0.5\n"); exit(1); } else if (_omega <= 0.0f) { fprintf(stderr,"error: randnakmf_pdf(), omega must be greater than zero\n"); exit(1); } if (_x <= 0.0f) return 0.0f; float t0 = liquid_lngammaf(_m); float t1 = _m * logf(_m/_omega); float t2 = (2*_m - 1.0f) * logf(_x); float t3 = -(_m/_omega)*_x*_x; return 2.0f * expf( -t0 + t1 + t2 + t3 ); } // Nakagami-m distribution cumulative distribution function // F(x) = gamma(m, x^2 m / omega) / Gamma(m) // where // gamma(z,a) = lower incomplete gamma function // Gamma(z) = regular gamma function // float randnakmf_cdf(float _x, float _m, float _omega) { // validate input if (_m < 0.5f) { fprintf(stderr,"error: randnakmf_cdf(), m cannot be less than 0.5\n"); exit(1); } else if (_omega <= 0.0f) { fprintf(stderr,"error: randnakmf_cdf(), omega must be greater than zero\n"); exit(1); } if (_x <= 0.0f) return 0.0f; float t0 = liquid_lnlowergammaf(_m, _x*_x*_m/_omega); float t1 = liquid_lngammaf(_m); return expf( t0 - t1 ); } liquid-dsp-1.3.1/src/random/src/randricek.c000066400000000000000000000062371317124540100205410ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Rice-K distribution // #include #include #include #include "liquid.internal.h" // Rice-K float randricekf(float _K, float _omega) { float complex x, y; float s = sqrtf((_omega*_K)/(_K+1)); float sig = sqrtf(0.5f*_omega/(_K+1)); crandnf(&x); y = _Complex_I*( crealf(x)*sig + s ) + ( cimagf(x)*sig ); return cabsf(y); } // Rice-K random number probability distribution function // f(x) = (x/sigma^2) exp{ -(x^2+s^2)/(2sigma^2) } I0( x s / sigma^2 ) // where // s = sqrt( omega*K/(K+1) ) // sigma = sqrt(0.5 omega/(K+1)) // and // K = shape parameter // omega = spread parameter // I0 = modified Bessel function of the first kind // x >= 0 float randricekf_pdf(float _x, float _K, float _omega) { if (_x < 0.0f) return 0.0f; float s = sqrtf((_omega*_K)/(_K+1)); float sig = sqrtf(0.5f*_omega/(_K+1)); float t = _x*_x + s*s; float sig2 = sig*sig; // check high tail condition if ( (_x*s/sig2) > 80.0f ) return 0.0f; float t0 = logf(_x) - logf(sig2); float t1 = -t / (2*sig2); float t2 = liquid_lnbesselif(0.0f, _x*s/sig2); return expf(t0 + t1 + t2); //return (_x / sig2) * expf(-t / (2*sig2)) * liquid_besseli0f(_x*s/sig2); } // Rice-K random number cumulative distribution function float randricekf_cdf(float _x, float _K, float _omega) { if (_x <= 0.0f) return 0.0f; float s = sqrtf((_omega*_K)/(_K+1)); float sig = sqrtf(0.5f*_omega/(_K+1)); // test arguments of Q1 function float alpha = s/sig; float beta = _x/sig; //float Q1 = liquid_MarcumQ1f(alpha, beta); //printf(" Q1(%12.4e, %12.4e) = %12.4e\n", alpha, beta, Q1); if ( (alpha / beta) > 3.0f ) return 0.0f; if ( (beta / alpha) > 3.0f ) return 1.0f; float F = 1.0f - liquid_MarcumQ1f(alpha, beta); // check for precision error if (F < 0.0f) return 0.0f; if (F > 1.0f) return 1.0f; return F; } liquid-dsp-1.3.1/src/random/src/randweib.c000066400000000000000000000057741317124540100203770ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Weibull distribution // #include #include #include #include "liquid.internal.h" // Weibull float randweibf(float _alpha, float _beta, float _gamma) { // validate input if (_alpha <= 0) { fprintf(stderr,"error: randweibf(), alpha must be greater than zero\n"); return 0.0f; } else if (_beta <= 0) { fprintf(stderr,"error: randweibf(), beta must be greater than zero\n"); return 0.0f; } float u; do { u = randf(); } while (u==0.0f); return _gamma + _beta*powf( -logf(u), 1.0f/_alpha ); } // Weibull random number probability distribution function float randweibf_pdf(float _x, float _alpha, float _beta, float _gamma) { #ifdef LIQUID_VALIDATE_INPUT // validate input if (_alpha <= 0) { fprintf(stderr,"error: randweibf_pdf(), alpha must be greater than zero\n"); return 0.0f; } else if (_beta <= 0) { fprintf(stderr,"error: randweibf_pdf(), beta must be greater than zero\n"); return 0.0f; } #endif if (_x < _gamma) return 0.0f; float t = _x - _gamma; return (_alpha/_beta) * powf(t/_beta, _alpha-1.0f) * expf( -powf(t/_beta, _alpha) ); } // Weibull random number cumulative distribution function float randweibf_cdf(float _x, float _alpha, float _beta, float _gamma) { #ifdef LIQUID_VALIDATE_INPUT // validate input if (_alpha <= 0) { fprintf(stderr,"error: randweibf_cdf(), alpha must be greater than zero\n"); return 0.0f; } else if (_beta <= 0) { fprintf(stderr,"error: randweibf_cdf(), beta must be greater than zero\n"); return 0.0f; } #endif if (_x <= _gamma) return 0.0f; return 1.0f - expf( -powf((_x-_gamma)/_beta, _alpha) ); } liquid-dsp-1.3.1/src/random/src/scramble.c000066400000000000000000000063731317124540100203700ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Finite impulse response filter design // #include #include #include #include "liquid.internal.h" void scramble_data(unsigned char * _x, unsigned int _n) { // t = 4*(floor(_n/4)) unsigned int t = (_n>>2)<<2; // apply static masks unsigned int i; for (i=0; i> (8-j-1)) & 0x01 ) _x[8*i+j] = 255 - _x[8*i+j]; } #else if ( mask & 0x80 ) _x[8*i+0] = 255 - _x[8*i+0]; if ( mask & 0x40 ) _x[8*i+1] = 255 - _x[8*i+1]; if ( mask & 0x20 ) _x[8*i+2] = 255 - _x[8*i+2]; if ( mask & 0x10 ) _x[8*i+3] = 255 - _x[8*i+3]; if ( mask & 0x08 ) _x[8*i+4] = 255 - _x[8*i+4]; if ( mask & 0x04 ) _x[8*i+5] = 255 - _x[8*i+5]; if ( mask & 0x02 ) _x[8*i+6] = 255 - _x[8*i+6]; if ( mask & 0x01 ) _x[8*i+7] = 255 - _x[8*i+7]; #endif } } liquid-dsp-1.3.1/src/random/tests/000077500000000000000000000000001317124540100167765ustar00rootroot00000000000000liquid-dsp-1.3.1/src/random/tests/random_autotest.c000066400000000000000000000072321317124540100223560ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.h" #define LIQUID_RANDOM_AUTOTEST_NUM_TRIALS (100000) #define LIQUID_RANDOM_AUTOTEST_ERROR_TOL (0.1) // uniform void autotest_randf() { unsigned long int N = LIQUID_RANDOM_AUTOTEST_NUM_TRIALS; unsigned long int i; float x, m1=0.0f, m2=0.0f; float tol = LIQUID_RANDOM_AUTOTEST_ERROR_TOL; // uniform for (i=0; i #include #include #include "autotest/autotest.h" #include "liquid.internal.h" // compute basic entropy metric float liquid_scramble_test_entropy(unsigned char * _x, unsigned int _n) { unsigned int i; // count ones unsigned int num_ones=0; for (i=0; i<_n; i++) num_ones += liquid_c_ones[_x[i]]; // compute probabilities (add small value to prevent // possible log(0)) float p1 = (float)num_ones / (float)(8*_n) + 1e-12f; float p0 = 1.0 - p1; return -p0*log2f(p0) - p1*log2f(p1); } // helper function to keep code base small void liquid_scramble_test(unsigned int _n) { unsigned char x[_n]; // input data unsigned char y[_n]; // scrambled data unsigned char z[_n]; // unscrambled data unsigned int i; // initialize data array for (i=0; i<_n; i++) x[i] = 0x00; // scramble input memmove(y,x,_n); scramble_data(y,_n); // unscramble result memmove(z,y,_n); unscramble_data(z,_n); // ensure data are equivalent CONTEND_SAME_DATA(x,z,_n*sizeof(unsigned char)); // compute entropy metric float H = liquid_scramble_test_entropy(y,_n); CONTEND_EXPRESSION( H > 0.8f ); } // test unscrambling of soft bits (helper function to keep code base small) void liquid_scramble_soft_test(unsigned int _n) { unsigned char msg_org[_n]; // input data unsigned char msg_enc[_n]; // scrambled data unsigned char msg_soft[8*_n]; // scrambled data (soft bits) unsigned char msg_dec[_n]; // unscrambled data unsigned int i; // initialize data array (random) for (i=0; i<_n; i++) msg_org[i] = rand() & 0xff; // scramble input memmove(msg_enc, msg_org, _n); scramble_data(msg_enc,_n); // convert to soft bits for (i=0; i<_n; i++) liquid_unpack_soft_bits(msg_enc[i], 8, &msg_soft[8*i]); // unscramble result unscramble_data_soft(msg_soft, _n); // unpack soft bits for (i=0; i<_n; i++) { unsigned int sym_out; liquid_pack_soft_bits(&msg_soft[8*i], 8, &sym_out); msg_dec[i] = sym_out; } // ensure data are equivalent CONTEND_SAME_DATA(msg_org, msg_dec, _n); } // // AUTOTESTS : simple data scrambling // void autotest_scramble_n16() { liquid_scramble_test(16); }; void autotest_scramble_n64() { liquid_scramble_test(64); }; void autotest_scramble_n256() { liquid_scramble_test(256); }; void autotest_scramble_n11() { liquid_scramble_test(11); }; void autotest_scramble_n33() { liquid_scramble_test(33); }; void autotest_scramble_n277() { liquid_scramble_test(277); }; // // AUTOTESTS : soft data scrambling // void autotest_scramble_soft_n16() { liquid_scramble_soft_test(16); }; void autotest_scramble_soft_n64() { liquid_scramble_soft_test(64); }; void autotest_scramble_soft_n256() { liquid_scramble_soft_test(256); }; void autotest_scramble_soft_n11() { liquid_scramble_soft_test(11); }; void autotest_scramble_soft_n33() { liquid_scramble_soft_test(33); }; void autotest_scramble_soft_n277() { liquid_scramble_soft_test(277); }; liquid-dsp-1.3.1/src/sequence/000077500000000000000000000000001317124540100161645ustar00rootroot00000000000000liquid-dsp-1.3.1/src/sequence/bench/000077500000000000000000000000001317124540100172435ustar00rootroot00000000000000liquid-dsp-1.3.1/src/sequence/bench/bsequence_benchmark.c000066400000000000000000000052601317124540100233760ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "liquid.h" // Helper function to keep code base small void bsequence_correlate_bench(struct rusage *_start, struct rusage *_finish, unsigned long int *_num_iterations, unsigned int _n) { // normalize number of iterations *_num_iterations *= 1000; *_num_iterations /= _n; if (*_num_iterations < 1) *_num_iterations = 1; // create and initialize binary sequences bsequence bs1 = bsequence_create(_n); bsequence bs2 = bsequence_create(_n); unsigned long int i; int rxy = 0; // start trials getrusage(RUSAGE_SELF, _start); for (i=0; i<(*_num_iterations); i++) { rxy += bsequence_correlate(bs1, bs2); rxy -= bsequence_correlate(bs1, bs2); rxy += bsequence_correlate(bs1, bs2); rxy -= bsequence_correlate(bs1, bs2); } getrusage(RUSAGE_SELF, _finish); *_num_iterations *= 4; // clean up memory bsequence_destroy(bs1); bsequence_destroy(bs2); } #define BSEQUENCE_BENCHMARK_API(N) \ ( struct rusage *_start, \ struct rusage *_finish, \ unsigned long int *_num_iterations) \ { bsequence_correlate_bench(_start, _finish, _num_iterations, N); } // void benchmark_bsequence_xcorr_n16 BSEQUENCE_BENCHMARK_API(16) void benchmark_bsequence_xcorr_n64 BSEQUENCE_BENCHMARK_API(64) void benchmark_bsequence_xcorr_n256 BSEQUENCE_BENCHMARK_API(256) void benchmark_bsequence_xcorr_n1024 BSEQUENCE_BENCHMARK_API(1024) liquid-dsp-1.3.1/src/sequence/src/000077500000000000000000000000001317124540100167535ustar00rootroot00000000000000liquid-dsp-1.3.1/src/sequence/src/bsequence.c000066400000000000000000000221711317124540100210740ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // bsequence.c // // generic binary sequence // #include #include #include #include #include "liquid.internal.h" // struct bsequence_s { unsigned int * s; // sequence array, memory pointer unsigned int num_bits; // number of bits in sequence unsigned int num_bits_msb; // number of bits in most-significant block unsigned int bit_mask_msb; // bit mask for most-significant block unsigned int s_len; // length of array, number of allocated blocks }; // Create a binary sequence of a specific length bsequence bsequence_create(unsigned int _num_bits) { bsequence bs; // allocate memory for binary sequence bs = (bsequence) malloc( sizeof(struct bsequence_s) ); // initialize variables bs->s_len = 0; bs->s = NULL; bs->num_bits = _num_bits; // initialize array length div_t d = div( bs->num_bits, sizeof(unsigned int)*8 ); bs->s_len = d.quot; bs->s_len += (d.rem > 0) ? 1 : 0; // number of bits in MSB block bs->num_bits_msb = (d.rem == 0) ? 8*sizeof(unsigned int) : (unsigned int) d.rem; // bit mask for MSB block unsigned int i; bs->bit_mask_msb = 0; for (i=0; inum_bits_msb; i++) { bs->bit_mask_msb <<= 1; bs->bit_mask_msb |= 1; } // initialze array with zeros bs->s = (unsigned int*) malloc( bs->s_len * sizeof(unsigned int) ); bsequence_reset(bs); return bs; } // Free memory in a binary sequence void bsequence_destroy(bsequence _bs) { free( _bs->s ); free( _bs ); } void bsequence_reset(bsequence _bs) { memset( _bs->s, 0x00, (_bs->s_len)*sizeof(unsigned int) ); } // initialize sequence on external array void bsequence_init(bsequence _bs, unsigned char * _v) { // push single bit at a time unsigned int i; unsigned int k=0; unsigned char byte = 0x00; unsigned char mask = 0x80; for (i=0; i<_bs->num_bits; i++) { if ( (i%8)==0 ) { byte = _v[k++]; mask = 0x80; } bsequence_push(_bs, byte & mask ? 1 : 0); mask >>= 1; } } // Print sequence to the screen void bsequence_print(bsequence _bs) { unsigned int i, j; unsigned int chunk; unsigned int p = 8*sizeof(unsigned int); printf("bsequence[%6u]: ", _bs->num_bits); for (i=0; i<_bs->s_len; i++) { // strip chunk from sequence, starting with most-significant bits chunk = _bs->s[i]; for (j=0; jnum_bits_msb) printf("."); // print '.' for each bit in byte not included in first byte else printf("%c", (chunk >> (p-j-1)) & 0x01 ? '1' : '0'); if ( ((j+1)%8)==0 ) printf(" "); } } printf("\n"); } // push bits in from the right void bsequence_push(bsequence _bs, unsigned int _bit) { unsigned int overflow; unsigned int i; unsigned int p = 8*sizeof(unsigned int); // shift first block _bs->s[0] <<= 1; _bs->s[0] &= _bs->bit_mask_msb; for (i=1; i<_bs->s_len; i++) { // overflow for i-th block is its MSB overflow = (_bs->s[i] >> (p-1)) & 1; // shift block 1 bit _bs->s[i] <<= 1; // apply overflow to (i-1)-th block's LSB _bs->s[i-1] |= overflow; } // apply input bit to LSB of last block _bs->s[_bs->s_len-1] |= ( _bit & 1 ); } // circular shift (left) void bsequence_circshift(bsequence _bs) { // extract most-significant (left-most) bit unsigned int msb_mask = 1 << (_bs->num_bits_msb-1); unsigned int b = (_bs->s[0] & msb_mask) >> (_bs->num_bits_msb-1); // push bit into sequence bsequence_push(_bs, b); } // Correlate two binary sequences together signed int bsequence_correlate(bsequence _bs1, bsequence _bs2) { signed int rxy = 0; unsigned int i; if ( _bs1->s_len != _bs2->s_len ) { printf("error: bsequence_correlate(), binary sequences must be the same length!\n"); exit(-1); } unsigned int chunk; for (i=0; i<_bs1->s_len; i++) { // chunk = _bs1->s[i] ^ _bs2->s[i]; chunk = ~chunk; rxy += liquid_count_ones(chunk); } // compensate for most-significant block and return rxy -= 8*sizeof(unsigned int) - _bs1->num_bits_msb; return rxy; } // compute the binary addition of two bit sequences void bsequence_add(bsequence _bs1, bsequence _bs2, bsequence _bs3) { // test lengths of all sequences if ( _bs1->s_len != _bs2->s_len || _bs1->s_len != _bs3->s_len || _bs2->s_len != _bs3->s_len ) { fprintf(stderr,"error: bsequence_add(), binary sequences must be same length!\n"); exit(-1); } // b3 = b1 + b2 unsigned int i; for (i=0; i<_bs1->s_len; i++) _bs3->s[i] = _bs1->s[i] ^ _bs2->s[i]; // no need to mask most-significant byte } // compute the binary multiplication of two bit sequences void bsequence_mul(bsequence _bs1, bsequence _bs2, bsequence _bs3) { // test lengths of all sequences if ( _bs1->s_len != _bs2->s_len || _bs1->s_len != _bs3->s_len || _bs2->s_len != _bs3->s_len ) { fprintf(stderr,"error: bsequence_mul(), binary sequences must be same length!\n"); exit(-1); } // b3 = b1 * b2 unsigned int i; for (i=0; i<_bs1->s_len; i++) _bs3->s[i] = _bs1->s[i] & _bs2->s[i]; // no need to mask most-significant byte } // accumulate the 1's in a binary sequence unsigned int bsequence_accumulate(bsequence _bs) { unsigned int i; unsigned int r=0; for (i=0; i<_bs->s_len; i++) r += liquid_count_ones(_bs->s[i]); return r; } // return the number of ones in a sequence unsigned int bsequence_get_length(bsequence _bs) { return _bs->num_bits; } // return the i-th bit of the sequence unsigned int bsequence_index(bsequence _bs, unsigned int _i) { if (_i >= _bs->num_bits) { fprintf(stderr,"error: bsequence_index(), invalid index %u\n", _i); exit(-1); } div_t d = div( _i, 8*sizeof(unsigned int) ); // compute byte index unsigned int k = _bs->s_len - d.quot - 1; // return particular bit at byte index return (_bs->s[k] >> d.rem ) & 1; } // intialize two sequences to complementary codes. sequences must // be of length at least 8 and a power of 2 (e.g. 8, 16, 32, 64,...) void bsequence_create_ccodes(bsequence _qa, bsequence _qb) { // make sure sequences are the same length if (_qa->num_bits != _qb->num_bits) { printf("error: bsequence_create_ccodes(), sequence lengths must match\n"); exit(1); } else if (_qa->num_bits < 8) { printf("error: bsequence_create_ccodes(), sequence too short\n"); exit(1); } else if ( (_qa->num_bits)%8 != 0 ) { printf("error: bsequence_create_ccodes(), sequence must be multiple of 8\n"); exit(1); } // generate two temporary arrays unsigned int num_bytes = _qa->num_bits / 8; unsigned char a[num_bytes]; unsigned char b[num_bytes]; memset(a, 0x00, num_bytes); memset(b, 0x00, num_bytes); // initialize a[num_bytes-1] = 0xb8; // 1011 1000 b[num_bytes-1] = 0xb7; // 1011 0111 unsigned int i; unsigned int n=1; unsigned int i_n1; unsigned int i_n0; while (n < num_bytes) { i_n1 = num_bytes - n; i_n0 = num_bytes - 2*n; // a -> [a b] // b -> [a ~b] memmove(&a[i_n0], &a[i_n1], n*sizeof(unsigned char)); memmove(&b[i_n0], &a[i_n1], n*sizeof(unsigned char)); memmove(&a[i_n1], &b[i_n1], n*sizeof(unsigned char)); memmove(&b[i_n1], &b[i_n1], n*sizeof(unsigned char)); // complement lower half for (i=0; i #include #include #include #include "liquid.internal.h" #define LIQUID_MIN_MSEQUENCE_M 2 #define LIQUID_MAX_MSEQUENCE_M 15 // msequence structure // Note that 'g' is stored as the default polynomial shifted to the // right by one bit; this bit is implied and not actually used in // the shift register's feedback bit computation. struct msequence_s msequence_default[16] = { // m, g, a, n, v, b {0, 0, 1, 0, 1, 0}, // dummy placeholder {0, 0, 1, 0, 1, 0}, // dummy placeholder {2, 0x0003, 0x0002, 3, 0x0002, 0}, {3, 0x0005, 0x0004, 7, 0x0004, 0}, {4, 0x0009, 0x0008, 15, 0x0008, 0}, {5, 0x0012, 0x0010, 31, 0x0010, 0}, {6, 0x0021, 0x0020, 63, 0x0020, 0}, {7, 0x0044, 0x0040, 127, 0x0040, 0}, {8, 0x008E, 0x0080, 255, 0x0080, 0}, {9, 0x0108, 0x0100, 511, 0x0100, 0}, {10, 0x0204, 0x0200, 1023, 0x0200, 0}, {11, 0x0402, 0x0400, 2047, 0x0400, 0}, {12, 0x0829, 0x0800, 4095, 0x0800, 0}, {13, 0x100d, 0x1000, 8191, 0x1000, 0}, {14, 0x2015, 0x2000, 16383, 0x2000, 0}, {15, 0x4001, 0x4000, 32767, 0x4000, 0} }; // create a maximal-length sequence (m-sequence) object with // an internal shift register length of _m bits. // _m : generator polynomial length, sequence length is (2^m)-1 // _g : generator polynomial, starting with most-significant bit // _a : initial shift register state, default: 000...001 msequence msequence_create(unsigned int _m, unsigned int _g, unsigned int _a) { // validate input if (_m > LIQUID_MAX_MSEQUENCE_M || _m < LIQUID_MIN_MSEQUENCE_M) { fprintf(stderr,"error: msequence_create(), m not in range\n"); exit(1); } // allocate memory for msequence object msequence ms = (msequence) malloc(sizeof(struct msequence_s)); // set internal values ms->m = _m; // generator polynomial length ms->g = _g >> 1; // generator polynomial (clip off most significant bit) // initialize state register, reversing order // 0001 -> 1000 unsigned int i; ms->a = 0; for (i=0; im; i++) { ms->a <<= 1; ms->a |= (_a & 0x01); _a >>= 1; } ms->n = (1<<_m)-1; // sequence length, (2^m)-1 ms->v = ms->a; // shift register ms->b = 0; // return bit return ms; } // create a maximal-length sequence (m-sequence) object from a generator polynomial msequence msequence_create_genpoly(unsigned int _g) { unsigned int t = liquid_msb_index(_g); // validate input if (t < 2) { fprintf(stderr,"error: msequence_create_genpoly(), invalid generator polynomial: 0x%x\n", _g); exit(1); } // compute derived values unsigned int m = t - 1; // m-sequence shift register length unsigned int a = 1; // m-sequence initial state // generate object and return return msequence_create(m,_g,a); } // creates a default maximal-length sequence msequence msequence_create_default(unsigned int _m) { // validate input if (_m > LIQUID_MAX_MSEQUENCE_M || _m < LIQUID_MIN_MSEQUENCE_M) { fprintf(stderr,"error: msequence_create(), m not in range\n"); exit(1); } // allocate memory for msequence object msequence ms = (msequence) malloc(sizeof(struct msequence_s)); // copy default sequence memmove(ms, &msequence_default[_m], sizeof(struct msequence_s)); // return return ms; } // destroy an msequence object, freeing all internal memory void msequence_destroy(msequence _ms) { free(_ms); } // prints the sequence's internal state to the screen void msequence_print(msequence _m) { unsigned int i; printf("msequence: m=%u (n=%u):\n", _m->m, _m->n); // print shift register printf(" shift register: "); for (i=0; i<_m->m; i++) printf("%c", ((_m->v) >> (_m->m-i-1)) & 0x01 ? '1' : '0'); printf("\n"); // print generator polynomial printf(" generator poly: "); for (i=0; i<_m->m; i++) printf("%c", ((_m->g) >> (_m->m-i-1)) & 0x01 ? '1' : '0'); printf("\n"); } // advance msequence on shift register, returning output bit unsigned int msequence_advance(msequence _ms) { // compute return bit as binary dot product between the // internal shift register and the generator polynomial _ms->b = liquid_bdotprod( _ms->v, _ms->g ); _ms->v <<= 1; // shift internal register _ms->v |= _ms->b; // push bit onto register _ms->v &= _ms->n; // apply mask to register return _ms->b; // return result } // generate pseudo-random symbol from shift register // _ms : m-sequence object // _bps : bits per symbol of output unsigned int msequence_generate_symbol(msequence _ms, unsigned int _bps) { unsigned int i; unsigned int s = 0; for (i=0; i<_bps; i++) { s <<= 1; s |= msequence_advance(_ms); } return s; } // reset msequence shift register to original state, typically '1' void msequence_reset(msequence _ms) { _ms->v = _ms->a; } // initialize a bsequence object on an msequence object // _bs : bsequence object // _ms : msequence object void bsequence_init_msequence(bsequence _bs, msequence _ms) { #if 0 if (_ms->n > LIQUID_MAX_MSEQUENCE_LENGTH) { fprintf(stderr,"error: bsequence_init_msequence(), msequence length exceeds maximum\n"); exit(1); } #endif // clear binary sequence bsequence_reset(_bs); unsigned int i; for (i=0; i<(_ms->n); i++) bsequence_push(_bs, msequence_advance(_ms)); } // get the length of the sequence unsigned int msequence_get_length(msequence _ms) { return _ms->n; } // get the internal state of the sequence unsigned int msequence_get_state(msequence _ms) { return _ms->v; } // set the internal state of the sequence void msequence_set_state(msequence _ms, unsigned int _a) { // set internal state // NOTE: if state is set to zero, this will lock the sequence generator, // but let the user set this value if they wish _ms->v = _a; } liquid-dsp-1.3.1/src/sequence/tests/000077500000000000000000000000001317124540100173265ustar00rootroot00000000000000liquid-dsp-1.3.1/src/sequence/tests/bsequence_autotest.c000066400000000000000000000142701317124540100234000ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.h" // // test initialization of binary sequence // void autotest_bsequence_init() { // 1111 0000 1100 1010 unsigned char v[2] = {0xf0, 0xca}; // create and initialize sequence bsequence q = bsequence_create(16); bsequence_init(q,v); // run tests CONTEND_EQUALITY( bsequence_index(q,15), 1 ); CONTEND_EQUALITY( bsequence_index(q,14), 1 ); CONTEND_EQUALITY( bsequence_index(q,13), 1 ); CONTEND_EQUALITY( bsequence_index(q,12), 1 ); CONTEND_EQUALITY( bsequence_index(q,11), 0 ); CONTEND_EQUALITY( bsequence_index(q,10), 0 ); CONTEND_EQUALITY( bsequence_index(q, 9), 0 ); CONTEND_EQUALITY( bsequence_index(q, 8), 0 ); CONTEND_EQUALITY( bsequence_index(q, 7), 1 ); CONTEND_EQUALITY( bsequence_index(q, 6), 1 ); CONTEND_EQUALITY( bsequence_index(q, 5), 0 ); CONTEND_EQUALITY( bsequence_index(q, 4), 0 ); CONTEND_EQUALITY( bsequence_index(q, 3), 1 ); CONTEND_EQUALITY( bsequence_index(q, 2), 0 ); CONTEND_EQUALITY( bsequence_index(q, 1), 1 ); CONTEND_EQUALITY( bsequence_index(q, 0), 0 ); // clean up memory bsequence_destroy(q); } // // test correlation between to sequences // void autotest_bsequence_correlate() { // v0 : 1111 0000 1100 1010 // v1 : 1100 1011 0001 1110 // sim : 1100 0100 0010 1011 (7 similar bits) unsigned char v0[2] = {0xf0, 0xca}; unsigned char v1[2] = {0xcb, 0x1e}; // create and initialize sequences bsequence q0 = bsequence_create(16); bsequence q1 = bsequence_create(16); bsequence_init(q0,v0); bsequence_init(q1,v1); // run tests CONTEND_EQUALITY( bsequence_correlate(q0,q1), 7 ); // clean up memory bsequence_destroy(q0); bsequence_destroy(q1); } // // test add operations on two sequences // void autotest_bsequence_add() { // v0 : 1111 0000 1100 1010 // v1 : 1100 1011 0001 1110 // sum : 0011 1011 1101 0100 unsigned char v0[2] = {0xf0, 0xca}; unsigned char v1[2] = {0xcb, 0x1e}; // create and initialize sequences bsequence q0 = bsequence_create(16); bsequence q1 = bsequence_create(16); bsequence_init(q0,v0); bsequence_init(q1,v1); // create result sequence bsequence r = bsequence_create(16); bsequence_add(q0, q1, r); // run tests CONTEND_EQUALITY( bsequence_index(r,15), 0 ); CONTEND_EQUALITY( bsequence_index(r,14), 0 ); CONTEND_EQUALITY( bsequence_index(r,13), 1 ); CONTEND_EQUALITY( bsequence_index(r,12), 1 ); CONTEND_EQUALITY( bsequence_index(r,11), 1 ); CONTEND_EQUALITY( bsequence_index(r,10), 0 ); CONTEND_EQUALITY( bsequence_index(r, 9), 1 ); CONTEND_EQUALITY( bsequence_index(r, 8), 1 ); CONTEND_EQUALITY( bsequence_index(r, 7), 1 ); CONTEND_EQUALITY( bsequence_index(r, 6), 1 ); CONTEND_EQUALITY( bsequence_index(r, 5), 0 ); CONTEND_EQUALITY( bsequence_index(r, 4), 1 ); CONTEND_EQUALITY( bsequence_index(r, 3), 0 ); CONTEND_EQUALITY( bsequence_index(r, 2), 1 ); CONTEND_EQUALITY( bsequence_index(r, 1), 0 ); CONTEND_EQUALITY( bsequence_index(r, 0), 0 ); // clean up memory bsequence_destroy(q0); bsequence_destroy(q1); bsequence_destroy(r); } // // test multiply operations on two sequences // void autotest_bsequence_mul() { // v0 : 1111 0000 1100 1010 // v1 : 1100 1011 0001 1110 // prod : 1100 0000 0000 1010 unsigned char v0[2] = {0xf0, 0xca}; unsigned char v1[2] = {0xcb, 0x1e}; // create and initialize sequences bsequence q0 = bsequence_create(16); bsequence q1 = bsequence_create(16); bsequence_init(q0,v0); bsequence_init(q1,v1); // create result sequence bsequence r = bsequence_create(16); bsequence_mul(q0, q1, r); // run tests CONTEND_EQUALITY( bsequence_index(r,15), 1 ); CONTEND_EQUALITY( bsequence_index(r,14), 1 ); CONTEND_EQUALITY( bsequence_index(r,13), 0 ); CONTEND_EQUALITY( bsequence_index(r,12), 0 ); CONTEND_EQUALITY( bsequence_index(r,11), 0 ); CONTEND_EQUALITY( bsequence_index(r,10), 0 ); CONTEND_EQUALITY( bsequence_index(r, 9), 0 ); CONTEND_EQUALITY( bsequence_index(r, 8), 0 ); CONTEND_EQUALITY( bsequence_index(r, 7), 0 ); CONTEND_EQUALITY( bsequence_index(r, 6), 0 ); CONTEND_EQUALITY( bsequence_index(r, 5), 0 ); CONTEND_EQUALITY( bsequence_index(r, 4), 0 ); CONTEND_EQUALITY( bsequence_index(r, 3), 1 ); CONTEND_EQUALITY( bsequence_index(r, 2), 0 ); CONTEND_EQUALITY( bsequence_index(r, 1), 1 ); CONTEND_EQUALITY( bsequence_index(r, 0), 0 ); // clean up memory bsequence_destroy(q0); bsequence_destroy(q1); bsequence_destroy(r); } // // test accumulation of binary sequence // void autotest_bsequence_accumulate() { // 1111 0000 1100 1010 (8 total bits) unsigned char v[2] = {0xf0, 0xca}; // create and initialize sequence bsequence q = bsequence_create(16); bsequence_init(q,v); // run tests CONTEND_EQUALITY( bsequence_accumulate(q), 8 ); // clean up memory bsequence_destroy(q); } liquid-dsp-1.3.1/src/sequence/tests/complementary_codes_autotest.c000066400000000000000000000054201317124540100254570ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.h" // // AUTOTEST: validate autocorrelation properties of // complementary codes // void complementary_codes_test(unsigned int _n) { // create and initialize codes bsequence a = bsequence_create(_n); bsequence b = bsequence_create(_n); bsequence_create_ccodes(a, b); // print if (liquid_autotest_verbose) { bsequence_print(a); bsequence_print(b); } // generate test sequences bsequence ax = bsequence_create(_n); bsequence bx = bsequence_create(_n); bsequence_create_ccodes(ax, bx); unsigned int i; signed int raa, rbb; for (i=0; i<_n; i++) { // correlate like sequences raa = 2*bsequence_correlate(a,ax) - _n; rbb = 2*bsequence_correlate(b,bx) - _n; if (i==0) { CONTEND_EQUALITY(raa+rbb,2*_n); } else { CONTEND_EQUALITY(raa+rbb,0); } bsequence_circshift(ax); bsequence_circshift(bx); } // clean up memory bsequence_destroy(a); bsequence_destroy(b); bsequence_destroy(ax); bsequence_destroy(bx); } void autotest_complementary_code_n8() { complementary_codes_test(8); } void autotest_complementary_code_n16() { complementary_codes_test(16); } void autotest_complementary_code_n32() { complementary_codes_test(32); } void autotest_complementary_code_n64() { complementary_codes_test(64); } void autotest_complementary_code_n128() { complementary_codes_test(128); } void autotest_complementary_code_n256() { complementary_codes_test(256); } void autotest_complementary_code_n512() { complementary_codes_test(512); } liquid-dsp-1.3.1/src/sequence/tests/msequence_autotest.c000066400000000000000000000075751317124540100234250ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.h" // test initialization of binary sequence on m-sequence void autotest_bsequence_init_msequence() { // create and initialize m-sequence msequence ms = msequence_create_default(4); // create and initialize binary sequence on m-sequence bsequence bs; bs = bsequence_create( msequence_get_length(ms) ); bsequence_init_msequence(bs, ms); if (liquid_autotest_verbose) bsequence_print(bs); CONTEND_EQUALITY( bsequence_get_length(bs), msequence_get_length(ms) ) // clean up memory bsequence_destroy(bs); msequence_destroy(ms); } // helper function to test auto-correlation properties of m-sequence void msequence_test_autocorrelation(unsigned int _m) { // create and initialize m-sequence msequence ms = msequence_create_default(_m); unsigned int n = msequence_get_length(ms); // create and initialize first binary sequence on m-sequence bsequence bs1 = bsequence_create(n); bsequence_init_msequence(bs1, ms); // create and initialize second binary sequence on same m-sequence bsequence bs2 = bsequence_create(n); bsequence_init_msequence(bs2, ms); // ensure sequences are the same length CONTEND_EQUALITY( bsequence_get_length(bs1), n ) CONTEND_EQUALITY( bsequence_get_length(bs2), n ) // when sequences are aligned, autocorrelation is equal to length signed int rxy; rxy = bsequence_correlate(bs1, bs2); CONTEND_EQUALITY( rxy, n ) // when sequences are misaligned, autocorrelation is equal to -1 unsigned int i; for (i=0; i #include #include #include "liquid.internal.h" // shift array to the left _b bits, filling in zeros // _src : source address [size: _n x 1] // _n : input data array size // _b : number of bits to shift void liquid_lbshift(unsigned char * _src, unsigned int _n, unsigned int _b) { // validate input if (_b >= 8) { fprintf(stderr,"error: liquid_lbshift(), shift amount must be in [0,7]\n"); exit(1); } // invoke circular shift left and mask last byte liquid_lbcircshift(_src, _n, _b); _src[_n-1] &= 0xff << _b; } // shift array to the right _b bits filling in zeros // _src : source address [size: _n x 1] // _n : input data array size // _b : number of bits to shift void liquid_rbshift(unsigned char * _src, unsigned int _n, unsigned int _b) { // validate input if (_b >= 8) { fprintf(stderr,"error: liquid_rbshift(), shift amount must be in [0,7]\n"); exit(1); } // invoke circular shift right and mask first byte liquid_rbcircshift(_src, _n, _b); _src[0] &= 0xff >> _b; } // circularly shift array to the left _b bits // _src : source address [size: _n x 1] // _n : input data array size // _b : number of bits to shift void liquid_lbcircshift(unsigned char * _src, unsigned int _n, unsigned int _b) { // validate input if (_b >= 8) { fprintf(stderr,"error: liquid_lbcircshift(), shift amount must be in [0,7]\n"); exit(1); } // unsigned int shift_0 = _b; // shift amount: first byte unsigned int shift_1 = 8 - _b; // shift amount: second byte unsigned char mask_0 = 0xff << shift_0; // bit mask: first byte unsigned char mask_1 = 0xff >> shift_1; // bit mask: second byte #if 0 printf("num_bits = %1u, shift_0 = %1u, shift_1 = %1u mask_0=%.2x, mask_1=%.2x\n", _b, shift_0, shift_1, mask_0, mask_1); #endif // shift then mask unsigned int i; unsigned char byte; unsigned char byte_0; unsigned char byte_1; unsigned char src_0 = _src[0]; // retain first byte for (i=0; i<_n; i++) { // strip bytes byte_0 = _src[i]; byte_1 = (i==_n-1) ? src_0 : _src[i+1]; // shift then mask byte = ((byte_0 << shift_0) & mask_0) | ((byte_1 >> shift_1) & mask_1); // store result _src[i] = byte; } } // circularly shift array to the right _b bits // _src : source address [size: _n x 1] // _n : input data array size // _b : number of bits to shift void liquid_rbcircshift(unsigned char * _src, unsigned int _n, unsigned int _b) { // validate input if (_b >= 8) { fprintf(stderr,"error: liquid_rbshift(), shift amount must be in [0,7]\n"); exit(1); } // unsigned int shift_0 = 8 - _b; // shift amount: first byte unsigned int shift_1 = _b; // shift amount: second byte unsigned char mask_0 = 0xff << shift_0; // bit mask: first byte unsigned char mask_1 = 0xff >> shift_1; // bit mask: second byte #if 0 printf("num_bits = %1u, shift_0 = %1u, shift_1 = %1u mask_0=%.2x, mask_1=%.2x\n", _b, shift_0, shift_1, mask_0, mask_1); #endif // shift then mask int i; unsigned char byte; unsigned char byte_0; unsigned char byte_1; unsigned char src_n = _src[_n-1]; // retain last byte for (i=_n-1; i>=0; i--) { // strip bytes byte_0 = (i==0) ? src_n : _src[i-1]; byte_1 = _src[i]; // shift then mask byte = ((byte_0 << shift_0) & mask_0) | ((byte_1 >> shift_1) & mask_1); // store result _src[i] = byte; } } liquid-dsp-1.3.1/src/utility/src/byte_utilities.c000066400000000000000000000203571317124540100220570ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // general utilities for manipulating bits and bytes, including // * counting ones in a byte, word, long word, etc. // * counting bit differences (e.g. errors) in arrays // * arrays for fast counting // * array for reversing bytes // #include #include "liquid.internal.h" // count the number of ones in an integer unsigned int liquid_count_ones(unsigned int _x) { #if SIZEOF_INT == 2 return liquid_count_ones_uint16(_x); #elif SIZEOF_INT == 4 return liquid_count_ones_uint32(_x); #else unsigned int i; unsigned int c=0; for (i=0; i>= 8; } return c; #endif } // count the number of ones in an integer, modulo 2 unsigned int liquid_count_ones_mod2(unsigned int _x) { #if SIZEOF_INT == 2 return liquid_count_ones_mod2_uint16(_x); #elif SIZEOF_INT == 4 return liquid_count_ones_mod2_uint32(_x); #else unsigned int i; unsigned int c=0; for (i=0; i>= 8; } return c & 1; #endif } // count the binary dot-product between two integers unsigned int liquid_bdotprod(unsigned int _x, unsigned int _y) { unsigned int t = _x & _y; #if SIZEOF_INT == 2 return liquid_count_ones_mod2_uint16(t); #elif SIZEOF_INT == 4 return liquid_count_ones_mod2_uint32(t); #else unsigned int i; unsigned int c=0; for (i=0; i>= 8; } return c & 1; #endif } // counts the number of different bits between two symbols unsigned int count_bit_errors(unsigned int _s1, unsigned int _s2) { return liquid_count_ones(_s1^_s2); } // counts the number of different bits between two arrays of symbols // _msg0 : original message [size: _n x 1] // _msg1 : copy of original message [size: _n x 1] // _n : message size unsigned int count_bit_errors_array(unsigned char * _msg0, unsigned char * _msg1, unsigned int _n) { unsigned int num_bit_errors = 0; unsigned int i; for (i=0; i<_n; i++) num_bit_errors += liquid_c_ones[_msg0[i] ^ _msg1[i]]; return num_bit_errors; } // print string of bits to standard output void liquid_print_bitstring(unsigned int _x, unsigned int _n) { unsigned int i; for (i=0; i<_n; i++) printf("%1u", (_x >> (_n-i-1)) & 1); } // number of ones in a byte unsigned const char liquid_c_ones[256] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8}; // number of ones in a byte modulo 2 unsigned const char liquid_c_ones_mod2[256] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0}; // reverse byte table unsigned const char liquid_reverse_byte_gentab[256] = { 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff}; // // byte reversal // // slow implementation of byte reversal unsigned char liquid_reverse_byte(unsigned char _x) { unsigned char y = 0x00; unsigned int i; for (i=0; i<8; i++) { y <<= 1; y |= _x & 1; _x >>= 1; } return y; } // reverse integer with 16 bits of data unsigned int liquid_reverse_uint16(unsigned int _x) { return (liquid_reverse_byte_gentab[(_x ) & 0xff] << 8) | (liquid_reverse_byte_gentab[(_x >> 8) & 0xff] ); } // reverse integer with 24 bits of data unsigned int liquid_reverse_uint24(unsigned int _x) { return (liquid_reverse_byte_gentab[(_x ) & 0xff] << 16) | (liquid_reverse_byte_gentab[(_x >> 8) & 0xff] << 8) | (liquid_reverse_byte_gentab[(_x >> 16) & 0xff] ); } // reverse integer with 32 bits of data unsigned int liquid_reverse_uint32(unsigned int _x) { return (liquid_reverse_byte_gentab[(_x ) & 0xff] << 24) | (liquid_reverse_byte_gentab[(_x >> 8) & 0xff] << 16) | (liquid_reverse_byte_gentab[(_x >> 16) & 0xff] << 8) | (liquid_reverse_byte_gentab[(_x >> 24) & 0xff] ); } liquid-dsp-1.3.1/src/utility/src/msb_index.c000066400000000000000000000101731317124540100207640ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "liquid.internal.h" // number of leading zeros in a byte // 0 0000 0000 : 8 // 1 0000 0001 : 7 // 2 0000 0010 : 6 // 3 0000 0011 : 6 // 4 0000 0100 : 5 // ... // 126 0111 1110 : 1 // 127 0111 1111 : 1 // 128 1000 0000 : 0 // 129 1000 0001 : 0 // ... // 253 1111 1101 : 0 // 254 1111 1110 : 0 // 255 1111 1111 : 0 unsigned int liquid_c_leading_zeros[256] = { 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // count leading zeros in an integer (like leading_zeros[], but // extending to integer) unsigned int liquid_count_leading_zeros(unsigned int _x) { #if 0 // look for first non-zero byte in _x int i, B, clz=0; for (i=(SIZEOF_UNSIGNED_INT-1)*8; i>=0; i-=8) { B = (_x >> i) & 0xff; if ( B ) // B != 0 return clz + leading_zeros[B]; else clz += 8; } return (SIZEOF_UNSIGNED_INT*8); #else return SIZEOF_UNSIGNED_INT*8 - liquid_msb_index(_x); #endif } // computes the index of the most-significant bit // // Examples: // 0x00000000 : 0 // 0x00000001 : 1 // 0x00000002 : 2 // ... // 0x00010000 : 17 // 0x00020000 : 17 // 0x00040000 : 17 // ... // 0x80000000 : 32 // // 0 0000 0000 : 0 // 1 0000 0001 : 1 // 2 0000 0010 : 2 // 3 0000 0011 : 2 // 4 0000 0100 : 3 // ... // 126 0111 1110 : 7 // 127 0111 1111 : 7 // 128 1000 0000 : 8 // 129 1000 0001 : 8 // ... // 253 1111 1101 : 8 // 254 1111 1110 : 8 // 255 1111 1111 : 8 unsigned int liquid_msb_index(unsigned int _x) { unsigned int bits; #if defined __i386__ || defined __amd64__ || defined __x86_64__ if (!_x) return 0; __asm volatile("bsrl %1,%0\n" : "=r" (bits) : "c" (_x) ); return bits + 1; #elif 0 // slow method; look one bit at a time for (bits = 0; _x != 0 && bits < 32; _x >>= 1, ++bits) ; return bits; #else // look for first non-zero byte unsigned int i, b; bits = 8*SIZEOF_UNSIGNED_INT; for (i=SIZEOF_UNSIGNED_INT*8; i>0; i-=8) { b = (_x >> (i-8)) & 0xff; if ( b ) return bits - liquid_c_leading_zeros[b]; else bits -= 8; } return 0; #endif } liquid-dsp-1.3.1/src/utility/src/msb_index.x86.s000066400000000000000000000002651317124540100214310ustar00rootroot00000000000000; Index of most-significant bit .text .globl msb_index msb_index: pushl %ebx pushl %ecx pushl %edx bsrl %eax,%eax popl %edx popl %ecx popl %ebx ret liquid-dsp-1.3.1/src/utility/src/pack_bytes.c000066400000000000000000000266411317124540100211470ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // pack_bytes.c // // Useful byte-packing utilities // #include #include #include "liquid.internal.h" // pack binary array with symbol(s) // _src : source array [size: _n x 1] // _n : input source array length // _k : bit index to write in _src // _b : number of bits in input symbol // _sym_in : input symbol void liquid_pack_array(unsigned char * _src, unsigned int _n, unsigned int _k, unsigned int _b, unsigned char _sym_in) { // validate input if (_k >= 8*_n) { fprintf(stderr,"error: liquid_pack_array(), bit index exceeds array length\n"); exit(1); } else if (_b > 8) { fprintf(stderr,"error: liquid_pack_array(), symbol size cannot exceed 8 bits\n"); exit(1); } // find base index unsigned int i0 = _k / 8; // byte index unsigned int b0 = _k - 8*i0; // bit index //printf("base index : %2u, %2u\n", i0, b0); // determine if index spans multiple bytes if (b0 + _b > 8) { // compute number of bits in each symbol unsigned int n0 = 8 - b0; unsigned int n1 = _b - n0; // generate mask for each symbol unsigned char mask_0 = 0xff >> (8-n0); unsigned char mask_1 = (0xff >> (8-n1)) << (8-n1); // shift then mask unsigned char sym_0 = (_sym_in >> n1 ) & mask_0; unsigned char sym_1 = (_sym_in << (8-n1)) & mask_1; // mask and pack first byte _src[i0] &= ~mask_0; // clear relevant bits _src[i0] |= sym_0; // set relevant bits // mask and pack second byte (if not exceeding array size) if (i0 < _n-1) { _src[i0+1] &= ~mask_1; // clear relevant bits _src[i0+1] |= sym_1; // set relevant bits } #if 0 printf(" output symbol spans multiple bytes\n"); printf(" n0 : %u\n", n0); printf(" n1 : %u\n", n1); printf(" mask0 : 0x%.2x\n", mask_0); printf(" mask1 : 0x%.2x\n", mask_1); printf(" sym 0 : 0x%.2x\n", sym_0); printf(" sym 1 : 0x%.2x\n", sym_1); #endif } else { // compute mask unsigned char mask_0 = (0xff >> (8-_b)) << (8-_b-b0); unsigned char sym_0 = (_sym_in << (8-_b-b0)) & mask_0; // shift then mask _src[i0] &= ~mask_0; // clear relevant bits _src[i0] |= sym_0; // set relevant bits #if 0 printf(" _b : %u\n", _b); printf(" b0 : %u\n", b0); printf(" mask : 0x%.2x\n", mask_0); #endif } } // unpack symbols from binary array // _src : source array [size: _n x 1] // _n : input source array length // _k : bit index to write in _src // _b : number of bits in output symbol // _sym_out : output symbol void liquid_unpack_array(unsigned char * _src, unsigned int _n, unsigned int _k, unsigned int _b, unsigned char * _sym_out) { // validate input if (_k >= 8*_n) { fprintf(stderr,"error: liquid_unpack_array(), bit index exceeds array length\n"); exit(1); } else if (_b > 8) { fprintf(stderr,"error: liquid_unpack_array(), symbol size cannot exceed 8 bits\n"); exit(1); } // find base index unsigned int i0 = _k / 8; // byte index unsigned int b0 = _k - 8*i0; // bit index //printf("base index : %2u, %2u\n", i0, b0); // determine if index spans multiple bytes if (b0 + _b > 8) { // compute number of bits in each symbol unsigned int n0 = 8 - b0; unsigned int n1 = _b - n0; // generate mask for each symbol unsigned char mask_0 = 0xff >> (8-n0); unsigned char mask_1 = 0xff >> (8-n1); // shift then mask unsigned char sym_0 = _src[i0] & mask_0; unsigned char sym_1 = (i0==_n-1) ? 0x00 : (_src[i0+1] >> (8-n1)) & mask_1; // concatenate output symbols *_sym_out = (sym_0 << n1) | sym_1; #if 0 printf(" output symbol spans multiple bytes\n"); printf(" n0 : %u\n", n0); printf(" n1 : %u\n", n1); printf(" mask0 : 0x%.2x\n", mask_0); printf(" mask1 : 0x%.2x\n", mask_1); printf(" sym 0 : 0x%.2x\n", sym_0); printf(" sym 1 : 0x%.2x\n", sym_1); #endif } else { // compute mask unsigned char mask_0 = ((1 << _b) - 1); // shift then mask *_sym_out = (_src[i0] >> (8-_b-b0)) & mask_0; #if 0 printf(" _b : %u\n", _b); printf(" b0 : %u\n", b0); printf(" mask : 0x%.2x\n", mask_0); #endif } } // pack one-bit symbols into bytes (8-bit symbols) // _sym_in : input symbols array [size: _sym_in_len x 1] // _sym_in_len : number of input symbols // _sym_out : output symbols // _sym_out_len : number of bytes allocated to output symbols array // _num_written : number of output symbols actually written void liquid_pack_bytes(unsigned char * _sym_in, unsigned int _sym_in_len, unsigned char * _sym_out, unsigned int _sym_out_len, unsigned int * _num_written) { div_t d = div(_sym_in_len,8); unsigned int req__sym_out_len = d.quot; req__sym_out_len += ( d.rem > 0 ) ? 1 : 0; if ( _sym_out_len < req__sym_out_len ) { fprintf(stderr,"error: pack_bytes(), output too short\n"); exit(-1); } unsigned int i; unsigned int N = 0; // number of bytes written to output unsigned char byte = 0; for (i=0; i<_sym_in_len; i++) { byte |= _sym_in[i] & 0x01; if ( (i+1)%8 == 0 ) { _sym_out[N++] = byte; byte = 0; } else { byte <<= 1; } } if ( i%8 != 0 ) _sym_out[N++] = byte >> 1; *_num_written = N; } // unpack 8-bit symbols (full bytes) into one-bit symbols // _sym_in : input symbols array [size: _sym_in_len x 1] // _sym_in_len : number of input symbols // _sym_out : output symbols array // _sym_out_len : number of bytes allocated to output symbols array // _num_written : number of output symbols actually written void liquid_unpack_bytes(unsigned char * _sym_in, unsigned int _sym_in_len, unsigned char * _sym_out, unsigned int _sym_out_len, unsigned int * _num_written) { unsigned int i; unsigned int n = 0; unsigned char byte; if ( _sym_out_len < 8*_sym_in_len ) { fprintf(stderr,"error: unpack_bytes(), output too short\n"); exit(-1); } for (i=0; i<_sym_in_len; i++) { // read input byte byte = _sym_in[i]; // unpack byte into 8 one-bit symbols _sym_out[n++] = (byte >> 7) & 0x01; _sym_out[n++] = (byte >> 6) & 0x01; _sym_out[n++] = (byte >> 5) & 0x01; _sym_out[n++] = (byte >> 4) & 0x01; _sym_out[n++] = (byte >> 3) & 0x01; _sym_out[n++] = (byte >> 2) & 0x01; _sym_out[n++] = (byte >> 1) & 0x01; _sym_out[n++] = byte & 0x01; } *_num_written = n; } // repack bytes with arbitrary symbol sizes // _sym_in : input symbols array [size: _sym_in_len x 1] // _sym_in_bps : number of bits per input symbol // _sym_in_len : number of input symbols // _sym_out : output symbols array // _sym_out_bps : number of bits per output symbol // _sym_out_len : number of bytes allocated to output symbols array // _num_written : number of output symbols actually written void liquid_repack_bytes(unsigned char * _sym_in, unsigned int _sym_in_bps, unsigned int _sym_in_len, unsigned char * _sym_out, unsigned int _sym_out_bps, unsigned int _sym_out_len, unsigned int * _num_written) { // compute number of output symbols and determine if output array // is sufficiently sized div_t d = div(_sym_in_len*_sym_in_bps,_sym_out_bps); unsigned int req__sym_out_len = d.quot; req__sym_out_len += ( d.rem > 0 ) ? 1 : 0; if ( _sym_out_len < req__sym_out_len ) { fprintf(stderr,"error: repack_bytes(), output too short\n"); fprintf(stderr," %u %u-bit symbols cannot be packed into %u %u-bit elements\n", _sym_in_len, _sym_in_bps, _sym_out_len, _sym_out_bps); exit(-1); } unsigned int i; unsigned char s_in = 0; // input symbol unsigned char s_out = 0; // output symbol // there is probably a more efficient way to do this, but... unsigned int total_bits = _sym_in_len*_sym_in_bps; unsigned int i_in = 0; // input index counter unsigned int i_out = 0; // output index counter unsigned int k=0; // input symbol enable unsigned int n=0; // output symbol enable unsigned int v; // bit mask for (i=0; i> v) & 0x01; //printf("\n b = %d, v = %d, s_in = %d, sym_out = %d", (sym_in >> v) & 0x01, v, s_in, sym_out ); // push output if available if ( n == _sym_out_bps-1 ) { //printf("\n _sym_out[%d] = %d", i_out, sym_out); _sym_out[i_out++] = s_out; s_out = 0; } // update input/output symbol pop/push flags k = (k+1) % _sym_in_bps; n = (n+1) % _sym_out_bps; } // if uneven, push zeros into remaining output symbol if (i_out != req__sym_out_len) { for (i=n; i<_sym_out_bps; i++) s_out <<= 1; _sym_out[i_out++] = s_out; } *_num_written = i_out; } liquid-dsp-1.3.1/src/utility/src/shift_array.c000066400000000000000000000106351317124540100213320ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // shift_array.c // // byte-wise array shifting // #include #include #include #include "liquid.internal.h" // shift array to the left _b bytes, filling in zeros // _src : source address [size: _n x 1] // _n : input data array size // _b : number of bytes to shift void liquid_lshift(unsigned char * _src, unsigned int _n, unsigned int _b) { // shift amount exceeds buffer size; fill with zeros if (_b >= _n) { memset(_src, 0x00, _n*sizeof(unsigned char)); return; } // move memory memmove(_src, &_src[_b], (_n-_b)*sizeof(unsigned char)); // fill remaining buffer with zeros memset(&_src[_n-_b], 0x00, _b*sizeof(unsigned char)); } // shift array to the right _b bytes, filling in zeros // _src : source address [size: _n x 1] // _n : input data array size // _b : number of bytes to shift void liquid_rshift(unsigned char * _src, unsigned int _n, unsigned int _b) { // shift amount exceeds buffer size; fill with zeros if (_b >= _n) { memset(_src, 0x00, _n*sizeof(unsigned char)); return; } // move memory memmove(&_src[_b], _src, (_n-_b)*sizeof(unsigned char)); // fill remaining buffer with zeros memset(_src, 0x00, _b*sizeof(unsigned char)); } // circular shift array to the left _n bytes // _src : source address [size: _n x 1] // _n : input data array size // _b : number of bytes to shift void liquid_lcircshift(unsigned char * _src, unsigned int _n, unsigned int _b) { // validate input if (_n == 0) return; // ensure 0 <= _b < _n _b = _b % _n; // check if less memory is used with rcircshift if (_b > (_n>>1)) { liquid_rcircshift(_src, _n, _n-_b); return; } // allocate memory for temporary array unsigned char * tmp = (unsigned char*) malloc(_b*sizeof(unsigned char)); // copy to temporary array memmove(tmp, _src, _b*sizeof(unsigned char)); // shift left memmove(_src, &_src[_b], (_n-_b)*sizeof(unsigned char)); // copy from temporary array memmove(&_src[_n-_b], tmp, _b*sizeof(unsigned char)); // free temporary array free(tmp); } // circular shift array to the right _n bytes // _src : source address [size: _n x 1] // _n : input data array size // _b : number of bytes to shift void liquid_rcircshift(unsigned char * _src, unsigned int _n, unsigned int _b) { // validate input if (_n == 0) return; // ensure 0 <= _b < _n _b = _b % _n; // check if less memory is used with lcircshift if (_b > (_n>>1)) { liquid_lcircshift(_src, _n, _n-_b); return; } // allocate memory for temporary array unsigned char * tmp = (unsigned char*) malloc(_b*sizeof(unsigned char)); // copy to temporary array memmove(tmp, &_src[_n-_b], _b*sizeof(unsigned char)); // shift right memmove(&_src[_b], _src, (_n-_b)*sizeof(unsigned char)); // copy from temporary array memmove(_src, tmp, _b*sizeof(unsigned char)); // free temporary array free(tmp); } liquid-dsp-1.3.1/src/utility/tests/000077500000000000000000000000001317124540100172215ustar00rootroot00000000000000liquid-dsp-1.3.1/src/utility/tests/bdotprod_gentest.m000066400000000000000000000005021317124540100227420ustar00rootroot00000000000000 clear all; close all; a = floor(rand(1) * 2^16); b = floor(rand(1) * 2^16); as = dec2bin(a,16); bs = dec2bin(b,16); ap = []; bp = []; for i=1:16, ap = [ap str2num(as(i))]; bp = [bp str2num(bs(i))]; end; bit = mod(sum(ap.*bp),2); printf('CONTEND_EQUALITY( liquid_bdotprod(0x%.4x, 0x%.4x), %1u);\n', a,b,bit); liquid-dsp-1.3.1/src/utility/tests/bshift_array_autotest.c000066400000000000000000000217111317124540100237740ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "autotest/autotest.h" #include "liquid.internal.h" // // AUTOTEST : lbshift // void autotest_lbshift() { // input : 1000 0001 1110 1111 0101 1111 1010 1010 // output [0] : 1000 0001 1110 1111 0101 1111 1010 1010 // output [1] : 0000 0011 1101 1110 1011 1111 0101 0100 // output [2] : 0000 0111 1011 1101 0111 1110 1010 1000 // output [3] : 0000 1111 0111 1010 1111 1101 0101 0000 // output [4] : 0001 1110 1111 0101 1111 1010 1010 0000 // output [5] : 0011 1101 1110 1011 1111 0101 0100 0000 // output [6] : 0111 1011 1101 0111 1110 1010 1000 0000 // output [7] : 1111 0111 1010 1111 1101 0101 0000 0000 unsigned char input[4] = {0x81, 0xEF, 0x5F, 0xAA}; unsigned char output_test_0[4] = {0x81, 0xEF, 0x5F, 0xAA}; unsigned char output_test_1[4] = {0x03, 0xDE, 0xBF, 0x54}; unsigned char output_test_2[4] = {0x07, 0xBD, 0x7E, 0xA8}; unsigned char output_test_3[4] = {0x0F, 0x7A, 0xFD, 0x50}; unsigned char output_test_4[4] = {0x1E, 0xF5, 0xFA, 0xA0}; unsigned char output_test_5[4] = {0x3D, 0xEB, 0xF5, 0x40}; unsigned char output_test_6[4] = {0x7B, 0xD7, 0xEA, 0x80}; unsigned char output_test_7[4] = {0xF7, 0xAF, 0xD5, 0x00}; unsigned char output[4]; // // run tests // unsigned int i; for (i=0; i<8; i++) { memmove(output, input, 4); liquid_lbshift( output, 4, i); switch (i) { case 0: CONTEND_SAME_DATA( output, output_test_0, 4 ); break; case 1: CONTEND_SAME_DATA( output, output_test_1, 4 ); break; case 2: CONTEND_SAME_DATA( output, output_test_2, 4 ); break; case 3: CONTEND_SAME_DATA( output, output_test_3, 4 ); break; case 4: CONTEND_SAME_DATA( output, output_test_4, 4 ); break; case 5: CONTEND_SAME_DATA( output, output_test_5, 4 ); break; case 6: CONTEND_SAME_DATA( output, output_test_6, 4 ); break; case 7: CONTEND_SAME_DATA( output, output_test_7, 4 ); break; default:; } } } // // AUTOTEST : rbshift // void autotest_rbshift() { // input : 1000 0001 1110 1111 0101 1111 1010 1010 // output [0] : 1000 0001 1110 1111 0101 1111 1010 1010 // output [1] : 0100 0000 1111 0111 1010 1111 1101 0101 // output [2] : 0010 0000 0111 1011 1101 0111 1110 1010 // output [3] : 0001 0000 0011 1101 1110 1011 1111 0101 // output [4] : 0000 1000 0001 1110 1111 0101 1111 1010 // output [5] : 0000 0100 0000 1111 0111 1010 1111 1101 // output [6] : 0000 0010 0000 0111 1011 1101 0111 1110 // output [7] : 0000 0001 0000 0011 1101 1110 1011 1111 unsigned char input[4] = {0x81, 0xEF, 0x5F, 0xAA}; unsigned char output_test_0[4] = {0x81, 0xEF, 0x5F, 0xAA}; unsigned char output_test_1[4] = {0x40, 0xF7, 0xAF, 0xD5}; unsigned char output_test_2[4] = {0x20, 0x7B, 0xD7, 0xEA}; unsigned char output_test_3[4] = {0x10, 0x3D, 0xEB, 0xF5}; unsigned char output_test_4[4] = {0x08, 0x1E, 0xF5, 0xFA}; unsigned char output_test_5[4] = {0x04, 0x0F, 0x7A, 0xFD}; unsigned char output_test_6[4] = {0x02, 0x07, 0xBD, 0x7E}; unsigned char output_test_7[4] = {0x01, 0x03, 0xDE, 0xBF}; unsigned char output[4]; // // run tests // unsigned int i; for (i=0; i<8; i++) { memmove(output, input, 4); liquid_rbshift( output, 4, i); switch (i) { case 0: CONTEND_SAME_DATA( output, output_test_0, 4 ); break; case 1: CONTEND_SAME_DATA( output, output_test_1, 4 ); break; case 2: CONTEND_SAME_DATA( output, output_test_2, 4 ); break; case 3: CONTEND_SAME_DATA( output, output_test_3, 4 ); break; case 4: CONTEND_SAME_DATA( output, output_test_4, 4 ); break; case 5: CONTEND_SAME_DATA( output, output_test_5, 4 ); break; case 6: CONTEND_SAME_DATA( output, output_test_6, 4 ); break; case 7: CONTEND_SAME_DATA( output, output_test_7, 4 ); break; default:; } } } // // AUTOTEST : lbcircshift // void autotest_lbcircshift() { // input : 1001 0001 1110 1111 0101 1111 1010 1010 // output [0] : 1001 0001 1110 1111 0101 1111 1010 1010 // output [1] : 0010 0011 1101 1110 1011 1111 0101 0101 // output [2] : 0100 0111 1011 1101 0111 1110 1010 1010 // output [3] : 1000 1111 0111 1010 1111 1101 0101 0100 // output [4] : 0001 1110 1111 0101 1111 1010 1010 1001 // output [5] : 0011 1101 1110 1011 1111 0101 0101 0010 // output [6] : 0111 1011 1101 0111 1110 1010 1010 0100 // output [7] : 1111 0111 1010 1111 1101 0101 0100 1000 unsigned char input[4] = {0x91, 0xEF, 0x5F, 0xAA}; unsigned char output_test_0[4] = {0x91, 0xEF, 0x5F, 0xAA}; unsigned char output_test_1[4] = {0x23, 0xDE, 0xBF, 0x55}; unsigned char output_test_2[4] = {0x47, 0xBD, 0x7E, 0xAA}; unsigned char output_test_3[4] = {0x8F, 0x7A, 0xFD, 0x54}; unsigned char output_test_4[4] = {0x1E, 0xF5, 0xFA, 0xA9}; unsigned char output_test_5[4] = {0x3D, 0xEB, 0xF5, 0x52}; unsigned char output_test_6[4] = {0x7B, 0xD7, 0xEA, 0xA4}; unsigned char output_test_7[4] = {0xF7, 0xAF, 0xD5, 0x48}; unsigned char output[4]; // // run tests // unsigned int i; for (i=0; i<8; i++) { memmove(output, input, 4); liquid_lbcircshift( output, 4, i); switch (i) { case 0: CONTEND_SAME_DATA( output, output_test_0, 4 ); break; case 1: CONTEND_SAME_DATA( output, output_test_1, 4 ); break; case 2: CONTEND_SAME_DATA( output, output_test_2, 4 ); break; case 3: CONTEND_SAME_DATA( output, output_test_3, 4 ); break; case 4: CONTEND_SAME_DATA( output, output_test_4, 4 ); break; case 5: CONTEND_SAME_DATA( output, output_test_5, 4 ); break; case 6: CONTEND_SAME_DATA( output, output_test_6, 4 ); break; case 7: CONTEND_SAME_DATA( output, output_test_7, 4 ); break; default:; } } } // // AUTOTEST : rbcircshift // void autotest_rbcircshift() { // input : 1001 0001 1110 1111 0101 1111 1010 1010 // output [0] : 1001 0001 1110 1111 0101 1111 1010 1010 // output [1] : 0100 1000 1111 0111 1010 1111 1101 0101 // output [2] : 1010 0100 0111 1011 1101 0111 1110 1010 // output [3] : 0101 0010 0011 1101 1110 1011 1111 0101 // output [4] : 1010 1001 0001 1110 1111 0101 1111 1010 // output [5] : 0101 0100 1000 1111 0111 1010 1111 1101 // output [6] : 1010 1010 0100 0111 1011 1101 0111 1110 // output [7] : 0101 0101 0010 0011 1101 1110 1011 1111 unsigned char input[4] = {0x91, 0xEF, 0x5F, 0xAA}; unsigned char output_test_0[4] = {0x91, 0xEF, 0x5F, 0xAA}; unsigned char output_test_1[4] = {0x48, 0xF7, 0xAF, 0xD5}; unsigned char output_test_2[4] = {0xA4, 0x7B, 0xD7, 0xEA}; unsigned char output_test_3[4] = {0x52, 0x3D, 0xEB, 0xF5}; unsigned char output_test_4[4] = {0xA9, 0x1E, 0xF5, 0xFA}; unsigned char output_test_5[4] = {0x54, 0x8F, 0x7A, 0xFD}; unsigned char output_test_6[4] = {0xAA, 0x47, 0xBD, 0x7E}; unsigned char output_test_7[4] = {0x55, 0x23, 0xDE, 0xBF}; unsigned char output[4]; // // run tests // unsigned int i; for (i=0; i<8; i++) { memmove(output, input, 4); liquid_rbcircshift( output, 4, i); switch (i) { case 0: CONTEND_SAME_DATA( output, output_test_0, 4 ); break; case 1: CONTEND_SAME_DATA( output, output_test_1, 4 ); break; case 2: CONTEND_SAME_DATA( output, output_test_2, 4 ); break; case 3: CONTEND_SAME_DATA( output, output_test_3, 4 ); break; case 4: CONTEND_SAME_DATA( output, output_test_4, 4 ); break; case 5: CONTEND_SAME_DATA( output, output_test_5, 4 ); break; case 6: CONTEND_SAME_DATA( output, output_test_6, 4 ); break; case 7: CONTEND_SAME_DATA( output, output_test_7, 4 ); break; default:; } } } liquid-dsp-1.3.1/src/utility/tests/count_bits_autotest.c000066400000000000000000000201151317124540100234650ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "autotest/autotest.h" #include "liquid.internal.h" // // AUTOTEST: count number of ones in an integer // void autotest_count_ones() { CONTEND_EQUALITY( liquid_count_ones(0x0000), 0 ); CONTEND_EQUALITY( liquid_count_ones(0x0001), 1 ); CONTEND_EQUALITY( liquid_count_ones(0x0003), 2 ); CONTEND_EQUALITY( liquid_count_ones(0xFFFF), 16 ); CONTEND_EQUALITY( liquid_count_ones(0x00FF), 8 ); CONTEND_EQUALITY( liquid_count_ones(0x5555), 8 ); CONTEND_EQUALITY( liquid_count_ones(0x0007), 3 ); CONTEND_EQUALITY( liquid_count_ones(0x0037), 5 ); CONTEND_EQUALITY( liquid_count_ones(0x0137), 6 ); CONTEND_EQUALITY( liquid_count_ones(0xf137), 10 ); } // // AUTOTEST: count number of ones in an integer (modulo 2) // void autotest_count_ones_mod2() { CONTEND_EQUALITY( liquid_count_ones_mod2(0x0000), 0 ); CONTEND_EQUALITY( liquid_count_ones_mod2(0x0001), 1 ); CONTEND_EQUALITY( liquid_count_ones_mod2(0x0003), 0 ); CONTEND_EQUALITY( liquid_count_ones_mod2(0xFFFF), 0 ); CONTEND_EQUALITY( liquid_count_ones_mod2(0x00FF), 0 ); CONTEND_EQUALITY( liquid_count_ones_mod2(0x5555), 0 ); CONTEND_EQUALITY( liquid_count_ones_mod2(0x0007), 1 ); CONTEND_EQUALITY( liquid_count_ones_mod2(0x0037), 1 ); CONTEND_EQUALITY( liquid_count_ones_mod2(0x0137), 0 ); CONTEND_EQUALITY( liquid_count_ones_mod2(0xf137), 0 ); } // // AUTOTEST: binary dot product // void autotest_bdotprod() { // simple checks CONTEND_EQUALITY( liquid_bdotprod(0x1111,0x1111), 0 ); CONTEND_EQUALITY( liquid_bdotprod(0xffff,0xffff), 0 ); CONTEND_EQUALITY( liquid_bdotprod(0xffff,0x0000), 0 ); CONTEND_EQUALITY( liquid_bdotprod(0x0001,0x0001), 1 ); // random data CONTEND_EQUALITY( liquid_bdotprod(0x4379, 0xf2dc), 1); CONTEND_EQUALITY( liquid_bdotprod(0xc9a1, 0xc99d), 0); CONTEND_EQUALITY( liquid_bdotprod(0xa8ba, 0x26d9), 0); CONTEND_EQUALITY( liquid_bdotprod(0x5235, 0x8e1b), 1); CONTEND_EQUALITY( liquid_bdotprod(0x0f85, 0xa3d1), 0); CONTEND_EQUALITY( liquid_bdotprod(0x23e0, 0x5869), 0); CONTEND_EQUALITY( liquid_bdotprod(0xc8a4, 0x32a4), 1); CONTEND_EQUALITY( liquid_bdotprod(0xe1c3, 0x000c), 0); CONTEND_EQUALITY( liquid_bdotprod(0x4039, 0x192d), 1); CONTEND_EQUALITY( liquid_bdotprod(0x2e1c, 0x55a3), 1); CONTEND_EQUALITY( liquid_bdotprod(0x5a1b, 0x0241), 0); CONTEND_EQUALITY( liquid_bdotprod(0x440c, 0x7ddb), 1); CONTEND_EQUALITY( liquid_bdotprod(0xd2e2, 0x5c98), 1); CONTEND_EQUALITY( liquid_bdotprod(0xe36c, 0x5bc9), 1); CONTEND_EQUALITY( liquid_bdotprod(0xaa96, 0xf233), 1); CONTEND_EQUALITY( liquid_bdotprod(0xab0f, 0x3912), 0); } // // AUTOTEST: count number of leading zeros in an integer // void autotest_count_leading_zeros() { // NOTE: this tests assumes a 4-byte integer CONTEND_EQUALITY( liquid_count_leading_zeros(0x00000000), 32 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00000001), 31 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00000002), 30 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00000004), 29 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00000008), 28 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00000010), 27 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00000020), 26 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00000040), 25 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00000080), 24 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00000100), 23 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00000200), 22 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00000400), 21 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00000800), 20 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00001000), 19 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00002000), 18 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00004000), 17 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00008000), 16 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00010000), 15 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00020000), 14 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00040000), 13 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00080000), 12 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00100000), 11 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00200000), 10 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00400000), 9 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x00800000), 8 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x01000000), 7 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x02000000), 6 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x04000000), 5 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x08000000), 4 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x10000000), 3 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x20000000), 2 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x40000000), 1 ); CONTEND_EQUALITY( liquid_count_leading_zeros(0x80000000), 0 ); } // // AUTOTEST: find location of most-significant bit // void autotest_msb_index() { // NOTE: this tests assumes a 4-byte integer CONTEND_EQUALITY( liquid_msb_index(0x00000000), 0 ); CONTEND_EQUALITY( liquid_msb_index(0x00000001), 1 ); CONTEND_EQUALITY( liquid_msb_index(0x00000002), 2 ); CONTEND_EQUALITY( liquid_msb_index(0x00000004), 3 ); CONTEND_EQUALITY( liquid_msb_index(0x00000008), 4 ); CONTEND_EQUALITY( liquid_msb_index(0x00000010), 5 ); CONTEND_EQUALITY( liquid_msb_index(0x00000020), 6 ); CONTEND_EQUALITY( liquid_msb_index(0x00000040), 7 ); CONTEND_EQUALITY( liquid_msb_index(0x00000080), 8 ); CONTEND_EQUALITY( liquid_msb_index(0x00000100), 9 ); CONTEND_EQUALITY( liquid_msb_index(0x00000200), 10 ); CONTEND_EQUALITY( liquid_msb_index(0x00000400), 11 ); CONTEND_EQUALITY( liquid_msb_index(0x00000800), 12 ); CONTEND_EQUALITY( liquid_msb_index(0x00001000), 13 ); CONTEND_EQUALITY( liquid_msb_index(0x00002000), 14 ); CONTEND_EQUALITY( liquid_msb_index(0x00004000), 15 ); CONTEND_EQUALITY( liquid_msb_index(0x00008000), 16 ); CONTEND_EQUALITY( liquid_msb_index(0x00010000), 17 ); CONTEND_EQUALITY( liquid_msb_index(0x00020000), 18 ); CONTEND_EQUALITY( liquid_msb_index(0x00040000), 19 ); CONTEND_EQUALITY( liquid_msb_index(0x00080000), 20 ); CONTEND_EQUALITY( liquid_msb_index(0x00100000), 21 ); CONTEND_EQUALITY( liquid_msb_index(0x00200000), 22 ); CONTEND_EQUALITY( liquid_msb_index(0x00400000), 23 ); CONTEND_EQUALITY( liquid_msb_index(0x00800000), 24 ); CONTEND_EQUALITY( liquid_msb_index(0x01000000), 25 ); CONTEND_EQUALITY( liquid_msb_index(0x02000000), 26 ); CONTEND_EQUALITY( liquid_msb_index(0x04000000), 27 ); CONTEND_EQUALITY( liquid_msb_index(0x08000000), 28 ); CONTEND_EQUALITY( liquid_msb_index(0x10000000), 29 ); CONTEND_EQUALITY( liquid_msb_index(0x20000000), 30 ); CONTEND_EQUALITY( liquid_msb_index(0x40000000), 31 ); CONTEND_EQUALITY( liquid_msb_index(0x80000000), 32 ); } liquid-dsp-1.3.1/src/utility/tests/pack_bytes_autotest.c000066400000000000000000000172601317124540100234470ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include "autotest/autotest.h" #include "liquid.internal.h" // // AUTOTEST : pack_array // void autotest_pack_array() { // input symbols unsigned int sym_size[9] = {8, 2, 3, 6, 1, 3, 3, 4, 3}; unsigned char input[9] = { 0x81, // 1000 0001 0x03, // 11 0x05, // 101 0x3a, // 11 1010 0x01, // 1 0x07, // 111 0x06, // 110 0x0a, // 1010 0x04 // 10[0] <- last bit is stripped }; // output : 1000 0001 1110 1111 0101 1111 1010 1010 // symbol : 0000 0000 1122 2333 3334 5556 6677 7788 unsigned char output_test[4] = {0x81, 0xEF, 0x5F, 0xAA}; unsigned char output[4] = {0xff, 0xff, 0xff, 0xff}; unsigned int k=0; unsigned int i; for (i=0; i<9; i++) { liquid_pack_array(output, 4, k, sym_size[i], input[i]); k += sym_size[i]; } CONTEND_SAME_DATA( output, output_test, 4 ); } // // AUTOTEST : unpack_array // void autotest_unpack_array() { // input : 1000 0001 1110 1111 0101 1111 1010 1010 // symbol : 0000 0000 1122 2333 3334 5556 6677 7788 unsigned char input[4] = {0x81, 0xEF, 0x5F, 0xAA}; unsigned int sym_size[9] = {8, 2, 3, 6, 1, 3, 3, 4, 3}; // output syms unsigned char output_test[9] = { 0x81, // 1000 0001 0x03, // 11 0x05, // 101 0x3a, // 11 1010 0x01, // 1 0x07, // 111 0x06, // 110 0x0a, // 1010 0x04 // 10[0] <- last bit is implied }; unsigned char output[9]; unsigned int k=0; unsigned int i; for (i=0; i<9; i++) { liquid_unpack_array(input, 4, k, sym_size[i], &output[i]); k += sym_size[i]; } CONTEND_SAME_DATA( output, output_test, 9 ); } // // AUTOTEST : unpack/pack_array // void autotest_repack_array() { unsigned int n=512; // input/output array size unsigned char src[n]; // original data array unsigned char dst[n]; // repacked data array unsigned int i; // initialize input/output arrays for (i=0; i #include "autotest/autotest.h" #include "liquid.internal.h" // // AUTOTEST : lshift // void autotest_lshift() { // input : 1000 0001 1110 1111 0101 1111 1010 1010 // output [0] : 1000 0001 1110 1111 0101 1111 1010 1010 // output [1] : 1110 1111 0101 1111 1010 1010 0000 0000 // output [2] : 0101 1111 1010 1010 0000 0000 0000 0000 // output [3] : 1010 1010 0000 0000 0000 0000 0000 0000 // output [4] : 0000 0000 0000 0000 0000 0000 0000 0000 unsigned char input[4] = {0x81, 0xEF, 0x5F, 0xAA}; unsigned char output_test_0[4] = {0x81, 0xEF, 0x5F, 0xAA}; unsigned char output_test_1[4] = {0xEF, 0x5F, 0xAA, 0x00}; unsigned char output_test_2[4] = {0x5F, 0xAA, 0x00, 0x00}; unsigned char output_test_3[4] = {0xAA, 0x00, 0x00, 0x00}; unsigned char output_test_4[4] = {0x00, 0x00, 0x00, 0x00}; unsigned char output[4]; // // run tests // unsigned int i; for (i=0; i<5; i++) { memmove(output, input, 4); liquid_lshift( output, 4, i); switch (i) { case 0: CONTEND_SAME_DATA( output, output_test_0, 4 ); break; case 1: CONTEND_SAME_DATA( output, output_test_1, 4 ); break; case 2: CONTEND_SAME_DATA( output, output_test_2, 4 ); break; case 3: CONTEND_SAME_DATA( output, output_test_3, 4 ); break; case 4: CONTEND_SAME_DATA( output, output_test_4, 4 ); break; default:; } } } // // AUTOTEST : rshift // void autotest_rshift() { // input : 1000 0001 1110 1111 0101 1111 1010 1010 // output [0] : 1000 0001 1110 1111 0101 1111 1010 1010 // output [1] : 0000 0000 1000 0001 1110 1111 0101 1111 // output [2] : 0000 0000 0000 0000 1000 0001 1110 1111 // output [3] : 0000 0000 0000 0000 0000 0000 1000 0001 // output [4] : 0000 0000 0000 0000 0000 0000 0000 0000 unsigned char input[4] = {0x81, 0xEF, 0x5F, 0xAA}; unsigned char output_test_0[4] = {0x81, 0xEF, 0x5F, 0xAA}; unsigned char output_test_1[4] = {0x00, 0x81, 0xEF, 0x5F}; unsigned char output_test_2[4] = {0x00, 0x00, 0x81, 0xEF}; unsigned char output_test_3[4] = {0x00, 0x00, 0x00, 0x81}; unsigned char output_test_4[4] = {0x00, 0x00, 0x00, 0x00}; unsigned char output[4]; // // run tests // unsigned int i; for (i=0; i<5; i++) { memmove(output, input, 4); liquid_rshift( output, 4, i); switch (i) { case 0: CONTEND_SAME_DATA( output, output_test_0, 4 ); break; case 1: CONTEND_SAME_DATA( output, output_test_1, 4 ); break; case 2: CONTEND_SAME_DATA( output, output_test_2, 4 ); break; case 3: CONTEND_SAME_DATA( output, output_test_3, 4 ); break; case 4: CONTEND_SAME_DATA( output, output_test_4, 4 ); break; default:; } } } // // AUTOTEST : lcircshift // void autotest_lcircshift() { // input : 1000 0001 1110 1111 0101 1111 1010 1010 // output [0] : 1000 0001 1110 1111 0101 1111 1010 1010 // output [1] : 1110 1111 0101 1111 1010 1010 1000 0001 // output [2] : 0101 1111 1010 1010 1000 0001 1110 1111 // output [3] : 1010 1010 1000 0001 1110 1111 0101 1111 // output [4] : 1000 0001 1110 1111 0101 1111 1010 1010 unsigned char input[4] = {0x81, 0xEF, 0x5F, 0xAA}; unsigned char output_test_0[4] = {0x81, 0xEF, 0x5F, 0xAA}; unsigned char output_test_1[4] = {0xEF, 0x5F, 0xAA, 0x81}; unsigned char output_test_2[4] = {0x5F, 0xAA, 0x81, 0xEF}; unsigned char output_test_3[4] = {0xAA, 0x81, 0xEF, 0x5F}; unsigned char output_test_4[4] = {0x81, 0xEF, 0x5F, 0xAA}; unsigned char output[4]; // // run tests // unsigned int i; for (i=0; i<5; i++) { memmove(output, input, 4); liquid_lcircshift( output, 4, i); switch (i) { case 0: CONTEND_SAME_DATA( output, output_test_0, 4 ); break; case 1: CONTEND_SAME_DATA( output, output_test_1, 4 ); break; case 2: CONTEND_SAME_DATA( output, output_test_2, 4 ); break; case 3: CONTEND_SAME_DATA( output, output_test_3, 4 ); break; case 4: CONTEND_SAME_DATA( output, output_test_4, 4 ); break; default:; } } } // // AUTOTEST : rcircshift // void autotest_rcircshift() { // input : 1000 0001 1110 1111 0101 1111 1010 1010 // output [0] : 1000 0001 1110 1111 0101 1111 1010 1010 // output [1] : 1010 1010 1000 0001 1110 1111 0101 1111 // output [2] : 0101 1111 1010 1010 1000 0001 1110 1111 // output [3] : 1110 1111 0101 1111 1010 1010 1000 0001 // output [4] : 1000 0001 1110 1111 0101 1111 1010 1010 unsigned char input[4] = {0x81, 0xEF, 0x5F, 0xAA}; unsigned char output_test_0[4] = {0x81, 0xEF, 0x5F, 0xAA}; unsigned char output_test_1[4] = {0xAA, 0x81, 0xEF, 0x5F}; unsigned char output_test_2[4] = {0x5F, 0xAA, 0x81, 0xEF}; unsigned char output_test_3[4] = {0xEF, 0x5F, 0xAA, 0x81}; unsigned char output_test_4[4] = {0x81, 0xEF, 0x5F, 0xAA}; unsigned char output[4]; // // run tests // unsigned int i; for (i=0; i<5; i++) { memmove(output, input, 4); liquid_rcircshift( output, 4, i); switch (i) { case 0: CONTEND_SAME_DATA( output, output_test_0, 4 ); break; case 1: CONTEND_SAME_DATA( output, output_test_1, 4 ); break; case 2: CONTEND_SAME_DATA( output, output_test_2, 4 ); break; case 3: CONTEND_SAME_DATA( output, output_test_3, 4 ); break; case 4: CONTEND_SAME_DATA( output, output_test_4, 4 ); break; default:; } } } liquid-dsp-1.3.1/src/vector/000077500000000000000000000000001317124540100156565ustar00rootroot00000000000000liquid-dsp-1.3.1/src/vector/src/000077500000000000000000000000001317124540100164455ustar00rootroot00000000000000liquid-dsp-1.3.1/src/vector/src/vector_add.c000066400000000000000000000051501317124540100207240ustar00rootroot00000000000000/* * Copyright (c) 2007 - 2015 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // // Generic vector addition // #include #include #include // basic vector addition, unrolling loop // _x : first array [size: _n x 1] // _y : second array [size: _n x 1] // _n : array lengths // _z : output array pointer [size: _n x 1] void VECTOR(_add)(T * _x, T * _y, unsigned int _n, T * _z) { // t = 4*(floor(_n/4)) unsigned int t=(_n>>2)<<2; // compute in groups of 4 unsigned int i; for (i=0; i>2)<<2; // compute in groups of 4 unsigned int i; for (i=0; i #include #include // basic vector multiplication, unrolling loop // _x : first array [size: _n x 1] // _y : second array [size: _n x 1] // _n : array lengths // _z : output array pointer [size: _n x 1] void VECTOR(_mul)(T * _x, T * _y, unsigned int _n, T * _z) { // t = 4*(floor(_n/4)) unsigned int t=(_n>>2)<<2; // compute in groups of 4 unsigned int i; for (i=0; i>2)<<2; // compute in groups of 4 unsigned int i; for (i=0; i #include #include #include // compute l2-norm on vector // _x : input array [size: _n x 1] // _n : array length TP VECTOR(_norm)(T * _x, unsigned int _n) { // t = 4*(floor(_n/4)) unsigned int t=(_n>>2)<<2; // initialize accumulator TP norm = 0; // compute in groups of 4 // TODO: use generic 'real' and 'conj' functions unsigned int i; for (i=0; i>2)<<2; // scale by inverse; compute in groups of 4 unsigned int i; for (i=0; i #include #include #include #include // compute complex phase rotation: x[i] = exp{ j theta[i] } // _theta : input primitive array [size: _n x 1] // _n : array length // _x : output array pointer [size: _n x 1] void VECTOR(_cexpj)(TP * _theta, unsigned int _n, T * _x) { // t = 4*(floor(_n/4)) unsigned int t=(_n>>2)<<2; // compute in groups of 4 unsigned int i; for (i=0; i 0 ? 1.0 : -1.0; _x[i+1] = _theta[i+1] > 0 ? 1.0 : -1.0; _x[i+2] = _theta[i+2] > 0 ? 1.0 : -1.0; _x[i+3] = _theta[i+3] > 0 ? 1.0 : -1.0; #endif } // clean up remaining for ( ; i<_n; i++) { #if T_COMPLEX _x[i] = cexpf(_Complex_I*_theta[i]); #else _x[i] = _theta[i] > 0 ? 1.0 : -1.0; #endif } } // compute complex phase rotation: x[i] = exp{ j theta[i] } // _x : input array [size: _n x 1] // _n : array length // _theta : output primitive array [size: _n x 1] void VECTOR(_carg)(T * _x, unsigned int _n, TP * _theta) { // t = 4*(floor(_n/4)) unsigned int t=(_n>>2)<<2; // compute in groups of 4 unsigned int i; for (i=0; i 0 ? 0 : M_PI; _theta[i+1] = _x[i+1] > 0 ? 0 : M_PI; _theta[i+2] = _x[i+2] > 0 ? 0 : M_PI; _theta[i+3] = _x[i+3] > 0 ? 0 : M_PI; #endif } // clean up remaining for ( ; i<_n; i++) { #if T_COMPLEX _theta[i] = cargf(_x[i]); #else _theta[i] = _x[i] > 0 ? 0 : M_PI; #endif } } // compute absolute value of each element: y[i] = |x[i]| // _x : input array [size: _n x 1] // _n : array length // _y : output primitive array pointer [size: _n x 1] void VECTOR(_abs)(T * _x, unsigned int _n, TP * _y) { // t = 4*(floor(_n/4)) unsigned int t=(_n>>2)<<2; // compute in groups of 4 unsigned int i; for (i=0; i