pax_global_header00006660000000000000000000000064137062504110014511gustar00rootroot0000000000000052 comment=1351c8aec426d7f871a3cc3aa30f7a2464cc96e7 rtfilter-1.3/000077500000000000000000000000001370625041100132075ustar00rootroot00000000000000rtfilter-1.3/.gitignore000066400000000000000000000011051370625041100151740ustar00rootroot00000000000000# python generated files *.pyc __pycache__ # external tool files *.swp tags /cscope.* *.unc-backup~ *.unc-backup.md5~ *.uncrustify *.gcno # autotools generated files aclocal.m4 Makefile.in configure config.log config.status configure.scan install-sh missing stamp-h1 libtool compile Makefile Makefile.in .deps INSTALL ABOUT-NLS .dirstamp *.tar.xz autom4te.cache/* build-aux/* .libs/ # unit-test generated files *.log *.trs # ignore build-directory if any /build* # C generated objects *.o *.la *.lo a.out # generated files /unittests.tap /butterworth # nfs tmp files *.nfs* rtfilter-1.3/AUTHORS000066400000000000000000000002561370625041100142620ustar00rootroot00000000000000Copyright (C) 2008-2011 Nicolas Bourdaud Nicolas Bourdaud (CNBI lab, EPFL) Juan Felipe Restrepo Rinckoar rtfilter-1.3/COPYING000066400000000000000000000167431370625041100142550ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. rtfilter-1.3/Makefile.am000066400000000000000000000170641370625041100152530ustar00rootroot00000000000000eol= ACLOCAL_AMFLAGS = -I m4 --install EXTRA_DIST = autogen.sh CLEANFILES = lib_LTLIBRARIES = librtfilter.la AM_CPPFLAGS = \ -I$(srcdir)/src \ -DSRCDIR=\"$(srcdir)\" \ -DBUILDDIR=\"$(builddir)\" \ $(CHECK_CPPFLAGS) \ $(eol) AM_CFLAGS = \ $(WARNFLAGS) \ $(eol) librtfilter_la_SOURCES = \ src/common-filters.c \ src/downsampler.c \ src/filter.c \ src/filter-complex-double.c \ src/filter-complex-single.c \ src/filter-funcs.h \ src/filter-inreal-outcomplex-double.c \ src/filter-inreal-outcomplex-single.c \ src/filter-internal.h \ src/filter-real-double.c \ src/filter-real-single.c \ src/probesimd.h \ src/rtf_common.h \ src/rtfilter.h \ $(eol) filter_templates = \ src/filter-func-template.c \ src/init-filter-func-template.c \ $(eol) EXTRA_DIST += $(filter_templates) include_HEADERS = \ src/rtfilter.h \ src/rtf_common.h \ $(eol) librtfilter_la_LDFLAGS = \ $(AM_LDFLAGS) \ -no-undefined \ -version-info $(CURRENT):$(REVISION):$(AGE) \ $(eol) librtfilter_la_CFLAGS = \ $(AM_CFLAGS) \ $(FASTMATH_CFLAG) \ $(eol) noinst_LTLIBRARIES = librtfilter_la_LIBADD = if BUILD_SSE_SUPPORT libfiltersse_la_SOURCES = \ src/filter-funcs.h \ src/filter-internal.h \ src/filter-sse.c \ $(eol) libfiltersse_la_CFLAGS = $(AM_CFLAGS) $(FASTMATH_CFLAG) $(SSE_CFLAGS) noinst_LTLIBRARIES += libfiltersse.la librtfilter_la_LIBADD += libfiltersse.la endif if BUILD_SSE2_SUPPORT libfiltersse2_la_SOURCES = \ src/filter-funcs.h \ src/filter-internal.h \ src/filter-sse2.c \ $(eol) libfiltersse2_la_CFLAGS = $(AM_CFLAGS) $(FASTMATH_CFLAG) $(SSE2_CFLAGS) noinst_LTLIBRARIES += libfiltersse2.la librtfilter_la_LIBADD += libfiltersse2.la endif if BUILD_SSE3_SUPPORT libfiltersse3_la_SOURCES = \ src/filter-funcs.h \ src/filter-internal.h \ src/filter-sse3.c \ $(eol) libfiltersse3_la_CFLAGS = $(AM_CFLAGS) $(FASTMATH_CFLAG) $(SSE3_CFLAGS) noinst_LTLIBRARIES += libfiltersse3.la librtfilter_la_LIBADD += libfiltersse3.la endif if HAVE_LD_OUTPUT_DEF librtfilter_la_LDFLAGS += -Wl,--output-def,librtfilter-$(CURRENT).def defexecdir = $(bindir) defexec_DATA = librtfilter-$(CURRENT).def DISTCLEANFILES = $(defexec_DATA) $(defexec_DATA): librtfilter.la endif # HAVE_LD_OUTPUT_DEF pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = src/rtfilter.pc # # DOC RULES # doc_DATA = AUTHORS NEWS README.md COPYING nobase_dist_doc_DATA = \ doc/examples/butterworth.c \ doc/examples/Makefile \ $(eol) # Verify at least that the example compiles check_PROGRAMS = butterworth butterworth_SOURCES = \ doc/examples/butterworth.c \ $(eol) butterworth_LDADD = \ librtfilter.la \ $(eol) DOC_SRCS = \ doc/index.rst \ doc/rtfilter.rst \ $(eol) export srctree=$(SRCTREE) # # Sphinx documentation build targets # Skipped if --enable-sphinxdoc=no # if BUILD_SPHINXDOC SPHINXBUILD = sphinx-build SRCTREE = $(top_srcdir) sphinx_verbose = $(sphinx_verbose_@AM_V@) sphinx_verbose_ = $(sphinx_verbose_@AM_DEFAULT_V@) sphinx_verbose_0 = -q ALLSPHINXOPTS = -d $(builddir)/.doctrees $(sphinx_verbose) $(srcdir)/doc -c $(srcdir)/doc # Due to a dependency bug in sphinx-build, we use the -M option instead of # the usual -b one. This hidden option sums up to the same as -b with makefile # dependency support ... except that it does not support -W option which turns # warnings into errors ! # => do this with a simple grep line on the output # Since html target depends on man target, this is only needed once sphinx-build.log: $(wildcard $(SRCTREE)/src/*.[ch]) $(DOC_SRCS) @$(RM) -f manpages-buildstamp $(AM_V_GEN) $(SPHINXBUILD) -M kernel-doc-man $(ALLSPHINXOPTS) $(builddir)/man &> sphinx-build.log # sphinx-build.log target does the doc generation # This target checks that it was done right manpages-buildstamp: sphinx-build.log @if [ "$(shell grep -c WARNING: sphinx-build.log)" != "0" ] ; then \ grep WARNING: sphinx-build.log; \ false; \ fi @echo @echo "Build finished. The man pages are in $(builddir)/man." @touch $@ .PHONY: man-pages man-pages: manpages-buildstamp html-local: html-buildstamp # always generate html after man: parallel sphinx invocation is not upported html-buildstamp: $(wildcard $(SRCTREE)/src/*.[ch]) $(DOC_SRCS) manpages-buildstamp @$(RM) -f $@ $(AM_V_GEN) $(SPHINXBUILD) -M html $(ALLSPHINXOPTS) $(builddir)/html @echo @echo "Build finished. The HTML pages are in $(builddir)/html." @touch $@ install-html: html-buildstamp @mkdir -p $(DESTDIR)$(docdir)/html/ cd $(builddir)/html && \ find . -type f -exec $(install_sh_DATA) '{}' $(DESTDIR)$(docdir)/html/'{}' \; uninstall-html: $(RM) -r $(DESTDIR)$(docdir)/html/ install-man3: manpages-buildstamp @mkdir -p $(DESTDIR)$(mandir)/man3 $(foreach manpage, $(notdir $(wildcard $(builddir)/man/*.3)), \ $(install_sh_DATA) $(builddir)/man/$(manpage) $(DESTDIR)$(mandir)/man3/$(manpage);) uninstall-man3: manpages-buildstamp $(foreach manpage, $(notdir $(wildcard $(builddir)/man/*.3)), \ $(RM) $(DESTDIR)$(mandir)/man3/$(manpage);) @-rmdir $(mandir)/man3 all-local: manpages-buildstamp html-buildstamp install-data-local: install-man3 install-html uninstall-local: uninstall-man3 uninstall-html endif # BUILD_SPHINXDOC # # TESTS RULES # # alias "test" and "check" targets targets .PHONY: test test: check TEST_EXTENSIONS = .test .tap # if check support TAP output, make use of it if TAP_SUPPORT_IN_CHECK AM_CPPFLAGS += -DCHECK_SUPPORT_TAP TAP_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(srcdir)/build-aux/tap-driver.sh else TAP_LOG_DRIVER = $(LOG_DRIVER) endif # TAP_SUPPORT_IN_CHECK TESTS = \ unittests.tap \ $(eol) check_PROGRAMS += \ unittests.tap \ $(eol) if HAVE_CLOCK_FN check_PROGRAMS += perf-test endif unittests_tap_SOURCES = \ test/float-comparison.c \ test/float-comparison.h \ test/lowpass_test.c \ test/rtfilter_combine_test.c \ test/rtfilter_test.c \ test/testcases.h \ test/test-common.c \ test/test-common.h \ test/unittests.c \ $(eol) unittests_tap_CFLAGS = \ $(AM_CFLAGS) \ $(CHECK_CFLAGS) \ $(eol) unittests_tap_LDADD = \ $(CHECK_LIBS) \ .libs/librtfilter.la \ $(MATH_LIB) \ $(eol) perf_test_SOURCES = \ test/perf-test.c \ $(eol) perf_test_CFLAGS = \ $(AM_CFLAGS) \ $(eol) perf_test_LDADD = \ .libs/librtfilter.la \ $(MATH_LIB) \ $(eol) TESTS_ENVIRONMENT = PATH="$(PATH):$(buildir)" TESTSSRCDIR="$(srcdir)/tests" # only test rtfilter.h and not all exported headers: $(include_HEADERS) # "rtf_common.h" contains a #warning which would always make the test fail # otherwise .PHONY: api-compat-test api-compat-test: src/rtfilter.h $(srcdir)/devtools/api-compat-test.sh $(srcdir)/src $^ # # DEV TARGETS # # rewrite in-place all the source files with correct coding style EXTRA_DIST += devtools/uncrustify.cfg .PHONY: fixstyle fixstyle: devtools/uncrustify.cfg cd $(srcdir) && uncrustify -c devtools/uncrustify.cfg -l C --replace \ $(librtfilter_la_SOURCES) $(filter_templates) $(unittests_tap_SOURCES) \ $(perf_test_SOURCES) \ doc/examples/butterworth.c # check all the source files for correct coding style .PHONY: checkstyle checkstyle: devtools/uncrustify.cfg cd $(srcdir) && uncrustify -c devtools/uncrustify.cfg -l C --check \ $(librtfilter_la_SOURCES) $(filter_templates) $(unittests_tap_SOURCES) \ $(perf_test_SOURCES) \ doc/examples/butterworth.c # primitive syntax check on all the source files .PHONY: spelling spelling: $(librtfilter_la_SOURCES) $(filter_templates) $(dist_man_MANS) \ $(perf_test_SOURCES) \ $(unittests_tap_SOURCES) doc/examples/butterworth.c codespell --ignore-words-list=sinc $^ .PHONY: coverage coverage: $(srcdir)/devtools/coverage.sh run clean-local: $(RM) -rf html .doctrees man manpages-buildstamp html-buildstamp sphinx-build.log cd test && $(RM) *.gcno *.gcda rtfilter-1.3/NEWS000066400000000000000000000014171370625041100137110ustar00rootroot00000000000000rtfilter-1.1 ============ * Relicense code to LGPL3 * Select at runtime the optimal filter function depending on the host cpu (use of cpuid for the selection if on x86/x86_64 architecture) rtfilter-1.0 ============ * Adds complex type * Provides analytic filter in the filter design functions * Prefix all API functions with rtf_ * Provides a downsampler filter * Adds rtf_get_type API function to check the input and output of a filter * There is now only one filter function (rtf_filter) in the API * Small API changes * As the version number indicates, this version is not API nor API compatible with the previous version. However, the logic is similar and code using old version can be easily adapted. rtfilter-0.0.0 ============== * Initial release rtfilter-1.3/README.md000066400000000000000000000036401370625041100144710ustar00rootroot00000000000000# RTFILTER ## Presentation This package provides a library written in C implementing realtime digital filtering functions for multichannel signals (i.e. filtering multiple signals with the same filter). The core library implements FIR and IIR filtering for float and double data type. Additional functions are also provided to design few usual filters: Butterworth, Chebyshev, windowed sinc... In addition, the filter functions have been especially optimized for multichannel signals. If data allows it (and if possible with the compilation flags used), the library automatically switch to optimized SIMD (Single Instruction Multiple Data) code, allowing to reduce by 3~4 the time spent in processing the data. ## Supported platforms Any POSIX platform and windows. The SIMD code operating on real data is possible if the host CPU supports SSE2 instruction sets (Intel pentium4, AMD k8 or later processors support SSE2), and SIMD code operating on complex data is possible if host CPU supports SSE3. ## Compilation This library is organized as a GNU package and can be compiled and installed in the same way (see INSTALL file for further information). In order the library to be compiled with SIMD version of the filter functions, make sure you specify the correct architecture (add -march=target\_arch to CFLAGS with gcc) or enable the necessary instruction set (add -msse2 or -msse3 to CFLAGS with gcc) On x86 family platform, the 387 floating point coprocessor is well known to introduce some numerical error whose symptoms may be seen in the filter design functions. Therefore it is recommended to generate floating point code using SSE instructions whenever possible. By default, the configure script will specify the necessary compiler flags if gcc is used. If you use another compiler you may need set manually CFLAGS at the invokation of the configure script (see your compiler documentation to know which flags should be passed). rtfilter-1.3/autogen.sh000077500000000000000000000001161370625041100152060ustar00rootroot00000000000000#!/bin/sh -e cd $(dirname $0) # Generate the build scripts autoreconf -fi rtfilter-1.3/config/000077500000000000000000000000001370625041100144545ustar00rootroot00000000000000rtfilter-1.3/config/api-exports/000077500000000000000000000000001370625041100167275ustar00rootroot00000000000000rtfilter-1.3/config/api-exports/meson.build000066400000000000000000000012301370625041100210650ustar00rootroot00000000000000if host_machine.system() == 'windows' config.set('API_EXPORTED', '__declspec(dllexport)') config.set('LOCAL_FN', '') config.set('API_EXPORTED_RELOCATABLE', '__declspec(dllexport)') config.set('DEPRECATED', '__attribute__ ((deprecated))') config.set('HOTSPOT', '__attribute__ ((hot))') else config.set('API_EXPORTED', '__attribute__ ((visibility ("protected")))') config.set('LOCAL_FN', '__attribute__ ((visibility ("hidden")))') config.set('API_EXPORTED_RELOCATABLE', '__attribute__ ((visibility ("default")))') config.set('DEPRECATED', '__attribute__ ((deprecated))') config.set('HOTSPOT', '__attribute__ ((hot))') endif rtfilter-1.3/configure.ac000066400000000000000000000070571370625041100155060ustar00rootroot00000000000000# - If the library source code has changed at all since the last update, # then increment revision. # - If any interfaces have been added, removed, or changed since the last # update, increment current, and set revision to 0. # - If any interfaces have been added since the last public release, then # increment age. # - If any interfaces have been removed since the last public release, then # set age to 0. m4_define([lib_current],2) m4_define([lib_revision],1) m4_define([lib_age],1) # Setup Automake AC_INIT(rtfilter, [1.3],[nicolas.bourdaud@gmail.com]) AC_CONFIG_SRCDIR([src/filter.c]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([src/config.h]) AC_REQUIRE_AUX_FILE([tap-driver.sh]) # Initialize Automake AM_INIT_AUTOMAKE([subdir-objects no-dist-gzip dist-bzip2 color-tests foreign]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) AC_CANONICAL_HOST AC_CANONICAL_BUILD CC_WARNFLAGS AC_PROG_CC_C99 AM_PROG_CC_C_O LT_INIT([win32-dll disable-static]) AC_SUBST(LIBTOOL_DEPS) AC_DEF_HOTSPOT_ATTR AC_DEF_API_EXPORT_ATTRS AC_CHECK_FASTMATH_FLAG AC_USE_SSEMATH gl_LD_OUTPUT_DEF AC_CHECK_CPUID([tryaddsimd=yes], [tryaddsimd=no]) AC_SUPPORT_SSE([has_sse=yes], [has_sse=no], tryaddsimd) AC_SUPPORT_SSE2([has_sse2=yes], [has_sse2=no], tryaddsimd) AC_SUPPORT_SSE3([has_sse3=yes], [has_sse3=no], tryaddsimd) AM_CONDITIONAL(BUILD_SSE_SUPPORT, test "x$has_sse" = "xyes") AM_CONDITIONAL(BUILD_SSE2_SUPPORT, test "x$has_sse2" = "xyes") AM_CONDITIONAL(BUILD_SSE3_SUPPORT, test "x$has_sse3" = "xyes") # Optional build of 'check' based tests PKG_CHECK_MODULES_EXT(CHECK, [check >= 0.9.12], [has_check=yes; tap_in_check=yes], [PKG_CHECK_MODULES_EXT(CHECK, [check], [has_check=yes], [has_check=no])]) AC_ARG_WITH([check], AC_HELP_STRING([--with-check], [Build and run check based tests. @<:@default=detect@:>@]), [], [with_check=detect]) AS_CASE([$with_check], [yes], [AS_IF([test "$has_check" != no], [build_check_tests=yes], [AC_MSG_FAILURE([check required but not found])]) ], [no], [build_check_tests=no], [detect], [build_check_tests=$has_check], [AC_MSG_FAILURE([invalid argument for '--with-check' option])]) AM_CONDITIONAL(BUILD_CHECK_TESTS, [test "$build_check_tests" = yes]) AM_CONDITIONAL(TAP_SUPPORT_IN_CHECK, [test "x$tap_in_check" = xyes]) # Test for sphinx doc with linuxdoc AC_ARG_ENABLE([sphinxdoc], AC_HELP_STRING([--enable-sphinxdoc], [Build sphinx documention. @<:@default=detect@:>@]), [], [enable_sphinxdoc=detect]) AM_PATH_PYTHON([3]) MM_PYTHON_MODULE([sphinx]) MM_PYTHON_MODULE([sphinx_rtd_theme]) MM_PYTHON_MODULE([linuxdoc]) AC_CHECK_PROG(HAVE_SPHINXBUILD, [sphinx-build], [$HAVE_PYMOD_LINUXDOC], [no]) AS_CASE([$enable_sphinxdoc], [yes], [AS_IF([test "x$HAVE_SPHINXBUILD" != xyes], [AC_MSG_ERROR(Cannot find sphinx or its plugin linuxdoc)])], [detect], [AS_IF([test "x$HAVE_SPHINXBUILD" = xyes], [enable_sphinxdoc=yes], [enable_sphinxdoc=no])]) AM_CONDITIONAL(BUILD_SPHINXDOC, [test "x$enable_sphinxdoc" = xyes]) AC_SEARCH_LIBS([cos], [m], [], AC_MSG_ERROR([The math library cannot be found.])) AC_CHECK_FUNCS([posix_memalign]) # Test optional library save_LIBS=$LIBS AC_SEARCH_LIBS([clock_gettime], [rt], [hasclockfn=true], [hasclockfn=false]) OPTION_LIBS=$LIBS LIBS=$save_LIBS AC_SUBST([OPTION_LIBS]) AC_SUBST([LIBS]) AM_CONDITIONAL(HAVE_CLOCK_FN, test "x$hasclockfn" = "xtrue") AC_SUBST([CURRENT],[lib_current]) AC_SUBST([REVISION],[lib_revision]) AC_SUBST([AGE],[lib_age]) AC_CONFIG_FILES([Makefile src/rtfilter.pc]) AC_OUTPUT rtfilter-1.3/devtools/000077500000000000000000000000001370625041100150465ustar00rootroot00000000000000rtfilter-1.3/devtools/api-compat-test.sh000077500000000000000000000020421370625041100204120ustar00rootroot00000000000000#!/bin/bash set -e includedir=$1 shift 1 randomize_header_list() { for header in $@ ; do echo $header done | sort -R } all_headers=$(randomize_header_list $@) all_included() { for header in $all_headers ; do echo "#include \"$(basename $header)\"" done echo "int main(void) { return 0; }" } # dump compilers versions gcc --version # dump generated file all_included # test headers for compliance with most warnings for std in c99 c11 c17 gnu99 gnu11 gnu17 do echo "Test C language standard : $std" all_included | gcc -std=$std -x c - -I"$includedir" -Werror -Wall -Wextra -pedantic done # also test with clang if available if [ -x "$(which clang)" ] ; then clang --version all_included | clang -x c - -I"$includedir" -Weverything \ -Wno-documentation-unknown-command # silence doxygen-related warnings fi # test headers for C++ compatibility for std in c++11 c++14 c++17 gnu++11 gnu++14 gnu++17 do echo "Test C++ language standard : $std" all_included | gcc -std=$std -x c++ - -I"$includedir" -Werror -Wall -Wextra -pedantic done rtfilter-1.3/devtools/coverage.sh000077500000000000000000000015601370625041100172020ustar00rootroot00000000000000#!/bin/sh set -e COVERAGE_CFLAGS="-O0 -fprofile-arcs -ftest-coverage" test_coverage() { TESTING_COVERAGE=false make clean mkdir -p $covdir lcov --directory . --zerocounters -q make check CFLAGS="$COVERAGE_CFLAGS" lcov --compat-libtool --directory . --capture --output-file $covdir/app.info TESTING_COVERAGE=true make clean genhtml -o $covdir/ $covdir/app.info set -x firefox $covdir/index.html & { set +x; } 2> /dev/null } print_usage() { echo "Usage:" echo "\t$0 run [outdir]" 2>&1 echo "\t$0 clean [outdir]" 2>&1 } if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then echo "Illegal number of parameters" 2>&1 print_usage exit 1 fi action=$1 covdir=${2:-coverage-results} case $action in "run") test_coverage ;; "clean") test "x$TESTING_COVERAGE" = "xtrue" || rm -rf $covdir ;; *) echo "Illegal action: $action" 2>&1 print_usage exit 1 esac rtfilter-1.3/devtools/uncrustify.cfg000066400000000000000000002464311370625041100177540ustar00rootroot00000000000000# Uncrustify 0.64 # # General options # # The type of line endings. Default=Auto newlines = lf # auto/lf/crlf/cr # The original size of tabs in the input. Default=8 input_tab_size = 8 # number # The size of tabs in the output (only used if align_with_tabs=true). Default=8 output_tab_size = 8 # number # The ASCII value of the string escape char, usually 92 (\) or 94 (^). (Pawn) string_escape_char = 92 # number # Alternate string escape char for Pawn. Only works right before the quote char. string_escape_char2 = 0 # number # Replace tab characters found in string literals with the escape sequence \t instead. string_replace_tab_chars = false # false/true # Allow interpreting '>=' and '>>=' as part of a template in 'void f(list>=val);'. # If true, 'assert(x<0 && y>=3)' will be broken. Default=False # Improvements to template detection may make this option obsolete. tok_split_gte = false # false/true # Override the default ' *INDENT-OFF*' in comments for disabling processing of part of the file. disable_processing_cmt = "" # string # Override the default ' *INDENT-ON*' in comments for enabling processing of part of the file. enable_processing_cmt = "" # string # Enable parsing of digraphs. Default=False enable_digraphs = false # false/true # Control what to do with the UTF-8 BOM (recommend 'remove') utf8_bom = ignore # ignore/add/remove/force # If the file contains bytes with values between 128 and 255, but is not UTF-8, then output as UTF-8 utf8_byte = false # false/true # Force the output encoding to UTF-8 utf8_force = false # false/true # # Indenting # # The number of columns to indent per level. # Usually 2, 3, 4, or 8. Default=8 indent_columns = 8 # number # The continuation indent. If non-zero, this overrides the indent of '(' and '=' continuation indents. # For FreeBSD, this is set to 4. Negative value is absolute and not increased for each ( level indent_continue = 0 # number # How to use tabs when indenting code # 0=spaces only # 1=indent with tabs to brace level, align with spaces (default) # 2=indent and align with tabs, using spaces when not on a tabstop indent_with_tabs = 1 # number # Comments that are not a brace level are indented with tabs on a tabstop. # Requires indent_with_tabs=2. If false, will use spaces. indent_cmt_with_tabs = false # false/true # Whether to indent strings broken by '\' so that they line up indent_align_string = false # false/true # The number of spaces to indent multi-line XML strings. # Requires indent_align_string=True indent_xml_string = 0 # number # Spaces to indent '{' from level indent_brace = 0 # number # Whether braces are indented to the body level indent_braces = false # false/true # Disabled indenting function braces if indent_braces is true indent_braces_no_func = false # false/true # Disabled indenting class braces if indent_braces is true indent_braces_no_class = false # false/true # Disabled indenting struct braces if indent_braces is true indent_braces_no_struct = false # false/true # Indent based on the size of the brace parent, i.e. 'if' => 3 spaces, 'for' => 4 spaces, etc. indent_brace_parent = false # false/true # Indent based on the paren open instead of the brace open in '({\n', default is to indent by brace. indent_paren_open_brace = false # false/true # indent a C# delegate by another level, default is to not indent by another level. indent_cs_delegate_brace = false # false/true # Whether the 'namespace' body is indented indent_namespace = false # false/true # Only indent one namespace and no sub-namespaces. # Requires indent_namespace=true. indent_namespace_single_indent = false # false/true # The number of spaces to indent a namespace block indent_namespace_level = 0 # number # If the body of the namespace is longer than this number, it won't be indented. # Requires indent_namespace=true. Default=0 (no limit) indent_namespace_limit = 0 # number # Whether the 'extern "C"' body is indented indent_extern = false # false/true # Whether the 'class' body is indented indent_class = false # false/true # Whether to indent the stuff after a leading base class colon indent_class_colon = false # false/true # Indent based on a class colon instead of the stuff after the colon. # Requires indent_class_colon=true. Default=False indent_class_on_colon = false # false/true # Whether to indent the stuff after a leading class initializer colon indent_constr_colon = false # false/true # Virtual indent from the ':' for member initializers. Default=2 indent_ctor_init_leading = 2 # number # Additional indenting for constructor initializer list indent_ctor_init = 0 # number # False=treat 'else\nif' as 'else if' for indenting purposes # True=indent the 'if' one level indent_else_if = false # false/true # Amount to indent variable declarations after a open brace. neg=relative, pos=absolute indent_var_def_blk = 0 # number # Indent continued variable declarations instead of aligning. indent_var_def_cont = false # false/true # Indent continued shift expressions ('<<' and '>>') instead of aligning. # Turn align_left_shift off when enabling this. indent_shift = false # false/true # True: force indentation of function definition to start in column 1 # False: use the default behavior indent_func_def_force_col1 = false # false/true # True: indent continued function call parameters one indent level # False: align parameters under the open paren indent_func_call_param = false # false/true # Same as indent_func_call_param, but for function defs indent_func_def_param = false # false/true # Same as indent_func_call_param, but for function protos indent_func_proto_param = false # false/true # Same as indent_func_call_param, but for class declarations indent_func_class_param = false # false/true # Same as indent_func_call_param, but for class variable constructors indent_func_ctor_var_param = false # false/true # Same as indent_func_call_param, but for templates indent_template_param = false # false/true # Double the indent for indent_func_xxx_param options indent_func_param_double = false # false/true # Indentation column for standalone 'const' function decl/proto qualifier indent_func_const = 0 # number # Indentation column for standalone 'throw' function decl/proto qualifier indent_func_throw = 0 # number # The number of spaces to indent a continued '->' or '.' # Usually set to 0, 1, or indent_columns. indent_member = 0 # number # Spaces to indent single line ('//') comments on lines before code indent_sing_line_comments = 0 # number # If set, will indent trailing single line ('//') comments relative # to the code instead of trying to keep the same absolute column indent_relative_single_line_comments = false # false/true # Spaces to indent 'case' from 'switch' # Usually 0 or indent_columns. indent_switch_case = 0 # number # Spaces to shift the 'case' line, without affecting any other lines # Usually 0. indent_case_shift = 0 # number # Spaces to indent '{' from 'case'. # By default, the brace will appear under the 'c' in case. # Usually set to 0 or indent_columns. indent_case_brace = 0 # number # Whether to indent comments found in first column indent_col1_comment = false # false/true # How to indent goto labels # >0: absolute column where 1 is the leftmost column # <=0: subtract from brace indent # Default=1 indent_label = 1 # number # Same as indent_label, but for access specifiers that are followed by a colon. Default=1 indent_access_spec = 1 # number # Indent the code after an access specifier by one level. # If set, this option forces 'indent_access_spec=0' indent_access_spec_body = false # false/true # If an open paren is followed by a newline, indent the next line so that it lines up after the open paren (not recommended) indent_paren_nl = false # false/true # Controls the indent of a close paren after a newline. # 0: Indent to body level # 1: Align under the open paren # 2: Indent to the brace level indent_paren_close = 0 # number # Controls the indent of a comma when inside a paren.If TRUE, aligns under the open paren indent_comma_paren = false # false/true # Controls the indent of a BOOL operator when inside a paren.If TRUE, aligns under the open paren indent_bool_paren = true # false/true # If 'indent_bool_paren' is true, controls the indent of the first expression. If TRUE, aligns the first expression to the following ones indent_first_bool_expr = true # false/true # If an open square is followed by a newline, indent the next line so that it lines up after the open square (not recommended) indent_square_nl = false # false/true # Don't change the relative indent of ESQL/C 'EXEC SQL' bodies indent_preserve_sql = false # false/true # Align continued statements at the '='. Default=True # If FALSE or the '=' is followed by a newline, the next line is indent one tab. indent_align_assign = true # false/true # Indent OC blocks at brace level instead of usual rules. indent_oc_block = false # false/true # Indent OC blocks in a message relative to the parameter name. # 0=use indent_oc_block rules, 1+=spaces to indent indent_oc_block_msg = 0 # number # Minimum indent for subsequent parameters indent_oc_msg_colon = 0 # number # If true, prioritize aligning with initial colon (and stripping spaces from lines, if necessary). # Default=True. indent_oc_msg_prioritize_first_colon = true # false/true # If indent_oc_block_msg and this option are on, blocks will be indented the way that Xcode does by default (from keyword if the parameter is on its own line; otherwise, from the previous indentation level). indent_oc_block_msg_xcode_style = false # false/true # If indent_oc_block_msg and this option are on, blocks will be indented from where the brace is relative to a msg keyword. indent_oc_block_msg_from_keyword = false # false/true # If indent_oc_block_msg and this option are on, blocks will be indented from where the brace is relative to a msg colon. indent_oc_block_msg_from_colon = false # false/true # If indent_oc_block_msg and this option are on, blocks will be indented from where the block caret is. indent_oc_block_msg_from_caret = false # false/true # If indent_oc_block_msg and this option are on, blocks will be indented from where the brace is. indent_oc_block_msg_from_brace = false # false/true # When identing after virtual brace open and newline add further spaces to reach this min. indent. indent_min_vbrace_open = 0 # number # TRUE: When identing after virtual brace open and newline add further spaces after regular indent to reach next tabstop. indent_vbrace_open_on_tabstop = false # false/true # If true, a brace followed by another token (not a newline) will indent all contained lines to match the token.Default=True. indent_token_after_brace = true # false/true # If true, cpp lambda body will be indentedDefault=False. indent_cpp_lambda_body = false # false/true # # Spacing options # # Add or remove space around arithmetic operator '+', '-', '/', '*', etc # also '>>>' '<<' '>>' '%' '|' sp_arith = ignore # ignore/add/remove/force # Add or remove space around assignment operator '=', '+=', etc sp_assign = ignore # ignore/add/remove/force # Add or remove space around '=' in C++11 lambda capture specifications. Overrides sp_assign sp_cpp_lambda_assign = ignore # ignore/add/remove/force # Add or remove space after the capture specification in C++11 lambda. sp_cpp_lambda_paren = ignore # ignore/add/remove/force # Add or remove space around assignment operator '=' in a prototype sp_assign_default = ignore # ignore/add/remove/force # Add or remove space before assignment operator '=', '+=', etc. Overrides sp_assign. sp_before_assign = force # ignore/add/remove/force # Add or remove space after assignment operator '=', '+=', etc. Overrides sp_assign. sp_after_assign = force # ignore/add/remove/force # Add or remove space in 'NS_ENUM (' sp_enum_paren = ignore # ignore/add/remove/force # Add or remove space around assignment '=' in enum sp_enum_assign = ignore # ignore/add/remove/force # Add or remove space before assignment '=' in enum. Overrides sp_enum_assign. sp_enum_before_assign = ignore # ignore/add/remove/force # Add or remove space after assignment '=' in enum. Overrides sp_enum_assign. sp_enum_after_assign = ignore # ignore/add/remove/force # Add or remove space around preprocessor '##' concatenation operator. Default=Add sp_pp_concat = add # ignore/add/remove/force # Add or remove space after preprocessor '#' stringify operator. Also affects the '#@' charizing operator. sp_pp_stringify = ignore # ignore/add/remove/force # Add or remove space before preprocessor '#' stringify operator as in '#define x(y) L#y'. sp_before_pp_stringify = ignore # ignore/add/remove/force # Add or remove space around boolean operators '&&' and '||' sp_bool = force # ignore/add/remove/force # Add or remove space around compare operator '<', '>', '==', etc sp_compare = force # ignore/add/remove/force # Add or remove space inside '(' and ')' sp_inside_paren = ignore # ignore/add/remove/force # Add or remove space between nested parens: '((' vs ') )' sp_paren_paren = ignore # ignore/add/remove/force # Add or remove space between back-to-back parens: ')(' vs ') (' sp_cparen_oparen = ignore # ignore/add/remove/force # Whether to balance spaces inside nested parens sp_balance_nested_parens = false # false/true # Add or remove space between ')' and '{' sp_paren_brace = force # ignore/add/remove/force # Add or remove space before pointer star '*' sp_before_ptr_star = ignore # ignore/add/remove/force # Add or remove space before pointer star '*' that isn't followed by a variable name # If set to 'ignore', sp_before_ptr_star is used instead. sp_before_unnamed_ptr_star = remove # ignore/add/remove/force # Add or remove space between pointer stars '*' sp_between_ptr_star = remove # ignore/add/remove/force # Add or remove space after pointer star '*', if followed by a word. sp_after_ptr_star = ignore # ignore/add/remove/force # Add or remove space after pointer star '*', if followed by a qualifier. sp_after_ptr_star_qualifier = ignore # ignore/add/remove/force # Add or remove space after a pointer star '*', if followed by a func proto/def. sp_after_ptr_star_func = ignore # ignore/add/remove/force # Add or remove space after a pointer star '*', if followed by an open paren (function types). sp_ptr_star_paren = ignore # ignore/add/remove/force # Add or remove space before a pointer star '*', if followed by a func proto/def. sp_before_ptr_star_func = ignore # ignore/add/remove/force # Add or remove space before a reference sign '&' sp_before_byref = ignore # ignore/add/remove/force # Add or remove space before a reference sign '&' that isn't followed by a variable name # If set to 'ignore', sp_before_byref is used instead. sp_before_unnamed_byref = ignore # ignore/add/remove/force # Add or remove space after reference sign '&', if followed by a word. sp_after_byref = ignore # ignore/add/remove/force # Add or remove space after a reference sign '&', if followed by a func proto/def. sp_after_byref_func = ignore # ignore/add/remove/force # Add or remove space before a reference sign '&', if followed by a func proto/def. sp_before_byref_func = ignore # ignore/add/remove/force # Add or remove space between type and word. Default=Force sp_after_type = force # ignore/add/remove/force # Add or remove space before the paren in the D constructs 'template Foo(' and 'class Foo('. sp_before_template_paren = ignore # ignore/add/remove/force # Add or remove space in 'template <' vs 'template<'. # If set to ignore, sp_before_angle is used. sp_template_angle = ignore # ignore/add/remove/force # Add or remove space before '<>' sp_before_angle = ignore # ignore/add/remove/force # Add or remove space inside '<' and '>' sp_inside_angle = ignore # ignore/add/remove/force # Add or remove space after '<>' sp_after_angle = ignore # ignore/add/remove/force # Add or remove space between '<>' and '(' as found in 'new List(foo);' sp_angle_paren = ignore # ignore/add/remove/force # Add or remove space between '<>' and '()' as found in 'new List();' sp_angle_paren_empty = ignore # ignore/add/remove/force # Add or remove space between '<>' and a word as in 'List m;' or 'template static ...' sp_angle_word = ignore # ignore/add/remove/force # Add or remove space between '>' and '>' in '>>' (template stuff C++/C# only). Default=Add sp_angle_shift = add # ignore/add/remove/force # Permit removal of the space between '>>' in 'foo >' (C++11 only). Default=False # sp_angle_shift cannot remove the space without this option. sp_permit_cpp11_shift = false # false/true # Add or remove space before '(' of 'if', 'for', 'switch', 'while', etc. sp_before_sparen = add # ignore/add/remove/force # Add or remove space inside if-condition '(' and ')' sp_inside_sparen = ignore # ignore/add/remove/force # Add or remove space before if-condition ')'. Overrides sp_inside_sparen. sp_inside_sparen_close = ignore # ignore/add/remove/force # Add or remove space after if-condition '('. Overrides sp_inside_sparen. sp_inside_sparen_open = ignore # ignore/add/remove/force # Add or remove space after ')' of 'if', 'for', 'switch', and 'while', etc. sp_after_sparen = remove # ignore/add/remove/force # Add or remove space between ')' and '{' of 'if', 'for', 'switch', and 'while', etc. sp_sparen_brace = force # ignore/add/remove/force # Add or remove space between 'invariant' and '(' in the D language. sp_invariant_paren = ignore # ignore/add/remove/force # Add or remove space after the ')' in 'invariant (C) c' in the D language. sp_after_invariant_paren = ignore # ignore/add/remove/force # Add or remove space before empty statement ';' on 'if', 'for' and 'while' sp_special_semi = ignore # ignore/add/remove/force # Add or remove space before ';'. Default=Remove sp_before_semi = remove # ignore/add/remove/force # Add or remove space before ';' in non-empty 'for' statements sp_before_semi_for = remove # ignore/add/remove/force # Add or remove space before a semicolon of an empty part of a for statement. sp_before_semi_for_empty = ignore # ignore/add/remove/force # Add or remove space after ';', except when followed by a comment. Default=Add sp_after_semi = add # ignore/add/remove/force # Add or remove space after ';' in non-empty 'for' statements. Default=Force sp_after_semi_for = force # ignore/add/remove/force # Add or remove space after the final semicolon of an empty part of a for statement: for ( ; ; ). sp_after_semi_for_empty = ignore # ignore/add/remove/force # Add or remove space before '[' (except '[]') sp_before_square = remove # ignore/add/remove/force # Add or remove space before '[]' sp_before_squares = ignore # ignore/add/remove/force # Add or remove space inside a non-empty '[' and ']' sp_inside_square = remove # ignore/add/remove/force # Add or remove space after ',' sp_after_comma = force # ignore/add/remove/force # Add or remove space before ','. Default=Remove sp_before_comma = remove # ignore/add/remove/force # Add or remove space between ',' and ']' in multidimensional array type 'int[,,]' sp_after_mdatype_commas = ignore # ignore/add/remove/force # Add or remove space between '[' and ',' in multidimensional array type 'int[,,]' sp_before_mdatype_commas = ignore # ignore/add/remove/force # Add or remove space between ',' in multidimensional array type 'int[,,]' sp_between_mdatype_commas = ignore # ignore/add/remove/force # Add or remove space between an open paren and comma: '(,' vs '( ,'. Default=Force sp_paren_comma = force # ignore/add/remove/force # Add or remove space before the variadic '...' when preceded by a non-punctuator sp_before_ellipsis = ignore # ignore/add/remove/force # Add or remove space after class ':' sp_after_class_colon = ignore # ignore/add/remove/force # Add or remove space before class ':' sp_before_class_colon = ignore # ignore/add/remove/force # Add or remove space after class constructor ':' sp_after_constr_colon = ignore # ignore/add/remove/force # Add or remove space before class constructor ':' sp_before_constr_colon = ignore # ignore/add/remove/force # Add or remove space before case ':'. Default=Remove sp_before_case_colon = remove # ignore/add/remove/force # Add or remove space between 'operator' and operator sign sp_after_operator = ignore # ignore/add/remove/force # Add or remove space between the operator symbol and the open paren, as in 'operator ++(' sp_after_operator_sym = ignore # ignore/add/remove/force # Add or remove space between the operator symbol and the open paren when the operator has no arguments, as in 'operator *()' sp_after_operator_sym_empty = ignore # ignore/add/remove/force # Add or remove space after C/D cast, i.e. 'cast(int)a' vs 'cast(int) a' or '(int)a' vs '(int) a' sp_after_cast = ignore # ignore/add/remove/force # Add or remove spaces inside cast parens sp_inside_paren_cast = ignore # ignore/add/remove/force # Add or remove space between the type and open paren in a C++ cast, i.e. 'int(exp)' vs 'int (exp)' sp_cpp_cast_paren = ignore # ignore/add/remove/force # Add or remove space between 'sizeof' and '(' sp_sizeof_paren = remove # ignore/add/remove/force # Add or remove space after the tag keyword (Pawn) sp_after_tag = ignore # ignore/add/remove/force # Add or remove space inside enum '{' and '}' sp_inside_braces_enum = ignore # ignore/add/remove/force # Add or remove space inside struct/union '{' and '}' sp_inside_braces_struct = ignore # ignore/add/remove/force # Add or remove space inside '{' and '}' sp_inside_braces = remove # ignore/add/remove/force # Add or remove space inside '{}' sp_inside_braces_empty = ignore # ignore/add/remove/force # Add or remove space between return type and function name # A minimum of 1 is forced except for pointer return types. sp_type_func = ignore # ignore/add/remove/force # Add or remove space between function name and '(' on function declaration sp_func_proto_paren = remove # ignore/add/remove/force # Add or remove space between function name and '()' on function declaration without parameters sp_func_proto_paren_empty = remove # ignore/add/remove/force # Add or remove space between function name and '(' on function definition sp_func_def_paren = remove # ignore/add/remove/force # Add or remove space between function name and '()' on function definition without parameters sp_func_def_paren_empty = remove # ignore/add/remove/force # Add or remove space inside empty function '()' sp_inside_fparens = ignore # ignore/add/remove/force # Add or remove space inside function '(' and ')' sp_inside_fparen = ignore # ignore/add/remove/force # Add or remove space inside the first parens in the function type: 'void (*x)(...)' sp_inside_tparen = ignore # ignore/add/remove/force # Add or remove between the parens in the function type: 'void (*x)(...)' sp_after_tparen_close = ignore # ignore/add/remove/force # Add or remove space between ']' and '(' when part of a function call. sp_square_fparen = ignore # ignore/add/remove/force # Add or remove space between ')' and '{' of function sp_fparen_brace = ignore # ignore/add/remove/force # Java: Add or remove space between ')' and '{{' of double brace initializer. sp_fparen_dbrace = ignore # ignore/add/remove/force # Add or remove space between function name and '(' on function calls sp_func_call_paren = remove # ignore/add/remove/force # Add or remove space between function name and '()' on function calls without parameters. # If set to 'ignore' (the default), sp_func_call_paren is used. sp_func_call_paren_empty = remove # ignore/add/remove/force # Add or remove space between the user function name and '(' on function calls # You need to set a keyword to be a user function, like this: 'set func_call_user _' in the config file. sp_func_call_user_paren = ignore # ignore/add/remove/force # Add or remove space between a constructor/destructor and the open paren sp_func_class_paren = ignore # ignore/add/remove/force # Add or remove space between a constructor without parameters or destructor and '()' sp_func_class_paren_empty = ignore # ignore/add/remove/force # Add or remove space between 'return' and '(' sp_return_paren = add # ignore/add/remove/force # Add or remove space between '__attribute__' and '(' sp_attribute_paren = remove # ignore/add/remove/force # Add or remove space between 'defined' and '(' in '#if defined (FOO)' sp_defined_paren = add # ignore/add/remove/force # Add or remove space between 'throw' and '(' in 'throw (something)' sp_throw_paren = remove # ignore/add/remove/force # Add or remove space between 'throw' and anything other than '(' as in '@throw [...];' sp_after_throw = ignore # ignore/add/remove/force # Add or remove space between 'catch' and '(' in 'catch (something) { }' # If set to ignore, sp_before_sparen is used. sp_catch_paren = add # ignore/add/remove/force # Add or remove space between 'version' and '(' in 'version (something) { }' (D language) # If set to ignore, sp_before_sparen is used. sp_version_paren = ignore # ignore/add/remove/force # Add or remove space between 'scope' and '(' in 'scope (something) { }' (D language) # If set to ignore, sp_before_sparen is used. sp_scope_paren = ignore # ignore/add/remove/force # Add or remove space between 'super' and '(' in 'super (something)'. Default=Remove sp_super_paren = remove # ignore/add/remove/force # Add or remove space between 'this' and '(' in 'this (something)'. Default=Remove sp_this_paren = remove # ignore/add/remove/force # Add or remove space between macro and value sp_macro = remove # ignore/add/remove/force # Add or remove space between macro function ')' and value sp_macro_func = ignore # ignore/add/remove/force # Add or remove space between 'else' and '{' if on the same line sp_else_brace = add # ignore/add/remove/force # Add or remove space between '}' and 'else' if on the same line sp_brace_else = add # ignore/add/remove/force # Add or remove space between '}' and the name of a typedef on the same line sp_brace_typedef = ignore # ignore/add/remove/force # Add or remove space between 'catch' and '{' if on the same line sp_catch_brace = ignore # ignore/add/remove/force # Add or remove space between '}' and 'catch' if on the same line sp_brace_catch = ignore # ignore/add/remove/force # Add or remove space between 'finally' and '{' if on the same line sp_finally_brace = ignore # ignore/add/remove/force # Add or remove space between '}' and 'finally' if on the same line sp_brace_finally = ignore # ignore/add/remove/force # Add or remove space between 'try' and '{' if on the same line sp_try_brace = ignore # ignore/add/remove/force # Add or remove space between get/set and '{' if on the same line sp_getset_brace = ignore # ignore/add/remove/force # Add or remove space between a variable and '{' for C++ uniform initialization. Default=Add sp_word_brace = add # ignore/add/remove/force # Add or remove space between a variable and '{' for a namespace. Default=Add sp_word_brace_ns = add # ignore/add/remove/force # Add or remove space before the '::' operator sp_before_dc = ignore # ignore/add/remove/force # Add or remove space after the '::' operator sp_after_dc = ignore # ignore/add/remove/force # Add or remove around the D named array initializer ':' operator sp_d_array_colon = ignore # ignore/add/remove/force # Add or remove space after the '!' (not) operator. Default=Remove sp_not = remove # ignore/add/remove/force # Add or remove space after the '~' (invert) operator. Default=Remove sp_inv = remove # ignore/add/remove/force # Add or remove space after the '&' (address-of) operator. Default=Remove # This does not affect the spacing after a '&' that is part of a type. sp_addr = remove # ignore/add/remove/force # Add or remove space around the '.' or '->' operators. Default=Remove sp_member = remove # ignore/add/remove/force # Add or remove space after the '*' (dereference) operator. Default=Remove # This does not affect the spacing after a '*' that is part of a type. sp_deref = remove # ignore/add/remove/force # Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'. Default=Remove sp_sign = remove # ignore/add/remove/force # Add or remove space before or after '++' and '--', as in '(--x)' or 'y++;'. Default=Remove sp_incdec = remove # ignore/add/remove/force # Add or remove space before a backslash-newline at the end of a line. Default=Add sp_before_nl_cont = remove # ignore/add/remove/force # Add or remove space after the scope '+' or '-', as in '-(void) foo;' or '+(int) bar;' sp_after_oc_scope = ignore # ignore/add/remove/force # Add or remove space after the colon in message specs # '-(int) f:(int) x;' vs '-(int) f: (int) x;' sp_after_oc_colon = ignore # ignore/add/remove/force # Add or remove space before the colon in message specs # '-(int) f: (int) x;' vs '-(int) f : (int) x;' sp_before_oc_colon = ignore # ignore/add/remove/force # Add or remove space after the colon in immutable dictionary expression # 'NSDictionary *test = @{@"foo" :@"bar"};' sp_after_oc_dict_colon = ignore # ignore/add/remove/force # Add or remove space before the colon in immutable dictionary expression # 'NSDictionary *test = @{@"foo" :@"bar"};' sp_before_oc_dict_colon = ignore # ignore/add/remove/force # Add or remove space after the colon in message specs # '[object setValue:1];' vs '[object setValue: 1];' sp_after_send_oc_colon = ignore # ignore/add/remove/force # Add or remove space before the colon in message specs # '[object setValue:1];' vs '[object setValue :1];' sp_before_send_oc_colon = ignore # ignore/add/remove/force # Add or remove space after the (type) in message specs # '-(int)f: (int) x;' vs '-(int)f: (int)x;' sp_after_oc_type = ignore # ignore/add/remove/force # Add or remove space after the first (type) in message specs # '-(int) f:(int)x;' vs '-(int)f:(int)x;' sp_after_oc_return_type = ignore # ignore/add/remove/force # Add or remove space between '@selector' and '(' # '@selector(msgName)' vs '@selector (msgName)' # Also applies to @protocol() constructs sp_after_oc_at_sel = ignore # ignore/add/remove/force # Add or remove space between '@selector(x)' and the following word # '@selector(foo) a:' vs '@selector(foo)a:' sp_after_oc_at_sel_parens = ignore # ignore/add/remove/force # Add or remove space inside '@selector' parens # '@selector(foo)' vs '@selector( foo )' # Also applies to @protocol() constructs sp_inside_oc_at_sel_parens = ignore # ignore/add/remove/force # Add or remove space before a block pointer caret # '^int (int arg){...}' vs. ' ^int (int arg){...}' sp_before_oc_block_caret = ignore # ignore/add/remove/force # Add or remove space after a block pointer caret # '^int (int arg){...}' vs. '^ int (int arg){...}' sp_after_oc_block_caret = ignore # ignore/add/remove/force # Add or remove space between the receiver and selector in a message. # '[receiver selector ...]' sp_after_oc_msg_receiver = ignore # ignore/add/remove/force # Add or remove space after @property. sp_after_oc_property = ignore # ignore/add/remove/force # Add or remove space around the ':' in 'b ? t : f' sp_cond_colon = ignore # ignore/add/remove/force # Add or remove space before the ':' in 'b ? t : f'. Overrides sp_cond_colon. sp_cond_colon_before = ignore # ignore/add/remove/force # Add or remove space after the ':' in 'b ? t : f'. Overrides sp_cond_colon. sp_cond_colon_after = ignore # ignore/add/remove/force # Add or remove space around the '?' in 'b ? t : f' sp_cond_question = ignore # ignore/add/remove/force # Add or remove space before the '?' in 'b ? t : f'. Overrides sp_cond_question. sp_cond_question_before = ignore # ignore/add/remove/force # Add or remove space after the '?' in 'b ? t : f'. Overrides sp_cond_question. sp_cond_question_after = ignore # ignore/add/remove/force # In the abbreviated ternary form (a ?: b), add/remove space between ? and :.'. Overrides all other sp_cond_* options. sp_cond_ternary_short = ignore # ignore/add/remove/force # Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make sense here. sp_case_label = ignore # ignore/add/remove/force # Control the space around the D '..' operator. sp_range = ignore # ignore/add/remove/force # Control the spacing after ':' in 'for (TYPE VAR : EXPR)' sp_after_for_colon = ignore # ignore/add/remove/force # Control the spacing before ':' in 'for (TYPE VAR : EXPR)' sp_before_for_colon = ignore # ignore/add/remove/force # Control the spacing in 'extern (C)' (D) sp_extern_paren = ignore # ignore/add/remove/force # Control the space after the opening of a C++ comment '// A' vs '//A' sp_cmt_cpp_start = ignore # ignore/add/remove/force # TRUE: If space is added with sp_cmt_cpp_start, do it after doxygen sequences like '///', '///<', '//!' and '//!<'. sp_cmt_cpp_doxygen = false # false/true # TRUE: If space is added with sp_cmt_cpp_start, do it after Qt translator or meta-data comments like '//:', '//=', and '//~'. sp_cmt_cpp_qttr = false # false/true # Controls the spaces between #else or #endif and a trailing comment sp_endif_cmt = ignore # ignore/add/remove/force # Controls the spaces after 'new', 'delete' and 'delete[]' sp_after_new = ignore # ignore/add/remove/force # Controls the spaces between new and '(' in 'new()' sp_between_new_paren = ignore # ignore/add/remove/force # Controls the spaces before a trailing or embedded comment sp_before_tr_emb_cmt = ignore # ignore/add/remove/force # Number of spaces before a trailing or embedded comment sp_num_before_tr_emb_cmt = 1 # number # Control space between a Java annotation and the open paren. sp_annotation_paren = ignore # ignore/add/remove/force # If true, vbrace tokens are dropped to the previous token and skipped. sp_skip_vbrace_tokens = false # false/true # # Code alignment (not left column spaces/tabs) # # Whether to keep non-indenting tabs align_keep_tabs = false # false/true # Whether to use tabs for aligning align_with_tabs = false # false/true # Whether to bump out to the next tab when aligning align_on_tabstop = false # false/true # Whether to keep whitespace not required for alignment. align_keep_extra_space = false # false/true # Align variable definitions in prototypes and functions align_func_params = false # false/true # Align parameters in single-line functions that have the same name. # The function names must already be aligned with each other. align_same_func_call_params = false # false/true # The span for aligning variable definitions (0=don't align) align_var_def_span = 0 # number # How to align the star in variable definitions. # 0=Part of the type 'void * foo;' # 1=Part of the variable 'void *foo;' # 2=Dangling 'void *foo;' align_var_def_star_style = 0 # number # How to align the '&' in variable definitions. # 0=Part of the type # 1=Part of the variable # 2=Dangling align_var_def_amp_style = 0 # number # The threshold for aligning variable definitions (0=no limit) align_var_def_thresh = 0 # number # The gap for aligning variable definitions align_var_def_gap = 0 # number # Whether to align the colon in struct bit fields align_var_def_colon = false # false/true # Whether to align any attribute after the variable name align_var_def_attribute = false # false/true # Whether to align inline struct/enum/union variable definitions align_var_def_inline = false # false/true # The span for aligning on '=' in assignments (0=don't align) align_assign_span = 0 # number # The threshold for aligning on '=' in assignments (0=no limit) align_assign_thresh = 0 # number # The span for aligning on '=' in enums (0=don't align) align_enum_equ_span = 0 # number # The threshold for aligning on '=' in enums (0=no limit) align_enum_equ_thresh = 0 # number # The span for aligning class (0=don't align) align_var_class_span = 0 # number # The threshold for aligning class member definitions (0=no limit) align_var_class_thresh = 0 # number # The gap for aligning class member definitions align_var_class_gap = 0 # number # The span for aligning struct/union (0=don't align) align_var_struct_span = 0 # number # The threshold for aligning struct/union member definitions (0=no limit) align_var_struct_thresh = 0 # number # The gap for aligning struct/union member definitions align_var_struct_gap = 0 # number # The span for aligning struct initializer values (0=don't align) align_struct_init_span = 0 # number # The minimum space between the type and the synonym of a typedef align_typedef_gap = 0 # number # The span for aligning single-line typedefs (0=don't align) align_typedef_span = 0 # number # How to align typedef'd functions with other typedefs # 0: Don't mix them at all # 1: align the open paren with the types # 2: align the function type name with the other type names align_typedef_func = 0 # number # Controls the positioning of the '*' in typedefs. Just try it. # 0: Align on typedef type, ignore '*' # 1: The '*' is part of type name: typedef int *pint; # 2: The '*' is part of the type, but dangling: typedef int *pint; align_typedef_star_style = 0 # number # Controls the positioning of the '&' in typedefs. Just try it. # 0: Align on typedef type, ignore '&' # 1: The '&' is part of type name: typedef int &pint; # 2: The '&' is part of the type, but dangling: typedef int &pint; align_typedef_amp_style = 0 # number # The span for aligning comments that end lines (0=don't align) align_right_cmt_span = 0 # number # If aligning comments, mix with comments after '}' and #endif with less than 3 spaces before the comment align_right_cmt_mix = false # false/true # If a trailing comment is more than this number of columns away from the text it follows, # it will qualify for being aligned. This has to be > 0 to do anything. align_right_cmt_gap = 0 # number # Align trailing comment at or beyond column N; 'pulls in' comments as a bonus side effect (0=ignore) align_right_cmt_at_col = 0 # number # The span for aligning function prototypes (0=don't align) align_func_proto_span = 0 # number # Minimum gap between the return type and the function name. align_func_proto_gap = 0 # number # Align function protos on the 'operator' keyword instead of what follows align_on_operator = false # false/true # Whether to mix aligning prototype and variable declarations. # If true, align_var_def_XXX options are used instead of align_func_proto_XXX options. align_mix_var_proto = false # false/true # Align single-line functions with function prototypes, uses align_func_proto_span align_single_line_func = false # false/true # Aligning the open brace of single-line functions. # Requires align_single_line_func=true, uses align_func_proto_span align_single_line_brace = false # false/true # Gap for align_single_line_brace. align_single_line_brace_gap = 0 # number # The span for aligning ObjC msg spec (0=don't align) align_oc_msg_spec_span = 0 # number # Whether to align macros wrapped with a backslash and a newline. # This will not work right if the macro contains a multi-line comment. align_nl_cont = false # false/true # # Align macro functions and variables together align_pp_define_together = false # false/true # The minimum space between label and value of a preprocessor define align_pp_define_gap = 0 # number # The span for aligning on '#define' bodies (0=don't align, other=number of lines including comments between blocks) align_pp_define_span = 0 # number # Align lines that start with '<<' with previous '<<'. Default=True align_left_shift = true # false/true # Align text after asm volatile () colons. align_asm_colon = false # false/true # Span for aligning parameters in an Obj-C message call on the ':' (0=don't align) align_oc_msg_colon_span = 0 # number # If true, always align with the first parameter, even if it is too short. align_oc_msg_colon_first = false # false/true # Aligning parameters in an Obj-C '+' or '-' declaration on the ':' align_oc_decl_colon = false # false/true # # Newline adding and removing options # # Whether to collapse empty blocks between '{' and '}' nl_collapse_empty_body = false # false/true # Don't split one-line braced assignments - 'foo_t f = { 1, 2 };' nl_assign_leave_one_liners = false # false/true # Don't split one-line braced statements inside a class xx { } body nl_class_leave_one_liners = false # false/true # Don't split one-line enums: 'enum foo { BAR = 15 };' nl_enum_leave_one_liners = false # false/true # Don't split one-line get or set functions nl_getset_leave_one_liners = false # false/true # Don't split one-line function definitions - 'int foo() { return 0; }' nl_func_leave_one_liners = false # false/true # Don't split one-line C++11 lambdas - '[]() { return 0; }' nl_cpp_lambda_leave_one_liners = false # false/true # Don't split one-line if/else statements - 'if(a) b++;' nl_if_leave_one_liners = false # false/true # Don't split one-line while statements - 'while(a) b++;' nl_while_leave_one_liners = false # false/true # Don't split one-line OC messages nl_oc_msg_leave_one_liner = false # false/true # Add or remove newline between Objective-C block signature and '{' nl_oc_block_brace = ignore # ignore/add/remove/force # Add or remove newlines at the start of the file nl_start_of_file = ignore # ignore/add/remove/force # The number of newlines at the start of the file (only used if nl_start_of_file is 'add' or 'force' nl_start_of_file_min = 0 # number # Add or remove newline at the end of the file nl_end_of_file = ignore # ignore/add/remove/force # The number of newlines at the end of the file (only used if nl_end_of_file is 'add' or 'force') nl_end_of_file_min = 0 # number # Add or remove newline between '=' and '{' nl_assign_brace = remove # ignore/add/remove/force # Add or remove newline between '=' and '[' (D only) nl_assign_square = ignore # ignore/add/remove/force # Add or remove newline after '= [' (D only). Will also affect the newline before the ']' nl_after_square_assign = ignore # ignore/add/remove/force # The number of blank lines after a block of variable definitions at the top of a function body # 0 = No change (default) nl_func_var_def_blk = 0 # number # The number of newlines before a block of typedefs # 0 = No change (default) # the option 'nl_after_access_spec' takes preference over 'nl_typedef_blk_start' nl_typedef_blk_start = 0 # number # The number of newlines after a block of typedefs # 0 = No change (default) nl_typedef_blk_end = 0 # number # The maximum consecutive newlines within a block of typedefs # 0 = No change (default) nl_typedef_blk_in = 0 # number # The number of newlines before a block of variable definitions not at the top of a function body # 0 = No change (default) # the option 'nl_after_access_spec' takes preference over 'nl_var_def_blk_start' nl_var_def_blk_start = 0 # number # The number of newlines after a block of variable definitions not at the top of a function body # 0 = No change (default) nl_var_def_blk_end = 0 # number # The maximum consecutive newlines within a block of variable definitions # 0 = No change (default) nl_var_def_blk_in = 0 # number # Add or remove newline between a function call's ')' and '{', as in: # list_for_each(item, &list) { } nl_fcall_brace = ignore # ignore/add/remove/force # Add or remove newline between 'enum' and '{' nl_enum_brace = ignore # ignore/add/remove/force # Add or remove newline between 'struct and '{' nl_struct_brace = ignore # ignore/add/remove/force # Add or remove newline between 'union' and '{' nl_union_brace = ignore # ignore/add/remove/force # Add or remove newline between 'if' and '{' nl_if_brace = remove # ignore/add/remove/force # Add or remove newline between '}' and 'else' nl_brace_else = remove # ignore/add/remove/force # Add or remove newline between 'else if' and '{' # If set to ignore, nl_if_brace is used instead nl_elseif_brace = ignore # ignore/add/remove/force # Add or remove newline between 'else' and '{' nl_else_brace = remove # ignore/add/remove/force # Add or remove newline between 'else' and 'if' nl_else_if = remove # ignore/add/remove/force # Add or remove newline between '}' and 'finally' nl_brace_finally = remove # ignore/add/remove/force # Add or remove newline between 'finally' and '{' nl_finally_brace = remove # ignore/add/remove/force # Add or remove newline between 'try' and '{' nl_try_brace = remove # ignore/add/remove/force # Add or remove newline between get/set and '{' nl_getset_brace = ignore # ignore/add/remove/force # Add or remove newline between 'for' and '{' nl_for_brace = remove # ignore/add/remove/force # Add or remove newline between 'catch' and '{' nl_catch_brace = remove # ignore/add/remove/force # Add or remove newline between '}' and 'catch' nl_brace_catch = ignore # ignore/add/remove/force # Add or remove newline between '}' and ']' nl_brace_square = ignore # ignore/add/remove/force # Add or remove newline between '}' and ')' in a function invocation nl_brace_fparen = ignore # ignore/add/remove/force # Add or remove newline between 'while' and '{' nl_while_brace = remove # ignore/add/remove/force # Add or remove newline between 'scope (x)' and '{' (D) nl_scope_brace = ignore # ignore/add/remove/force # Add or remove newline between 'unittest' and '{' (D) nl_unittest_brace = ignore # ignore/add/remove/force # Add or remove newline between 'version (x)' and '{' (D) nl_version_brace = ignore # ignore/add/remove/force # Add or remove newline between 'using' and '{' nl_using_brace = ignore # ignore/add/remove/force # Add or remove newline between two open or close braces. # Due to general newline/brace handling, REMOVE may not work. nl_brace_brace = ignore # ignore/add/remove/force # Add or remove newline between 'do' and '{' nl_do_brace = remove # ignore/add/remove/force # Add or remove newline between '}' and 'while' of 'do' statement nl_brace_while = remove # ignore/add/remove/force # Add or remove newline between 'switch' and '{' nl_switch_brace = remove # ignore/add/remove/force # Add or remove newline between 'synchronized' and '{' nl_synchronized_brace = ignore # ignore/add/remove/force # Add a newline between ')' and '{' if the ')' is on a different line than the if/for/etc. # Overrides nl_for_brace, nl_if_brace, nl_switch_brace, nl_while_switch and nl_catch_brace. nl_multi_line_cond = false # false/true # Force a newline in a define after the macro name for multi-line defines. nl_multi_line_define = false # false/true # Whether to put a newline before 'case' statement, not after the first 'case' nl_before_case = false # false/true # Add or remove newline between ')' and 'throw' nl_before_throw = ignore # ignore/add/remove/force # Whether to put a newline after 'case' statement nl_after_case = false # false/true # Add or remove a newline between a case ':' and '{'. Overrides nl_after_case. nl_case_colon_brace = ignore # ignore/add/remove/force # Newline between namespace and { nl_namespace_brace = ignore # ignore/add/remove/force # Add or remove newline between 'template<>' and whatever follows. nl_template_class = ignore # ignore/add/remove/force # Add or remove newline between 'class' and '{' nl_class_brace = ignore # ignore/add/remove/force # Add or remove newline before/after each ',' in the base class list, # (tied to pos_class_comma). nl_class_init_args = ignore # ignore/add/remove/force # Add or remove newline after each ',' in the constructor member initialization. # Related to nl_constr_colon, pos_constr_colon and pos_constr_comma. nl_constr_init_args = ignore # ignore/add/remove/force # Add or remove newline before first element, after comma, and after last element in enum nl_enum_own_lines = ignore # ignore/add/remove/force # Add or remove newline between return type and function name in a function definition nl_func_type_name = ignore # ignore/add/remove/force # Add or remove newline between return type and function name inside a class {} # Uses nl_func_type_name or nl_func_proto_type_name if set to ignore. nl_func_type_name_class = ignore # ignore/add/remove/force # Add or remove newline between class specification and '::' in 'void A::f() { }' # Only appears in separate member implementation (does not appear with in-line implmementation) nl_func_class_scope = ignore # ignore/add/remove/force # Add or remove newline between function scope and name # Controls the newline after '::' in 'void A::f() { }' nl_func_scope_name = ignore # ignore/add/remove/force # Add or remove newline between return type and function name in a prototype nl_func_proto_type_name = ignore # ignore/add/remove/force # Add or remove newline between a function name and the opening '(' in the declaration nl_func_paren = remove # ignore/add/remove/force # Add or remove newline between a function name and the opening '(' in the definition nl_func_def_paren = remove # ignore/add/remove/force # Add or remove newline after '(' in a function declaration nl_func_decl_start = remove # ignore/add/remove/force # Add or remove newline after '(' in a function definition nl_func_def_start = remove # ignore/add/remove/force # Overrides nl_func_decl_start when there is only one parameter. nl_func_decl_start_single = ignore # ignore/add/remove/force # Overrides nl_func_def_start when there is only one parameter. nl_func_def_start_single = ignore # ignore/add/remove/force # Whether to add newline after '(' in a function declaration if '(' and ')' are in different lines. nl_func_decl_start_multi_line = false # false/true # Whether to add newline after '(' in a function definition if '(' and ')' are in different lines. nl_func_def_start_multi_line = false # false/true # Add or remove newline after each ',' in a function declaration nl_func_decl_args = ignore # ignore/add/remove/force # Add or remove newline after each ',' in a function definition nl_func_def_args = ignore # ignore/add/remove/force # Whether to add newline after each ',' in a function declaration if '(' and ')' are in different lines. nl_func_decl_args_multi_line = false # false/true # Whether to add newline after each ',' in a function definition if '(' and ')' are in different lines. nl_func_def_args_multi_line = false # false/true # Add or remove newline before the ')' in a function declaration nl_func_decl_end = remove # ignore/add/remove/force # Add or remove newline before the ')' in a function definition nl_func_def_end = remove # ignore/add/remove/force # Overrides nl_func_decl_end when there is only one parameter. nl_func_decl_end_single = ignore # ignore/add/remove/force # Overrides nl_func_def_end when there is only one parameter. nl_func_def_end_single = ignore # ignore/add/remove/force # Whether to add newline before ')' in a function declaration if '(' and ')' are in different lines. nl_func_decl_end_multi_line = false # false/true # Whether to add newline before ')' in a function definition if '(' and ')' are in different lines. nl_func_def_end_multi_line = false # false/true # Add or remove newline between '()' in a function declaration. nl_func_decl_empty = ignore # ignore/add/remove/force # Add or remove newline between '()' in a function definition. nl_func_def_empty = ignore # ignore/add/remove/force # Whether to add newline after '(' in a function call if '(' and ')' are in different lines. nl_func_call_start_multi_line = false # false/true # Whether to add newline after each ',' in a function call if '(' and ')' are in different lines. nl_func_call_args_multi_line = false # false/true # Whether to add newline before ')' in a function call if '(' and ')' are in different lines. nl_func_call_end_multi_line = false # false/true # Whether to put each OC message parameter on a separate line # See nl_oc_msg_leave_one_liner nl_oc_msg_args = false # false/true # Add or remove newline between function signature and '{' nl_fdef_brace = add # ignore/add/remove/force # Add or remove newline between C++11 lambda signature and '{' nl_cpp_ldef_brace = ignore # ignore/add/remove/force # Add or remove a newline between the return keyword and return expression. nl_return_expr = ignore # ignore/add/remove/force # Whether to put a newline after semicolons, except in 'for' statements nl_after_semicolon = false # false/true # Java: Control the newline between the ')' and '{{' of the double brace initializer. nl_paren_dbrace_open = ignore # ignore/add/remove/force # Whether to put a newline after brace open. # This also adds a newline before the matching brace close. nl_after_brace_open = false # false/true # If nl_after_brace_open and nl_after_brace_open_cmt are true, a newline is # placed between the open brace and a trailing single-line comment. nl_after_brace_open_cmt = false # false/true # Whether to put a newline after a virtual brace open with a non-empty body. # These occur in un-braced if/while/do/for statement bodies. nl_after_vbrace_open = false # false/true # Whether to put a newline after a virtual brace open with an empty body. # These occur in un-braced if/while/do/for statement bodies. nl_after_vbrace_open_empty = false # false/true # Whether to put a newline after a brace close. # Does not apply if followed by a necessary ';'. nl_after_brace_close = false # false/true # Whether to put a newline after a virtual brace close. # Would add a newline before return in: 'if (foo) a++; return;' nl_after_vbrace_close = true # false/true # Control the newline between the close brace and 'b' in: 'struct { int a; } b;' # Affects enums, unions and structures. If set to ignore, uses nl_after_brace_close nl_brace_struct_var = ignore # ignore/add/remove/force # Whether to alter newlines in '#define' macros nl_define_macro = false # false/true # Whether to remove blanks after '#ifxx' and '#elxx', or before '#elxx' and '#endif'. Does not affect top-level #ifdefs. nl_squeeze_ifdef = false # false/true # Makes the nl_squeeze_ifdef option affect the top-level #ifdefs as well. nl_squeeze_ifdef_top_level = false # false/true # Add or remove blank line before 'if' nl_before_if = ignore # ignore/add/remove/force # Add or remove blank line after 'if' statement nl_after_if = add # ignore/add/remove/force # Add or remove blank line before 'for' nl_before_for = ignore # ignore/add/remove/force # Add or remove blank line after 'for' statement nl_after_for = add # ignore/add/remove/force # Add or remove blank line before 'while' nl_before_while = ignore # ignore/add/remove/force # Add or remove blank line after 'while' statement nl_after_while = add # ignore/add/remove/force # Add or remove blank line before 'switch' nl_before_switch = ignore # ignore/add/remove/force # Add or remove blank line after 'switch' statement nl_after_switch = add # ignore/add/remove/force # Add or remove blank line before 'synchronized' nl_before_synchronized = ignore # ignore/add/remove/force # Add or remove blank line after 'synchronized' statement nl_after_synchronized = ignore # ignore/add/remove/force # Add or remove blank line before 'do' nl_before_do = ignore # ignore/add/remove/force # Add or remove blank line after 'do/while' statement nl_after_do = add # ignore/add/remove/force # Whether to double-space commented-entries in struct/union/enum nl_ds_struct_enum_cmt = false # false/true # force nl before } of a struct/union/enum # (lower priority than 'eat_blanks_before_close_brace') nl_ds_struct_enum_close_brace = false # false/true # Add or remove blank line before 'func_class_def' nl_before_func_class_def = 0 # number # Add or remove blank line before 'func_class_proto' nl_before_func_class_proto = 0 # number # Add or remove a newline before/after a class colon, # (tied to pos_class_colon). nl_class_colon = ignore # ignore/add/remove/force # Add or remove a newline around a class constructor colon. # Related to nl_constr_init_args, pos_constr_colon and pos_constr_comma. nl_constr_colon = ignore # ignore/add/remove/force # Change simple unbraced if statements into a one-liner # 'if(b)\n i++;' => 'if(b) i++;' nl_create_if_one_liner = false # false/true # Change simple unbraced for statements into a one-liner # 'for (i=0;i<5;i++)\n foo(i);' => 'for (i=0;i<5;i++) foo(i);' nl_create_for_one_liner = false # false/true # Change simple unbraced while statements into a one-liner # 'while (i<5)\n foo(i++);' => 'while (i<5) foo(i++);' nl_create_while_one_liner = false # false/true # Change a one-liner if statement into simple unbraced if # 'if(b) i++;' => 'if(b) i++;' nl_split_if_one_liner = true # false/true # Change a one-liner for statement into simple unbraced for # 'for (i=0;<5;i++) foo(i);' => 'for (i=0;<5;i++) foo(i);' nl_split_for_one_liner = true # false/true # Change simple unbraced while statements into a one-liner while # 'while (i<5)\n foo(i++);' => 'while (i<5) foo(i++);' nl_split_while_one_liner = true # false/true # # Positioning options # # The position of arithmetic operators in wrapped expressions pos_arith = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force # The position of assignment in wrapped expressions. # Do not affect '=' followed by '{' pos_assign = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force # The position of boolean operators in wrapped expressions pos_bool = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force # The position of comparison operators in wrapped expressions pos_compare = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force # The position of conditional (b ? t : f) operators in wrapped expressions pos_conditional = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force # The position of the comma in wrapped expressions pos_comma = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force # The position of the comma in enum entries pos_enum_comma = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force # The position of the comma in the base class list if there are more than one line, # (tied to nl_class_init_args). pos_class_comma = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force # The position of the comma in the constructor initialization list. # Related to nl_constr_colon, nl_constr_init_args and pos_constr_colon. pos_constr_comma = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force # The position of trailing/leading class colon, between class and base class list # (tied to nl_class_colon). pos_class_colon = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force # The position of colons between constructor and member initialization, # (tied to UO_nl_constr_colon). # Related to nl_constr_colon, nl_constr_init_args and pos_constr_comma. pos_constr_colon = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force # # Line Splitting options # # Try to limit code width to N number of columns code_width = 80 # number # Whether to fully split long 'for' statements at semi-colons ls_for_split_full = false # false/true # Whether to fully split long function protos/calls at commas ls_func_split_full = true # false/true # Whether to split lines as close to code_width as possible and ignore some groupings ls_code_width = false # false/true # # Blank line options # # The maximum consecutive newlines (3 = 2 blank lines) nl_max = 0 # number # The number of newlines after a function prototype, if followed by another function prototype nl_after_func_proto = 0 # number # The number of newlines after a function prototype, if not followed by another function prototype nl_after_func_proto_group = 0 # number # The number of newlines after a function class prototype, if followed by another function class prototype nl_after_func_class_proto = 0 # number # The number of newlines after a function class prototype, if not followed by another function class prototype nl_after_func_class_proto_group = 0 # number # The number of newlines before a multi-line function def body nl_before_func_body_def = 0 # number # The number of newlines before a multi-line function prototype body nl_before_func_body_proto = 0 # number # The number of newlines after '}' of a multi-line function body nl_after_func_body = 0 # number # The number of newlines after '}' of a multi-line function body in a class declaration nl_after_func_body_class = 0 # number # The number of newlines after '}' of a single line function body nl_after_func_body_one_liner = 0 # number # The minimum number of newlines before a multi-line comment. # Doesn't apply if after a brace open or another multi-line comment. nl_before_block_comment = 0 # number # The minimum number of newlines before a single-line C comment. # Doesn't apply if after a brace open or other single-line C comments. nl_before_c_comment = 0 # number # The minimum number of newlines before a CPP comment. # Doesn't apply if after a brace open or other CPP comments. nl_before_cpp_comment = 0 # number # Whether to force a newline after a multi-line comment. nl_after_multiline_comment = false # false/true # Whether to force a newline after a label's colon. nl_after_label_colon = false # false/true # The number of newlines after '}' or ';' of a struct/enum/union definition nl_after_struct = 0 # number # The number of newlines before a class definition nl_before_class = 0 # number # The number of newlines after '}' or ';' of a class definition nl_after_class = 0 # number # The number of newlines before a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label. # Will not change the newline count if after a brace open. # 0 = No change. nl_before_access_spec = 0 # number # The number of newlines after a 'private:', 'public:', 'protected:', 'signals:' or 'slots:' label. # 0 = No change. # the option 'nl_after_access_spec' takes preference over 'nl_typedef_blk_start' and 'nl_var_def_blk_start' nl_after_access_spec = 0 # number # The number of newlines between a function def and the function comment. # 0 = No change. nl_comment_func_def = 0 # number # The number of newlines after a try-catch-finally block that isn't followed by a brace close. # 0 = No change. nl_after_try_catch_finally = 0 # number # The number of newlines before and after a property, indexer or event decl. # 0 = No change. nl_around_cs_property = 0 # number # The number of newlines between the get/set/add/remove handlers in C#. # 0 = No change. nl_between_get_set = 0 # number # Add or remove newline between C# property and the '{' nl_property_brace = ignore # ignore/add/remove/force # Whether to remove blank lines after '{' eat_blanks_after_open_brace = false # false/true # Whether to remove blank lines before '}' eat_blanks_before_close_brace = false # false/true # How aggressively to remove extra newlines not in preproc. # 0: No change # 1: Remove most newlines not handled by other config # 2: Remove all newlines and reformat completely by config nl_remove_extra_newlines = 0 # number # Whether to put a blank line before 'return' statements, unless after an open brace. nl_before_return = false # false/true # Whether to put a blank line after 'return' statements, unless followed by a close brace. nl_after_return = false # false/true # Whether to put a newline after a Java annotation statement. # Only affects annotations that are after a newline. nl_after_annotation = ignore # ignore/add/remove/force # Controls the newline between two annotations. nl_between_annotation = ignore # ignore/add/remove/force # # Code modifying options (non-whitespace) # # Add or remove braces on single-line 'do' statement mod_full_brace_do = ignore # ignore/add/remove/force # Add or remove braces on single-line 'for' statement mod_full_brace_for = ignore # ignore/add/remove/force # Add or remove braces on single-line function definitions. (Pawn) mod_full_brace_function = ignore # ignore/add/remove/force # Add or remove braces on single-line 'if' statement. Will not remove the braces if they contain an 'else'. mod_full_brace_if = ignore # ignore/add/remove/force # Make all if/elseif/else statements in a chain be braced or not. Overrides mod_full_brace_if. # If any must be braced, they are all braced. If all can be unbraced, then the braces are removed. mod_full_brace_if_chain = false # false/true # Make all if/elseif/else statements with at least one 'else' or 'else if' fully braced. # If mod_full_brace_if_chain is used together with this option, all if-else chains will get braces, # and simple 'if' statements will lose them (if possible). mod_full_brace_if_chain_only = false # false/true # Don't remove braces around statements that span N newlines mod_full_brace_nl = 0 # number # Add or remove braces on single-line 'while' statement mod_full_brace_while = ignore # ignore/add/remove/force # Add or remove braces on single-line 'using ()' statement mod_full_brace_using = ignore # ignore/add/remove/force # Add or remove unnecessary paren on 'return' statement mod_paren_on_return = ignore # ignore/add/remove/force # Whether to change optional semicolons to real semicolons mod_pawn_semicolon = false # false/true # Add parens on 'while' and 'if' statement around bools mod_full_paren_if_bool = false # false/true # Whether to remove superfluous semicolons mod_remove_extra_semicolon = false # false/true # If a function body exceeds the specified number of newlines and doesn't have a comment after # the close brace, a comment will be added. mod_add_long_function_closebrace_comment = 0 # number # If a namespace body exceeds the specified number of newlines and doesn't have a comment after # the close brace, a comment will be added. mod_add_long_namespace_closebrace_comment = 0 # number # If a class body exceeds the specified number of newlines and doesn't have a comment after # the close brace, a comment will be added. mod_add_long_class_closebrace_comment = 0 # number # If a switch body exceeds the specified number of newlines and doesn't have a comment after # the close brace, a comment will be added. mod_add_long_switch_closebrace_comment = 0 # number # If an #ifdef body exceeds the specified number of newlines and doesn't have a comment after # the #endif, a comment will be added. mod_add_long_ifdef_endif_comment = 10 # number # If an #ifdef or #else body exceeds the specified number of newlines and doesn't have a comment after # the #else, a comment will be added. mod_add_long_ifdef_else_comment = 0 # number # If TRUE, will sort consecutive single-line 'import' statements [Java, D] mod_sort_import = false # false/true # If TRUE, will sort consecutive single-line 'using' statements [C#] mod_sort_using = false # false/true # If TRUE, will sort consecutive single-line '#include' statements [C/C++] and '#import' statements [Obj-C] # This is generally a bad idea, as it may break your code. mod_sort_include = false # false/true # If TRUE, it will move a 'break' that appears after a fully braced 'case' before the close brace. mod_move_case_break = false # false/true # Will add or remove the braces around a fully braced case statement. # Will only remove the braces if there are no variable declarations in the block. mod_case_brace = remove # ignore/add/remove/force # If TRUE, it will remove a void 'return;' that appears as the last statement in a function. mod_remove_empty_return = false # false/true # If TRUE, it will organize the properties (Obj-C) mod_sort_oc_properties = false # false/true # Determines weight of atomic/nonatomic (Obj-C) mod_sort_oc_property_thread_safe_weight = 0 # number # Determines weight of readwrite (Obj-C) mod_sort_oc_property_readwrite_weight = 0 # number # Determines weight of reference type (retain, copy, assign, weak, strong) (Obj-C) mod_sort_oc_property_reference_weight = 0 # number # Determines weight of getter type (getter=) (Obj-C) mod_sort_oc_property_getter_weight = 0 # number # Determines weight of setter type (setter=) (Obj-C) mod_sort_oc_property_setter_weight = 0 # number # Determines weight of nullability type (nullable/nonnull) (Obj-C) mod_sort_oc_property_nullability_weight = 0 # number # # Comment modifications # # Try to wrap comments at cmt_width columns cmt_width = 0 # number # Set the comment reflow mode (default: 0) # 0: no reflowing (apart from the line wrapping due to cmt_width) # 1: no touching at all # 2: full reflow cmt_reflow_mode = 0 # number # Whether to convert all tabs to spaces in comments. Default is to leave tabs inside comments alone, unless used for indenting. cmt_convert_tab_to_spaces = false # false/true # If false, disable all multi-line comment changes, including cmt_width. keyword substitution and leading chars. # Default=True. cmt_indent_multi = true # false/true # Whether to group c-comments that look like they are in a block cmt_c_group = false # false/true # Whether to put an empty '/*' on the first line of the combined c-comment cmt_c_nl_start = false # false/true # Whether to put a newline before the closing '*/' of the combined c-comment cmt_c_nl_end = false # false/true # Whether to group cpp-comments that look like they are in a block cmt_cpp_group = false # false/true # Whether to put an empty '/*' on the first line of the combined cpp-comment cmt_cpp_nl_start = false # false/true # Whether to put a newline before the closing '*/' of the combined cpp-comment cmt_cpp_nl_end = false # false/true # Whether to change cpp-comments into c-comments cmt_cpp_to_c = false # false/true # Whether to put a star on subsequent comment lines cmt_star_cont = true # false/true # The number of spaces to insert at the start of subsequent comment lines cmt_sp_before_star_cont = 0 # number # The number of spaces to insert after the star on subsequent comment lines cmt_sp_after_star_cont = 0 # number # For multi-line comments with a '*' lead, remove leading spaces if the first and last lines of # the comment are the same length. Default=True cmt_multi_check_last = false # false/true # For multi-line comments with a '*' lead, remove leading spaces if the first and last lines of # the comment are the same length AND if the length is bigger as the first_len minimum. Default=4 cmt_multi_first_len_minimum = 4 # number # The filename that contains text to insert at the head of a file if the file doesn't start with a C/C++ comment. # Will substitute $(filename) with the current file's name. cmt_insert_file_header = "" # string # The filename that contains text to insert at the end of a file if the file doesn't end with a C/C++ comment. # Will substitute $(filename) with the current file's name. cmt_insert_file_footer = "" # string # The filename that contains text to insert before a function implementation if the function isn't preceded with a C/C++ comment. # Will substitute $(function) with the function name and $(javaparam) with the javadoc @param and @return stuff. # Will also substitute $(fclass) with the class name: void CFoo::Bar() { ... } cmt_insert_func_header = "" # string # The filename that contains text to insert before a class if the class isn't preceded with a C/C++ comment. # Will substitute $(class) with the class name. cmt_insert_class_header = "" # string # The filename that contains text to insert before a Obj-C message specification if the method isn't preceded with a C/C++ comment. # Will substitute $(message) with the function name and $(javaparam) with the javadoc @param and @return stuff. cmt_insert_oc_msg_header = "" # string # If a preprocessor is encountered when stepping backwards from a function name, then # this option decides whether the comment should be inserted. # Affects cmt_insert_oc_msg_header, cmt_insert_func_header and cmt_insert_class_header. cmt_insert_before_preproc = false # false/true # If a function is declared inline to a class definition, then # this option decides whether the comment should be inserted. # Affects cmt_insert_func_header. cmt_insert_before_inlines = true # false/true # If the function is a constructor/destructor, then # this option decides whether the comment should be inserted. # Affects cmt_insert_func_header. cmt_insert_before_ctor_dtor = false # false/true # # Preprocessor options # # Control indent of preprocessors inside #if blocks at brace level 0 (file-level) pp_indent = ignore # ignore/add/remove/force # Whether to indent #if/#else/#endif at the brace level (true) or from column 1 (false) pp_indent_at_level = false # false/true # Specifies the number of columns to indent preprocessors per level at brace level 0 (file-level). # If pp_indent_at_level=false, specifies the number of columns to indent preprocessors per level at brace level > 0 (function-level). # Default=1. pp_indent_count = 1 # number # Add or remove space after # based on pp_level of #if blocks pp_space = ignore # ignore/add/remove/force # Sets the number of spaces added with pp_space pp_space_count = 0 # number # The indent for #region and #endregion in C# and '#pragma region' in C/C++ pp_indent_region = 0 # number # Whether to indent the code between #region and #endregion pp_region_indent_code = false # false/true # If pp_indent_at_level=true, sets the indent for #if, #else and #endif when not at file-level. # 0: indent preprocessors using output_tab_size. # >0: column at which all preprocessors will be indented. pp_indent_if = 0 # number # Control whether to indent the code between #if, #else and #endif. pp_if_indent_code = false # false/true # Whether to indent '#define' at the brace level (true) or from column 1 (false) pp_define_at_level = false # false/true # # Use or Do not Use options # # True: indent_func_call_param will be used (default) # False: indent_func_call_param will NOT be used use_indent_func_call_param = true # false/true # The value of the indentation for a continuation line is calculate differently if the line is: # a declaration :your case with QString fileName ... # an assigment :your case with pSettings = new QSettings( ... # At the second case the option value might be used twice: # at the assigment # at the function call (if present) # To prevent the double use of the option value, use this option with the value 'true'. # True: indent_continue will be used only once # False: indent_continue will be used every time (default) use_indent_continue_only_once = false # false/true # SIGNAL/SLOT Qt macros have special formatting options. See options_for_QT.cpp for details. # Default=True. use_options_overriding_for_qt_macros = true # false/true # # Warn levels - 1: error, 2: warning (default), 3: note # # Warning is given if doing tab-to-\t replacement and we have found one in a C# verbatim string literal. warn_level_tabs_found_in_verbatim_string_literals = 2 # number # You can force a token to be a type with the 'type' option. # Example: # type myfoo1 myfoo2 # # You can create custom macro-based indentation using macro-open, # macro-else and macro-close. # Example: # macro-open BEGIN_TEMPLATE_MESSAGE_MAP # macro-open BEGIN_MESSAGE_MAP # macro-close END_MESSAGE_MAP # # You can assign any keyword to any type with the set option. # set func_call_user _ N_ # # The full syntax description of all custom definition config entries # is shown below: # # define custom tokens as: # - embed whitespace in token using '' escape character, or # put token in quotes # - these: ' " and ` are recognized as quote delimiters # # type token1 token2 token3 ... # ^ optionally specify multiple tokens on a single line # define def_token output_token # ^ output_token is optional, then NULL is assumed # macro-open token # macro-close token # macro-else token # set id token1 token2 ... # ^ optionally specify multiple tokens on a single line # ^ id is one of the names in token_enum.h sans the CT_ prefix, # e.g. PP_PRAGMA # # all tokens are separated by any mix of ',' commas, '=' equal signs # and whitespace (space, tab) # # You can add support for other file extensions using the 'file_ext' command. # The first arg is the language name used with the '-l' option. # The remaining args are file extensions, matched with 'endswith'. # file_ext CPP .ch .cxx .cpp.in # # option(s) with 'not default' value: 0 # rtfilter-1.3/doc/000077500000000000000000000000001370625041100137545ustar00rootroot00000000000000rtfilter-1.3/doc/conf.py000066400000000000000000000236001370625041100152540ustar00rootroot00000000000000# -*- coding: utf-8 -*- # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. import linuxdoc extensions = [ 'sphinx.ext.todo', 'linuxdoc.rstFlatTable', # Implementation of the 'flat-table' reST-directive. 'linuxdoc.rstKernelDoc', # Implementation of the 'kernel-doc' reST-directive. 'linuxdoc.kernel_include', # Implementation of the 'kernel-include' reST-directive. 'linuxdoc.manKernelDoc', # Implementation of the 'kernel-doc-man' builder 'linuxdoc.cdomain', # Replacement for the sphinx c-domain. ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] source_suffix = '.rst' # The encoding of source files. # # source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'rtfilter' copyright = u'2008-2011, Nicolas Bourdaud' author = u'nicolas.bourdaud@gmail.com' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = u'1.2' # The full version, including alpha/beta/rc tags. release = u'1.2-next' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # # today = '' # # Else, today_fmt is used as the format for a strftime call. # # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all # documents. # # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. # keep_warnings = False # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False primary_domain = 'c' # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # import sphinx_rtd_theme html_theme = 'sphinx_rtd_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # # html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # A shorter title for the navigation bar. Default is the same as html_title. # # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # # html_logo = None # The name of an image file (relative to this directory) to use as a favicon of # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". # html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. # # html_extra_path = [] # If not None, a 'Last updated on:' timestamp is inserted at every page # bottom, using the given strftime format. # The empty string is equivalent to '%b %d, %Y'. # # html_last_updated_fmt = None # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # # html_additional_pages = {} # If false, no module index is generated. # # html_domain_indices = True # If false, no index is generated. # # html_use_index = True # If true, the index is split into individual pages for each letter. # # html_split_index = False # If true, links to the reST sources are added to the pages. # # html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # # html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # # html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # # html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None # Language to be used for generating the HTML full-text search index. # Sphinx supports the following languages: # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh' # # html_search_language = 'en' # A dictionary with options for the search language support, empty by default. # 'ja' uses this config value. # 'zh' user can custom change `jieba` dictionary path. # # html_search_options = {'type': 'default'} # The name of a javascript file (relative to the configuration directory) that # implements a search results scorer. If empty, the default will be used. # # html_search_scorer = 'scorer.js' # Output file base name for HTML help builder. htmlhelp_basename = 'rtfilterdoc' # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # # 'preamble': '', # Latex figure (float) alignment # # 'figure_align': 'htbp', } # The name of an image file (relative to this directory) to place at the top of # the title page. # # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # # latex_use_parts = False # If true, show page references after internal links. # # latex_show_pagerefs = False # If true, show URL addresses after external links. # # latex_show_urls = False # Documents to append as an appendix to all manuals. # # latex_appendices = [] # It false, will not define \strong, \code, itleref, \crossref ... but only # \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added # packages. # # latex_keep_old_macro_names = True # If false, no module index is generated. # # latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ] # If true, show URL addresses after external links. # # man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Documents to append as an appendix to all manuals. # # texinfo_appendices = [] # If false, no module index is generated. # # texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. # # texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. # # texinfo_no_detailmenu = False kernel_doc_exp_method = 'attribute' kernel_doc_exp_ids = 'API_EXPORTED API_EXPORTED_RELOCATABLE' kernel_doc_known_attrs = 'LOCAL_FN noreturn' kernel_doc_mansect = 3 # In nickpick mode, it will complain about lots of missing references that # # 1) are just typedefs like: bool, __u32, etc; # 2) It will complain for things like: enum, NULL; # 3) It will complain for symbols that should be on different # books (but currently aren't ported to ReST) # # The list below has a list of such symbols to be ignored in nitpick mode # nitpick_ignore = [ ("c:type", "bool"), ("c:type", "enum"), # stdint declarations ("c:type", "int8_t"), ("c:type", "uint8_t"), ("c:type", "int16_t"), ("c:type", "uint16_t"), ("c:type", "int32_t"), ("c:type", "uint32_t"), ("c:type", "int64_t"), ("c:type", "uint64_t"), # some complex types and structures ("c:type", "socklen_t"), ("c:type", "sockaddr"), ("c:type", "addrinfo"), ("c:type", "iovec"), ("c:type", "timespec"), # ignore warnings about variadic arguments ("c:type", "ellipsis"), # ... ("c:type", "va_list"), # ignore warnings about some unknown functions ("c:func", "poll"), ("c:func", "getaddrinfo"), ("c:func", "getnamedinfo"), ("c:func", "getsockname"), ] rtfilter-1.3/doc/examples/000077500000000000000000000000001370625041100155725ustar00rootroot00000000000000rtfilter-1.3/doc/examples/Makefile000066400000000000000000000002071370625041100172310ustar00rootroot00000000000000LIBS=-lrtfilter all: butterworth butterworth: butterworth.c $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) clean: $(RM) butterworth rtfilter-1.3/doc/examples/butterworth.c000066400000000000000000000055061370625041100203350ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Nicolas Bourdaud * * The program is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /* This program presents a very simple example of the use of the rtfilter * library. It simply creates a multichannel signal. Each channel contains a * ramp of the same length with an amplitude specific to each channel. * * The input data in created and processd by chunk of CHUNKNS samples. The * input and output data are then recorded on 2 files: input.bin and * output.bin. */ #include #include #include #define NCH 8 #define FS 512 /* in Hz */ #define CUTOFF 8 /* in Hz */ #define CHUNKNS 16 #define RAMPDUR 0.1 /* in seconds */ #define DURATION 10 /* in seconds */ #define NPOLES 2 /* Create a ramp signal in each channel */ static void create_input(float* data, int ns, int cs) { int j, i, ramplen; ramplen = RAMPDUR * FS; for (j = 0; j < NCH; j++) { for (i = 0; i < ns; i++) { data[i*NCH+j] = (j+1)*((cs+i) % ramplen); } } } int main(int argc, char* argv[]) { (void)argc; /* Disable warning about unused variable */ (void)argv; /* Disable warning about unused variable */ float input[CHUNKNS * NCH], output[CHUNKNS * NCH]; double normfc; int i; hfilter filt = NULL; FILE *fin = NULL, *fout = NULL; size_t input_ns, output_ns; int retcode = EXIT_FAILURE; /* Create the butterworth filter */ normfc = (double) CUTOFF / (double) FS; filt = rtf_create_butterworth(NCH, RTF_FLOAT, normfc, NPOLES, 0); if (filt == NULL) goto exit; /* Open the streams for writing input and output signals */ fin = fopen("input.bin", "wb"); fout = fopen("output.bin", "wb"); if (fin == NULL || fout == NULL) goto exit; /* Loop over sample */ for (i = 0; i < DURATION * FS; i += CHUNKNS) { /* prepare the input chunk */ create_input(input, CHUNKNS, i); /* Filter the data */ rtf_filter(filt, input, output, CHUNKNS); /* Write the input and output on files */ input_ns = fwrite(input, sizeof(float) * NCH, CHUNKNS, fin); output_ns = fwrite(output, sizeof(float) * NCH, CHUNKNS, fout); if (input_ns < CHUNKNS || output_ns < CHUNKNS) goto exit; } retcode = EXIT_SUCCESS; exit: fclose(fin); fclose(fout); rtf_destroy_filter(filt); return retcode; } rtfilter-1.3/doc/index.rst000066400000000000000000000016621370625041100156220ustar00rootroot00000000000000Welcome to rtfilter's documentation! ===================================== This package provides a library written in C implementing realtime digital filtering functions for multichannel signals (i.e. filtering multiple signal with the same filter). The core library implements FIR and IIR filtering for float and double data type. Additional functions are also provided to design few usual filters: Butterworth, Chebyshev, windowed sinc... In addition, the filter functions have been especially optimized for multichannel signals. If data allows it (and if possible with the compilation flags used), the library automatically switch to optimized SIMD (Single Instruction Multiple Data) code, allowing to reduce by 3~4 the time spent in processing the data. .. toctree:: :caption: API module list :titlesonly: :maxdepth: 2 rtfilter.rst Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` rtfilter-1.3/doc/rtfilter.rst000066400000000000000000000004321370625041100163400ustar00rootroot00000000000000rtfilter.rst ============ .. kernel-doc:: src/filter.c :no-header: :headers: rtfilter.h :export: .. kernel-doc:: src/common-filters.c :no-header: :headers: rtfilter.h :export: .. kernel-doc:: src/downsampler.c :no-header: :headers: rtfilter.h :export: rtfilter-1.3/doc/sphinx-build-wrapper.sh000066400000000000000000000002611370625041100203730ustar00rootroot00000000000000#!/bin/sh sphinxbuild=$1 source_root=$2 builder=$3 doc_srcdir=$4 out_dir=$5 export srctree=$source_root $sphinxbuild -M $builder -d doc/.doctrees -j auto $doc_srcdir $out_dir rtfilter-1.3/m4/000077500000000000000000000000001370625041100135275ustar00rootroot00000000000000rtfilter-1.3/m4/.gitignore000066400000000000000000000001341370625041100155150ustar00rootroot00000000000000libtool.m4 ltdl.m4 ltoptions.m4 ltsugar.m4 ltversion.m4 lt~obsolete.m4 pkg.m4 visibility.m4 rtfilter-1.3/m4/api-exports.m4000066400000000000000000000016521370625041100162500ustar00rootroot00000000000000 AC_DEFUN([AC_DEF_API_EXPORT_ATTRS], [AC_REQUIRE([gl_VISIBILITY]) AC_REQUIRE([AC_CANONICAL_HOST]) case $host in *win32* | *mingw* | *cygwin* | *windows*) os_support=win32 ;; *) os_support=other ;; esac if test $HAVE_VISIBILITY = 1 -a $os_support != "win32"; then AC_DEFINE(LOCAL_FN, [__attribute__ ((visibility ("hidden")))], [attribute of the non-exported symbols]) AC_DEFINE(API_EXPORTED, [__attribute__ ((visibility ("default")))], [attribute of the symbols exported in the API]) AC_DEFINE(DEPRECATED, [__attribute__ ((deprecated))], [attribute of the deprecated symbols exported in the API]) else AC_DEFINE(LOCAL_FN, [], [attribute of the non-exported symbols]) AC_DEFINE(API_EXPORTED, [__declspec(dllexport)], [attribute of the symbols exported in the API]) AC_DEFINE(DEPRECATED, [__declspec(deprecated)], [attribute of the deprecated symbols exported in the API]) fi ]) rtfilter-1.3/m4/fastmath.m4000066400000000000000000000016031370625041100156000ustar00rootroot00000000000000AC_DEFUN([AC_CHECK_FASTMATH_FLAG], [ AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING([for fast math compiler flag]) fm_save_CFLAGS="$CFLAGS" CFLAGS="-ffast-math $CFLAGS" FASTMATH_CFLAG= AC_TRY_COMPILE( [], [], gl_cv_cc_fastmath=yes, gl_cv_cc_fastmath=no) CFLAGS="$fm_save_CFLAGS" if test $gl_cv_cc_fastmath = yes; then FASTMATH_CFLAG="-ffast-math" fi AC_MSG_RESULT([$gl_cv_cc_fastmath]) AC_SUBST([FASTMATH_CFLAG]) ]) AC_DEFUN([AC_USE_SSEMATH], [ AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING([for sse based math flag]) sm_save_CFLAGS="$CFLAGS" CFLAGS="-mfpmath=sse $CFLAGS" AC_TRY_COMPILE( [], [], gl_cv_cc_ssemath=yes, gl_cv_cc_ssemath=no) CFLAGS="$sm_save_CFLAGS" if test $gl_cv_cc_ssemath = yes; then CFLAGS="-mfpmath=sse $CFLAGS" fi AC_MSG_RESULT([$gl_cv_cc_ssemath]) AC_SUBST([CFLAGS]) ]) rtfilter-1.3/m4/hotspot.m4000066400000000000000000000010521370625041100154670ustar00rootroot00000000000000AC_DEFUN([AC_DEF_HOTSPOT_ATTR], [ AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING([for hot spot attribute]) HOTATTR="" save_CFLAGS=$CFLAGS CFLAGS=-Werror AC_TRY_COMPILE( [int dummyfunc (void) __attribute__ ((hot));], [], gl_cv_cc_hotspot=yes, gl_cv_cc_hotspot=no) if test $gl_cv_cc_hotspot = yes; then HOTATTR="__attribute__ ((hot))" fi CFLAGS=$save_CFLAGS AC_MSG_RESULT([$gl_cv_cc_hotspot]) AC_DEFINE_UNQUOTED([HOTSPOT], [$HOTATTR], [Define to the supported attribute to specify a hot spot]) ]) rtfilter-1.3/m4/ld-output-def.m4000066400000000000000000000020361370625041100164630ustar00rootroot00000000000000# ld-output-def.m4 serial 2 dnl Copyright (C) 2008-2016 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Simon Josefsson # gl_LD_OUTPUT_DEF() # ------------- # Check if linker supports -Wl,--output-def and define automake # conditional HAVE_LD_OUTPUT_DEF if it is. AC_DEFUN([gl_LD_OUTPUT_DEF], [ AC_CACHE_CHECK([if gcc/ld supports -Wl,--output-def], [gl_cv_ld_output_def], [if test "$enable_shared" = no; then gl_cv_ld_output_def="not needed, shared libraries are disabled" else gl_ldflags_save=$LDFLAGS LDFLAGS="-Wl,--output-def,conftest.def" AC_LINK_IFELSE([AC_LANG_PROGRAM([])], [gl_cv_ld_output_def=yes], [gl_cv_ld_output_def=no]) rm -f conftest.def LDFLAGS="$gl_ldflags_save" fi]) AM_CONDITIONAL([HAVE_LD_OUTPUT_DEF], test "x$gl_cv_ld_output_def" = "xyes") ]) rtfilter-1.3/m4/mm_python_module.m4000066400000000000000000000023201370625041100173450ustar00rootroot00000000000000# # SYNOPSIS # # MM_PYTHON_MODULE(modname[, fatal, python]) # # DESCRIPTION # # Checks for Python module. # # If fatal is non-empty then absence of a module will trigger an error. # The third parameter can either be "python" for Python 2 or "python3" for # Python 3; defaults to Python 3. # # LICENSE # # Copyright (c) 2008 Andrew Collier # # 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. #serial 8 AC_DEFUN([MM_PYTHON_MODULE],[ if test -z $PYTHON; then if test -z "$3"; then PYTHON="python3" else PYTHON="$3" fi fi PYTHON_NAME=`basename $PYTHON` AC_MSG_CHECKING($PYTHON_NAME module: $1) $PYTHON -c "import $1" 2>/dev/null if test $? -eq 0; then AC_MSG_RESULT(yes) eval AS_TR_CPP(HAVE_PYMOD_$1)=yes else AC_MSG_RESULT(no) eval AS_TR_CPP(HAVE_PYMOD_$1)=no # if test -n "$2" then AC_MSG_ERROR(failed to find required module $1) exit 1 fi fi ]) rtfilter-1.3/m4/pkg-ext.m4000066400000000000000000000052531370625041100153550ustar00rootroot00000000000000# pkg-fine.m4 - Macros to locate and utilise pkg-config in a fine grain way # PKG_CHECK_MODULES_EXT(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES_EXT], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_CPPFLAGS], [C preprocessor flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LDFLAGS], [linker flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [libraries for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags-only-other], [$2]) _PKG_CONFIG([$1][_CPPFLAGS], [cflags-only-I], [$2]) _PKG_CONFIG([$1][_LDFLAGS], [libs-only-L], [$2]) _PKG_CONFIG([$1][_LIBS], [libs-only-l], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CPPFLAGS, $1[]_CFLAGS, $1[]_LDFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs-only-L --libs-only-l "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs-only-L --libs-only-l "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_CPPFLAGS=$pkg_cv_[]$1[]_CPPFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS $1[]_LDFLAGS=$pkg_cv_[]$1[]_LDFLAGS AC_MSG_RESULT([yes]) $3 fi[]dnl ])# PKG_CHECK_MODULES_EXT # PKG_CHECK_VAR(VARIABLENAME, MODULE, VAR) # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [Variable $3 for $2, overriding pkg-config])dnl AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1], [variable=$3], [$2]) $1=$pkg_cv_$1 AC_MSG_RESULT([$$1]) ])# PKG_CHECK_VAR rtfilter-1.3/m4/simdtest.m4000066400000000000000000000070271370625041100156330ustar00rootroot00000000000000# AC_SUPPORT_INSTR_SET(INSTRSET, SEARCH-FLAGS, [INCLUDES], [CODES], # [ISFLAGS], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # -------------------------------------------------------- # Search for support of a instruction set, if it's not already available. AC_DEFUN([AC_SUPPORT_INSTR_SET], [AS_VAR_PUSHDEF([ac_Search], [ac_cv_search_support_$1])dnl AC_CACHE_CHECK([for support of $1], [ac_Search], [ac_support_instr_search_save_CFLAGS=$CFLAGS; AC_LANG_CONFTEST([AC_LANG_PROGRAM([$3], [$4])]) for ac_flag in '' $2; do if test -z "$ac_flag"; then ac_res="none required" else ac_res=$ac_flag CFLAGS="$ac_flag $ac_support_instr_search_save_CFLAGS" fi AC_LINK_IFELSE([], [AS_VAR_SET([ac_Search], [$ac_res])]) AS_VAR_SET_IF([ac_Search], [break]) done AS_VAR_SET_IF([ac_Search], , [AS_VAR_SET([ac_Search], [no])]) rm conftest.$ac_ext CFLAGS=$ac_support_instr_search_save_CFLAGS]) AS_VAR_COPY([ac_res], [ac_Search]) AS_IF([test "$ac_res" != no], [test "$ac_res" = "none required" || $1_CFLAGS="$ac_res" $5], [$6]) AS_VAR_POPDEF([ac_Search])dnl ]) # AC_SUPPORT_SSE([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], # [TEST-OTHER-CFLAG], SEARCH-OTHER-CFLAGS) # -------------------------------------------------------- # Search for support SSE compiler flag if supported AC_DEFUN([AC_SUPPORT_SSE], [AS_VAR_IF($3, [yes], [test_sse_cflags="-msse $4"], [test_sse_cflags=""]) AC_SUPPORT_INSTR_SET(SSE, $test_sse_cflags, [#include ], [[__m128 a, b, c; a = _mm_set1_ps(1.0f); b = _mm_set1_ps(0.0f); c = _mm_add_ps(a, b);]], [AC_DEFINE([SUPPORT_SSE_SET], [1], [Define to built SSE support]) AC_SUBST([SSE_CFLAGS]) $1], [$2])]) ]) # AC_SUPPORT_SSE2([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], # [TEST-OTHER-CFLAG], SEARCH-OTHER-CFLAGS) # -------------------------------------------------------- # Search for support SSE2 compiler flag if supported AC_DEFUN([AC_SUPPORT_SSE2], [AS_VAR_IF($3, [yes], [test_sse2_cflags="-msse2 $4"], [test_sse2_cflags=""]) AC_SUPPORT_INSTR_SET(SSE2, $test_sse2_cflags, [#include ], [[__m128d a, b, c; a = _mm_set1_pd(1.0); b = _mm_set1_pd(0.0); c = _mm_add_pd(a, b);]], [AC_DEFINE([SUPPORT_SSE2_SET], [1], [Define to built SSE2 support]) AC_SUBST([SSE2_CFLAGS]) $1], [$2])]) ]) # AC_SUPPORT_SSE3([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], # [TEST-OTHER-CFLAG], SEARCH-OTHER-CFLAGS) # -------------------------------------------------------- # Search for support SSE3 compiler flag if supported AC_DEFUN([AC_SUPPORT_SSE3], [AS_VAR_IF($3, [yes], [test_sse3_cflags="-msse3 $4"], [test_sse3_cflags=""]) AC_SUPPORT_INSTR_SET(SSE3, $test_sse3_cflags, [#include ], [[__m128 a, b, c; a = _mm_set1_ps(1.0f); b = _mm_movehdup_ps(a); c = _mm_add_ps(a, b);]], [AC_DEFINE([SUPPORT_SSE3_SET], [1], [Define to built SSE3 support]) AC_SUBST([SSE3_CFLAGS]) $1], [$2])]) ]) # AC_CHECK_CPUID([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # -------------------------------------------------------- # Check that the host can use cpuid intrinsics AC_DEFUN([AC_CHECK_CPUID], [AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING([for cpuid instruction]) AC_TRY_COMPILE( [#include ], [__get_cpuid(1, 0, 0, 0, 0);], gl_cv_cc_cpuid=yes, gl_cv_cc_cpuid=no) AS_IF([test "$gl_cv_cc_cpuid" != no], [AC_DEFINE(HAVE_CPUID, [1], [Define to 1 if cpuid can be used]) $1], [$2]) AC_MSG_RESULT([$gl_cv_cc_cpuid]) ]) rtfilter-1.3/m4/warnings.m4000066400000000000000000000012741370625041100156250ustar00rootroot00000000000000# CC_WARNFLAGS() #------------------------------------------- AC_DEFUN([CC_WARNFLAGS], [AC_ARG_ENABLE([warn-all], [AS_HELP_STRING([--enable-warn-all], [turn on all warnings (default: yes)])], [case $enableval in yes|no|error) ;; *) AC_MSG_ERROR([bad value $enableval for enable-warn-all option]) ;; esac mm_warnings=$enableval], [mm_warnings=yes]) case $mm_warnings in yes) WARNFLAGS="-Wall -Wextra -Wshadow -Wstrict-prototypes -Wmissing-prototypes" ;; error) WARNFLAGS="-Wall -Wextra -Wshadow -Wstrict-prototypes -Wmissing-prototypes -Werror" ;; no) WARNFLAGS="" ;; esac AC_SUBST([WARNFLAGS]) ]) #CC_WARNINGS rtfilter-1.3/meson.build000066400000000000000000000221131370625041100153500ustar00rootroot00000000000000project('rtfilter', 'c', version : '1.3', default_options : [ 'warning_level=3', ], license : 'LGPL-3.0', meson_version: '>= 0.49' ) # follow semantic versionning (https://semver.org) # * MAJOR version when you make incompatible API changes, # * MINOR version when you add functionality in a backwards-compatible manner # * PATCH version when you make backwards-compatible bug fixes. major = '1' minor = '1' patch = '1' version = major + '.' + minor + '.' + patch cc = meson.get_compiler('c') configuration_inc = include_directories('.', 'src') # additional (optional) warnings flags = [ '-Wshadow', '-Wstrict-prototypes', '-Wmissing-prototypes', ] add_project_arguments(cc.get_supported_arguments(flags), language : 'c') # define HAVE_CONFIG_H with compiler command line to include the generated # config.h file (same as autotools) add_project_arguments('-DHAVE_CONFIG_H', language : 'c') config = configuration_data() subdir('config/api-exports') # Defined for compatibility with autotools # The other such macros defined by autotools are not used and will not be added config.set('PACKAGE_STRING', '"' + meson.project_name() + ' ' + meson.project_version() + '"') # list of mandatory headers check_headers = [ 'complex.h', 'math.h', ] foreach h : check_headers cc.check_header(h) endforeach # sse instructions handling sse_common_sources = files('src/filter-funcs.h', 'src/filter-internal.h') sse_libraries = [] if cc.has_header_symbol('cpuid.h', '__get_cpuid') config.set('HAVE_CPUID', 1) # sse support if cc.has_header_symbol('xmmintrin.h', '_mm_set1_ps') config.set('SUPPORT_SSE_SET', 1) sse_libraries += static_library('rtfilter sse filter implementation', sse_common_sources + files('src/filter-sse.c'), c_args : '-msse', include_directories : configuration_inc, ) endif # sse2 support if cc.has_header_symbol('emmintrin.h', '_mm_set1_pd') config.set('SUPPORT_SSE2_SET', 1) sse_libraries += static_library('rtfilter sse2 filter implementation', sse_common_sources + files('src/filter-sse2.c'), c_args : '-msse2', include_directories : configuration_inc, ) endif # sse3 support if cc.has_header_symbol('pmmintrin.h', '_mm_movehdup_ps') config.set('SUPPORT_SSE3_SET', 1) sse_libraries += static_library('rtfilter sse3 filter implementation', sse_common_sources + files('src/filter-sse3.c'), c_args : '-msse3', include_directories : configuration_inc, ) endif endif # check posix_memalign presence if cc.has_function('posix_memalign', prefix : '#include') config.set('HAVE_POSIX_MEMALIGN', 1) else config.set('HAVE_POSIX_MEMALIGN', 0) endif # write config file build_cfg = 'config.h' # named as such to match autotools build system configure_file(output : build_cfg, configuration : config) headers = files( 'src/rtfilter.h', 'src/rtf_common.h', ) sources = files( 'src/common-filters.c', 'src/downsampler.c', 'src/filter.c', 'src/filter-complex-double.c', 'src/filter-complex-single.c', 'src/filter-funcs.h', 'src/filter-inreal-outcomplex-double.c', 'src/filter-inreal-outcomplex-single.c', 'src/filter-internal.h', 'src/filter-real-double.c', 'src/filter-real-single.c', 'src/probesimd.h', 'src/rtf_common.h', 'src/rtfilter.h', ) install_headers(headers) libmath = cc.find_library('m', required : true) rtfilter = shared_library('rtfilter', sources, install : true, version : version, include_directories : configuration_inc, link_with : sse_libraries, dependencies : [libmath], ) import('pkgconfig').generate(rtfilter) # # TESTS # librt = [] perf_enabled = true if get_option('perf').enabled() # clock_gettime() may be provided by librt or libc depending # on their versions. clock_gettime_code = ''' #include int clock_gettime(); int main(void){return 0;} ''' if not cc.links(clock_gettime_code) if cc.links(clock_gettime_code, args : '-lrt') librt = cc.find_library('rt', required : get_option('perf')) elif get_option('perf').enabled() error('''clock_gettime() cannot be found, but is required to build the perf-test tool !''') else perf_enabled = false endif endif endif if perf_enabled # test tool to ease performance regression tests # not run as part of unit tests perf_test = executable('perf-test', files('test/perf-test.c'), include_directories : configuration_inc, link_with : rtfilter, dependencies : [libmath, librt], ) endif if get_option('tests').enabled() checklib = dependency('check', required : get_option('tests')) test_sources = files( 'test/float-comparison.c', 'test/float-comparison.h', 'test/lowpass_test.c', 'test/rtfilter_combine_test.c', 'test/rtfilter_test.c', 'test/testcases.h', 'test/test-common.c', 'test/test-common.h', 'test/unittests.c' ) unittests = executable('unittests', test_sources, include_directories : include_directories('.', 'src', 'test'), link_with : rtfilter, dependencies: [libmath, checklib], ) test('rtfilter unit tests', unittests) endif # # DOC # # compile example as a test, only install the sources example = executable('documentation example', files('doc/examples/butterworth.c'), include_directories : include_directories('.', 'src'), link_with : rtfilter, ) install_subdir('doc/examples', install_dir : get_option('datadir') / 'doc' / 'rtfilter') install_data(files('AUTHORS', 'COPYING', 'NEWS', 'README.md'), install_dir : get_option('datadir') / 'doc' / 'rtfilter') docs_state = 'disabled' sphinxbuild = find_program('sphinx-build', required : get_option('docs')) if sphinxbuild.found() and not get_option('docs').disabled() python3 = import('python').find_installation('python3', required : true) check_linuxdoc = run_command(python3, '-c', '"import linuxdoc"') if check_linuxdoc.returncode() != 0 and get_option('docs').enabled() error('python3 module "linuxdoc" is required to build documentation') elif check_linuxdoc.returncode() == 0 docs_state = 'enabled' endif endif if docs_state == 'enabled' doc_sources = files( 'doc/index.rst', 'doc/rtfilter.rst', ) sphinxbuild_wrapper = files('doc/sphinx-build-wrapper.sh') gen_man_pages = custom_target('man3', output : 'man3', command : [ 'sh', sphinxbuild_wrapper, sphinxbuild, meson.source_root(), 'kernel-doc-man', meson.source_root() / 'doc', 'man3', ], build_by_default : true, depend_files : [sources, doc_sources], install : true, install_dir : get_option('mandir'), ) custom_target('html', output : 'html', command : [ 'sh', sphinxbuild_wrapper, sphinxbuild, meson.source_root(), 'html', meson.source_root() / 'doc', 'html', ], build_by_default : true, depend_files : [sources, doc_sources], depends : gen_man_pages, # re-use .doctree from man install : true, install_dir : get_option('datadir') / 'doc/rtfilter', ) endif # # DEVTOOLS # uncrustify = find_program('uncrustify', required : false) if uncrustify.found() run_target('checkstyle', command : [ uncrustify, '-l', 'c', '-c', join_paths(meson.source_root(), 'devtools', 'uncrustify.cfg'), '--check', sources, ], ) run_target('fixstyle', command : [ uncrustify, '-l', 'c', '-c', join_paths(meson.source_root(), 'devtools', 'uncrustify.cfg'), '--replace', sources, ], ) endif # uncrustify codespell = find_program('codespell', required : false) if codespell.found() run_target('spelling', command : [ codespell, sources, ] ) endif # codespell # test public headers for most warnings and C++ compatibility # only test rtfilter.h and not all exported headers: $(include_HEADERS) # "rtf_common.h" contains a #warning which would always make the test fail # otherwise run_target('api-compat-test', command : [ 'bash', files('devtools/api-compat-test.sh'), meson.current_source_dir() / 'src', files('src/rtfilter.h'), ] ) rtfilter-1.3/meson_options.txt000066400000000000000000000004141370625041100166430ustar00rootroot00000000000000option('tests', type: 'feature', value: 'auto', description: 'build unit tests') option('perf', type: 'feature', value: 'auto', description: 'build perf-test') option('docs', type : 'feature', value: 'auto', description: 'build documentation') rtfilter-1.3/mmpack/000077500000000000000000000000001370625041100144575ustar00rootroot00000000000000rtfilter-1.3/mmpack/specs000066400000000000000000000015201370625041100155150ustar00rootroot00000000000000general: name: rtfilter version: 1.3 maintainer: Nicolas Bourdaud url: ssh://intranet.mindmaze.ch:29418/rtfilter licenses: [ LGPL-3 ] Copyright: | Copyright (C) 2008 Nicolas Bourdaud Copyright (C) 2009-2012 EPFL (Ecole Polytechnique Fédérale de Lausanne) Copyright (C) 2015-2019 MindMaze Holdings SA description: | This package provides a library written in C implementing realtime digital filtering functions for multichannel signals (i.e. filtering multiple signals with the same filter). The core library implements FIR and IIR filtering for float and double data type. Additional functions are also provided to design few usual filters: Butterworth, Chebyshev, windowed sinc... build-system: meson rtfilter-1.3/src/000077500000000000000000000000001370625041100137765ustar00rootroot00000000000000rtfilter-1.3/src/.gitignore000066400000000000000000000000641370625041100157660ustar00rootroot00000000000000# generated files config.h config.h.in* rtfilter.pc rtfilter-1.3/src/common-filters.c000066400000000000000000000572601370625041100171120ustar00rootroot00000000000000/* * Copyright (C) 2008-2011 Nicolas Bourdaud * Copyright (C) 2018-2020 Mindmaze Holdings SA * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include "rtfilter.h" #ifndef M_PI #define M_PI 3.14159265358979323846 #endif /*************************************************************** * * * Helper functions * * * ***************************************************************/ static void apply_window(double *fir, int length, KernelWindow window) { int i; double M = length - 1; switch (window) { case HAMMING_WINDOW: for (i = 0; i < length; i++) { fir[i] *= 0.54 + 0.46 * cos(2. * M_PI * ( i / M - 0.5)); } break; case BLACKMAN_WINDOW: for (i = 0; i < length; i++) { fir[i] *= (0.42 + 0.5 * cos(2. * M_PI * (i / M - 0.5)) + 0.08 * cos(4. * M_PI * (i / M - 0.5))); } break; case RECT_WINDOW: break; } } static void normalize_fir(double *fir, int length) { int i; double sum = 0.0; for (i = 0; i < length; i++) sum += fir[i]; for (i = 0; i < length; i++) fir[i] /= sum; } static void compute_convolution(double *product, double *sig1, int len1, double *sig2, int len2) { int i, j; memset(product, 0, (len1 + len2 - 1) * sizeof(*product)); for (i = 0; i < len1; i++) { for (j = 0; j < len2; j++) { product[i + j] += sig1[i] * sig2[j]; } } } static void FFT(complex double *X, double *t, int length) { int i, j; for (i = 0; i < length; i++) { X[i] = 0; for (j = 0; j < length; j++) { X[i] = X[i] + t[j]*cexp((-2.0*I*M_PI)*(j)*(i)/length); } } } static void compute_fir_lowpass(double *fir, int length, double fc) { int i; double half_len = (double) (length / 2); for (i = 0; i < length; i++) if (i != length / 2) { fir[i] = sin(2. * M_PI * fc * ((double) i - half_len)) / ((double) i - half_len); } else { fir[i] = 2.0 * M_PI * fc; } } static void reverse_fir(double *fir, int length) { int i; // compute delay minus lowpass fir for (i = 0; i < length; i++) fir[i] = -1.0 * fir[i]; fir[length - 1] += 1.0; } /* Algorithm taken form: * * "Introduction to Digital Filters with Audio Applications", * by Julius O. Smith III, (September 2007 Edition). * https://ccrma.stanford.edu/~jos/filters/Numerical_Computation_Group_Delay.html */ static double compute_IIR_filter_delay(double *num, double *den, int length) { int i, length_c; double *a, *b, *c, *cr; complex double *X, *Y; double Delay = 0.0, d = 0.0; length_c = 2*length-1; a = malloc( (length)*sizeof(*a)); b = malloc( (length)*sizeof(*b)); c = malloc( (length_c)*sizeof(*c)); cr = malloc( (length_c)*sizeof(*cr)); X = malloc( (length_c)*sizeof(*X)); Y = malloc( (length_c)*sizeof(*Y)); if (!a || !b || !c || !cr || !X || !Y) { Delay = 0.0; goto exit; } for (i = 0; i < length; i++) { b[i] = den[length-i-1]; a[i] = num[i]; } compute_convolution(c, b, length, a, length); for (i = 0; i < length_c; i++) cr[i] = c[i]*i; FFT(Y, c, length_c); FFT(X, cr, length_c); for (i = 0; i < length_c; i++) { d = creal(X[i]/Y[i]); if (d > Delay) Delay = d; } exit: free(a); free(b); free(c); free(cr); free(X); free(Y); return Delay; } /****************************** * inspired by DSP guide ch33 * ******************************/ static void get_pole_coefs(double p, double np, double fc, double r, int highpass, double a[3], double b[3]) { double rp, ip, es, vx, kx, t, w, m, d, x0, x1, x2, y1, y2, k; // calculate pole locate on the unit circle rp = -cos(M_PI / (np * 2.0) + (p - 1.0) * M_PI / np); ip = sin(M_PI / (np * 2.0) + (p - 1.0) * M_PI / np); // Warp from a circle to an ellipse if (r != 0.0) { /* es = sqrt(pow(1.0 / (1.0 - r), 2) - 1.0); * vx = (1.0 / np) * log((1.0 / es) + * sqrt((1.0 / (es * es)) + * 1.0)); * kx = (1.0 / np) * log((1.0 / es) + * sqrt((1.0 / (es * es)) - * 1.0)); * kx = (exp(kx) + exp(-kx)) / 2.0; * rp = rp * ((exp(vx) - exp(-vx)) / 2.0) / kx; * ip = ip * ((exp(vx) + exp(-vx)) / 2.0) / kx; */ es = sqrt(pow(1.0 / (1.0 - r), 2) - 1.0); vx = asinh(1.0/es) / np; kx = acosh(1.0/es) / np; kx = cosh( kx ); rp *= sinh(vx) / kx; ip *= cosh(vx) / kx; } // s to z domains conversion t = 2.0*tan(0.5); w = 2.0*M_PI*fc; m = rp*rp + ip*ip; d = 4.0 - 4.0*rp*t + m*t*t; x0 = t*t/d; x1 = 2.0*t*t/d; x2 = t*t/d; y1 = (8.0 - 2.0*m*t*t)/d; y2 = (-4.0 - 4.0*rp*t - m*t*t)/d; // LP(s) to LP(z) or LP(s) to HP(z) if (highpass) k = -cos(w/2.0 + 0.5)/cos(w/2.0 - 0.5); else k = sin(0.5 - w/2.0)/sin(0.5 + w/2.0); d = 1.0 + y1*k - y2*k*k; a[0] = (x0 - x1*k + x2*k*k)/d; a[1] = (-2.0*x0*k + x1 + x1*k*k - 2.0*x2*k)/d; a[2] = (x0*k*k - x1*k + x2)/d; b[1] = (2.0*k + y1 + y1*k*k - 2.0*y2*k)/d; b[2] = (-k*k - y1*k + y2)/d; if (highpass) { a[1] *= -1.0; b[1] *= -1.0; } } /****************************** * inspired by DSP guide ch33 * ******************************/ static int compute_cheby_iir(double *num, double *den, int num_pole, int highpass, double ripple, double cutoff_freq) { double *a, *b, *ta, *tb; double ap[3], bp[3]; double sa, sb, gain; int i, p; int retval = 1; // Allocate temporary arrays a = malloc((num_pole + 3) * sizeof(*a)); b = malloc((num_pole + 3) * sizeof(*b)); ta = malloc((num_pole + 3) * sizeof(*ta)); tb = malloc((num_pole + 3) * sizeof(*tb)); if (!a || !b || !ta || !tb) { retval = 0; goto exit; } memset(a, 0, (num_pole + 3) * sizeof(*a)); memset(b, 0, (num_pole + 3) * sizeof(*b)); a[2] = 1.0; b[2] = 1.0; for (p = 1; p <= num_pole / 2; p++) { // Compute the coefficients for this pole get_pole_coefs(p, num_pole, cutoff_freq, ripple, highpass, ap, bp); // Add coefficients to the cascade memcpy(ta, a, (num_pole + 3) * sizeof(*a)); memcpy(tb, b, (num_pole + 3) * sizeof(*b)); for (i = 2; i <= num_pole + 2; i++) { a[i] = ap[0]*ta[i] + ap[1]*ta[i-1] + ap[2]*ta[i-2]; b[i] = tb[i] - bp[1]*tb[i-1] - bp[2]*tb[i-2]; } } // Finish combining coefficients b[2] = 0.0; for (i = 0; i <= num_pole; i++) { a[i] = a[i + 2]; b[i] = -b[i + 2]; } // Normalize the gain sa = sb = 0.0; for (i = 0; i <= num_pole; i++) { sa += a[i] * ((highpass && i % 2) ? -1.0 : 1.0); sb += b[i] * ((highpass && i % 2) ? -1.0 : 1.0); } gain = sa / (1.0 - sb); for (i = 0; i <= num_pole; i++) a[i] /= gain; // Copy the results to the num and den for (i = 0; i <= num_pole; i++) { num[i] = a[i]; den[i] = -b[i]; } // den[0] must be 1.0 den[0] = 1.0; exit: free(a); free(b); free(ta); free(tb); return retval; } /** compute_bandpass_complex_filter: * \param fl normalized lowest cutoff freq of the bandpass filter. (the normal frequency divided by the sampling freq) * \param fh normalized highest cutoff freq of the bandpass filter. (the normal frequency divided by the sampling freq) * \param num_pole The number of pole the z-transform of the filter should possess * * This function creates a complex bandpass filter from a Chebyshev low pass filter. */ static int compute_bandpass_complex_filter(complex double *num, complex double *den, int num_pole, double fl, double fh) { double *a = NULL, *b = NULL; complex double *ac, *bc; double ripple, fc, alpha, Delay; int i, retval = 1; // Allocate temporary arrays a = malloc( (num_pole+1)*sizeof(*a)); b = malloc( (num_pole+1)*sizeof(*b)); ac = malloc((num_pole+1)*sizeof(*ac)); bc = malloc( (num_pole+1)*sizeof(*bc)); if (!a || !b || !ac || !bc) { retval = 0; goto exit; } alpha = M_PI*(fl+fh); // Rotation angle in radians to produces // the desired analytic filter fc = (fh-fl)/2.0; // Normalized cutoff frequency // of the low pass filter ripple = 0.01; // prepare the z-transform of low pass filter if (!compute_cheby_iir(b, a, num_pole, 0, ripple, fc)) { retval = 0; goto exit; } // Compute the low pass filter delay; the complex filter Delay = compute_IIR_filter_delay(b, a, num_pole+1); /* Note: The complex filter introduces a delay equal to * e^(j*alpha*D) (D: Delay low pass filter).To get rid of the * undesired frequency independent phase factor, the filter with * rotated poles and zeros should be multiplied by * the constant e^(-j*alpha*D).*/ // compute complex coefficients (rotating poles and zeros). for (i = 0; i < num_pole + 1; i++) { // complex numerator ac[i] = 2.0*cexp(-1.0*I*alpha*Delay) *b[i]*cexp(1.0*I*alpha*(i+1)); // complex denominator bc[i] = a[i]*cexp(1.0*I*alpha*(i+1)); } for (i = 0; i < num_pole + 1; i++) { num[i] = ac[i]; den[i] = bc[i]; } exit: free(a); free(b); free(ac); free(bc); return retval; } /************************************************************************** * * * Create particular filters * * * **************************************************************************/ /** * rtf_create_fir_mean() - creates FIR mean filters * @nchann: number of channels the filter will process * @proctype: type of data the filter will process (RTF_FLOAT or RTF_DOUBLE) * @fir_length: number of sample used to compute the mean * * Return: * the handle of the newly created filter in case of success, NULL otherwise. */ API_EXPORTED hfilter rtf_create_fir_mean(int nchann, int proctype, int fir_length) { int i; double* fir = NULL; hfilter filt; // Alloc temporary fir fir = malloc(fir_length*sizeof(*fir)); if (!fir) return NULL; // prepare the finite impulse response for (i = 0; i < fir_length; i++) fir[i] = 1. / (double) fir_length; filt = rtf_create_filter(nchann, proctype, fir_length, fir, 0, NULL, RTF_DOUBLE); free(fir); return filt; } /** * rtf_create_fir_lowpass() - creates FIR lowpass windowed sinc filters * @nchann: number of channels the filter will process * @proctype: type of data the filter will process (RTF_FLOAT or RTF_DOUBLE) * @fc: Normalized cutoff frequency (the normal frequency divided by the * sampling frequency) * @half_length: the half size of the impulse response (in number of samples) * @window: the type of the kernel wondow to use for designing the filter * * rtf_create_fir_lowpass() creates a lowpass windowed sinc filter * processing @nchann channels of data type specified by @proctype * with @fc as normalized cutoff frequency and @half_length as the half * length of the window. * * A normalized frequency is the ratio between the absolute frequency and the * sampling frequency (i.e. a value of 1.0 refers to the sampling frequency). * * The parameter @proctype has the same meaning as in rtf_create_filter(). * Refers to its manpage for more details. * * The parameter @window specifies the type of window applied to the * impulse response and can take the following values: BLACKMAN_WINDOW, * HAMMING_WINDOW or BRECT_WINDOW (see a book on signal processing for details * about their meaning). * * Return: the handle to the created filter in case of success, NULL otherwise. */ API_EXPORTED hfilter rtf_create_fir_lowpass(int nchann, int proctype, double fc, int half_length, KernelWindow window) { double *fir = NULL; hfilter filt; int fir_length = 2 * half_length + 1; // Alloc temporary fir fir = malloc(fir_length*sizeof(*fir)); if (!fir) return NULL; // prepare the finite impulse response compute_fir_lowpass(fir, fir_length, fc); apply_window(fir, fir_length, window); normalize_fir(fir, fir_length); filt = rtf_create_filter(nchann, proctype, fir_length, fir, 0, NULL, RTF_DOUBLE); free(fir); return filt; } /** * rtf_create_fir_highpass() - creates FIR highpass windowed sinc filters * @nchann: number of channels the filter will process * @proctype: type of data the filter will process (RTF_FLOAT or RTF_DOUBLE) * @fc: Normalized cutoff frequency (the normal frequency divided by the * sampling frequency) * @half_length: the half size of the impulse response (in number of samples) * @window: the type of the kernel wondow to use for designing the filter * * rtf_create_fir_highpass() creates a highpass windowed sinc filter * processing @nchann channels of data type specified by @proctype * with @fc as normalized cutoff frequency and @half_length as the half * length of the window. * * A normalized frequency is the ratio between the absolute frequency and the * sampling frequency (i.e. a value of 1.0 refers to the sampling frequency). * * The parameter @proctype has the same meaning as in rtf_create_filter(). * Refers to its manpage for more details. * * The parameter @window specifies the type of window applied to the * impulse response and can take the following values: BLACKMAN_WINDOW, * HAMMING_WINDOW or BRECT_WINDOW (see a book on signal processing for details * about their meaning). * * Return: the handle to the created filter in case of success, NULL otherwise. */ API_EXPORTED hfilter rtf_create_fir_highpass(int nchann, int proctype, double fc, int half_length, KernelWindow window) { double *fir = NULL; hfilter filt; int fir_length = 2 * half_length + 1; // Alloc temporary fir fir = malloc(fir_length*sizeof(*fir)); if (!fir) return NULL; // prepare the finite impulse response compute_fir_lowpass(fir, fir_length, fc); apply_window(fir, fir_length, window); normalize_fir(fir, fir_length); reverse_fir(fir, fir_length); filt = rtf_create_filter(nchann, proctype, fir_length, fir, 0, NULL, RTF_DOUBLE); free(fir); return filt; } /** * rtf_create_fir_bandpass() - creates FIR bandpass windowed sinc filters * @nchann: number of channels the filter will process * @proctype: type of data the filter will process (RTF_FLOAT or * RTF_DOUBLE) * @fc_low: normalized cutoff frequency of the lowpass part (the normal * frequency divided by the sampling frequency) * @fc_high: normalized cutoff frequency of the highpass part (the normal * frequency divided by the sampling frequency) * @half_length: the half size of the impulse response (in number of samples) * @window: the type of the kernel wondow to use for designing the filter * * rtf_create_fir_bandpass() creates a bandpass windowed sinc filter * processing @nchann channels of data type specified by @proctype * with @fc_low and @fc_high as respectively the lowpass and highpass * normalized cutoff frequency and @half_length as the half * length of the window. * * A normalized frequency is the ratio between the absolute frequency and the * sampling frequency (i.e. a value of 1.0 refers to the sampling frequency). * * The parameter @proctype has the same meaning as in rtf_create_filter(). * Refers to its manpage for more details. * * The parameter @window specifies the type of window applied to the * impulse response and can take the following values: BLACKMAN_WINDOW, * HAMMING_WINDOW or BRECT_WINDOW (see a book on signal processing for details * about their meaning). * * Return: the handle to the created filter in case of success, NULL otherwise. */ API_EXPORTED hfilter rtf_create_fir_bandpass(int nchann, int proctype, double fc_low, double fc_high, int half_length, KernelWindow window) { int len = 2 * (half_length / 2) + 1; double fir_low[len], fir_high[len]; double *fir = NULL; hfilter filt; int fir_length = 2 * half_length + 1; // Alloc temporary fir fir = malloc(fir_length*sizeof(*fir)); if (!fir) return NULL; // Create the lowpass finite impulse response compute_fir_lowpass(fir_low, len, fc_low); apply_window(fir_low, len, window); normalize_fir(fir_low, len); // Create the highpass finite impulse response compute_fir_lowpass(fir_high, len, fc_high); apply_window(fir_high, len, window); normalize_fir(fir_high, len); reverse_fir(fir_high, len); // compute the convolution product of the two FIR compute_convolution(fir, fir_low, len, fir_high, len); filt = rtf_create_filter(nchann, proctype, fir_length, fir, 0, NULL, RTF_DOUBLE); free(fir); return filt; } /** * rtf_create_chebychev() - creates IIR Chebychev filter * @nchann: number of channels the filter will process * @proctype: type of data the filter will process (RTF_FLOAT or * RTF_DOUBLE) * @fc: normalized cutoff frequency (the normal frequency divided by the * sampling frequency) * @num_pole: the number of pole the z-transform of the filter should possess * @highpass: flag to specify the type of filter (0 for a lowpass, 1 for * a highpass) * @ripple: ripple * * rtf_create_chebychev() creates a IIR chebychev filter processing * @nchann channels of data type specified by @proctype with * @fc as normalized cutoff frequency, whose the Z-transform has * @num_pole poles and whose the impulse response has a ripple of @ripple. * This latter is expressed as the ratio between the overshoot (difference * between the max value of the response to a unit step and the unit length) * and the unit length (ratio not expressed in decibels). * * A normalized frequency is the ratio between the absolute frequency and the * sampling frequency (i.e. a value of 1.0 refers to the sampling frequency). * * If @highpass is 0, it specifies the filter should be a lowpass. If * @highpass is non-zero, the should be a highpass. * * Return: the handle to the created filter in case of success, NULL otherwise. */ API_EXPORTED hfilter rtf_create_chebychev(int nchann, int proctype, double fc, int num_pole, int highpass, double ripple) { double *num = NULL, *den = NULL; hfilter filt = NULL; if (num_pole % 2 != 0) return NULL; num = malloc( (num_pole+1)*sizeof(*num)); den = malloc( (num_pole+1)*sizeof(*den)); if (!num || !den) goto out; // prepare the z-transform of the filter if (!compute_cheby_iir(num, den, num_pole, highpass, ripple, fc)) goto out; filt = rtf_create_filter(nchann, proctype, num_pole+1, num, num_pole+1, den, RTF_DOUBLE); out: free(num); free(den); return filt; } /** * rtf_create_butterworth - creates Butterwoth filter * @nchann: number of channels the filter will process * @proctype: type of data the filter will process (RTF_FLOAT * or RTF_DOUBLE) * @fc: normalized cutoff frequency (the normal frequency divided * by the sampling frequency) * @num_pole: the number of pole the z-transform of the filter should possess * @highpass: flag to specify the type of filter (0 for a lowpass, 1 for a * highpass) * * rtf_create_butterworth() is the same as rtf_create_chebychev() * but creates a butterworth filter (which a special case of a chebychev filter * with a ripple of 0). * * A normalized frequency is the ratio between the absolute frequency and the * sampling frequency (i.e. a value of 1.0 refers to the sampling frequency). * * If @highpass is 0, it specifies the filter should be a lowpass. If * @highpass is non-zero, the should be a highpass. * * Return: the handle to the created filter in case of success, NULL otherwise. */ API_EXPORTED hfilter rtf_create_butterworth(int nchann, int proctype, double fc, int num_pole, int highpass) { return rtf_create_chebychev(nchann, proctype, fc, num_pole, highpass, 0.0); } /** * rtf_create_integral() - creates integral filters * @nchann: number of channels the filter will process * @type: type of data the filter will process (RTF_FLOAT or * RTF_DOUBLE) * @fs: sampling frequency in Hz * * Return: * the handle of the newly created filter in case of success, null otherwise. */ API_EXPORTED hfilter rtf_create_integral(int nchann, int type, double fs) { hfilter filt; double a = 1.0/fs, b[2] = {1.0, -1.0}; filt = rtf_create_filter(nchann, type, 1, &a, 2, &b, RTF_DOUBLE); return filt; } /** * rtf_create_bandpass_analytic() - creates an IIR filter estimating the * analytic signal in a bandpass * @nchann: number of channels the filter will process * @proctype: type of data the filter will process (RTF_FLOAT or * RTF_DOUBLE) * @fl: normalized low bandpass cutoff frequency (the normal * frequency divided by the sampling frequency) * @fh: normalized hihg bandpass cutoff frequency (the normal * frequency divided by the sampling frequency) * @num_pole: the number of pole the z-transform of the filter should possess * * rtf_create_bandpass_analytic() creates a complex bandpass filter from a * Chebychev low pass filter processing * @nchann channels of data type specified by @proctype. The output of * the filter is the analytic signal of the bandpassed data between the * normalized frequencies @fl and @fh. The @um_pole parameter * specifies the number of poles of the Chebychev filter used as the basis of * the analytic filter. * * A normalized frequency is the ratio between the absolute frequency and the * sampling frequency (i.e. a value of 1.0 refers to the sampling frequency). * * The Z-transform of this filter has complex coefficients. So like * rtf_create_filter() the created filter will output complex values * keeping the precision specified by @proctype. * * It is important to note that this filter can quickly become unstable as the * number of pole specified increased. Please refers to the authors of the * library to know the stability domain. * * Return: the handle to the created filter in case of success, NULL otherwise. */ API_EXPORTED hfilter rtf_create_bandpass_analytic(int nchann, int proctype, double fl, double fh, int num_pole) { complex double *a = NULL, *b = NULL; hfilter filt = NULL; if (num_pole % 2 != 0) return NULL; a = malloc((num_pole+1)*sizeof(*a)); b = malloc((num_pole+1)*sizeof(*b)); if (!a || !b) goto out; // prepare the z-transform of the complex bandpass filter if (!compute_bandpass_complex_filter(b, a, num_pole, fl, fh)) goto out; filt = rtf_create_filter(nchann, proctype, num_pole+1, b, num_pole+1, a, RTF_CDOUBLE); out: free(a); free(b); return filt; } rtfilter-1.3/src/downsampler.c000066400000000000000000000104311370625041100164740ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Nicolas Bourdaud * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if HAVE_CONFIG_H # include #endif #include #include #include "filter-internal.h" #include "rtfilter.h" #define BUFFNS 64 struct sampler { struct rtf_filter filt; filter_proc lp_filter_fn; int r; int ci; int samsize; void* buff; }; #define get_sampler(p)\ ((struct sampler*)(((char*)p)-offsetof(struct sampler, filt))) static int downsampler_filter(struct rtf_filter* filt, const void* x, void* y, int ns) { int i, j, nsproc; struct sampler* sampler = get_sampler(filt); const char* in = x; char* out = y, *tmpbuf = sampler->buff; int samsize = sampler->samsize, r = sampler->r; int nsret = 0, ci = sampler->ci; // Process data by chunk of BUFFNS samples maximum while (ns) { nsproc = (ns > BUFFNS) ? BUFFNS : ns; // Apply lowpass sampler->lp_filter_fn(&(sampler->filt), in, tmpbuf, nsproc); // Apply decimation i = r-1 - ci; j = 0; while (i < ns) { memcpy(out+j*samsize, tmpbuf+i*samsize, samsize); j++; i += r; } nsret += j; ns -= nsproc; in += nsproc*samsize; out += nsproc*samsize; ci = (ci + nsproc) % r; } sampler->ci = ci; return nsret; } static void downsampler_init_filter(struct rtf_filter* filt, const void* in) { struct sampler* sampler = get_sampler(filt); default_init_filter(filt, in); sampler->ci = 0; } static void downsampler_destroy_filter(struct rtf_filter* filt) { struct sampler* sampler = get_sampler(filt); default_free_filter(filt); align_free(sampler->buff); free(sampler); } /** * rtf_create_downsampler() - creates downsampling filter * @nch: number of channels the filter will process * @type: type of data the filter will process * @r: decimation factor * * rtf_create_downsampler() creates a filter that downsamples signals * coming from @nch channels of type @type (see rtf_create_filter()) by a * decimation factor of @r (i.e. the sampling frequency of the input will be * @r times the sampling frequency of the output). This is achieved internally * by applying a lowpass 4-order Chebychev filter to the input data using a * normalized cutoff frequency of 0.8 / (2 * @r) and decimating the result * every @r samples. * * Return: * the handle to the created filter in case of success, NULL otherwise. * On the contrary of most other filters, the number of samples returned by * rtf_create_downsampler() is different than the input (as expected) but also may * vary at each call if the number of sample supplied in input is not a * multiple of @r. */ DEPRECATED API_EXPORTED hfilter rtf_create_downsampler(int nch, int type, int r) { struct rtf_filter* lowpass; struct sampler* sampler; void* buff; double cutoff = 0.8/(double)(2*r); int samsize = nch*sizeof_data(type); // Allocate resource (+ create lowpass) sampler = malloc(sizeof(*sampler)); buff = align_alloc(16, BUFFNS*samsize); lowpass = rtf_create_chebychev(nch, type, cutoff, 8, 0, 0.0005); if (sampler == NULL || buff == NULL || lowpass == NULL) { free(sampler); align_free(buff); rtf_destroy_filter(lowpass); return NULL; } // Integrate the lowpass into the sampler structure memcpy(&(sampler->filt), lowpass, sizeof(*lowpass)); free((void*) lowpass); // fill sampler structure sampler->lp_filter_fn = sampler->filt.filter_fn; sampler->samsize = samsize; sampler->r = r; sampler->ci = 0; sampler->buff = buff; // Setup virtual methods sampler->filt.filter_fn = downsampler_filter; sampler->filt.destroy_filter_fn = downsampler_destroy_filter; sampler->filt.init_filter_fn = downsampler_init_filter; return &(sampler->filt); } rtfilter-1.3/src/filter-complex-double.c000066400000000000000000000043771370625041100203570ustar00rootroot00000000000000/* * Copyright (C) 2010-2012 Nicolas Bourdaud * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include "filter-funcs.h" #include "filter-internal.h" #include "probesimd.h" #include "rtfilter.h" /************************************************************************** * Complex double precision version * * ( complex double ) * **************************************************************************/ #define TYPEIN cdouble #define TYPEOUT cdouble #define add_dat(d1, d2) ((d1)+(d2)) #define mul_in_dat(d1, d2, part) ((d1)*(d2)) #define mul_dat(d1, d2) ((d1)*(d2)) #define zero_dat() (0) #define set1_dat(data) (data) #define TYPEIN_LOCAL TYPEIN #define TYPEOUT_LOCAL TYPEOUT #define FILTER_DATADEP_FUNC filter_cd_noop #define INIT_DATADEP_FUNC init_filter_cd #include "filter-func-template.c" #include "init-filter-func-template.c" static HOTSPOT int filtfunc(hfilter filt, const void* x, void* y, int ns) { #if SUPPORT_SSE3_SET if ( (filt->dispatch_code == 1) && !(((uintptr_t)x) % (2*sizeof(double))) && !(((uintptr_t)y) % (2*sizeof(double))) ) filter_cd_sse3(filt, x, y, ns); else #endif //SUPPORT_SSE3_SET filter_cd_noop(filt, x, y, ns); return ns; } LOCAL_FN void set_filterfn_cd(struct rtf_filter* filt) { filt->filter_fn = filtfunc; filt->dispatch_code = cputest_sse3() ? 1 : 0; } rtfilter-1.3/src/filter-complex-single.c000066400000000000000000000046731370625041100203650ustar00rootroot00000000000000/* * Copyright (C) 2009-2011 Nicolas Bourdaud * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include "filter-funcs.h" #include "filter-internal.h" #include "probesimd.h" #include "rtfilter.h" /************************************************************************** * Complex single precision version * * ( complex float ) * **************************************************************************/ #define TYPEIN cfloat #define TYPEOUT cfloat #define add_dat(d1, d2) ((d1)+(d2)) #define mul_in_dat(d1, d2, part) ((d1)*(d2)) #define mul_dat(d1, d2) ((d1)*(d2)) #define zero_dat() (0) #define set1_dat(data) (data) #define TYPEIN_LOCAL TYPEIN #define TYPEOUT_LOCAL TYPEOUT #define FILTER_DATADEP_FUNC filter_cf_noop #define INIT_DATADEP_FUNC init_filter_cf #include "filter-func-template.c" #include "init-filter-func-template.c" static HOTSPOT int filtfunc(hfilter filt, const void* x, void* y, int ns) { #if SUPPORT_SSE3_SET // Check that sample can be aligned on 16 byte boundaries if ( (filt->dispatch_code == 1) && !(((uintptr_t)x) % (4*sizeof(float))) && !(((uintptr_t)y) % (4*sizeof(float))) ) filter_cf_sse3(filt, x, y, ns); else #endif //SUPPORT_SSE3_SET filter_cf_noop(filt, x, y, ns); return ns; } LOCAL_FN void set_filterfn_cf(struct rtf_filter* filt) { filt->filter_fn = filtfunc; #if SUPPORT_SSE3_SET // Check that sample can be aligned on 16 byte boundaries if (cputest_sse3() && !(filt->num_chann%4)) filt->dispatch_code = 1; #endif //SUPPORT_SSE3_SET } rtfilter-1.3/src/filter-func-template.c000066400000000000000000000073741370625041100202040ustar00rootroot00000000000000/* * Copyright (C) 2008-2011 Nicolas Bourdaud * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ /** \internal * \file filter-func-template.c * \brief Templates for filter functions * \author Nicolas Bourdaud * * This file includes the template of the different filter functions */ #undef NELEM_DAT #undef NELEM_DATIN #undef RATIO_INOUT #define NELEM_DAT (sizeof(TYPEOUT_LOCAL)/sizeof(TYPEOUT)) #define NELEM_DATIN (sizeof(TYPEIN_LOCAL)/sizeof(TYPEIN)) #define RATIO_INOUT ((int)(NELEM_DATIN/NELEM_DAT)) HOTSPOT LOCAL_FN void FILTER_DATADEP_FUNC(struct rtf_filter* filt, const void* restrict input, void* restrict output, int nsamples) { int i, p; int k, ic, ii, len, midlen; const TYPEIN_LOCAL* in = input; TYPEOUT_LOCAL* out = output; const TYPEIN_LOCAL *x; const TYPEOUT_LOCAL *y; int a_len = filt->a_len; const TYPEOUT*restrict a = filt->a; int b_len = filt->b_len; const TYPEOUT*restrict b = filt->b; int nch = filt->num_chann / NELEM_DAT; int nchin = nch/RATIO_INOUT; const TYPEIN_LOCAL*restrict xprev = (TYPEIN_LOCAL*)(filt->xoff) + (a_len - 1) * (nch/RATIO_INOUT); const TYPEOUT_LOCAL*restrict yprev = (TYPEOUT_LOCAL*)(filt->yoff) + b_len * nch; TYPEOUT_LOCAL h, *s, *odest; const TYPEOUT_LOCAL *osrc; TYPEIN_LOCAL *idest; const TYPEIN_LOCAL *isrc; if (!nch) return; // compute the product of convolution of the input with the infinite // impulse response (iir) for (i = 0; i < nsamples; i++) { s = out + i*nch; // Init to convolution to 0 for (ic = 0; ic < nch; ic++) s[ic] = zero_dat(); // Compute the convolution with numerator for (k = a_len-1; k >= 0; k--) { ii = (i - k) * nchin; h = set1_dat(a[k]); // If the convolution must be done with samples not // provided, use the stored ones x = (ii >= 0) ? in : xprev; for (ic = 0; ic < nchin; ic++) for (p = 0; p < RATIO_INOUT; p++) { int ind = RATIO_INOUT*ic+p; s[ind] = add_dat(mul_in_dat(h, x[ii+ic], p), s[ind]); } } // compute the convolution in the denominator for (k = b_len-1; k >= 0; k--) { ii = (i - k - 1) * nch; h = set1_dat(b[k]); // If the convolution must be done with samples not // provided, use the stored ones y = (ii >= 0) ? out : yprev; for (ic = 0; ic < nch; ic++) s[ic] = add_dat(mul_dat(h, y[ii+ic]), s[ic]); } } // Store the latest input samples idest = (TYPEIN_LOCAL*)(filt->xoff); len = (a_len-1)*nchin; midlen = (a_len-1-nsamples)*nchin; if (midlen > 0) { isrc = idest + nsamples*nchin; memmove(idest, isrc, midlen*sizeof(*isrc)); idest += midlen; len -= midlen; isrc = in; } else isrc = in-midlen; memcpy(idest, isrc, len*sizeof(*isrc)); // Store the latest output samples odest = (TYPEOUT_LOCAL*)(filt->yoff); len = b_len*nch; midlen = (b_len-nsamples)*nch; if (midlen > 0) { osrc = odest + nsamples*nch; memmove(odest, osrc, midlen*sizeof(*osrc)); odest += midlen; len -= midlen; osrc = out; } else osrc = out-midlen; memcpy(odest, osrc, len*sizeof(*osrc)); } rtfilter-1.3/src/filter-funcs.h000066400000000000000000000027601370625041100165550ustar00rootroot00000000000000/* * Copyright (C) 2011 Nicolas Bourdaud * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef FILTER_FUNCS_H #define FILTER_FUNCS_H #include "filter-internal.h" #define DECLARE_FILTFUNC(fnname)\ LOCAL_FN void fnname(struct rtf_filter* filt,\ const void* restrict in, void* restrict out,\ int nsamples) // Normal version DECLARE_FILTFUNC(filter_f_noop); DECLARE_FILTFUNC(filter_d_noop); DECLARE_FILTFUNC(filter_fcf_noop); DECLARE_FILTFUNC(filter_cf_noop); DECLARE_FILTFUNC(filter_dcd_noop); DECLARE_FILTFUNC(filter_cd_noop); // SSE version DECLARE_FILTFUNC(filter_f_sse); // SSE2 version DECLARE_FILTFUNC(filter_d_sse2); // SSE3 version DECLARE_FILTFUNC(filter_fcf_sse3); DECLARE_FILTFUNC(filter_cf_sse3); DECLARE_FILTFUNC(filter_dcd_sse3); DECLARE_FILTFUNC(filter_cd_sse3); #endif //FILTER_FUNCS_H rtfilter-1.3/src/filter-inreal-outcomplex-double.c000066400000000000000000000046101370625041100223450ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Nicolas Bourdaud * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include "filter-funcs.h" #include "filter-internal.h" #include "probesimd.h" #include "rtfilter.h" /************************************************************************** * complex output real input double precision version * * ( complex double out double in) * **************************************************************************/ #define TYPEIN double #define TYPEOUT cdouble #define add_dat(d1, d2) ((d1)+(d2)) #define mul_in_dat(d1, d2, part) ((d1)*(d2)) #define mul_dat(d1, d2) ((d1)*(d2)) #define zero_dat() (0) #define set1_dat(data) (data) #define TYPEIN_LOCAL TYPEIN #define TYPEOUT_LOCAL TYPEOUT #define FILTER_DATADEP_FUNC filter_dcd_noop #define INIT_DATADEP_FUNC init_filter_dcd #include "filter-func-template.c" #include "init-filter-func-template.c" static HOTSPOT int filtfunc(hfilter filt, const void* x, void* y, int ns) { #if SUPPORT_SSE3_SET if ( (filt->dispatch_code == 1) && !(((uintptr_t)x) % (2*sizeof(double))) && !(((uintptr_t)y) % (2*sizeof(double))) ) filter_dcd_sse3(filt, x, y, ns); else #endif //SUPPORT_SSE3_SET filter_dcd_noop(filt, x, y, ns); return ns; } LOCAL_FN void set_filterfn_dcd(struct rtf_filter* filt) { filt->filter_fn = filtfunc; #if SUPPORT_SSE3_SET // Check that sample can be aligned on 16 byte boundaries if (cputest_sse3() && !(filt->num_chann%4)) filt->dispatch_code = 1; #endif //SUPPORT_SSE3_SET } rtfilter-1.3/src/filter-inreal-outcomplex-single.c000066400000000000000000000046041370625041100223570ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Nicolas Bourdaud * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include "filter-funcs.h" #include "filter-internal.h" #include "probesimd.h" #include "rtfilter.h" /************************************************************************** * complex output real input single precision version * * ( complex float out float in) * **************************************************************************/ #define TYPEIN float #define TYPEOUT cfloat #define add_dat(d1, d2) ((d1)+(d2)) #define mul_in_dat(d1, d2, part) ((d1)*(d2)) #define mul_dat(d1, d2) ((d1)*(d2)) #define zero_dat() (0) #define set1_dat(data) (data) #define TYPEIN_LOCAL TYPEIN #define TYPEOUT_LOCAL TYPEOUT #define FILTER_DATADEP_FUNC filter_fcf_noop #define INIT_DATADEP_FUNC init_filter_fcf #include "filter-func-template.c" #include "init-filter-func-template.c" static HOTSPOT int filtfunc(hfilter filt, const void* x, void* y, int ns) { #if SUPPORT_SSE3_SET if ( (filt->dispatch_code == 1) && !(((uintptr_t)x) % (4*sizeof(float))) && !(((uintptr_t)y) % (4*sizeof(float))) ) filter_fcf_sse3(filt, x, y, ns); else #endif //SUPPORT_SSE3_SET filter_fcf_noop(filt, x, y, ns); return ns; } LOCAL_FN void set_filterfn_fcf(struct rtf_filter* filt) { filt->filter_fn = filtfunc; #if SUPPORT_SSE3_SET // Check that sample can be aligned on 16 byte boundaries if (cputest_sse3() && !(filt->num_chann%4)) filt->dispatch_code = 1; #endif //SUPPORT_SSE3_SET } rtfilter-1.3/src/filter-internal.h000066400000000000000000000057251370625041100172570ustar00rootroot00000000000000/* * Copyright (C) 2008-2011 Nicolas Bourdaud * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef FILTER_INTERNAL_H #define FILTER_INTERNAL_H #include #include #ifndef likely #define likely(expr) __builtin_expect(!!(expr), 1) #endif #ifndef unlikely #define unlikely(expr) __builtin_expect(!!(expr), 0) #endif #ifndef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif #ifndef MAX #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif typedef complex float cfloat; typedef complex double cdouble; struct rtf_filter; typedef int (*filter_proc)(struct rtf_filter*, const void*, void*, int); typedef void (*set_filterfn_proc)(struct rtf_filter*); typedef void (*init_filter_proc)(struct rtf_filter*, const void*); typedef void (*destroy_filter_proc)(struct rtf_filter*); struct rtf_filter { int lazy_init; filter_proc filter_fn; int dispatch_code; int num_chann; int a_len; int b_len; const void* a; const void* b; void* xoff; void* yoff; init_filter_proc init_filter_fn; destroy_filter_proc destroy_filter_fn; int advertised_intype, advertised_outtype, intype, outtype; }; struct filter_seq { /* keep first */ struct rtf_filter filter; int num_filters; void * buffer; /* is of type outtype */ struct rtf_filter ** filters; }; LOCAL_FN void default_init_filter(struct rtf_filter* filt, const void* data); LOCAL_FN void default_free_filter(struct rtf_filter* filt); LOCAL_FN size_t sizeof_data(int type); LOCAL_FN void* align_alloc(size_t alignment, size_t size); LOCAL_FN void align_free(void* memptr); LOCAL_FN void set_filterfn_f(struct rtf_filter* filt); LOCAL_FN void set_filterfn_d(struct rtf_filter* filt); LOCAL_FN void set_filterfn_fcf(struct rtf_filter* filt); LOCAL_FN void set_filterfn_dcd(struct rtf_filter* filt); LOCAL_FN void set_filterfn_cf(struct rtf_filter* filt); LOCAL_FN void set_filterfn_cd(struct rtf_filter* filt); LOCAL_FN void init_filter_f(struct rtf_filter* filt, const void* data); LOCAL_FN void init_filter_d(struct rtf_filter* filt, const void* data); LOCAL_FN void init_filter_fcf(struct rtf_filter* filt, const void* data); LOCAL_FN void init_filter_dcd(struct rtf_filter* filt, const void* data); LOCAL_FN void init_filter_cf(struct rtf_filter* filt, const void* data); LOCAL_FN void init_filter_cd(struct rtf_filter* filt, const void* data); #endif //FILTER_INTERNAL_H rtfilter-1.3/src/filter-real-double.c000066400000000000000000000045521370625041100176260ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Nicolas Bourdaud * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include "filter-funcs.h" #include "filter-internal.h" #include "probesimd.h" #include "rtfilter.h" /************************************************************************** * Real double precision version * * ( double ) * **************************************************************************/ #define TYPEIN double #define TYPEOUT double #define add_dat(d1, d2) ((d1)+(d2)) #define mul_in_dat(d1, d2, part) ((d1)*(d2)) #define mul_dat(d1, d2) ((d1)*(d2)) #define zero_dat() (0) #define set1_dat(data) (data) #define TYPEIN_LOCAL TYPEIN #define TYPEOUT_LOCAL TYPEOUT #define FILTER_DATADEP_FUNC filter_d_noop #define INIT_DATADEP_FUNC init_filter_d #include "filter-func-template.c" #include "init-filter-func-template.c" static HOTSPOT int filtfunc(hfilter filt, const void* x, void* y, int ns) { #if SUPPORT_SSE2_SET if ( (filt->dispatch_code == 1) && !(((uintptr_t)x) % (2*sizeof(double))) && !(((uintptr_t)y) % (2*sizeof(double))) ) filter_d_sse2(filt, x, y, ns); else #endif //SUPPORT_SSE2_SET filter_d_noop(filt, x, y, ns); return ns; } LOCAL_FN void set_filterfn_d(struct rtf_filter* filt) { filt->filter_fn = filtfunc; #if SUPPORT_SSE2_SET // Check that sample can be aligned on 16 byte boundaries if (cputest_sse2() && !(filt->num_chann%2)) filt->dispatch_code = 1; #endif //SUPPORT_SSE2_SET } rtfilter-1.3/src/filter-real-single.c000066400000000000000000000045371370625041100176400ustar00rootroot00000000000000/* * Copyright (C) 2009-2011 Nicolas Bourdaud * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include "filter-funcs.h" #include "filter-internal.h" #include "probesimd.h" #include "rtfilter.h" /************************************************************************** * Real single precision version * * ( float ) * **************************************************************************/ #define TYPEIN float #define TYPEOUT float #define add_dat(d1, d2) ((d1)+(d2)) #define mul_in_dat(d1, d2, part) ((d1)*(d2)) #define mul_dat(d1, d2) ((d1)*(d2)) #define zero_dat() (0) #define set1_dat(data) (data) #define TYPEIN_LOCAL TYPEIN #define TYPEOUT_LOCAL TYPEOUT #define FILTER_DATADEP_FUNC filter_f_noop #define INIT_DATADEP_FUNC init_filter_f #include "filter-func-template.c" #include "init-filter-func-template.c" static HOTSPOT int filtfunc(hfilter filt, const void* x, void* y, int ns) { #if SUPPORT_SSE_SET if ( (filt->dispatch_code == 1) && !(((uintptr_t)x) % (4*sizeof(float))) && !(((uintptr_t)y) % (4*sizeof(float))) ) filter_f_sse(filt, x, y, ns); else #endif //SUPPORT_SSE_SET filter_f_noop(filt, x, y, ns); return ns; } LOCAL_FN void set_filterfn_f(struct rtf_filter* filt) { filt->filter_fn = filtfunc; #if SUPPORT_SSE_SET // Check that sample can be aligned on 16 byte boundaries if (cputest_sse() && !(filt->num_chann%4)) filt->dispatch_code = 1; #endif //SUPPORT_SSE_SET } rtfilter-1.3/src/filter-sse.c000066400000000000000000000032661370625041100162260ustar00rootroot00000000000000/* Copyright (C) 2009-2011 Nicolas Bourdaud This file is part of the rtfilter library The rtfilter library is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU Lesser General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include "filter-funcs.h" #include "filter-internal.h" #include "probesimd.h" #include "rtfilter.h" /************************************************************************** * Real single precision version : SSE * * ( float ) * **************************************************************************/ #define TYPEIN float #define TYPEOUT float #define add_dat(d1,d2) _mm_add_ps(d1,d2) #define mul_in_dat(d1,d2,part) _mm_mul_ps(d1,d2) #define mul_dat(d1,d2) _mm_mul_ps(d1,d2) #define zero_dat() _mm_setzero_ps() #define set1_dat(data) _mm_set1_ps(data) #define TYPEIN_LOCAL __m128 #define TYPEOUT_LOCAL __m128 #define FILTER_DATADEP_FUNC filter_f_sse #include "filter-func-template.c" rtfilter-1.3/src/filter-sse2.c000066400000000000000000000032721370625041100163050ustar00rootroot00000000000000/* Copyright (C) 2009-2011 Nicolas Bourdaud This file is part of the rtfilter library The rtfilter library is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU Lesser General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include "filter-funcs.h" #include "filter-internal.h" #include "probesimd.h" #include "rtfilter.h" /************************************************************************** * Real double precision version : SSE2 * * ( double ) * **************************************************************************/ #define TYPEIN double #define TYPEOUT double #define add_dat(d1,d2) _mm_add_pd(d1,d2) #define mul_in_dat(d1,d2,part) _mm_mul_pd(d1,d2) #define mul_dat(d1,d2) _mm_mul_pd(d1,d2) #define zero_dat() _mm_setzero_pd() #define set1_dat(data) _mm_set1_pd(data) #define TYPEIN_LOCAL __m128d #define TYPEOUT_LOCAL __m128d #define FILTER_DATADEP_FUNC filter_d_sse2 #include "filter-func-template.c" rtfilter-1.3/src/filter-sse3.c000066400000000000000000000143501370625041100163050ustar00rootroot00000000000000/* Copyright (C) 2009-2011 Nicolas Bourdaud This file is part of the rtfilter library The rtfilter library is free software: you can redistribute it and/or modify it under the terms of the version 3 of the GNU Lesser General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include "emmintrin.h" #include "filter-funcs.h" #include "filter-internal.h" #include "probesimd.h" #include "rtfilter.h" #include "xmmintrin.h" static inline __m128 complex_mul_ps(__m128 a, __m128 b) { //a0+ia1 * b0+ib1 = a0*(b0+ib1) + ia1*(b0+ib1) // = (a0b0-a1b1) + i(a1b0+a0b1) __m128 pl, ph, coef; coef = _mm_moveldup_ps(a); pl = _mm_mul_ps(coef, b); coef = _mm_movehdup_ps(a); ph = _mm_mul_ps(coef, b); ph = _mm_shuffle_ps(ph, ph, _MM_SHUFFLE(2,3,0,1)); return _mm_addsub_ps(pl, ph); } static inline __m128 realcomp_mul_ps(__m128 a, __m128 b, int part) { __m128 in; if (part == 0) in = _mm_shuffle_ps(b, b, _MM_SHUFFLE(1,1,0,0)); else in = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3,3,2,2)); return _mm_mul_ps(in, a); } static inline __m128 complex_set1_ps(complex float a) { /*__m128 c; c = _mm_loadl_pi(c, (const void*)&a); c = _mm_loadh_pi(c, (const void*)&a); return c;*/ return _mm_castpd_ps(_mm_loaddup_pd((const void*)&a)); } static inline __m128d complex_mul_pd(__m128d a, __m128d b) { //a0+ia1 * b0+ib1 = a0*(b0+ib1) + ia1*(b0+ib1) // = (a0b0-a1b1) + i(a1b0+a0b1) __m128d pl, ph, coef; coef = _mm_movedup_pd(a); pl = _mm_mul_pd(coef, b); coef = _mm_shuffle_pd(a, a, _MM_SHUFFLE2(1,1)); ph = _mm_mul_pd(coef, b); ph = _mm_shuffle_pd(ph, ph, _MM_SHUFFLE2(0,1)); return _mm_addsub_pd(pl, ph); } static inline __m128d realcomp_mul_pd(__m128d a, __m128d b, int part) { __m128d in; if (part == 0) in = _mm_shuffle_pd(b, b, _MM_SHUFFLE2(0,0)); else in = _mm_shuffle_pd(b, b, _MM_SHUFFLE2(1,1)); return _mm_mul_pd(in, a); } static inline __m128d complex_set1_pd(complex double a) { /*__m128 c; c = _mm_loadl_pi(c, (const void*)&a); c = _mm_loadh_pi(c, (const void*)&a); return c;*/ return _mm_loadu_pd((const double*)&a); } /************************************************************************** * complex output real input single precision version : SSE3 * * ( complex float out float in) * **************************************************************************/ #define TYPEIN float #define TYPEOUT cfloat #define add_dat(d1,d2) _mm_add_ps(d1,d2) #define mul_in_dat(d1,d2,part) realcomp_mul_ps(d1,d2,part) #define mul_dat(d1,d2) complex_mul_ps(d1,d2) #define zero_dat() _mm_setzero_ps() #define set1_dat(data) complex_set1_ps(data) #define TYPEIN_LOCAL __m128 #define TYPEOUT_LOCAL __m128 #define FILTER_DATADEP_FUNC filter_fcf_sse3 #include "filter-func-template.c" #undef TYPEIN #undef TYPEOUT #undef add_dat #undef mul_in_dat #undef mul_dat #undef zero_dat #undef set1_dat #undef TYPEIN_LOCAL #undef TYPEOUT_LOCAL #undef FILTER_DATADEP_FUNC /************************************************************************** * complex output real input double precision version : SSE3 * * ( complex double out double in) * **************************************************************************/ #define TYPEIN double #define TYPEOUT cdouble #define add_dat(d1,d2) _mm_add_pd(d1,d2) #define mul_in_dat(d1,d2,part) realcomp_mul_pd(d1,d2,part) #define mul_dat(d1,d2) complex_mul_pd(d1,d2) #define zero_dat() _mm_setzero_pd() #define set1_dat(data) complex_set1_pd(data) #define TYPEIN_LOCAL __m128d #define TYPEOUT_LOCAL __m128d #define FILTER_DATADEP_FUNC filter_dcd_sse3 #include "filter-func-template.c" #undef TYPEIN #undef TYPEOUT #undef add_dat #undef mul_in_dat #undef mul_dat #undef zero_dat #undef set1_dat #undef TYPEIN_LOCAL #undef TYPEOUT_LOCAL #undef FILTER_DATADEP_FUNC /************************************************************************** * Complex single precision version : SSE3 * * ( complex float ) * **************************************************************************/ #define TYPEIN cfloat #define TYPEOUT cfloat #define add_dat(d1,d2) _mm_add_ps(d1,d2) #define mul_in_dat(d1,d2,part) complex_mul_ps(d1,d2) #define mul_dat(d1,d2) complex_mul_ps(d1,d2) #define zero_dat() _mm_setzero_ps() #define set1_dat(data) complex_set1_ps(data) #define TYPEIN_LOCAL __m128 #define TYPEOUT_LOCAL __m128 #define FILTER_DATADEP_FUNC filter_cf_sse3 #include "filter-func-template.c" #undef TYPEIN #undef TYPEOUT #undef add_dat #undef mul_in_dat #undef mul_dat #undef zero_dat #undef set1_dat #undef TYPEIN_LOCAL #undef TYPEOUT_LOCAL #undef FILTER_DATADEP_FUNC /************************************************************************** * Complex double precision version : SSE3 * * ( complex double ) * **************************************************************************/ #define TYPEIN cdouble #define TYPEOUT cdouble #define add_dat(d1,d2) _mm_add_pd(d1,d2) #define mul_in_dat(d1,d2,part) complex_mul_pd(d1,d2) #define mul_dat(d1,d2) complex_mul_pd(d1,d2) #define zero_dat() _mm_setzero_pd() #define set1_dat(data) complex_set1_pd(data) #define TYPEIN_LOCAL __m128d #define TYPEOUT_LOCAL __m128d #define FILTER_DATADEP_FUNC filter_cd_sse3 #include "filter-func-template.c" #undef TYPEIN #undef TYPEOUT #undef add_dat #undef mul_in_dat #undef mul_dat #undef zero_dat #undef set1_dat #undef TYPEIN_LOCAL #undef TYPEOUT_LOCAL #undef FILTER_DATADEP_FUNC rtfilter-1.3/src/filter.c000066400000000000000000000611531370625041100154350ustar00rootroot00000000000000/* * Copyright (C) 2008-2011 Nicolas Bourdaud * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include "filter-internal.h" #include "rtfilter.h" #define NS_MAX 8 LOCAL_FN size_t sizeof_data(int type) { size_t dsize = 0; if (type == RTF_FLOAT) dsize = sizeof(float); else if (type == RTF_DOUBLE) dsize = sizeof(double); else if (type == RTF_CFLOAT) dsize = sizeof(complex float); else if (type == RTF_CDOUBLE) dsize = sizeof(complex double); return dsize; } #define DECLARE_COPY_PARAM_FN(copy_param_fn, in_t, out_t)\ static void copy_param_fn(int len, void* dst, const void* src,\ const void* factor, int isdenum)\ {\ int i;\ const in_t *tsrc = src;\ out_t *tdst = dst;\ in_t normfactor = (!factor) ? 1.0 : *((const in_t*)factor);\ if (!isdenum) {\ for (i = 0; i < len; i++)\ tdst[i] = tsrc[i] / normfactor;\ } else {\ for (i = 0; i < len; i++)\ tdst[i] = -tsrc[i+1] / normfactor;\ }\ } DECLARE_COPY_PARAM_FN(copy_param_ff, float, float) DECLARE_COPY_PARAM_FN(copy_param_fd, float, double) DECLARE_COPY_PARAM_FN(copy_param_df, double, float) DECLARE_COPY_PARAM_FN(copy_param_dd, double, double) DECLARE_COPY_PARAM_FN(copy_param_fcf, float, complex float) DECLARE_COPY_PARAM_FN(copy_param_fcd, float, complex double) DECLARE_COPY_PARAM_FN(copy_param_dcf, double, complex float) DECLARE_COPY_PARAM_FN(copy_param_dcd, double, complex double) DECLARE_COPY_PARAM_FN(copy_param_cfcf, complex float, complex float) DECLARE_COPY_PARAM_FN(copy_param_cfcd, complex float, complex double) DECLARE_COPY_PARAM_FN(copy_param_cdcf, complex double, complex float) DECLARE_COPY_PARAM_FN(copy_param_cdcd, complex double, complex double) typedef void (*copy_param_proc)(int, void*, const void*, const void*, int); static copy_param_proc convtab[4][4] = { [RTF_FLOAT] = {[RTF_FLOAT] = copy_param_ff, [RTF_DOUBLE] = copy_param_fd, [RTF_CFLOAT] = copy_param_fcf, [RTF_CDOUBLE] = copy_param_fcd}, [RTF_DOUBLE] = {[RTF_FLOAT] = copy_param_df, [RTF_DOUBLE] = copy_param_dd, [RTF_CFLOAT] = copy_param_dcf, [RTF_CDOUBLE] = copy_param_dcd}, [RTF_CFLOAT] = {[RTF_CFLOAT] = copy_param_cfcf, [RTF_CDOUBLE] = copy_param_cfcd}, [RTF_CDOUBLE] = {[RTF_CFLOAT] = copy_param_cdcf, [RTF_CDOUBLE] = copy_param_cdcd}, }; static set_filterfn_proc setfiltfnproctab[4][4] = { [RTF_FLOAT] = {[RTF_FLOAT] = set_filterfn_f, [RTF_CFLOAT] = set_filterfn_fcf}, [RTF_DOUBLE] = {[RTF_DOUBLE] = set_filterfn_d, [RTF_CDOUBLE] = set_filterfn_dcd}, [RTF_CFLOAT] = {[RTF_CFLOAT] = set_filterfn_cf}, [RTF_CDOUBLE] = {[RTF_CDOUBLE] = set_filterfn_cd} }; typedef void (*init_filter_proc)(struct rtf_filter*, const void*); static const init_filter_proc init_filter_proc_tab[4][4] = { [RTF_FLOAT] = {[RTF_FLOAT] = init_filter_f, [RTF_CFLOAT] = init_filter_fcf}, [RTF_DOUBLE] = {[RTF_DOUBLE] = init_filter_d, [RTF_CDOUBLE] = init_filter_dcd}, [RTF_CFLOAT] = {[RTF_CFLOAT] = init_filter_cf}, [RTF_CDOUBLE] = {[RTF_CDOUBLE] = init_filter_cd} }; static void reset_filter(hfilter filt) { if (filt->xoff) memset(filt->xoff, 0, (filt->a_len - 1) * filt->num_chann * sizeof_data(filt->intype)); if (filt->yoff) memset(filt->yoff, 0, (filt->b_len) * filt->num_chann * sizeof_data( filt->outtype)); } LOCAL_FN void* align_alloc(size_t alignment, size_t size) { #if HAVE_POSIX_MEMALIGN void* memptr = NULL; if (posix_memalign(&memptr, alignment, size)) return NULL; return memptr; #else void* origptr = malloc(sizeof(void*) + alignment + size); if (origptr == NULL) return NULL; char* ptr = ((char*)origptr) + sizeof(void*); ptr += alignment - ((uintptr_t)ptr)%alignment; *(void**)(ptr-sizeof(origptr)) = origptr; return ptr; #endif /* if HAVE_POSIX_MEMALIGN */ } LOCAL_FN void align_free(void* memptr) { #if HAVE_POSIX_MEMALIGN free(memptr); #else if (memptr == NULL) return; free(*(((void**)memptr)-1)); #endif } static void define_types(int proctp, int paramtp, int* intp, int* outtp) { int tpi, tpo; tpi = proctp; tpo = proctp; if (paramtp & RTF_COMPLEX_MASK) tpo |= RTF_COMPLEX_MASK; *intp = tpi; *outtp = tpo; } LOCAL_FN void default_init_filter(struct rtf_filter* filt, const void* data) { int itp = filt->intype, otp = filt->outtype; if (data == NULL) { reset_filter(filt); return; } init_filter_proc_tab[itp][otp](filt, data); } LOCAL_FN void default_free_filter(struct rtf_filter* filt) { free((void*) filt->a); free((void*) filt->b); align_free(filt->xoff); align_free(filt->yoff); } static void default_destroy_filter(struct rtf_filter* filt) { default_free_filter(filt); free(filt); } static void destroy_filter_seq(struct rtf_filter* filt) { int i; struct filter_seq * seq = (struct filter_seq*) filt; for (i = 0; i < seq->num_filters; i++) default_destroy_filter(seq->filters[i]); free(seq->filters); align_free(seq->buffer); free(seq); } /** * rtf_destroy_filter() - destroys a filter * @filt: handle of the filter to destroy * * This function destroys the filter referenced by the handle @filt and * free all the associated resources. After destruction, no reference to * @filt should be made. If @filt is NULL, the function returns * without doing anything. */ API_EXPORTED void rtf_destroy_filter(hfilter filt) { if (!filt) return; filt->destroy_filter_fn(filt); } /** * rtf_init_filter() - reinitializes the filter with given data * @filt: the filter to reinitialize * @data: data with which the filter is reinitialized * * rtf_init_filter() initializes the internal states of the filter with * one sample of data as if the filter has been applied indefinitely to * constant data consisting by this only sample. * * @data is allowed to be NULL. In such case, the filter is initialized * with null signals (i.e. initialized with an input full of 0.0 values). * * If @data is not NULL, the array pointed by @data should be * organized the same way as it would be if used in a call to * rtf_filter() with one sample. */ API_EXPORTED void rtf_init_filter(hfilter filt, const void *data) { filt->init_filter_fn(filt, data); } /** * rtf_create_filter() - creates a custom filter * @nchann: number of channels the filter will process * @proctype: type of data the filter will process * @numlen: number of elements in @num * @num: array representing a numerator * @denlen: number of element in @den * @den: array representing a denominator * @paramtype: type of data in @num and in @den * * This function creates and initializes a digital linear filter whose the * Z-transform is rational and processing @nchann channels of a data type * specified by @proctype. * * The numerator and denominator of the rational expression are specified by * respectively two arrays @num and @denum containing the * coefficients in the ascending order of the 2 polynoms. The number of * elements in each arrays is controlled by @numlen and @denlen. * @denlen is allowed to be equal to zero as well as @den is * allowed to be NULL. In such case, the denominator will be set to 1. * The data type of the values in @num and @den are specified by * @paramtype. * * The values @num, @den, @numlen, and @denlen can * also be passed using the coeffs structure while using the function * rtf_create_filter_coeffs(). * * The @proctype and @paramtype must be one the following constants: * * RTF_FLOAT * specifies real single precision (float) * * RTF_DOUBLE * specifies real double precision (double) * * RTF_CFLOAT * specifies complex single precision (complex float) * * RTF_CDOUBLE * specifies complex double precision (complex double) * * The expected data type of the output of the filter has the same precision as * the one specified by @proctype and is complex @proctype or @paramtype * specifies a complex type. Said otherwise: * * If @proctype is RTF_FLOAT or RTF_CFLOAT then the output * data type will have single precision. Otherwise it will have double * precision. * * If @proctype or @paramtype specifies a complex type, then the output * will be complex as well. Otherwise, it will be real. * * rtf_create_filter() can be used to use a filter that has been * designed somewhere else. In particular, this function can be used directly * with the output of filter design function of MATLAB. In such case, the usual * B and A arrays returned by the filter design functions corresponds exactly * to respectively @num and @denum. * * Return: the handle to the created filter in case of success, NULL otherwise. */ API_EXPORTED hfilter rtf_create_filter(int nchann, int proctype, int numlen, const void *num, int denlen, const void *den, int paramtype) { struct rtf_filter *filt = NULL; void *a = NULL; void *xoff = NULL; void *b = NULL; void *yoff = NULL; int xoffsize, yoffsize; int intype, outtype, adv_intype, adv_outtype; define_types(proctype, paramtype, &adv_intype, &adv_outtype); // Processing complex data with real transfer function is equivalent // (and faster) to process real and imaginary part as 2 channels if ( (proctype & RTF_COMPLEX_MASK) && !(paramtype & RTF_COMPLEX_MASK)) { proctype &= ~RTF_COMPLEX_MASK; nchann *= 2; } define_types(proctype, paramtype, &intype, &outtype); // Check if a denominator exists if ((denlen == 0) || (den == NULL)) { denlen = 0; den = NULL; } else { denlen--; } xoffsize = (numlen - 1) * nchann; yoffsize = denlen * nchann; filt = malloc(sizeof(*filt)); a = (numlen > 0) ? malloc(numlen * sizeof_data(outtype)) : NULL; b = (denlen > 0) ? malloc(denlen * sizeof_data(outtype)) : NULL; if (xoffsize > 0) xoff = align_alloc(16, xoffsize * sizeof_data(intype)); if (yoffsize > 0) yoff = align_alloc(16, yoffsize * sizeof_data(outtype)); // handle memory allocation problem if ( !filt || ((numlen > 0) && !a) || ((xoffsize > 0) && !xoff) || ((denlen > 0) && !b) || ((yoffsize > 0) && !yoff)) { free(filt); free(a); align_free(xoff); free(b); align_free(yoff); return NULL; } // copy the numerator and denerator // (and normalize and convert to recursive rule) convtab[paramtype][outtype](numlen, a, num, den, 0); convtab[paramtype][outtype](denlen, b, den, den, 1); // prepare the filt struct memset(filt, 0, sizeof(*filt)); filt->init_filter_fn = default_init_filter; filt->destroy_filter_fn = default_destroy_filter; filt->num_chann = nchann; filt->intype = intype; filt->outtype = outtype; filt->a = a; filt->a_len = numlen; filt->xoff = xoff; filt->b = b; filt->b_len = denlen; filt->yoff = yoff; filt->advertised_intype = adv_intype; filt->advertised_outtype = adv_outtype; filt->dispatch_code = 0; setfiltfnproctab[intype][outtype](filt); rtf_init_filter(filt, NULL); return filt; } /* typed with char instead of void to prevent compiler warning */ static inline void swap_ptr(char ** ptr1, char ** ptr2) { char * tmp = *ptr1; *ptr1 = *ptr2; *ptr2 = tmp; } /** * rtf_filter_seq() - apply filter cascade * @filt: initialized rtf_filter structure * @ns: number of samples * @_in: array of (ns * nch) input data * @_out: array of (ns * nch) output data * * Return: the number of samples written in @_out */ static int rtf_filter_seq(struct rtf_filter * filt, void const * _in, void * _out, int ns) { int i; int num_samples, ns_chunk, ns_out; char const * in = _in; char * out = _out; char * tmp_in, * tmp_out; struct rtf_filter * f; struct filter_seq * seq = (struct filter_seq*) filt; ns_out = 0; while (ns > 0) { num_samples = MIN(ns, NS_MAX); if (seq->num_filters % 2 == 1) { tmp_in = out; tmp_out = seq->buffer; } else { tmp_in = seq->buffer; tmp_out = out; } f = seq->filters[0]; ns_chunk = f->filter_fn(f, in, tmp_out, num_samples); for (i = 1; i < seq->num_filters; i++) { f = seq->filters[i]; swap_ptr(&tmp_in, &tmp_out); ns_chunk = f->filter_fn(f, tmp_in, tmp_out, ns_chunk); } ns -= num_samples; in += num_samples * f->num_chann * sizeof_data(f->intype); out += ns_chunk * f->num_chann * sizeof_data(f->outtype); ns_out += ns_chunk; } return ns_out; } /** * rtf_filter_combine() - combines vector of filters into one * @nfilters: number of filters to combine * @filters: array of pointers to filters to combine * * Combines the @nfilters rtf_filters structures into a single one. This is * so that a sequence of filters can be manipulated more easily. * * On success, the combination-filter assumes ownership of all the filters * passed as arguments. * * Return: * a pointer to rtf_filter structure handling the combination, NULL on error */ API_EXPORTED struct rtf_filter* rtf_filter_combine(int nfilters, struct rtf_filter ** filters) { int i; struct filter_seq * seq; struct rtf_filter * last; if (nfilters <= 0 || filters == NULL) return NULL; /* ensure all the input filters exist */ for (i = 0; i < nfilters; i++) { if (filters[i] == NULL) return NULL; } if (nfilters == 1) return *filters; seq = malloc(sizeof(*seq)); if (seq == NULL) return NULL; last = filters[nfilters - 1]; *seq = (struct filter_seq) {0}; seq->filters = malloc(sizeof(*seq->filters) * nfilters); seq->buffer = align_alloc(16, NS_MAX * last->num_chann * sizeof_data(last->outtype)); if (seq->filters == NULL || seq->buffer == NULL) { destroy_filter_seq((struct rtf_filter*) seq); return NULL; } memcpy(seq->filters, filters, sizeof(*seq->filters) * nfilters); seq->num_filters = nfilters; seq->filter.filter_fn = rtf_filter_seq; seq->filter.destroy_filter_fn = destroy_filter_seq; seq->filter.num_chann = last->num_chann; return (struct rtf_filter*) seq; } /** * rtf_create_filter_coeffs() - creates a custom filter * @nchann: number of channels the filter will process * @data_type: type of data the filter will process * @coeffs: structure giving information * * This function creates and initializes a digital linear filter whose the * Z-transform is rational and processing @nchann channels of a data type * specified by @proctype. * * This function is identical to rtf_create_filter() except that the * arguments num, denum, numlen, and denlen of rtf_create_filter() are * given thanks to the coeffs structure. * * See rtf_create_filter() for more information. * * Return: the handle to the created filter in case of success, NULL otherwise. */ hfilter rtf_create_filter_coeffs(int nchann, int data_type, struct rtf_coeffs * coeffs) { assert(nchann > 0 && coeffs != NULL); if (coeffs->is_complex) { return rtf_create_filter(nchann, data_type, coeffs->coeffs.cplx.num_len, coeffs->coeffs.cplx.num, coeffs->coeffs.cplx.denum_len, coeffs->coeffs.cplx.denum, RTF_CDOUBLE); } else { return rtf_create_filter(nchann, data_type, coeffs->coeffs.real.num_len, coeffs->coeffs.real.num, coeffs->coeffs.real.denum_len, coeffs->coeffs.real.denum, RTF_DOUBLE); } } /** * rtf_filter_set_lazy_init() - sets the filter lazy-init flag * @filt: the filter whose lazy-init flag is set * @do_lazy_init: the value with which the lazy-init flag is set * * Sets the lazy-init state of the hfilter @filt to given value * @do_lazy_init. * If the filter lazy-inits, then on its first call, the first data is used * to initialize the filter by calling rtf_init_filter(). */ API_EXPORTED void rtf_filter_set_lazy_init(hfilter filt, int do_lazy_init) { filt->lazy_init = do_lazy_init; } /** * rtf_filter() - filters a chunk of data * @filt: the filter to apply on the data * @x: array of samples on which to apply the filter * @y: array to fill with the filtered data * @ns: number of samples on which to apply the filter * * This function applies the filter referenced by @filt on @ns * samples specified by the pointer @x and writes the filtered data into * the array pointed by @y. The arrays pointed by @x and @y must be * made of values whose correspond to the type specified at the creation of * the filter. In addition, the two arrays MUST NOT overlap (failing to * comply will lead to undefined results). * * Their number of elements have to be equal to @ns multiplied by the * number of channels processed (specified at the creation of the filter). The * arrays should be packed by channels with the following pattern * * +----+----+---+----+----+----+---+----+---+-----+ * |S1C1|S1C2|...|S1Ck|S2C1|S2C2|...|S2Ck|...|SnsCk| * +----+----+---+----+----+----+---+----+---+-----+ * * where SiCj refers to the data value of the i-th sample and the j-th * channel and k refers to the number of channel specified at the creation * of the filter. * * Return: * the number of samples written in the array pointer by @y. For * most of the filters, this value will always be equal to @ns. This is * however not the case of a downsampling filter whose the number of samples * returned may vary from one call to another. * * Performances: * On platforms that support SIMD instructions, rtf_filter() is * implemented in 2 different versions: one normal and one using SIMD * instruction set which performs nearly 4x faster than the normal one when * processing float data types. The SIMD version is automatically * selected at runtime if the following conditions are met (otherwise, the * implementation falls back to the normal version): * * - The input @x and output @y are aligned on 16 bytes boundary (128 bits). * * - The sample strides (the size of the data type multiplied by the number * of channel) of the input and output are multiples of 16 bytes. * * The first condition is easily met by allocating @x and @y using * memory allocation function mandating a certain alignment (for example, * posix_memalign() on POSIX platform). * * The second condition is met if the number of channels is carefully chosen. * Given the boost obtained with the SIMD version, it is often interesting to * add unused channels into the input and output (when possible) just to make * the strides multiple of 16 bytes (for example using always a multiple of 4 * channels when dealing with float and real values). */ API_EXPORTED HOTSPOT int rtf_filter(hfilter filt, const void* x, void* y, int ns) { if (unlikely(filt->lazy_init)) { rtf_init_filter(filt, x); filt->lazy_init = 0; } return filt->filter_fn(filt, x, y, ns); } /** * rtf_get_type() - gets the input or output data type of a filter * @filt: filter whose input or output data type is requested * @in: indicates whether it is the input or the output data type that is * requested * * This function returns the data type of the input or output of the filter * @filt depending on @in. If @in is zero, then the returned * type is the output data type. If @in is non-zero, the function * returns the input data type of the filter. * * In case of the success, the returned type will be one of the constants * (RTF_FLOAT, RTF_DOUBLE, RTF_CFLOAT or RTF_CDOUBLE) defined in the man page * of rtf_create_filter(). * * Return: the requested data type in case of success, -1 otherwise. */ API_EXPORTED int rtf_get_type(hfilter filt, int in) { if (filt == NULL) return -1; return (in ? filt->advertised_intype : filt->advertised_outtype); } static const char rtf_version_string[] = PACKAGE_STRING #if HAVE_CPUID " (compiled with cpu detection)"; #elif __SSE3__ " (compiled with sse3)"; #elif __SSE2__ " (compiled with sse2)"; #elif __SSE__ " (compiled with sse2)"; #elif __ARM_NEON__ " (compiled with NEON)"; #else " (compiled with no SIMD)"; #endif /* if HAVE_CPUID */ /** * rtf_get_version() - returns the version of the library * @string: string to fill with the version * @len: maximal size of the string put in @string * @line: indicates whether only the version of the library is requested * or if the versions of the dependencies as well are requested * * This function fills in @string the version of the library if @line * is 0. It fills at most @len character in @string including the * terminating null byte ('\0'). If the implementation of library depends on * other non-standard libraries, it will return the version of them in * subsequent lines (@line > 0). If there is no more dependency, nothing * is copied on @string and 0 is returned by the function. * * Return: the number of characters copied on @string. */ API_EXPORTED size_t rtf_get_version(char* string, size_t len, int line) { if (line > 0) return 0; strncpy(string, rtf_version_string, len-1); string[len-1] = '\0'; return strlen(string); } /** * rtf_coeffs_destroy() - destroy rtf_coeffs structure * @coeffs: rtf_coeffs structure to destroy */ void rtf_coeffs_destroy(struct rtf_coeffs * coeffs) { if (coeffs != NULL) { if (coeffs->is_complex) { free(coeffs->coeffs.cplx.num); free(coeffs->coeffs.cplx.denum); } else { free(coeffs->coeffs.real.num); free(coeffs->coeffs.real.denum); } free(coeffs); } } static inline int is_complex_filter(const struct rtf_filter * filt) { return (filt->outtype == RTF_CFLOAT || filt->outtype == RTF_CDOUBLE); } /** * rtf_get_coeffs() - get filter coeffs * @filt: initialized rtfilter * * Note: the copy function we get from convtab is a tad too specific for our use: * it expects a flag specifying whether we copy the num/denum, but processes and * transforms the denum in a way we do not want here: we wand the raw values. * However, we still need to multiply their values by -1 so as to ensure their * values are the same as with scipy. * * Return: newly allocated rtf_coeffs structure on success, NULL on error */ API_EXPORTED struct rtf_coeffs* rtf_get_coeffs(const struct rtf_filter * filt) { int i; struct rtf_coeffs * coeffs; copy_param_proc copy_fn; coeffs = malloc(sizeof(*coeffs)); if (coeffs == NULL) return NULL; memset(coeffs, 0, sizeof(*coeffs)); coeffs->is_complex = is_complex_filter(filt); if (coeffs->is_complex) { coeffs->coeffs.cplx.num_len = filt->a_len; coeffs->coeffs.cplx.denum_len = filt->b_len + 1; coeffs->coeffs.cplx.num = malloc( coeffs->coeffs.cplx.denum_len * sizeof(rtf_cdouble)); coeffs->coeffs.cplx.denum = malloc( coeffs->coeffs.cplx.num_len * sizeof(rtf_cdouble)); if ( coeffs->coeffs.cplx.num == NULL || coeffs->coeffs.cplx.denum == NULL) goto enomem; copy_fn = convtab[filt->outtype][RTF_CDOUBLE]; copy_fn(filt->a_len, coeffs->coeffs.cplx.num, filt->a, NULL, 0); coeffs->coeffs.cplx.denum[0] = (rtf_cdouble) {1.}; copy_fn(filt->b_len, coeffs->coeffs.cplx.denum + 1, filt->b, NULL, 0); for (i = 1; i < coeffs->coeffs.cplx.denum_len; i++) { #ifdef _MSC_VER coeffs->coeffs.cplx.denum[i] = cmul_d( coeffs->coeffs.cplx.denum[i], -1.); #else coeffs->coeffs.cplx.denum[i] *= -1.; #endif } } else { coeffs->coeffs.real.num_len = filt->a_len; coeffs->coeffs.real.denum_len = filt->b_len + 1; coeffs->coeffs.real.num = malloc(coeffs->coeffs.real.num_len * sizeof(double)); coeffs->coeffs.real.denum = malloc( coeffs->coeffs.real.denum_len * sizeof(double)); if ( coeffs->coeffs.real.num == NULL || coeffs->coeffs.real.denum == NULL) goto enomem; copy_fn = convtab[filt->outtype][RTF_DOUBLE]; copy_fn(filt->a_len, coeffs->coeffs.real.num, filt->a, NULL, 0); coeffs->coeffs.real.denum[0] = 1.; copy_fn(filt->b_len, coeffs->coeffs.real.denum + 1, filt->b, NULL, 0); for (i = 1; i < coeffs->coeffs.real.denum_len; i++) { coeffs->coeffs.real.denum[i] *= -1.; } } return coeffs; enomem: rtf_coeffs_destroy(coeffs); return NULL; } rtfilter-1.3/src/init-filter-func-template.c000066400000000000000000000044721370625041100211410ustar00rootroot00000000000000/* * Copyright (C) 2018 MindMaze SA * Nicolas Bourdaud * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ /** * INIT_DATADEP_FUNC - template for initialization of filter states * @filt: filter to initialize * @data: pointer to input data to use for initialization (underlying * type must be the filter input type and the length equal to * the number of channel) * * This is the template for the initialization function. It computes the * internal states of the filter @filt as the steady state response of a * step whose amplitude is given by @data. In other words, it sets the * states as if @data would have been constantly given as input to the * filter since beginning of the times. */ LOCAL_FN void INIT_DATADEP_FUNC(struct rtf_filter* filt, const void* data) { const TYPEIN* in = data; TYPEIN* xoff = filt->xoff; TYPEOUT* yoff = filt->yoff; const TYPEOUT* a = filt->a; const TYPEOUT* b = filt->b; int a_len = filt->a_len; int b_len = filt->b_len; int nch = filt->num_chann; int i, k; TYPEOUT scale, a_sum, b_sum; // Copy initializer to past input buffer for (i = 0; i < a_len-1; i++) { for (k = 0; k < nch; k++) xoff[i*nch + k] = in[k]; } // If no denuminator, nothing else has to be set if (b_len == 0) return; // Compute the scaling factor to apply to output when signal is in // steady state a_sum = 0.0; for (i = 0; i < a_len; i++) a_sum += a[i]; b_sum = 0.0; for (i = 0; i < b_len; i++) b_sum += b[i]; scale = a_sum / (1.0 - b_sum); // Set past output to scaled input (when in steady state) for (i = 0; i < b_len; i++) { for (k = 0; k < nch; k++) yoff[i*nch + k] = scale * in[k]; } } rtfilter-1.3/src/probesimd.h000066400000000000000000000032211370625041100161310ustar00rootroot00000000000000/* * Copyright (C) 2011-2012 Nicolas Bourdaud * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef PROBESIMD_H #define PROBESIMD_H #if HAVE_CPUID #include static inline int cputest_sse(void) { unsigned int eax, ebx, ecx, edx; if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (edx & bit_SSE)) return 1; return 0; } static inline int cputest_sse2(void) { unsigned int eax, ebx, ecx, edx; if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (edx & bit_SSE2)) return 1; return 0; } static inline int cputest_sse3(void) { unsigned int eax, ebx, ecx, edx; if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx & bit_SSE3)) return 1; return 0; } #else /* HAVE_CPUID */ static inline int cputest_sse(void) { #ifdef __SSE__ return 1; #else return 0; #endif } static inline int cputest_sse2(void) { #ifdef __SSE2__ return 1; #else return 0; #endif } static inline int cputest_sse3(void) { #ifdef __SSE3__ return 1; #else return 0; #endif } #endif /* HAVE_CPUID */ #endif /* PROBESIMD_H */ rtfilter-1.3/src/rtf_common.h000066400000000000000000000020361370625041100163130ustar00rootroot00000000000000/* * Copyright (C) 2008-2011 Nicolas Bourdaud * Copyright (C) 2018-2020 Mindmaze Holdings SA * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef COMMON_FILTERS_H #define COMMON_FILTERS_H #warning "This header has been deprecated, and will be removed in a subsequent\ rtfilter release. Please only include ." #include #endif /* COMMON_FILTERS_H */ rtfilter-1.3/src/rtfilter.h000066400000000000000000000113361370625041100160060ustar00rootroot00000000000000/* * Copyright (C) 2008-2011 Nicolas Bourdaud * Copyright (C) 2018-2020 Mindmaze Holdings SA * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef RTFILTER_H #define RTFILTER_H #include #ifdef __cplusplus #include typedef std::complex < double > rtf_cdouble; #else /* __cplusplus */ #ifdef _MSC_VER typedef struct { double real; double img; } rtf_cdouble; #else #include typedef complex double rtf_cdouble; #endif /* _MSC_VER */ #endif /* __cplusplus */ #ifdef __cplusplus extern "C" { #endif /* Data type specifications */ #define RTF_FLOAT 0 #define RTF_DOUBLE 1 #define RTF_CFLOAT 2 #define RTF_CDOUBLE 3 #define RTF_PRECISION_MASK 1 #define RTF_COMPLEX_MASK 2 //! Handle to a filter. Used by all the functions to manipulate a filter. typedef struct rtf_filter* hfilter; //! create a digital filter hfilter rtf_create_filter(int nchann, int proctype, int num_len, const void *num, int denum_len, const void *denum, int type); //! set filter lazy-init void rtf_filter_set_lazy_init(hfilter filt, int do_lazy_init); //! filter chunk of data int rtf_filter(hfilter filt, const void* x, void* y, int ns); //! initialize a filter with particular data void rtf_init_filter(hfilter filt, const void* data); //! destroy a filter void rtf_destroy_filter(hfilter filt); //! Return the type of the input or output of a filter int rtf_get_type(hfilter filt, int in); // Creates a filter that downsample signals hfilter rtf_create_downsampler(int nch, int type, int r); //! Return the version of the library in a string size_t rtf_get_version(char* string, size_t len, int line); struct real_coeffs { int num_len; int denum_len; double * num; double * denum; }; struct complex_coeffs { int num_len; int denum_len; rtf_cdouble * num; rtf_cdouble * denum; }; struct rtf_coeffs { int is_complex; union { struct real_coeffs real; struct complex_coeffs cplx; } coeffs; }; void rtf_coeffs_destroy(struct rtf_coeffs * coeffs); struct rtf_coeffs* rtf_get_coeffs(const struct rtf_filter * filt); hfilter rtf_create_filter_coeffs(int nchann, int data_type, struct rtf_coeffs * coeffs); /* helpers to create common filters */ /* Enumeration specifying some kernel windows */ typedef enum { BLACKMAN_WINDOW, HAMMING_WINDOW, RECT_WINDOW } KernelWindow; //! Create a local mean filter based on a sliding window hfilter rtf_create_fir_mean(int nchann, int proctype, int nsamples); //! Lowpass windowed sinc filter hfilter rtf_create_fir_lowpass(int nchann, int proctype, double fc, int half_length, KernelWindow window); //! Highpass windowed sinc filter hfilter rtf_create_fir_highpass(int nchann, int proctype, double fc, int half_length, KernelWindow window); //! Bandpass windowed sinc filter hfilter rtf_create_fir_bandpass(int nchann, int proctype, double fc_low, double fc_high, int half_length, KernelWindow window); //! Butterworth filter (IIR filter) hfilter rtf_create_butterworth(int nchann, int proctype, double fc, int num_pole, int highpass); //! Chebychev filter (IIR filter) hfilter rtf_create_chebychev(int nchann, int proctype, double fc, int num_pole, int highpass, double ripple); //! Simple first order integral filter (IIR filter) hfilter rtf_create_integral(int nchann, int proctype, double fs); hfilter rtf_create_bandpass_analytic(int nchann, int proctype, double fl, double fh, int num_pole); //! Combine filters struct rtf_filter* rtf_filter_combine(int nfilters, struct rtf_filter ** filters); #ifdef __cplusplus } #endif #endif //RTFILTER_H rtfilter-1.3/src/rtfilter.pc.in000066400000000000000000000003651370625041100165660ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: rtfilter Description: multichannel filtering library Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lrtfilter Libs.private: @LIBS@ Cflags: -I${includedir} rtfilter-1.3/test/000077500000000000000000000000001370625041100141665ustar00rootroot00000000000000rtfilter-1.3/test/float-comparison.c000066400000000000000000000034141370625041100176110ustar00rootroot00000000000000/* * Copyright (C) 2018-2020 Mindmaze Holdings SA * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include "float-comparison.h" #define NB_BITS_THOLD_MANTISSA 10 typedef union { float f; struct { uint32_t mantisa_exp : 31; uint32_t sign : 1; } parts; } parse_float; /** * compare_floats() - Compare the distance between two floats * @infloat1: first input float to compare * @infloat2: second input float to compare * * Return: 0 if the distance is lower than thold, -1 otherwise. */ int compare_floats(float infloat1, float infloat2) { int diff; int thold = (2 << NB_BITS_THOLD_MANTISSA) -1; parse_float parse_input1; parse_float parse_input2; parse_input1.f = infloat1; parse_input2.f = infloat2; /* If the input is negative apply 2's complement */ if (parse_input1.parts.sign) parse_input1.parts.mantisa_exp = ~parse_input1.parts.mantisa_exp; if (parse_input2.parts.sign) parse_input2.parts.mantisa_exp = ~parse_input2.parts.mantisa_exp; diff = parse_input1.parts.mantisa_exp - parse_input2.parts.mantisa_exp; if (abs(diff) > thold) return -1; return 0; } rtfilter-1.3/test/float-comparison.h000066400000000000000000000015371370625041100176220ustar00rootroot00000000000000/* * Copyright (C) 2018-2020 Mindmaze Holdings SA * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef FLOAT_COMPARISON_H #define FLOAT_COMPARISON_H int compare_floats(float f1, float f2); #endif /* FLOAT_COMPARISON_H */ rtfilter-1.3/test/lowpass_test.c000066400000000000000000000054401370625041100170640ustar00rootroot00000000000000/* * Copyright (C) 2018-2020 Mindmaze Holdings SA * * This file is part of the rtfilter library * * The rtfilter library is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "float-comparison.h" #include "rtfilter.h" #include "testcases.h" #include "test-common.h" #define NCH 4 #define NS 128 #define FS 2000 static struct rtf_filter* create_lowpass(int nch, double fs, int order, double lowcut, int data_type) { double fc; struct rtf_filter * f; ck_assert(nch > 0); ck_assert(lowcut > 0.); ck_assert(fs > lowcut); ck_assert(order > 0); fc = lowcut / fs; f = rtf_create_butterworth(nch, data_type, fc, order, 0); ck_assert(f != NULL); return f; } START_TEST(test_lowpass_coeffs) { struct rtf_filter * f; f = create_lowpass(NCH, FS, 2, 50., RTF_FLOAT); ck_assert(f != NULL); struct rtf_coeffs * _coeffs = rtf_get_coeffs(f); struct real_coeffs * coeffs = &_coeffs->coeffs.real; /* compare generated coeffs against values computed by matlab */ ck_assert(!_coeffs->is_complex); /* test generated num */ ck_assert_int_eq(coeffs->num_len, 3); ck_assert(compare_floats(coeffs->num[0], 0.005542717408) == 0); ck_assert(compare_floats(coeffs->num[1], 0.011085434817) == 0); ck_assert(compare_floats(coeffs->num[2], 0.0055427174084) == 0); /* test generated denum */ ck_assert(coeffs->denum[0] == 1.); /* exact value */ ck_assert_int_eq(coeffs->denum_len, 3); ck_assert(compare_floats(coeffs->denum[1], -1.778631806374) == 0); ck_assert(compare_floats(coeffs->denum[2], 0.8008026480675) == 0); rtf_destroy_filter(f); } END_TEST START_TEST(test_lowpass_smoke) { struct rtf_filter * f; f = create_lowpass(NCH, FS, 2, 50., RTF_FLOAT); ck_assert(f != NULL); smoke_test(f, NCH, NS); rtf_destroy_filter(f); } END_TEST START_TEST(test_lowpass_flat) { struct rtf_filter * f; f = create_lowpass(NCH, FS, 2, 50., RTF_FLOAT); ck_assert(f != NULL); flat_test(f, NCH, NS); rtf_destroy_filter(f); } END_TEST TCase* create_lowpass_tcase(void) { TCase * tc; tc = tcase_create("lowpass"); tcase_add_test(tc, test_lowpass_coeffs); tcase_add_test(tc, test_lowpass_flat); tcase_add_test(tc, test_lowpass_smoke); return tc; } rtfilter-1.3/test/perf-test.c000066400000000000000000000130371370625041100162470ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Nicolas Bourdaud * * The program is free software: you can redistribute it and/or * modify it under the terms of the version 3 of the GNU General * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include "rtfilter.h" #define NCHANN 64 #define NSAMPLE 4 #define NITER 10000 #define FILTORDER 4 static void* align_alloc(size_t alignment, size_t size) { #if HAVE_POSIX_MEMALIGN void* memptr = NULL; if (posix_memalign(&memptr, alignment, size)) return NULL; return memptr; #else void* origptr = malloc(sizeof(void*) + alignment + size); char* ptr = ((char*) origptr) + sizeof(void*); ptr += alignment - ((uintptr_t) ptr) % alignment; *(void**)(ptr - sizeof(origptr)) = origptr; return ptr; #endif /* if HAVE_POSIX_MEMALIGN */ } static void align_free(void* memptr) { #if HAVE_POSIX_MEMALIGN free(memptr); #else free(*(((void**) memptr) - 1)); #endif } static size_t sizeof_data(int type) { size_t dsize = 0; if (type == RTF_FLOAT) dsize = sizeof(float); else if (type == RTF_DOUBLE) dsize = sizeof(double); else if (type == RTF_CFLOAT) dsize = sizeof(complex float); else if (type == RTF_CDOUBLE) dsize = sizeof(complex double); return dsize; } static void set_coeffs(unsigned int len, int type, void* coef, void** num, void** den) { memset(coef, 0, sizeof_data(type)*2*len); *num = coef; if (type == RTF_FLOAT) { ((float*) coef)[len] = 1.0; *den = ((float*) coef) + len; } else if (type == RTF_DOUBLE) { ((double*) coef)[len] = 1.0; *den = ((double*) coef) + len; } else if (type == RTF_CFLOAT) { ((complex float*) coef)[len] = 1.0; *den = ((complex float*) coef) + len; } else if (type == RTF_CDOUBLE) { ((complex double*) coef)[len] = 1.0; *den = ((complex double*) coef) + len; } } static void print_version(void) { unsigned int line = 0; char version[128]; while (rtf_get_version(version, sizeof(version), line)) printf((line++ ? " %s\n" : "version: %s\n"), version); } int main(int argc, char *argv[]) { int nch, ns, niter, filtorder; int k, opt, datintype, datouttype, ptype, vect; struct timespec start, stop; long long delay = 0, delayv = 0; long long tc, dt, timing, mintime, mintimev; hfilter filt = NULL; void *buff1, *buff2, *origbuff, *coef; void *num = NULL, *den = NULL; /* Process command-line options */ nch = NCHANN; ns = NSAMPLE; niter = NITER; filtorder = FILTORDER; vect = 1; ptype = datintype = RTF_FLOAT; while ((opt = getopt(argc, argv, "c:s:i:o:d:p:v:h")) != -1) { switch (opt) { case 'c': nch = atoi(optarg); break; case 's': ns = atoi(optarg); break; case 'i': niter = atoi(optarg); break; case 'o': filtorder = atoi(optarg); break; case 'd': datintype = atoi(optarg); break; case 'p': ptype = atoi(optarg); break; case 'v': vect = atoi(optarg); break; case 'h': default: /* '?' */ fprintf(stderr, "Usage: %s [-c numchannel] [-s numsample] [-i numiteration] [-o filterorder]\n", argv[0]); exit(EXIT_FAILURE); } } print_version(); printf( "filter order: %i \tnumber of channels: %i \t\tlength of batch: %i\n", filtorder, nch, ns); datouttype = datintype; if (ptype & RTF_COMPLEX_MASK) datouttype |= RTF_COMPLEX_MASK; /* Allocate buffers */ origbuff = align_alloc(16, sizeof_data(datintype) * nch * ns + 8); buff2 = align_alloc(16, sizeof_data(datouttype) * nch * ns); coef = malloc(2 * sizeof_data(ptype) * filtorder); if (!origbuff || !buff2 || !coef) { fprintf(stderr, "buffer allocation failed\n"); goto out; } buff1 = (vect == 0) ? (char*) origbuff + 8 : origbuff; /* set signals (zeros) */ memset(buff1, 0, nch * ns * sizeof_data(datintype)); set_coeffs(filtorder, ptype, coef, &num, &den); /* Estimate timecall of clockgettime */ tc = LONG_MAX; for (k = 0; k < 1000; k++) { clock_gettime(CLOCK_MONOTONIC, &start); clock_gettime(CLOCK_MONOTONIC, &stop); delay = ((stop.tv_sec - start.tv_sec) * 1000000000 + (stop.tv_nsec - start.tv_nsec)); tc = delay >= tc ? tc : delay; } /* create filters */ filt = rtf_create_filter(nch, datintype, filtorder, num, filtorder, den, ptype); if (!filt) { fprintf(stderr, "Creation of filter failed\n"); goto out; } delay = delayv = 0; mintime = mintimev = LONG_MAX; for (k = 0; k < niter; k++) { /* Test normal version */ clock_gettime(CLOCK_REALTIME, &start); rtf_filter(filt, buff1, buff2, ns); clock_gettime(CLOCK_REALTIME, &stop); timing = ((stop.tv_sec - start.tv_sec) * 1000000000 + (stop.tv_nsec - start.tv_nsec)) - tc; delay += timing; mintime = mintime > timing ? timing : mintime; } dt = mintime; printf("min time per call: %i nsec\n", (int) dt); printf("min time per sample: %lg nsec\n", (double) dt / (double) (ns * nch)); out: rtf_destroy_filter(filt); align_free(origbuff); align_free(buff2); free(coef); return 0; } rtfilter-1.3/test/rtfilter_combine_test.c000066400000000000000000000032011370625041100207140ustar00rootroot00000000000000#include #include #include #include #include #include #include "rtfilter.h" #include "testcases.h" #include "test-common.h" #define NCH 4 #define NS 128 #define NUM_FILTERS 2 START_TEST(test_rtfilter_combine_smoke) { int i; struct rtf_filter * filters[NUM_FILTERS]; struct rtf_filter * f; double num[3] = {0., 1., 2.}; double denum[4] = {3., 4., 5., 6.}; for (i = 0; i < arraylen(filters); i++) { filters[i] = rtf_create_filter(NCH, RTF_FLOAT, arraylen(num), num, arraylen(denum), denum, RTF_DOUBLE); ck_assert(filters[i] != NULL); } f = rtf_filter_combine(NUM_FILTERS, filters); ck_assert(f != NULL); smoke_test(f, NCH, NS); rtf_destroy_filter(f); } END_TEST START_TEST(test_rtfilter_combine_flat) { int i; struct rtf_filter * filters[NUM_FILTERS]; struct rtf_filter * f; double num[3] = {0., 1., 2.}; double denum[4] = {3., 4., 5., 6.}; for (i = 0; i < arraylen(filters); i++) { filters[i] = rtf_create_filter(NCH, RTF_FLOAT, arraylen(num), num, arraylen(denum), denum, RTF_DOUBLE); ck_assert(filters[i] != NULL); } f = rtf_filter_combine(NUM_FILTERS, filters); ck_assert(f != NULL); flat_test(f, NCH, NS); rtf_destroy_filter(f); } END_TEST TCase* create_rtfilter_combine_tcase(void) { TCase * tc; tc = tcase_create("rtfilter-combine"); tcase_add_test(tc, test_rtfilter_combine_flat); tcase_add_test(tc, test_rtfilter_combine_smoke); return tc; } rtfilter-1.3/test/rtfilter_test.c000066400000000000000000000246261370625041100172360ustar00rootroot00000000000000#include #include #include #include #include #include #include "rtfilter.h" #include "testcases.h" #include "test-common.h" #define NCH 4 #define NS 128 /* helpers to test different data types for rtfilter * Test the filter api itself throrougly , and test the higher-level * APIs (Eg. lowpass filter creation) with float only */ #define NANd __builtin_nanl("") #define NANcf (NAN + I * NAN) #define NANcd (NANd + I * NANd) static int finite_cf(complex float x) { return isfinite(crealf(x)) && isfinite(cimagf(x)); } static int finite_cd(complex double x) { return isfinite(creal(x)) && isfinite(cimag(x)); } START_TEST(test_rtfilter_smoke_float) { struct rtf_filter * f; double num[3] = {0., 1., 2.}; double denum[4] = {3., 4., 5., 6.}; f = rtf_create_filter(NCH, RTF_FLOAT, arraylen(num), num, arraylen(denum), denum, RTF_DOUBLE); ck_assert(f != NULL); smoke_test(f, NCH, NS); rtf_destroy_filter(f); } END_TEST START_TEST(test_rtfilter_flat_float) { struct rtf_filter * f; double num[3] = {0., 1., 2.}; double denum[4] = {3., 4., 5., 6.}; f = rtf_create_filter(NCH, RTF_FLOAT, arraylen(num), num, arraylen(denum), denum, RTF_DOUBLE); ck_assert(f != NULL); flat_test(f, NCH, NS); rtf_destroy_filter(f); } END_TEST START_TEST(test_rtfilter_smoke_double) { int i; double * in, * out; struct rtf_filter * f; double num[3] = {0., 1., 2.}; double denum[4] = {3., 4., 5., 6.}; f = rtf_create_filter(NCH, RTF_DOUBLE, arraylen(num), num, arraylen(denum), denum, RTF_DOUBLE); ck_assert(f != NULL); in = malloc(NS * NCH * sizeof(*in)); out = malloc(NS * NCH * sizeof(*out)); for (i = 0; i < NS * NCH; i++) in[i] = (double) rand(); for (i = 0; i < NS * NCH; i++) out[i] = NANd; rtf_filter(f, in, out, NS); /* Smoke test: * - no check on output values. * - only ensure they are valid numbers */ for (i = 0; i < NS * NCH; i++) ck_assert(isfinite(out[i])); rtf_destroy_filter(f); free(out); free(in); } END_TEST START_TEST(test_rtfilter_flat_double) { int i; double * in, * out; struct rtf_filter * f; double num[3] = {0., 1., 2.}; double denum[4] = {3., 4., 5., 6.}; f = rtf_create_filter(NCH, RTF_DOUBLE, arraylen(num), num, arraylen(denum), denum, RTF_DOUBLE); ck_assert(f != NULL); in = malloc(NS * NCH * sizeof(*in)); out = malloc(NS * NCH * sizeof(*out)); for (i = 0; i < NS * NCH; i++) in[i] = 0.; for (i = 0; i < NS * NCH; i++) out[i] = NANd; rtf_filter(f, in, out, NS); /* Smoke test: * - no check on output values. * - only ensure they are valid numbers */ for (i = 0; i < NS * NCH; i++) ck_assert(out[i] == 0.); rtf_destroy_filter(f); free(out); free(in); } END_TEST START_TEST(test_rtfilter_smoke_complex_float) { int i; complex float * in, * out; struct rtf_filter * f; double num[3] = {0., 1., 2.}; double denum[4] = {3., 4., 5., 6.}; f = rtf_create_filter(NCH, RTF_CFLOAT, arraylen(num), num, arraylen(denum), denum, RTF_DOUBLE); ck_assert(f != NULL); in = malloc(NS * NCH * sizeof(*in)); out = malloc(NS * NCH * sizeof(*out)); for (i = 0; i < NS * NCH; i++) in[i] = rand() + I * rand(); for (i = 0; i < NS * NCH; i++) out[i] = NANcf; rtf_filter(f, in, out, NS); /* Smoke test: * - no check on output values. * - only ensure they are valid numbers */ for (i = 0; i < NS * NCH; i++) { ck_assert(finite_cf(out[i])); } rtf_destroy_filter(f); free(out); free(in); } END_TEST START_TEST(test_rtfilter_flat_complex_float) { int i; complex float * in, * out; struct rtf_filter * f; double num[3] = {0., 1., 2.}; double denum[4] = {3., 4., 5., 6.}; f = rtf_create_filter(NCH, RTF_CFLOAT, arraylen(num), num, arraylen(denum), denum, RTF_DOUBLE); ck_assert(f != NULL); in = malloc(NS * NCH * sizeof(*in)); out = malloc(NS * NCH * sizeof(*out)); for (i = 0; i < NS * NCH; i++) in[i] = 0.; for (i = 0; i < NS * NCH; i++) out[i] = NANcf; rtf_filter(f, in, out, NS); /* Smoke test: * - no check on output values. * - only ensure they are valid numbers */ for (i = 0; i < NS * NCH; i++) ck_assert(out[i] == 0.); rtf_destroy_filter(f); free(out); free(in); } END_TEST START_TEST(test_rtfilter_smoke_complex_double) { int i; complex double * in, * out; struct rtf_filter * f; double num[3] = {0., 1., 2.}; double denum[4] = {3., 4., 5., 6.}; f = rtf_create_filter(NCH, RTF_CDOUBLE, arraylen(num), num, arraylen(denum), denum, RTF_DOUBLE); ck_assert(f != NULL); in = malloc(NS * NCH * sizeof(*in)); out = malloc(NS * NCH * sizeof(*out)); for (i = 0; i < NS * NCH; i++) in[i] = rand() + I * rand(); for (i = 0; i < NS * NCH; i++) out[i] = NANcd; rtf_filter(f, in, out, NS); /* Smoke test: * - no check on output values. * - only ensure they are valid numbers */ for (i = 0; i < NS * NCH; i++) { ck_assert(finite_cd(out[i])); } rtf_destroy_filter(f); free(out); free(in); } END_TEST START_TEST(test_rtfilter_flat_complex_double) { int i; complex double * in, * out; struct rtf_filter * f; double num[3] = {0., 1., 2.}; double denum[4] = {3., 4., 5., 6.}; f = rtf_create_filter(NCH, RTF_CDOUBLE, arraylen(num), num, arraylen(denum), denum, RTF_DOUBLE); ck_assert(f != NULL); in = malloc(NS * NCH * sizeof(*in)); out = malloc(NS * NCH * sizeof(*out)); for (i = 0; i < NS * NCH; i++) in[i] = 0.; for (i = 0; i < NS * NCH; i++) out[i] = NANcd; rtf_filter(f, in, out, NS); /* Smoke test: * - no check on output values. * - only ensure they are valid numbers */ for (i = 0; i < NS * NCH; i++) ck_assert(out[i] == 0.); rtf_destroy_filter(f); free(out); free(in); } END_TEST START_TEST(test_complex_rtfilter_smoke_complex_float) { int i; complex float * in, * out; struct rtf_filter * f; complex double num[3] = {0., 1., 2.}; complex double denum[4] = {3., 4., 5., 6.}; f = rtf_create_filter(NCH, RTF_CFLOAT, arraylen(num), num, arraylen(denum), denum, RTF_CDOUBLE); ck_assert(f != NULL); in = malloc(NS * NCH * sizeof(*in)); out = malloc(NS * NCH * sizeof(*out)); for (i = 0; i < NS * NCH; i++) in[i] = (complex float) rand(); for (i = 0; i < NS * NCH; i++) out[i] = NANcf; rtf_filter(f, in, out, NS); /* Smoke test: * - no check on output values. * - only ensure they are valid numbers */ for (i = 0; i < NS * NCH; i++) { ck_assert(finite_cf(out[i])); } rtf_destroy_filter(f); free(out); free(in); } END_TEST START_TEST(test_complex_rtfilter_flat_complex_float) { int i; complex float * in, * out; struct rtf_filter * f; complex double num[3] = {0., 1., 2.}; complex double denum[4] = {3., 4., 5., 6.}; f = rtf_create_filter(NCH, RTF_CFLOAT, arraylen(num), num, arraylen(denum), denum, RTF_CDOUBLE); ck_assert(f != NULL); in = malloc(NS * NCH * sizeof(*in)); out = malloc(NS * NCH * sizeof(*out)); for (i = 0; i < NS * NCH; i++) in[i] = 0.; for (i = 0; i < NS * NCH; i++) out[i] = NANcf; rtf_filter(f, in, out, NS); /* Smoke test: * - no check on output values. * - only ensure they are valid numbers */ for (i = 0; i < NS * NCH; i++) ck_assert(out[i] == 0.); rtf_destroy_filter(f); free(out); free(in); } END_TEST START_TEST(test_complex_rtfilter_smoke_complex_double) { int i; complex double * in, * out; struct rtf_filter * f; complex double num[3] = {0., 1., 2.}; complex double denum[4] = {3., 4., 5., 6.}; f = rtf_create_filter(NCH, RTF_CDOUBLE, arraylen(num), num, arraylen(denum), denum, RTF_CDOUBLE); ck_assert(f != NULL); in = malloc(NS * NCH * sizeof(*in)); out = malloc(NS * NCH * sizeof(*out)); for (i = 0; i < NS * NCH; i++) in[i] = (complex float) rand(); for (i = 0; i < NS * NCH; i++) out[i] = NANcd; rtf_filter(f, in, out, NS); /* Smoke test: * - no check on output values. * - only ensure they are valid numbers */ for (i = 0; i < NS * NCH; i++) { ck_assert(finite_cd(out[i])); } rtf_destroy_filter(f); free(out); free(in); } END_TEST START_TEST(test_complex_rtfilter_flat_complex_double) { int i; complex double * in, * out; struct rtf_filter * f; complex double num[3] = {0., 1., 2.}; complex double denum[4] = {3., 4., 5., 6.}; f = rtf_create_filter(NCH, RTF_CDOUBLE, arraylen(num), num, arraylen(denum), denum, RTF_CDOUBLE); ck_assert(f != NULL); in = malloc(NS * NCH * sizeof(*in)); out = malloc(NS * NCH * sizeof(*out)); for (i = 0; i < NS * NCH; i++) in[i] = 0.; for (i = 0; i < NS * NCH; i++) out[i] = NANcd; rtf_filter(f, in, out, NS); /* Smoke test: * - no check on output values. * - only ensure they are valid numbers */ for (i = 0; i < NS * NCH; i++) ck_assert(out[i] == 0.); rtf_destroy_filter(f); free(out); free(in); } END_TEST TCase* create_rtfilter_tcase(void) { TCase * tc = tcase_create("rtfilter"); /* smoke tests on float data with real coeffs */ tcase_add_test(tc, test_rtfilter_flat_float); tcase_add_test(tc, test_rtfilter_smoke_float); /* smoke tests on double data with real coeffs */ tcase_add_test(tc, test_rtfilter_flat_double); tcase_add_test(tc, test_rtfilter_smoke_double); /* smoke tests on complex float data with real coeffs */ tcase_add_test(tc, test_rtfilter_flat_complex_float); tcase_add_test(tc, test_rtfilter_smoke_complex_float); /* smoke tests on complex double data with real coeffs */ tcase_add_test(tc, test_rtfilter_flat_complex_double); tcase_add_test(tc, test_rtfilter_smoke_complex_double); /* smoke tests on complex float data with complex coeffs */ tcase_add_test(tc, test_complex_rtfilter_flat_complex_float); tcase_add_test(tc, test_complex_rtfilter_smoke_complex_float); /* smoke tests on complex double data with complex coeffs */ tcase_add_test(tc, test_complex_rtfilter_flat_complex_double); tcase_add_test(tc, test_complex_rtfilter_smoke_complex_double); return tc; } rtfilter-1.3/test/test-common.c000066400000000000000000000021621370625041100166000ustar00rootroot00000000000000#include #include #include #include "rtfilter.h" #include "test-common.h" static inline void create_random_signal(float * signal, int nch, int ns) { int i; for (i = 0; i < ns * nch; i++) signal[i] = (float) rand(); } void smoke_test(struct rtf_filter * f, int nch, int ns) { int i; float * in, * out; ck_assert(f != NULL); in = malloc(ns * nch * sizeof(*in)); out = malloc(ns * nch * sizeof(*out)); create_random_signal(in, nch, ns); fill_signal(out, nch, ns, NAN); rtf_filter(f, in, out, ns); /* Smoke test: * - no check on output values. * - only ensure they are valid numbers */ for (i = 0; i < ns * nch; i++) ck_assert(isfinite(out[i])); free(out); free(in); } void flat_test(struct rtf_filter * f, int nch, int ns) { int i; float * in, * out; ck_assert(f != NULL); in = malloc(ns * nch * sizeof(*in)); out = malloc(ns * nch * sizeof(*out)); fill_signal(in, nch, ns, 0.f); fill_signal(out, nch, ns, NAN); rtf_filter(f, in, out, ns); /* should return 0 on flat input */ for (i = 0; i < ns * nch; i++) ck_assert(out[i] == 0.f); free(out); free(in); } rtfilter-1.3/test/test-common.h000066400000000000000000000022601370625041100166040ustar00rootroot00000000000000#ifndef TEST_COMMON_H #define TEST_COMMON_H #include #define arraylen(v) ((int) (sizeof(v) / sizeof(*v))) #ifndef NAN #define NAN __builtin_nanf("") #endif static inline double db(double x) { return 10 * log(x); } static inline double energy(float const * signal, int nch, int ns) { double energy; int i, j; energy = 0.; for (i = 0; i < nch; i++) { for (j = 0; j < ns; j++) { energy = signal[j * nch + i] * signal[j * nch + i]; } } return energy; } /** * create_signal() - create signal at given frequency * @signal: buffer to fill * @nch: number of channels * @ns: number of samples * @freq: requested frequency * @fs: sampling frequency */ static inline void create_signal(float * signal, int nch, int ns, double freq, double fs) { int i, j; for (i = 0; i < nch; i++) { for (j = 0; j < ns; j++) { signal[j * nch + i] = sinf(2.f * M_PI * freq * j / fs); } } } static inline void fill_signal(float * signal, int nch, int ns, float value) { int i; for (i = 0; i < ns * nch; i++) signal[i] = value; } void smoke_test(struct rtf_filter * f, int nch, int ns); void flat_test(struct rtf_filter * f, int nch, int ns); #endif /* TEST_COMMON_H */ rtfilter-1.3/test/testcases.h000066400000000000000000000003121370625041100163310ustar00rootroot00000000000000#ifndef TESTCASES_H #define TESTCASES_H #include TCase* create_rtfilter_tcase(void); TCase* create_rtfilter_combine_tcase(void); TCase* create_lowpass_tcase(void); #endif /* TESTCASES_H */ rtfilter-1.3/test/unittests.c000066400000000000000000000011501370625041100163710ustar00rootroot00000000000000#include #include #include "testcases.h" static Suite* api_test_suite(void) { Suite * s = suite_create("api"); suite_add_tcase(s, create_rtfilter_tcase()); suite_add_tcase(s, create_rtfilter_combine_tcase()); suite_add_tcase(s, create_lowpass_tcase()); return s; } int main(void) { Suite * s; SRunner * sr; int exitcode = EXIT_SUCCESS; s = api_test_suite(); sr = srunner_create(s); #ifdef CHECK_SUPPORT_TAP srunner_set_tap(sr, "-"); #endif srunner_run_all(sr, CK_ENV); if (srunner_ntests_failed(sr) != 0) exitcode = EXIT_FAILURE; srunner_free(sr); return exitcode; }