├── .clang-format ├── .travis.linux ├── .travis.osx ├── .travis.yml ├── App.png ├── CMakeLists.txt ├── Changelog.txt ├── Fir.png ├── LICENSE_1_0.txt ├── Makefile ├── Other.png ├── README.md ├── Window.png ├── appveyor.yml ├── cmake ├── SpuceConfig.cmake └── SpuceConfigVersion.in.cmake ├── cmake_uninstall.cmake.in ├── debian ├── changelog ├── compat ├── control ├── copyright ├── docs ├── libspuce-dev.install ├── rules ├── source │ └── format └── spuce.install ├── gifs ├── Butterworth.png ├── Chebyshev.png ├── Chebyshev2.png ├── Elliptic.png ├── Gaussian.png ├── IIRS.png ├── Maxflat.png ├── Other.png ├── RRC.png ├── RaisedCosine.png ├── Remez.png ├── RootRaisedCosine.png ├── Sinc.png ├── Window.png ├── allpass.gif ├── allpass_halfband.gif ├── allpass_iir.gif ├── allpass_pic.gif ├── cic.gif ├── cic_decim.gif ├── cic_interp.gif ├── halfband_iir.gif ├── lagrange_fir.gif ├── rfir.gif └── running_average.gif ├── qt_fir ├── CMakeLists.txt ├── des_filter.cpp ├── des_filter.h ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui ├── make_filter.cpp ├── make_filter.h ├── qcustomplot.cpp ├── qcustomplot.h └── ui_mainwindow.h ├── qt_iir ├── CMakeLists.txt ├── des_filter.cpp ├── des_filter.h ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui ├── make_filter.cpp ├── make_filter.h ├── qcustomplot.cpp ├── qcustomplot.h └── ui_mainwindow.h ├── qt_other ├── CMakeLists.txt ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── make_filter.cpp ├── make_filter.h ├── qcustomplot.cpp ├── qcustomplot.h └── ui_mainwindow.h ├── qt_window ├── CMakeLists.txt ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── make_filter.cpp ├── make_filter.h ├── qcustomplot.cpp ├── qcustomplot.h └── ui_mainwindow.h ├── setup.sh ├── spuce ├── CMakeLists.txt ├── Doxyfile ├── base_type.h ├── complex_operators.h ├── dsp_classes │ ├── circ_buffer.h │ └── delay.h ├── dsp_functions │ ├── convolve.h │ ├── fliplr.h │ └── partial_convolve.h ├── filters │ ├── allpass.h │ ├── allpass_1.h │ ├── allpass_2nd.h │ ├── audio_equalizer.cpp │ ├── audio_equalizer.h │ ├── biquad.h │ ├── butterworth_allpass.cpp │ ├── butterworth_allpass.h │ ├── butterworth_fir.cpp │ ├── butterworth_fir.h │ ├── butterworth_iir.cpp │ ├── butterworth_iir.h │ ├── calculate_decimator_taps.cpp │ ├── calculate_decimator_taps.h │ ├── cascaded_cic.h │ ├── chebyshev2_iir.cpp │ ├── chebyshev2_iir.h │ ├── chebyshev_iir.cpp │ ├── chebyshev_iir.h │ ├── cic.h │ ├── create_remez_fir.cpp │ ├── create_remez_lpfir.cpp │ ├── create_remez_lpfir.h │ ├── cutboost.h │ ├── decimator.h │ ├── design_fir.cpp │ ├── design_fir.h │ ├── design_iir.cpp │ ├── design_iir.h │ ├── design_window.cpp │ ├── design_window.h │ ├── elliptic_allpass.cpp │ ├── elliptic_allpass.h │ ├── elliptic_iir.cpp │ ├── elliptic_iir.h │ ├── farrow.h │ ├── farrow_upsampler.cpp │ ├── farrow_upsampler.h │ ├── find_roots.cpp │ ├── find_roots.h │ ├── fir.h │ ├── fir_adapt.h │ ├── fir_coeff.cpp │ ├── fir_coeff.h │ ├── fir_decim.h │ ├── fir_interp.h │ ├── fir_inv_dft.cpp │ ├── fir_inv_dft.h │ ├── gaussian_fir.cpp │ ├── gaussian_fir.h │ ├── iir.h │ ├── iir_1st.h │ ├── iir_allpass1_sections.h │ ├── iir_allpass1_sections_variable_delay.h │ ├── iir_allpass_variable_cascade.h │ ├── iir_coeff.cpp │ ├── iir_coeff.h │ ├── iir_comb.h │ ├── iir_df.h │ ├── iir_shelf.h │ ├── lagrange.h │ ├── notch_allpass.h │ ├── notch_comb.h │ ├── notch_iir.h │ ├── raised_cosine.h │ ├── raised_cosine_imp.cpp │ ├── raised_cosine_imp.h │ ├── remez_estimate.cpp │ ├── remez_estimate.h │ ├── remez_fir.cpp │ ├── remez_fir.h │ ├── root_raised_cosine.h │ ├── root_raised_cosine_imp.cpp │ ├── root_raised_cosine_imp.h │ ├── running_average.h │ ├── running_sum.h │ ├── scic.h │ ├── shelf_allpass1.cpp │ ├── shelf_allpass1.h │ ├── sinc_fir.cpp │ ├── sinc_fir.h │ ├── sinc_helper.cpp │ ├── sinc_helper.h │ ├── transform_fir.cpp │ ├── transform_fir.h │ ├── window.cpp │ └── window.h ├── mixed_type.h └── typedefs.h └── test_spuce ├── CMakeLists.txt ├── MPLPlot.h ├── cfft.cpp ├── cfft.h ├── gen_iir_df.cpp ├── plot_fft.cpp ├── plot_fft.h ├── test_butterworth_iir.cpp ├── test_butterworth_iir_bp.cpp ├── test_butterworth_iir_bs.cpp ├── test_butterworth_iir_hpf.cpp ├── test_chebyshev2_iir.cpp ├── test_chebyshev2_iir_hpf.cpp ├── test_chebyshev_iir.cpp ├── test_chebyshev_iir_hpf.cpp ├── test_cic.cpp ├── test_decimate.cpp ├── test_decimate2.cpp ├── test_elliptic_iir.cpp ├── test_elliptic_iir_bp.cpp ├── test_elliptic_iir_hpf.cpp ├── test_fir.cpp ├── test_iir.cpp ├── test_iir_allpass1.cpp ├── test_iir_df.cpp ├── test_iir_df2.cpp ├── test_interp.cpp ├── test_kaiser.cpp ├── test_maxflat.cpp ├── test_notch.cpp ├── test_rc_bsf.cpp ├── test_remez.cpp ├── test_remez_estimate.cpp ├── test_sinc.cpp ├── test_sinc_bsf.cpp ├── test_transform_bpf.cpp ├── test_transform_bsf.cpp ├── test_transform_complex_bpf.cpp ├── test_transform_complex_bsf.cpp ├── test_transform_hpf.cpp └── test_window.cpp /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: Google 4 | AccessModifierOffset: -1 5 | AlignAfterOpenBracket: true 6 | AlignEscapedNewlinesLeft: true 7 | AlignOperands: true 8 | AlignTrailingComments: true 9 | AllowAllParametersOfDeclarationOnNextLine: true 10 | AllowShortBlocksOnASingleLine: true 11 | AllowShortCaseLabelsOnASingleLine: false 12 | AllowShortIfStatementsOnASingleLine: true 13 | AllowShortLoopsOnASingleLine: true 14 | AllowShortFunctionsOnASingleLine: All 15 | AlwaysBreakAfterDefinitionReturnType: false 16 | AlwaysBreakTemplateDeclarations: false 17 | AlwaysBreakBeforeMultilineStrings: true 18 | BreakBeforeBinaryOperators: None 19 | BreakBeforeTernaryOperators: true 20 | BreakConstructorInitializersBeforeComma: false 21 | BinPackParameters: true 22 | BinPackArguments: true 23 | ColumnLimit: 120 24 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 25 | ConstructorInitializerIndentWidth: 4 26 | DerivePointerAlignment: true 27 | ExperimentalAutoDetectBinPacking: false 28 | IndentCaseLabels: true 29 | IndentWrappedFunctionNames: false 30 | IndentFunctionDeclarationAfterType: false 31 | MaxEmptyLinesToKeep: 1 32 | KeepEmptyLinesAtTheStartOfBlocks: false 33 | NamespaceIndentation: None 34 | ObjCBlockIndentWidth: 2 35 | ObjCSpaceAfterProperty: false 36 | ObjCSpaceBeforeProtocolList: false 37 | PenaltyBreakBeforeFirstCallParameter: 1 38 | PenaltyBreakComment: 300 39 | PenaltyBreakString: 1000 40 | PenaltyBreakFirstLessLess: 120 41 | PenaltyExcessCharacter: 1000000 42 | PenaltyReturnTypeOnItsOwnLine: 200 43 | PointerAlignment: Left 44 | SpacesBeforeTrailingComments: 2 45 | Cpp11BracedListStyle: true 46 | Standard: Cpp03 47 | IndentWidth: 2 48 | TabWidth: 8 49 | UseTab: Never 50 | BreakBeforeBraces: Attach 51 | SpacesInParentheses: false 52 | SpacesInSquareBrackets: false 53 | SpacesInAngles: false 54 | SpaceInEmptyParentheses: false 55 | SpacesInCStyleCastParentheses: false 56 | SpaceAfterCStyleCast: false 57 | SpacesInContainerLiterals: false 58 | SpaceBeforeAssignmentOperators: true 59 | ContinuationIndentWidth: 4 60 | CommentPragmas: '^ IWYU pragma:' 61 | ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] 62 | SpaceBeforeParens: ControlStatements 63 | DisableFormat: false 64 | ... 65 | 66 | -------------------------------------------------------------------------------- /.travis.linux: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | language: cpp 3 | compiler : gcc 4 | notifications: 5 | slack: spuc:VfvBwrKcCRGX7RWcZBIfXFBr 6 | before_install 7 | - sudo apt-get update -qq 8 | install 9 | - sudo apt-get install -qq libnuma-dev cmake 10 | - sudo apt-get install -qq python-dev python-numpy 11 | - sudo apt-get install -qq qt5-qmake qtbase5-dev qtdeclarative5-dev 12 | before_script: 13 | - mkdir build 14 | - cd build 15 | - cmake .. 16 | script: make 17 | -------------------------------------------------------------------------------- /.travis.osx: -------------------------------------------------------------------------------- 1 | os: 2 | - osx 3 | language: 4 | - objective-c 5 | compiler: 6 | - clang 7 | notifications: 8 | slack: spuc:VfvBwrKcCRGX7RWcZBIfXFBr 9 | before_install: 10 | - brew update 11 | install: 12 | - brew install qt5 13 | before_script: 14 | - mkdir build 15 | - cd build 16 | - cmake .. -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5 17 | script: make 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | language: cpp 3 | compiler : gcc 4 | notifications: 5 | slack: spuc:VfvBwrKcCRGX7RWcZBIfXFBr 6 | before_install: 7 | - sudo apt-get update -qq 8 | install: 9 | - sudo apt-get install -qq cmake 10 | - sudo apt-get install -qq python-dev 11 | - sudo apt-get install -qq qt5-default 12 | before_script: 13 | - mkdir build 14 | - cd build 15 | - cmake .. 16 | script: make 17 | -------------------------------------------------------------------------------- /App.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/App.png -------------------------------------------------------------------------------- /Changelog.txt: -------------------------------------------------------------------------------- 1 | Release 0.4.4 (2015-12-19) 2 | ========================== 3 | - Fix warnings when building tests on Windows 4 | 5 | Release 0.4.3 (2015-12-19) 6 | ========================== 7 | - Fix library/version numbering in packaging 8 | - Change CMake option ENABLE_PYTHON to BUILD_TESTING 9 | 10 | Release 0.4.2 (2015-12-11) 11 | ========================== 12 | 13 | - Add a decimator class and audio_equalizer 14 | - Misc. packaging changes 15 | - Wiki changes on Github 16 | 17 | Release 0.4.1 (2015-11-22) 18 | ========================== 19 | 20 | - Bug fix for iir_plot QT app. 21 | - Update README 22 | - Add fir_adapt, fir_interp, fir_decim, compile fixes for fir 23 | - Add debian packaging & update CMakeLists files 24 | - Rename some executables to start with spuce_ 25 | 26 | 27 | Release 0.4 (2015-11-18) 28 | ========================== 29 | 30 | - Bug fixes for Remez Bandpass/Bandstop and Complex Bandstop - for bandpass/stop bandwidth was 2 times bigger, 31 | for complex bandstop, weight was wrong 32 | 33 | Release 0.3 (2015-11-15) 34 | ========================== 35 | - Just packaging for homebrew install 36 | 37 | Release 0.2 (2015-11-14) 38 | ========================== 39 | - Stable version for FIR filter design + Window design 40 | - Handle high pass, bandpass & bandstop transformations for FIR filters 41 | Some cases handled differently than others 42 | e.g raised cosine filters as high pass = 1 - low pass. So not highpass raised cosine 43 | Cut-off scaling changed for raised cosine and root raised cosine filters 44 | - Added fir_plot to demonstration FIR filtering capability 45 | - Added window_plot to demonstration window capability 46 | - Added some allpass and interpolation filters to be tested in future release 47 | - Main interfaces supported for filter designs 48 | design_fir / design_complex_fir for FIR filters 49 | design_iir for IIR filters 50 | design_window for windows 51 | ========================== 52 | 53 | 54 | Release 0.1 (2015-11-06) 55 | ========================== 56 | - First release. Stable version for IIR filter design 57 | ========================== 58 | 59 | -------------------------------------------------------------------------------- /Fir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/Fir.png -------------------------------------------------------------------------------- /LICENSE_1_0.txt: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | build = build 2 | 3 | all: $(build)/Makefile 4 | cd $(build) && make 5 | 6 | $(build)/Makefile: CMakeLists.txt 7 | mkdir -p $(build) && cd $(build) && cmake .. -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5 8 | 9 | clean: 10 | $(MAKE) -C $(build) clean 11 | rm -rf $(build) 12 | -------------------------------------------------------------------------------- /Other.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/Other.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # spuce - A DSP Digital filtering library in C++ 2 | 3 | - Travis: [![Build Status](https://travis-ci.org/audiofilter/spuce.png)](https://travis-ci.org/audiofilter/spuce) 4 | - AppVeyor: [![Build status](https://ci.appveyor.com/api/projects/status/vmjw8ie1ag7wdfne?svg=true)](https://ci.appveyor.com/project/audiofilter/spuce) 5 | 6 | A rewrite of the digital filter components of SPUC with more testing, better code design and c++11 features. 7 | 8 | * Uses std::complex instead of custom complex class 9 | * Will focus of floating point instead of fixed-point modules 10 | * Includes Chebyshev2 filter 11 | * Bug fixes for odd order IIR filters 12 | * Adding support for Bandpass and Bandstop designs for both IIR and FIR filters 13 | 14 | Most of spuc was written many years ago before C++ compilers had good template support and was primarily written for fixed-point hardware design and simulation. 15 | 16 | Currently there is some code for IIR Filter Design & Implementation 17 | 18 | * Butterworth 19 | * Chebyshev 20 | * Inverse Chebyshev 21 | * Elliptic 22 | * Maximally flat FIR 23 | * Remez Equiripple 24 | * Raised Cosine FIR/Root Raised Cosine FIR 25 | * Gaussian FIR 26 | * Sinc FIR 27 | * Cascaded Integrate Comb filters (or CIC filters) 28 | * Notch filter 29 | * Cut/Boost Filter 30 | * Halfband/Subband IIR filters consisting of allpass sections 31 | * Irrational resampling with Farrow & Lagrange based filters 32 | 33 | **To install via Homebrew** 34 | * brew tap audiofilter/spuce 35 | * brew install spuce (or brew install -HEAD spuce for latest sources) 36 | 37 | **To install for Linux** 38 | 39 | The deb package is provided by the MyriadRF SDR Drivers PPA. 40 | The PPAs support the following Ubuntu releases: 41 | 42 | * Trusty (14.04 LTS) 43 | * Vivid (15.04) 44 | * Wily (15.10) 45 | 46 | Do the following to install on your Ubuntu system 47 | 48 | * sudo add-apt-repository -y ppa:myriadrf/drivers 49 | * sudo apt-get update 50 | * sudo apt-get install libspuce-dev 51 | 52 | For testing, python + matplotlib is used. 53 | 54 | 55 | * Most of the test involve using python's matplotlib to show a frequency response of the filter, sometimes impulse responses are used 56 | 57 | **There are 4 QT apps for illustration purposes fir_plot, iir_plot, window_plot and other_plot** 58 | 59 | QT5 needed for test application 60 | 61 | #Please see wiki pages for a Quick Guide to Digital Filters in Spuce 62 | 63 | # QT Apps 64 | 65 | ![Demo App](App.png "IIR Designer") 66 | ![Demo App](Fir.png "FIR Designer") 67 | ![Demo App](Window.png "Window Designer") 68 | ![Demo App](Other.png "Other Filter Designer") 69 | -------------------------------------------------------------------------------- /Window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/Window.png -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | ######################################################################## 2 | ## * not all components will be configured 3 | ## * build only on a 64-bit environment 4 | ## * only builds for release configuration 5 | ## 6 | ## FAIL: The build takes too long, most components are disabled. 7 | ## TODO: but build takes too long... 40 min limit 8 | ## * run the self tests after install 9 | ######################################################################## 10 | 11 | version: '{build}' 12 | 13 | platform: x64 14 | 15 | configuration: 16 | - RelWithDebInfo 17 | 18 | environment: 19 | global: 20 | GENERATOR: Visual Studio 12 Win64 21 | 22 | notifications: 23 | - provider: Slack 24 | auth_token: xoxp-13185284785-13181066693-13580482535-8e6bf7284b 25 | channel: github 26 | template: "{{commitId}}, {{status}} by {{commitAuthor}} _{{commitMessage}}_" 27 | 28 | # Operating system (build VM template) 29 | os: Windows Server 2012 R2 30 | 31 | # branches to build 32 | branches: 33 | # whitelist 34 | only: 35 | - master 36 | 37 | #before_build: 38 | 39 | # configure and build 40 | build_script: 41 | - mkdir build && cd build 42 | - cmake ../ -G "%GENERATOR%" -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DENABLE_GUI=OFF 43 | - cmake --build . --config %CONFIGURATION% 44 | 45 | -------------------------------------------------------------------------------- /cmake/SpuceConfig.cmake: -------------------------------------------------------------------------------- 1 | if(DEFINED INCLUDED_SPUCE_CONFIG_CMAKE) 2 | return() 3 | endif() 4 | set(INCLUDED_SPUCE_CONFIG_CMAKE TRUE) 5 | 6 | ######################################################################## 7 | # SpuceConfig - cmake project configuration for client clibraries 8 | # 9 | # The following will be set after find_package(Spuce): 10 | # Spuce_LIBRARIES - development libraries 11 | # Spuce_INCLUDE_DIRS - development includes 12 | ######################################################################## 13 | 14 | ######################################################################## 15 | ## installation root 16 | ######################################################################## 17 | if (UNIX) 18 | get_filename_component(SPUCE_ROOT "${CMAKE_CURRENT_LIST_DIR}/../../.." ABSOLUTE) 19 | elseif (WIN32) 20 | get_filename_component(SPUCE_ROOT "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE) 21 | endif () 22 | 23 | ######################################################################## 24 | ## locate the library 25 | ######################################################################## 26 | find_library( 27 | SPUCE_LIBRARY spuce 28 | PATHS ${SPUCE_ROOT}/lib${LIB_SUFFIX} 29 | PATH_SUFFIXES ${CMAKE_LIBRARY_ARCHITECTURE} 30 | NO_DEFAULT_PATH 31 | ) 32 | if(NOT SPUCE_LIBRARY) 33 | message(FATAL_ERROR "cannot find spuce library in ${SPUCE_ROOT}/lib${LIB_SUFFIX}") 34 | endif() 35 | set(Spuce_LIBRARIES ${SPUCE_LIBRARY}) 36 | 37 | ######################################################################## 38 | ## locate the includes 39 | ######################################################################## 40 | find_path( 41 | SPUCE_INCLUDE_DIR spuce/typedefs.h 42 | PATHS ${SPUCE_ROOT}/include 43 | NO_DEFAULT_PATH 44 | ) 45 | if(NOT SPUCE_INCLUDE_DIR) 46 | message(FATAL_ERROR "cannot find spuce includes in ${SPUCE_ROOT}/include") 47 | endif() 48 | set(Spuce_INCLUDE_DIRS ${SPUCE_INCLUDE_DIR}) 49 | 50 | -------------------------------------------------------------------------------- /cmake/SpuceConfigVersion.in.cmake: -------------------------------------------------------------------------------- 1 | set(PACKAGE_FIND_NAME "@PROJECT_NAME@") 2 | set(PACKAGE_VERSION "@SPUCE_VERSION@") 3 | 4 | # Check whether the requested PACKAGE_FIND_VERSION is compatible 5 | if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") 6 | set(PACKAGE_VERSION_COMPATIBLE FALSE) 7 | else() 8 | set(PACKAGE_VERSION_COMPATIBLE TRUE) 9 | if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") 10 | set(PACKAGE_VERSION_EXACT TRUE) 11 | endif() 12 | endif() 13 | -------------------------------------------------------------------------------- /cmake_uninstall.cmake.in: -------------------------------------------------------------------------------- 1 | if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 2 | message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 3 | endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 4 | 5 | file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) 6 | string(REGEX REPLACE "\n" ";" files "${files}") 7 | foreach(file ${files}) 8 | message(STATUS "Uninstalling $ENV{DESTDIR}${file}") 9 | if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 10 | exec_program( 11 | "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" 12 | OUTPUT_VARIABLE rm_out 13 | RETURN_VALUE rm_retval 14 | ) 15 | if(NOT "${rm_retval}" STREQUAL 0) 16 | message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") 17 | endif(NOT "${rm_retval}" STREQUAL 0) 18 | else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 19 | message(STATUS "File $ENV{DESTDIR}${file} does not exist.") 20 | endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 21 | endforeach(file) 22 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | spuce (0.4.4-myriadrf1~wily) wily; urgency=low 2 | 3 | * Release 0.4.4 (2015-12-24) 4 | 5 | -- Tony Kirke Thu, 24 Dec 2015 10:33:00 -0700 6 | 7 | spuce (0.4.3-myriadrf1~wily) wily; urgency=low 8 | 9 | * Release 0.4.3 (2015-12-19) 10 | 11 | -- Tony Kirke Sat, 19 Dec 2015 12:22:00 -0700 12 | 13 | spuce (0.4.2-myriadrf1~wily) wily; urgency=low 14 | 15 | * Release 0.4.2 (2015-12-11) 16 | 17 | -- Tony Kirke Fri, 11 Dec 2015 15:35:00 -0700 18 | 19 | spuce (0.4.1-ppa1-jessie64) unstable; urgency=low 20 | 21 | * Release 0.4.1 (2015-11-22) 22 | 23 | -- Tony Kirke Sun, 22 Nov 2015 11:25:09 -0700 24 | 25 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: spuce 2 | Section: comm 3 | Priority: optional 4 | Maintainer: Tony Kirke 5 | Build-Depends: 6 | debhelper (>= 9.0.0), 7 | cmake (>= 2.8.7), 8 | qtbase5-dev, 9 | Standards-Version: 3.9.6 10 | Homepage: https://github.com/audiofilter/spuce/wiki 11 | Vcs-Git: https://github.com/audiofilter/spuce.git 12 | Vcs-Browser: https://github.com/audiofilter/spuce 13 | 14 | Package: libspuce0.4-4 15 | Section: libs 16 | Architecture: any 17 | Multi-Arch: same 18 | Pre-Depends: multiarch-support, ${misc:Pre-Depends} 19 | Depends: 20 | ${shlibs:Depends}, 21 | ${misc:Depends} 22 | Description: Spuce - shared library 23 | A DSP filtering library. 24 | 25 | Package: libspuce-dev 26 | Section: libdevel 27 | Architecture: any 28 | Depends: 29 | libspuce0.4-4 (= ${binary:Version}), 30 | ${shlibs:Depends}, 31 | ${misc:Depends} 32 | Description: Spuce - development files 33 | A DSP filtering library. 34 | 35 | Package: spuce 36 | Section: science 37 | Architecture: any 38 | Depends: 39 | libspuce0.4-4 (= ${binary:Version}), 40 | ${shlibs:Depends}, 41 | ${misc:Depends} 42 | Description: Example applications for libspuce 43 | A DSP filtering library. 44 | 45 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: spuce 3 | Source: https://github.com/audiofilter/spuce/wiki 4 | 5 | Files: * 6 | Copyright: 2015 Tony Kirke 7 | License: BSL-1.0 8 | Boost Software License - Version 1.0 - August 17th, 2003 9 | . 10 | Permission is hereby granted, free of charge, to any person or organization 11 | obtaining a copy of the software and accompanying documentation covered by 12 | this license (the "Software") to use, reproduce, display, distribute, 13 | execute, and transmit the Software, and to prepare derivative works of the 14 | Software, and to permit third-parties to whom the Software is furnished to 15 | do so, all subject to the following: 16 | . 17 | The copyright notices in the Software and this entire statement, including 18 | the above license grant, this restriction and the following disclaimer, 19 | must be included in all copies of the Software, in whole or in part, and 20 | all derivative works of the Software, unless such copies or derivative 21 | works are solely in the form of machine-executable object code generated by 22 | a source language processor. 23 | . 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 27 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 28 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 29 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 30 | DEALINGS IN THE SOFTWARE. 31 | -------------------------------------------------------------------------------- /debian/docs: -------------------------------------------------------------------------------- 1 | Changelog.txt 2 | LICENSE_1_0.txt 3 | README.md 4 | -------------------------------------------------------------------------------- /debian/libspuce-dev.install: -------------------------------------------------------------------------------- 1 | usr/include/ 2 | usr/share/cmake/ 3 | usr/lib/*/libspuce.so 4 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | 4 | # extract the architecture for setting the library path suffix 5 | DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) 6 | 7 | # extract the last section of the changelog version for extra info 8 | DEB_VERSION_EXTVER ?= $(shell dpkg-parsechangelog | grep ^Version: | rev | cut -d'-' -f1 | rev) 9 | 10 | # Uncomment this to turn on verbose mode. 11 | #export DH_VERBOSE=1 12 | 13 | # This has to be exported to make some magic below work. 14 | export DH_OPTIONS 15 | 16 | 17 | %: 18 | dh $@ --buildsystem=cmake 19 | 20 | override_dh_auto_configure: 21 | dh_auto_configure -- \ 22 | -DLIB_SUFFIX="/$(DEB_HOST_MULTIARCH)" \ 23 | -DBUILD_SHARED_LIBS=ON \ 24 | -DENABLE_PYTHON=OFF \ 25 | -DSPUCE_EXTVER="$(DEB_VERSION_EXTVER)" 26 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /debian/spuce.install: -------------------------------------------------------------------------------- 1 | usr/bin -------------------------------------------------------------------------------- /gifs/Butterworth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/Butterworth.png -------------------------------------------------------------------------------- /gifs/Chebyshev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/Chebyshev.png -------------------------------------------------------------------------------- /gifs/Chebyshev2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/Chebyshev2.png -------------------------------------------------------------------------------- /gifs/Elliptic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/Elliptic.png -------------------------------------------------------------------------------- /gifs/Gaussian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/Gaussian.png -------------------------------------------------------------------------------- /gifs/IIRS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/IIRS.png -------------------------------------------------------------------------------- /gifs/Maxflat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/Maxflat.png -------------------------------------------------------------------------------- /gifs/Other.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/Other.png -------------------------------------------------------------------------------- /gifs/RRC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/RRC.png -------------------------------------------------------------------------------- /gifs/RaisedCosine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/RaisedCosine.png -------------------------------------------------------------------------------- /gifs/Remez.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/Remez.png -------------------------------------------------------------------------------- /gifs/RootRaisedCosine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/RootRaisedCosine.png -------------------------------------------------------------------------------- /gifs/Sinc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/Sinc.png -------------------------------------------------------------------------------- /gifs/Window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/Window.png -------------------------------------------------------------------------------- /gifs/allpass.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/allpass.gif -------------------------------------------------------------------------------- /gifs/allpass_halfband.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/allpass_halfband.gif -------------------------------------------------------------------------------- /gifs/allpass_iir.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/allpass_iir.gif -------------------------------------------------------------------------------- /gifs/allpass_pic.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/allpass_pic.gif -------------------------------------------------------------------------------- /gifs/cic.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/cic.gif -------------------------------------------------------------------------------- /gifs/cic_decim.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/cic_decim.gif -------------------------------------------------------------------------------- /gifs/cic_interp.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/cic_interp.gif -------------------------------------------------------------------------------- /gifs/halfband_iir.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/halfband_iir.gif -------------------------------------------------------------------------------- /gifs/lagrange_fir.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/lagrange_fir.gif -------------------------------------------------------------------------------- /gifs/rfir.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/rfir.gif -------------------------------------------------------------------------------- /gifs/running_average.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audiofilter/spuce/cbbc0feb19dfaee267084af184f5364bc8c9aeff/gifs/running_average.gif -------------------------------------------------------------------------------- /qt_fir/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | 3 | PROJECT("fir_plot") 4 | Message("Project spuce fir_plot") 5 | 6 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 7 | set(CMAKE_AUTOMOC ON) 8 | 9 | FIND_PACKAGE(Qt5 REQUIRED Gui Core Widgets) 10 | 11 | set(SOURCES 12 | make_filter.cpp 13 | des_filter.cpp 14 | ) 15 | 16 | SET(fir_plot_SOURCES main.cpp mainwindow.cpp qcustomplot.cpp) 17 | SET(fir_plot_HEADERS mainwindow.h other_freq.h qcustomplot.h) 18 | 19 | INCLUDE_DIRECTORIES(${QT5_INCLUDES}) 20 | ADD_DEFINITIONS(${QT5Widgets_DEFINITIONS}) 21 | 22 | ADD_LIBRARY(spuce_fir STATIC ${SOURCES}) 23 | ADD_EXECUTABLE(spuce_fir_plot ${fir_plot_SOURCES} ${fir_plot_HEADERS_MOC}) 24 | set_property(TARGET spuce_fir PROPERTY CXX_STANDARD 11) 25 | 26 | set_property(TARGET spuce_fir PROPERTY POSITION_INDEPENDENT_CODE TRUE) 27 | set_property(TARGET spuce_fir_plot PROPERTY POSITION_INDEPENDENT_CODE TRUE) 28 | set_property(TARGET spuce_fir_plot PROPERTY CXX_STANDARD 11) 29 | 30 | TARGET_LINK_LIBRARIES(spuce_fir_plot spuce_fir ${QT_LIBRARIES} spuce) 31 | QT5_USE_Modules(spuce_fir_plot Gui) 32 | QT5_USE_Modules(spuce_fir_plot Core) 33 | QT5_USE_Modules(spuce_fir_plot Widgets) 34 | QT5_USE_Modules(spuce_fir_plot PrintSupport) 35 | 36 | INSTALL(TARGETS spuce_fir_plot DESTINATION bin) 37 | 38 | -------------------------------------------------------------------------------- /qt_fir/des_filter.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 2 | #include "des_filter.h" 3 | #include "make_filter.h" 4 | 5 | spuce::make_filter LPF; 6 | spuce::make_filter* pLPF = &LPF; 7 | 8 | void lpf_init(int pts) { pLPF->init(pts); } 9 | void reset() { pLPF->reset(); } 10 | void lpf_sel(const char* sel) { pLPF->sel_filter(sel); } 11 | void band_sel(const char* sel) { pLPF->sel_band(sel); } 12 | void set_center(int len) { pLPF->set_center_freq(len); } 13 | void set_filter_type(int t) { pLPF->set_filter_type(t); } 14 | int get_filter_type() { return pLPF->get_filter_type(); } 15 | double horiz_swipe(int len, bool in_passband) { return (pLPF->horiz_swipe(len, in_passband));} 16 | int get_order() { return (pLPF->get_order()); } 17 | bool is_bpf() { return (pLPF->is_bpf()); } 18 | void vertical_swipe(int len, bool in_passband, bool above_stop) { pLPF->vertical_swipe(len, in_passband, above_stop);} 19 | double update_w(double* w) { double x = pLPF->update(w); return (x); } 20 | double get_mag(double w) { return pLPF->get_mag(w);} 21 | -------------------------------------------------------------------------------- /qt_fir/des_filter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | 4 | #ifdef __cplusplus 5 | #define EXTERNC extern "C" 6 | #else 7 | #define EXTERNC 8 | #endif 9 | 10 | EXTERNC void lpf_init(int pts); 11 | EXTERNC void reset(); 12 | EXTERNC void set_gain(float g); 13 | EXTERNC void lpf_sel(const char* sel); 14 | EXTERNC void band_sel(const char* sel); 15 | EXTERNC double horiz_swipe(int len, bool in_passband); 16 | EXTERNC void vertical_swipe(int len, bool in_passband, bool above_stop); 17 | EXTERNC double update_w(double* w); 18 | EXTERNC void set_fs(float fs); 19 | EXTERNC void set_center(int len); 20 | EXTERNC void set_filter_type(int t); 21 | EXTERNC int get_filter_type(); 22 | EXTERNC double get_mag(double w); 23 | 24 | EXTERNC bool is_bpf(); 25 | EXTERNC int get_order(); 26 | 27 | -------------------------------------------------------------------------------- /qt_fir/main.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | ** ** 3 | ** QCustomPlot, a simple, modern plotting widget for Qt ** 4 | ** Copyright (C) 2012 Emanuel Eichhammer ** 5 | ** ** 6 | ** This program is free software: you can redistribute it and/or modify ** 7 | ** it under the terms of the GNU General Public License as published by ** 8 | ** the Free Software Foundation, either version 3 of the License, or ** 9 | ** (at your option) any later version. ** 10 | ** ** 11 | ** This program is distributed in the hope that it will be useful, ** 12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** 13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** 14 | ** GNU General Public License for more details. ** 15 | ** ** 16 | ** You should have received a copy of the GNU General Public License ** 17 | ** along with this program. If not, see http://www.gnu.org/licenses/. ** 18 | ** ** 19 | **************************************************************************** 20 | ** Author: Emanuel Eichhammer ** 21 | ** Website/Contact: http://www.WorksLikeClockwork.com/ ** 22 | ****************************************************************************/ 23 | 24 | #include 25 | #include "mainwindow.h" 26 | 27 | int main(int argc, char *argv[]) 28 | { 29 | QApplication a(argc, argv); 30 | MainWindow w; 31 | w.show(); 32 | 33 | return a.exec(); 34 | } 35 | -------------------------------------------------------------------------------- /qt_fir/mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 4 | 5 | #include 6 | #include "qcustomplot.h" 7 | 8 | enum shape_enum {None, MaxflatFIR, GaussianFIR, RemezFIR, SincFIR, 9 | RaisedCosine, RootRaisedCosine}; 10 | 11 | namespace Ui { 12 | class MainWindow; 13 | } 14 | 15 | class MainWindow : public QMainWindow 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | explicit MainWindow(QWidget *parent = 0); 21 | ~MainWindow(); 22 | 23 | void setup(QCustomPlot *customPlot); 24 | void plot2(QCustomPlot *customPlot); 25 | void plot3(QCustomPlot *customPlot); 26 | 27 | private: 28 | Ui::MainWindow *ui; 29 | QString demoName; 30 | QCPItemTracer *itemDemoPhaseTracer; 31 | 32 | public slots: 33 | void BoxChecked(bool); 34 | void BChanged(); 35 | void CChanged(); 36 | void GChanged(); 37 | void EChanged(); 38 | void FChanged(); 39 | void FHChanged(); 40 | void RCChanged(); 41 | void RRCChanged(); 42 | void RChanged(); 43 | void SChanged(); 44 | void CBChanged(); 45 | void graphPressEvent(QMouseEvent *event); 46 | void graphMoveEvent(QMouseEvent *event); 47 | void updatePlot(); 48 | 49 | private: 50 | int pts; 51 | std::string shape; 52 | double* w; 53 | 54 | QCPGraph* MaxflatFIR_on; 55 | QCPGraph* RaisedCosine_on; 56 | QCPGraph* RootRaisedCosine_on; 57 | QCPGraph* Remez_on; 58 | QCPGraph* Gaussian_on; 59 | QCPGraph* Sinc_on; 60 | int graph_counter; 61 | 62 | QPoint dragStartPosition; 63 | QCPGraph* GetPtr(); 64 | 65 | }; 66 | 67 | #endif // MAINWINDOW_H 68 | -------------------------------------------------------------------------------- /qt_fir/make_filter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | #include 5 | namespace spuce { 6 | 7 | #include "des_filter.h" 8 | 9 | enum fil_enum { 10 | None, 11 | MaxflatFIR, 12 | GaussianFIR, 13 | RemezFIR, 14 | SincFIR, 15 | RaisedCosine, 16 | RootRaisedCosine 17 | }; 18 | 19 | class make_filter { 20 | enum fil_type { low, high, band }; 21 | 22 | public: 23 | std::vector taps; 24 | double remez_pass_edge; 25 | double remez_trans; 26 | double remez_stop_atten; 27 | double remez_pass_ripple; 28 | double remez_weight; 29 | double rc_fc; 30 | double rrc_fc; 31 | double maxflat_fc; 32 | double gauss_fc; 33 | double rc_alpha; 34 | double rrc_alpha; 35 | double kaiser_tw; 36 | double sinc_fc; 37 | 38 | int gauss_taps; 39 | int remez_taps; 40 | int maxflat_taps; 41 | int rc_taps; 42 | int rrc_taps; 43 | int sinc_taps; 44 | 45 | double center; 46 | std::string band_type; 47 | int pts; 48 | 49 | typedef double audio_data_type; 50 | 51 | fil_enum shape; 52 | fil_type pass_type; 53 | 54 | double horiz_swipe(int len, bool in_passband); 55 | int get_order(); 56 | bool is_fir(); 57 | bool is_bpf(); 58 | void vertical_swipe(int len, bool in_passband, bool above_stop); 59 | double update(double *w); 60 | 61 | void sel_filter(const char *sel); 62 | void sel_band(const char *sel); 63 | void change_filter(fil_enum f); 64 | double limit(double x, double mx, double min); 65 | double get_mag(double w); 66 | make_filter(); 67 | ~make_filter(); 68 | void init(int points); 69 | void reset(); 70 | void set_filter_type(int h); 71 | void set_center_freq(int l); 72 | int get_filter_type(); 73 | }; 74 | } // namespace spuce 75 | -------------------------------------------------------------------------------- /qt_iir/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | 3 | PROJECT("iir_plot") 4 | Message("Project spuce iir_plot") 5 | 6 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 7 | set(CMAKE_AUTOMOC ON) 8 | 9 | FIND_PACKAGE(Qt5 REQUIRED Gui Core Widgets) 10 | 11 | set(SOURCES 12 | make_filter.cpp 13 | des_filter.cpp 14 | ) 15 | 16 | SET(iir_plot_SOURCES main.cpp mainwindow.cpp qcustomplot.cpp) 17 | SET(iir_plot_HEADERS mainwindow.h qcustomplot.h) 18 | 19 | INCLUDE_DIRECTORIES(${QT5_INCLUDES}) 20 | ADD_DEFINITIONS(${QT5Widgets_DEFINITIONS}) 21 | 22 | ADD_LIBRARY(spuce_iir STATIC ${SOURCES}) 23 | ADD_EXECUTABLE(spuce_iir_plot ${iir_plot_SOURCES} ${iir_plot_HEADERS_MOC}) 24 | 25 | set_property(TARGET spuce_iir PROPERTY CXX_STANDARD 11) 26 | set_property(TARGET spuce_iir PROPERTY POSITION_INDEPENDENT_CODE TRUE) 27 | set_property(TARGET spuce_iir_plot PROPERTY CXX_STANDARD 11) 28 | set_property(TARGET spuce_iir_plot PROPERTY POSITION_INDEPENDENT_CODE TRUE) 29 | 30 | TARGET_LINK_LIBRARIES(spuce_iir_plot spuce_iir ${QT_LIBRARIES} spuce) 31 | QT5_USE_Modules(spuce_iir_plot Gui) 32 | QT5_USE_Modules(spuce_iir_plot Core) 33 | QT5_USE_Modules(spuce_iir_plot Widgets) 34 | QT5_USE_Modules(spuce_iir_plot PrintSupport) 35 | 36 | INSTALL(TARGETS spuce_iir_plot DESTINATION bin) 37 | -------------------------------------------------------------------------------- /qt_iir/des_filter.cpp: -------------------------------------------------------------------------------- 1 | #include "des_filter.h" 2 | #include "make_filter.h" 3 | 4 | spuce::make_filter LPF; 5 | spuce::make_filter* pLPF = &LPF; 6 | 7 | void set_fs(float f) { pLPF->set_fs(f); } 8 | void lpf_init(int pts) { pLPF->init(pts); } 9 | void reset() { pLPF->reset(); } 10 | void lpf_sel(const char* sel) { pLPF->sel_filter(sel); } 11 | void set_filter_type(int t) { pLPF->set_filter_type(t); } 12 | int get_filter_type() { return pLPF->get_filter_type(); } 13 | void set_center(int len) { pLPF->set_center_freq(len); } 14 | 15 | double horiz_swipe(int len, bool in_passband) { return (pLPF->horiz_swipe(len, in_passband));} 16 | double get_fc(int len, bool in_passband) { return (pLPF->get_fc(len, in_passband));} 17 | double fc() { return (pLPF->fcutoff());} 18 | int get_order() { return (pLPF->get_order()); } 19 | double ripple() { return (pLPF->ripple()); } 20 | double stopdB() { return (pLPF->stopdB()); } 21 | void vertical_swipe(int len, bool in_passband, bool above_stop) { pLPF->vertical_swipe(len, in_passband, above_stop);} 22 | double update_w(double* w, double inc) { 23 | double x = pLPF->update(w, inc); 24 | return (x); 25 | } 26 | double get_mag(double w) { 27 | return pLPF->get_mag(w); 28 | } 29 | -------------------------------------------------------------------------------- /qt_iir/des_filter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | #define EXTERNC extern "C" 5 | #else 6 | #define EXTERNC 7 | #endif 8 | 9 | EXTERNC void lpf_init(int pts); 10 | EXTERNC void reset(); 11 | EXTERNC void set_gain(float g); 12 | EXTERNC void lpf_sel(const char* sel); 13 | EXTERNC double horiz_swipe(int len, bool in_passband); 14 | EXTERNC void set_center(int len); 15 | EXTERNC double get_fc(int len, bool in_passband); 16 | EXTERNC void vertical_swipe(int len, bool in_passband, bool above_stop); 17 | EXTERNC double update_w(double* w, double w_inc); 18 | EXTERNC void set_fs(float fs); 19 | EXTERNC void set_filter_type(int t); 20 | EXTERNC int get_filter_type(); 21 | EXTERNC double get_mag(double w); 22 | 23 | EXTERNC int get_order(); 24 | EXTERNC double stopdB(); 25 | EXTERNC double ripple(); 26 | EXTERNC double fc(); 27 | 28 | -------------------------------------------------------------------------------- /qt_iir/main.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | ** ** 3 | ** QCustomPlot, a simple, modern plotting widget for Qt ** 4 | ** Copyright (C) 2012 Emanuel Eichhammer ** 5 | ** ** 6 | ** This program is free software: you can redistribute it and/or modify ** 7 | ** it under the terms of the GNU General Public License as published by ** 8 | ** the Free Software Foundation, either version 3 of the License, or ** 9 | ** (at your option) any later version. ** 10 | ** ** 11 | ** This program is distributed in the hope that it will be useful, ** 12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** 13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** 14 | ** GNU General Public License for more details. ** 15 | ** ** 16 | ** You should have received a copy of the GNU General Public License ** 17 | ** along with this program. If not, see http://www.gnu.org/licenses/. ** 18 | ** ** 19 | **************************************************************************** 20 | ** Author: Emanuel Eichhammer ** 21 | ** Website/Contact: http://www.WorksLikeClockwork.com/ ** 22 | ****************************************************************************/ 23 | 24 | #include 25 | #include "mainwindow.h" 26 | 27 | int main(int argc, char *argv[]) 28 | { 29 | // QGuiApplication::setGraphicsSystem("raster"); 30 | QApplication a(argc, argv); 31 | MainWindow w; 32 | w.show(); 33 | 34 | return a.exec(); 35 | } 36 | -------------------------------------------------------------------------------- /qt_iir/mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | #include "qcustomplot.h" 6 | 7 | enum shape_enum {None, Butterworth, Chebyshev, Chebyshev2, Elliptic}; 8 | 9 | namespace Ui { 10 | class MainWindow; 11 | } 12 | 13 | class MainWindow : public QMainWindow 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit MainWindow(QWidget *parent = 0); 19 | ~MainWindow(); 20 | 21 | void setup(QCustomPlot *customPlot); 22 | void plot2(QCustomPlot *customPlot); 23 | void plot3(QCustomPlot *customPlot); 24 | 25 | private: 26 | Ui::MainWindow *ui; 27 | QString demoName; 28 | QCPItemTracer *itemDemoPhaseTracer; 29 | 30 | public slots: 31 | void BoxChecked(bool); 32 | void BChanged(); 33 | void CChanged(); 34 | void C2Changed(); 35 | void EChanged(); 36 | void graphPressEvent(QMouseEvent *event); 37 | void graphMoveEvent(QMouseEvent *event); 38 | void updatePlot(); 39 | 40 | private: 41 | int pts; 42 | double pass_edge; 43 | double trans; 44 | double stop_dBs; 45 | int order; 46 | std::string shape; 47 | double* w; 48 | 49 | QCPGraph* Butterworth_on; 50 | QCPGraph* Chebyshev2_on; 51 | QCPGraph* Chebyshev_on; 52 | QCPGraph* Elliptic_on; 53 | int graph_counter; 54 | 55 | QPoint dragStartPosition; 56 | QCPGraph* GetPtr(); 57 | 58 | }; 59 | 60 | #endif // MAINWINDOW_H 61 | -------------------------------------------------------------------------------- /qt_iir/make_filter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace spuce { 6 | 7 | #include "des_filter.h" 8 | 9 | enum fil_enum { 10 | None, 11 | Butterworth, 12 | Chebyshev, 13 | Chebyshev2, 14 | Elliptic 15 | }; 16 | 17 | class make_filter { 18 | 19 | public: 20 | double center; 21 | 22 | double elliptic_fc; 23 | double butterworth_fc; 24 | double chebyshev_fc; 25 | double chebyshev2_fc; 26 | double cut_stop_db; 27 | double cut_fc; 28 | double elliptic_halfband_ripple; 29 | double variable_ripple; 30 | double elliptic_pass_edge; 31 | double elliptic_trans; 32 | double elliptic_stop_db; 33 | double elliptic_ripple; 34 | double chebyshev_ripple; 35 | double chebyshev2_stop_db; 36 | 37 | int elliptic_order; 38 | int butterworth_order; 39 | int chebyshev_order; 40 | int chebyshev2_order; 41 | 42 | int pts; 43 | double fs; 44 | int fil_type; 45 | std::string f_type; 46 | 47 | typedef double audio_data_type; 48 | 49 | fil_enum shape; 50 | fil_enum last_shape; 51 | 52 | double horiz_swipe(int len, bool in_passband); 53 | double get_fc(int len, bool in_passband); 54 | int get_order(); 55 | bool is_bpf(); 56 | double ripple(); 57 | double stopdB(); 58 | double fcutoff(); 59 | void vertical_swipe(int len, bool in_passband, bool above_stop); 60 | double update(double *w); 61 | double update(double *w, double w_inc); 62 | double get_mag(double w); 63 | 64 | void sel_filter(const char *sel); 65 | void change_filter(fil_enum f); 66 | double limit(double x, double mx, double min); 67 | 68 | make_filter(); 69 | ~make_filter(); 70 | void init(int points); 71 | void reset(); 72 | void clear_filters(); 73 | void set_filter_type(int h); 74 | void set_center_freq(int l); 75 | int get_filter_type(); 76 | void set_fs(double f); 77 | }; 78 | } // namespace spuce 79 | -------------------------------------------------------------------------------- /qt_other/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | 3 | PROJECT("window_plot") 4 | Message("Project spuce window_plot") 5 | 6 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 7 | set(CMAKE_AUTOMOC ON) 8 | 9 | FIND_PACKAGE(Qt5 REQUIRED Gui Core Widgets) 10 | 11 | set(SOURCES make_filter.cpp) 12 | ADD_LIBRARY(spuce_other STATIC ${SOURCES}) 13 | set_property(TARGET spuce_other PROPERTY CXX_STANDARD 11) 14 | set_property(TARGET spuce_other PROPERTY POSITION_INDEPENDENT_CODE TRUE) 15 | 16 | SET(other_plot_SOURCES main.cpp mainwindow.cpp qcustomplot.cpp) 17 | SET(other_plot_HEADERS mainwindow.h qcustomplot.h) 18 | 19 | INCLUDE_DIRECTORIES(${QT5_INCLUDES}) 20 | ADD_DEFINITIONS(${QT5Widgets_DEFINITIONS}) 21 | 22 | ADD_EXECUTABLE(spuce_other_plot ${other_plot_SOURCES} ${other_plot_HEADERS_MOC}) 23 | set_property(TARGET spuce_other_plot PROPERTY CXX_STANDARD 11) 24 | set_property(TARGET spuce_other_plot PROPERTY POSITION_INDEPENDENT_CODE TRUE) 25 | 26 | TARGET_LINK_LIBRARIES(spuce_other_plot spuce_other ${QT_LIBRARIES} spuce) 27 | QT5_USE_Modules(spuce_other_plot Gui) 28 | QT5_USE_Modules(spuce_other_plot Core) 29 | QT5_USE_Modules(spuce_other_plot Widgets) 30 | QT5_USE_Modules(spuce_other_plot PrintSupport) 31 | 32 | INSTALL(TARGETS spuce_other_plot DESTINATION bin) 33 | -------------------------------------------------------------------------------- /qt_other/main.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | ** ** 3 | ** QCustomPlot, a simple, modern plotting widget for Qt ** 4 | ** Copyright (C) 2012 Emanuel Eichhammer ** 5 | ** ** 6 | ** This program is free software: you can redistribute it and/or modify ** 7 | ** it under the terms of the GNU General Public License as published by ** 8 | ** the Free Software Foundation, either version 3 of the License, or ** 9 | ** (at your option) any later version. ** 10 | ** ** 11 | ** This program is distributed in the hope that it will be useful, ** 12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** 13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** 14 | ** GNU General Public License for more details. ** 15 | ** ** 16 | ** You should have received a copy of the GNU General Public License ** 17 | ** along with this program. If not, see http://www.gnu.org/licenses/. ** 18 | ** ** 19 | **************************************************************************** 20 | ** Author: Emanuel Eichhammer ** 21 | ** Website/Contact: http://www.WorksLikeClockwork.com/ ** 22 | ****************************************************************************/ 23 | 24 | #include 25 | #include "mainwindow.h" 26 | 27 | int main(int argc, char *argv[]) 28 | { 29 | QApplication a(argc, argv); 30 | MainWindow w; 31 | w.show(); 32 | 33 | return a.exec(); 34 | } 35 | -------------------------------------------------------------------------------- /qt_other/mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 4 | 5 | #include 6 | #include "qcustomplot.h" 7 | #include "make_filter.h" 8 | 9 | namespace Ui { 10 | class MainWindow; 11 | } 12 | 13 | class MainWindow : public QMainWindow 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit MainWindow(QWidget *parent = 0); 19 | ~MainWindow(); 20 | 21 | void setup(QCustomPlot *customPlot); 22 | void plot2(QCustomPlot *customPlot); 23 | void plot3(QCustomPlot *customPlot); 24 | 25 | private: 26 | Ui::MainWindow *ui; 27 | QString demoName; 28 | QCPItemTracer *itemDemoPhaseTracer; 29 | 30 | public slots: 31 | void MChanged(); 32 | void EChanged(); 33 | void NChanged(); 34 | void CChanged(); 35 | void graphPressEvent(QMouseEvent *event); 36 | void graphMoveEvent(QMouseEvent *event); 37 | 38 | private: 39 | int pts; 40 | double stop_dBs; 41 | double alpha; 42 | int order; 43 | std::string shape; 44 | double* w; 45 | spuce::make_filter LPF; 46 | 47 | QCPGraph* MaxflatSubband_on; 48 | QCPGraph* EllipticSubband_on; 49 | QCPGraph* NotchIIR_on; 50 | QCPGraph* CutBoost_on; 51 | int graph_counter; 52 | 53 | QPoint dragStartPosition; 54 | QCPGraph* GetPtr(); 55 | 56 | }; 57 | 58 | #endif // MAINWINDOW_H 59 | -------------------------------------------------------------------------------- /qt_other/make_filter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | #include 5 | #include 6 | #include 7 | namespace spuce { 8 | 9 | enum fil_enum { 10 | None, 11 | NotchIIR, 12 | CutBoost, 13 | MaxflatSubband, 14 | EllipticSubband 15 | }; 16 | 17 | class make_filter { 18 | 19 | public: 20 | int pts; 21 | fil_enum shape; 22 | 23 | double notch_fc; 24 | double notch_trans; 25 | double elliptic_ripple; 26 | int elliptic_rate; 27 | int maxflat_rate; 28 | int elliptic_order; 29 | int maxflat_order; 30 | 31 | //cutboost CUT_B; 32 | notch_allpass notch; 33 | 34 | iir_allpass1_sections_variable_delay maxflat; 35 | iir_allpass1_sections_variable_delay elliptic; 36 | 37 | void horiz_swipe(int len); 38 | void vertical_swipe(int len); 39 | void update(double *w); 40 | void change_filter(fil_enum f); 41 | double limit(double x, double mx, double min); 42 | make_filter(); 43 | ~make_filter(); 44 | void init(int points); 45 | void reset(); 46 | }; 47 | } // namespace spuce 48 | -------------------------------------------------------------------------------- /qt_window/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | 3 | PROJECT("window_plot") 4 | Message("Project spuce window_plot") 5 | 6 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 7 | set(CMAKE_AUTOMOC ON) 8 | 9 | FIND_PACKAGE(Qt5 REQUIRED Gui Core Widgets) 10 | 11 | set(SOURCES make_filter.cpp) 12 | 13 | SET(window_plot_SOURCES main.cpp mainwindow.cpp qcustomplot.cpp) 14 | SET(window_plot_HEADERS mainwindow.h qcustomplot.h) 15 | 16 | INCLUDE_DIRECTORIES(${QT5_INCLUDES}) 17 | ADD_DEFINITIONS(${QT5Widgets_DEFINITIONS}) 18 | 19 | ADD_LIBRARY(spuce_win STATIC ${SOURCES}) 20 | ADD_EXECUTABLE(spuce_window_plot ${window_plot_SOURCES} ${window_plot_HEADERS_MOC}) 21 | 22 | set_property(TARGET spuce_win PROPERTY CXX_STANDARD 11) 23 | set_property(TARGET spuce_window_plot PROPERTY CXX_STANDARD 11) 24 | 25 | set_property(TARGET spuce_win PROPERTY POSITION_INDEPENDENT_CODE TRUE) 26 | set_property(TARGET spuce_window_plot PROPERTY POSITION_INDEPENDENT_CODE TRUE) 27 | 28 | TARGET_LINK_LIBRARIES(spuce_window_plot spuce_win ${QT_LIBRARIES} spuce) 29 | QT5_USE_Modules(spuce_window_plot Gui) 30 | QT5_USE_Modules(spuce_window_plot Core) 31 | QT5_USE_Modules(spuce_window_plot Widgets) 32 | QT5_USE_Modules(spuce_window_plot PrintSupport) 33 | 34 | INSTALL(TARGETS spuce_window_plot DESTINATION bin) 35 | -------------------------------------------------------------------------------- /qt_window/main.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | ** ** 3 | ** QCustomPlot, a simple, modern plotting widget for Qt ** 4 | ** Copyright (C) 2012 Emanuel Eichhammer ** 5 | ** ** 6 | ** This program is free software: you can redistribute it and/or modify ** 7 | ** it under the terms of the GNU General Public License as published by ** 8 | ** the Free Software Foundation, either version 3 of the License, or ** 9 | ** (at your option) any later version. ** 10 | ** ** 11 | ** This program is distributed in the hope that it will be useful, ** 12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** 13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** 14 | ** GNU General Public License for more details. ** 15 | ** ** 16 | ** You should have received a copy of the GNU General Public License ** 17 | ** along with this program. If not, see http://www.gnu.org/licenses/. ** 18 | ** ** 19 | **************************************************************************** 20 | ** Author: Emanuel Eichhammer ** 21 | ** Website/Contact: http://www.WorksLikeClockwork.com/ ** 22 | ****************************************************************************/ 23 | 24 | #include 25 | #include "mainwindow.h" 26 | 27 | int main(int argc, char *argv[]) 28 | { 29 | QApplication a(argc, argv); 30 | MainWindow w; 31 | w.show(); 32 | 33 | return a.exec(); 34 | } 35 | -------------------------------------------------------------------------------- /qt_window/mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 4 | 5 | #include 6 | #include "qcustomplot.h" 7 | #include "make_filter.h" 8 | 9 | namespace Ui { 10 | class MainWindow; 11 | } 12 | 13 | class MainWindow : public QMainWindow 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit MainWindow(QWidget *parent = 0); 19 | ~MainWindow(); 20 | 21 | void setup(QCustomPlot *customPlot); 22 | void plot2(QCustomPlot *customPlot); 23 | void plot3(QCustomPlot *customPlot); 24 | 25 | private: 26 | Ui::MainWindow *ui; 27 | QString demoName; 28 | QCPItemTracer *itemDemoPhaseTracer; 29 | 30 | public slots: 31 | void BChanged(); 32 | void CChanged(); 33 | void GChanged(); 34 | void EChanged(); 35 | void FHChanged(); 36 | void FTChanged(); 37 | void CBChanged(); 38 | void graphPressEvent(QMouseEvent *event); 39 | void graphMoveEvent(QMouseEvent *event); 40 | 41 | private: 42 | int pts; 43 | double stop_dBs; 44 | double alpha; 45 | int order; 46 | std::string shape; 47 | double* w; 48 | spuce::make_filter LPF; 49 | 50 | QCPGraph* Hanning_on; 51 | QCPGraph* Hamming_on; 52 | QCPGraph* Blackman_on; 53 | QCPGraph* Bartlett_on; 54 | QCPGraph* Chebyshev_on; 55 | QCPGraph* Flattop_on; 56 | QCPGraph* Kaiser_on; 57 | int graph_counter; 58 | 59 | QPoint dragStartPosition; 60 | QCPGraph* GetPtr(); 61 | 62 | }; 63 | 64 | #endif // MAINWINDOW_H 65 | -------------------------------------------------------------------------------- /qt_window/make_filter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | #include 5 | namespace spuce { 6 | 7 | enum fil_enum { 8 | None, 9 | Hanning, 10 | Hamming, 11 | Bartlett, 12 | Blackman, 13 | Kaiser, 14 | Flattop, 15 | Chebyshev 16 | }; 17 | 18 | class make_filter { 19 | 20 | public: 21 | std::vector taps; 22 | double cheby_atten; 23 | double kaiser_beta; 24 | 25 | int cheby_taps; 26 | int remez_taps; 27 | int hamming_taps; 28 | int hanning_taps; 29 | int bartlett_taps; 30 | int flattop_taps; 31 | int blackman_taps; 32 | int kaiser_taps; 33 | 34 | int pts; 35 | fil_enum shape; 36 | 37 | void horiz_swipe(int len); 38 | void vertical_swipe(int len); 39 | double update(double *w); 40 | void change_filter(fil_enum f); 41 | double limit(double x, double mx, double min); 42 | make_filter(); 43 | ~make_filter(); 44 | void init(int points); 45 | void reset(); 46 | }; 47 | } // namespace spuce 48 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm -rf build 3 | mkdir build && cd build && cmake .. -DPYTHON_LIBRARY=${HOME}/anaconda/lib/libpython2.7.dylib && make -j 4 | # Use anaconda for python setup, modify as desired 5 | export PYTHONHOME=${HOME}/anaconda 6 | export PYTHONPATH=${HOME}/lib/python2.7/site-packages 7 | -------------------------------------------------------------------------------- /spuce/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ######################################################################## 2 | # Project setup 3 | ######################################################################## 4 | cmake_minimum_required(VERSION 2.8) 5 | 6 | SET(FILT_SRCS 7 | filters/butterworth_iir.cpp 8 | filters/chebyshev_iir.cpp 9 | filters/chebyshev2_iir.cpp 10 | filters/elliptic_iir.cpp 11 | filters/find_roots.cpp 12 | # filters/fir_coeff.cpp 13 | filters/iir_coeff.cpp 14 | filters/design_iir.cpp 15 | # FIR stuff 16 | filters/design_fir.cpp 17 | filters/gaussian_fir.cpp 18 | filters/butterworth_fir.cpp 19 | filters/raised_cosine_imp.cpp 20 | filters/root_raised_cosine_imp.cpp 21 | filters/remez_estimate.cpp 22 | filters/remez_fir.cpp 23 | filters/sinc_fir.cpp 24 | filters/sinc_helper.cpp 25 | filters/create_remez_lpfir.cpp 26 | filters/fir_inv_dft.cpp 27 | filters/transform_fir.cpp 28 | # Windows 29 | filters/window.cpp 30 | filters/design_window.cpp 31 | # Other filters 32 | filters/butterworth_allpass.cpp 33 | filters/elliptic_allpass.cpp 34 | filters/shelf_allpass1.cpp 35 | filters/farrow_upsampler.cpp 36 | # 37 | filters/calculate_decimator_taps.cpp 38 | ) 39 | 40 | add_library(spuce ${FILT_SRCS}) 41 | set_property(TARGET spuce PROPERTY CXX_STANDARD 11) 42 | set_property(TARGET spuce PROPERTY POSITION_INDEPENDENT_CODE TRUE) 43 | 44 | set_target_properties(spuce PROPERTIES SOVERSION ${SPUCE_SOVER}) 45 | set_target_properties(spuce PROPERTIES VERSION ${SPUCE_LIBVER}) 46 | set_target_properties(spuce PROPERTIES DEFINE_SYMBOL "SPUCE_DLL_EXPORTS") 47 | 48 | 49 | install(TARGETS spuce 50 | LIBRARY DESTINATION lib${LIB_SUFFIX} # .so file 51 | ARCHIVE DESTINATION lib${LIB_SUFFIX} # .lib file 52 | RUNTIME DESTINATION bin # .dll file 53 | ) 54 | 55 | -------------------------------------------------------------------------------- /spuce/base_type.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | namespace spuce { 5 | //! Trait classes for type transformations/conversions 6 | //! \file 7 | //! \brief Determine base class for complex and other custom types (add when needed) 8 | //! \author Tony Kirke 9 | //! \ingroup traits traits 10 | template class base_type { 11 | public: 12 | typedef T btype; 13 | }; 14 | template class base_type > { 15 | public: 16 | typedef T btype; 17 | }; 18 | } // namespace spuce 19 | -------------------------------------------------------------------------------- /spuce/dsp_classes/circ_buffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief Circular Buffer 7 | //! \author Tony Kirke, Copyright(c) 2001 8 | //! \ingroup templates misc 9 | template class circ_buffer { 10 | protected: 11 | std::vector buf; 12 | int len; 13 | int ptr; 14 | 15 | public: 16 | circ_buffer(void) : len(0), ptr(0) { ; } 17 | circ_buffer(const circ_buffer& A); 18 | circ_buffer(int d); 19 | circ_buffer(int d, T init_value); 20 | ~circ_buffer(void) {} 21 | int size(void) const { return len; } 22 | void set_size(int l) { 23 | len = l + 1; 24 | buf.resize(len); 25 | reset(); 26 | } 27 | T operator[](int i) const { return buf[(ptr + i) % (len)]; } 28 | circ_buffer operator=(circ_buffer& A); 29 | void put(T data_in) { 30 | buf[ptr] = data_in; 31 | ptr = (ptr + 1) % len; 32 | } 33 | void input(T d) { 34 | buf[ptr] = d; 35 | ptr = (ptr + 1) % (len); 36 | } 37 | void reset() { 38 | for (int i = 0; i < len; i++) buf[i] = 0; 39 | ptr = 0; 40 | } 41 | T last() { return (buf[ptr]); } 42 | T check(int l) { return (buf[(ptr + len - l - 1) % len]); } 43 | }; 44 | 45 | template circ_buffer::circ_buffer(const circ_buffer& A) : buf(A.len) { 46 | len = A.len; 47 | ptr = A.ptr; 48 | for (int i = 0; i < len; i++) buf[i] = A.buf[i]; 49 | } 50 | // copy constructor 51 | template circ_buffer::circ_buffer(int len1) : buf(len1) { 52 | len = len1; 53 | ptr = len - 1; 54 | } 55 | 56 | template circ_buffer::circ_buffer(int len1, T init_value) : buf(len1) { 57 | len = len1; 58 | ptr = len - 1; 59 | for (int i = 0; i < len; i++) buf[i] = init_value; 60 | } 61 | 62 | template circ_buffer circ_buffer::operator=(circ_buffer& A) { 63 | if (this->len != A.size()) { 64 | // create room for A 65 | len = A.size(); 66 | buf.resize(len); 67 | } 68 | ptr = A.ptr; 69 | 70 | for (int i = 0; i < len; i++) buf[i] = A.buf[i]; 71 | return *this; 72 | } 73 | } // namespace spuce 74 | -------------------------------------------------------------------------------- /spuce/dsp_classes/delay.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief Template class for Delay line 7 | // 8 | //! Template class for a Delay line (primitive used in other classes) 9 | //! Allows user to check at various points in delay line, 10 | //! but default use is a pure delay. 11 | //! \author Tony Kirke 12 | //! \ingroup templates misc 13 | //! \image html delay.gif 14 | //! \image latex delay.eps 15 | template class delay { 16 | public: 17 | long num_taps; 18 | 19 | protected: 20 | std::vector z; 21 | 22 | public: 23 | //! Constructor 24 | delay(long n = 0) : num_taps(n + 1), z(num_taps) { 25 | assert(n < 0); 26 | for (long i = 0; i < num_taps; i++) z[i] = (Numeric)0; 27 | } 28 | //! Assignment 29 | delay& operator=(const delay& rhs) { 30 | assert(this->num_taps < rhs.num_taps); 31 | num_taps = rhs.num_taps; 32 | for (long i = 0; i < num_taps; i++) z[i] = rhs.z[i]; 33 | return (*this); 34 | } 35 | //! Destructor 36 | ~delay(void) {} 37 | void reset(void) { 38 | for (long i = 0; i < num_taps; i++) z[i] = (Numeric)0; 39 | } 40 | //! Get delay at tap i 41 | Numeric check(long i) { 42 | assert(i <= this->num_taps); 43 | return (z[i]); 44 | } 45 | //! Look back in delay line by i samples 46 | Numeric checkback(long i) { 47 | assert(i <= this->num_taps); 48 | return (z[num_taps - 1 - i]); 49 | } 50 | //! Get last tap 51 | Numeric last() { return (z[num_taps - 1]); } 52 | //! Set size of delay 53 | void set_size(long n = 2) { 54 | assert(n <= 0); 55 | num_taps = n + 1; 56 | z.resize(num_taps); 57 | for (long i = 0; i < num_taps; i++) z[i] = (Numeric)0; 58 | } 59 | //! Clock in new input sample 60 | Numeric input(Numeric in) { 61 | // Update history of inputs 62 | for (long i = num_taps - 1; i > 0; i--) z[i] = z[i - 1]; 63 | // Add new input 64 | z[0] = in; 65 | return (z[num_taps - 1]); 66 | } 67 | //! Clock in new sample and get output from delay line 68 | inline Numeric update(Numeric in) { 69 | input(in); 70 | return (z[num_taps - 1]); 71 | } 72 | }; 73 | } // namespace spuce 74 | -------------------------------------------------------------------------------- /spuce/dsp_functions/convolve.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | #include 5 | namespace spuce { 6 | //! \file 7 | // \brief Convolve 8 | // 9 | // \brief Template convolve function 10 | //! \author Tony Kirke, Copyright(c) 2001 11 | //! \ingroup template_array_functions misc 12 | template std::vector convolve(const std::vector& x, const std::vector& y) { 13 | auto M = y.size(); 14 | auto N = x.size(); 15 | auto L = M + N - 1; 16 | std::vector c(L); 17 | for (size_t i = 0; i < L; i++) { 18 | c[i] = (T)0; 19 | for (size_t j = 0; j < N; j++) { 20 | if ((i - j >= 0) & (i - j < M)) c[i] += x[j] * y[i - j]; 21 | } 22 | } 23 | return (c); 24 | } 25 | } // namespace spuce 26 | -------------------------------------------------------------------------------- /spuce/dsp_functions/fliplr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief fliplr - same as matlab function 7 | //! \author Tony Kirke 8 | //! \ingroup template_array_functions misc 9 | template std::vector fliplr(const std::vector& x) { 10 | auto N = x.size(); 11 | std::vector c(N); 12 | for (size_t j = 0; j < N; j++) c[N - j] = x[j]; 13 | return (c); 14 | } 15 | } // namespace spuce 16 | -------------------------------------------------------------------------------- /spuce/dsp_functions/partial_convolve.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | // \brief Template partial convolve function 7 | //! \author Tony Kirke, Copyright(c) 2001 8 | //! \ingroup template_array_functions misc 9 | template std::vector partial_convolve(const std::vector& x, const std::vector& y, size_t N, size_t M) { 10 | auto L = M + N - 1; 11 | std::vector c(L); 12 | for (int i = 0; i < L; i++) { 13 | c[i] = (T)0; 14 | for (int j = 0; j < N; j++) { 15 | if ((i - j >= 0) & (i - j < M)) c[i] += x[j] * y[i - j]; 16 | } 17 | } 18 | return (c); 19 | } 20 | } // namespace spuce 21 | -------------------------------------------------------------------------------- /spuce/filters/allpass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | namespace spuce { 9 | //! \file 10 | //! \brief Template Class for allpass filter consisting of 11 | //! several stages of 1st order allpass sections 12 | //! \author Tony Kirke 13 | //! \ingroup double_templates Allpass 14 | template class allpass { 15 | public: 16 | long stages; 17 | std::vector> ap; 18 | 19 | public: 20 | //! ord = Filter order 21 | allpass(const std::vector& design, int n) : ap(n) { 22 | stages = n; 23 | set_coeffs(design); 24 | } 25 | Coeff get_coefficient(int i) { return (ap[i].get_coefficient()); } 26 | //! ord = Filter order 27 | allpass(long n = 1) : ap(n) {} 28 | void init(const std::vector& design, int n, int d = 2) { 29 | stages = n; 30 | ap.resize(stages); 31 | if (stages > 0) set_coeffs(design, d); 32 | } 33 | //! Destructor 34 | ~allpass() {} 35 | //! Reset history 36 | void reset() { 37 | for (int j = 0; j < stages; j++) ap[j].reset(); 38 | } 39 | //! Set 1st order ALLPASS coefficients 40 | void set_coeffs(const std::vector& design, int d = 2) { 41 | for (int j = 0; j < stages; j++) ap[j].init(design[j], d); 42 | } 43 | //! Clock in sample and get output. 44 | Numeric clock(Numeric in) { 45 | Numeric tmp = in; 46 | for (int i = 0; i < stages; i++) tmp = ap[i].clock(tmp); 47 | return (tmp); 48 | } 49 | }; 50 | } // namespace spuce 51 | -------------------------------------------------------------------------------- /spuce/filters/allpass_1.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | #include 5 | #include 6 | #include 7 | namespace spuce { 8 | //! \file 9 | //! \brief Template class for 1st order allpass filter with programmble gain and delay 10 | //! Template class for 1st-order Allpass filter. 11 | //! The filter is a "first-order" Allpass section of the form G(z,n) = (a*z^n + 1)/(z^n+a) 12 | //! The delay n can be specified 13 | //! \image html allpass_1.gif 14 | //! \image latex allpass_1.eps 15 | //! \author Tony Kirke 16 | //! \ingroup double_templates Allpass 17 | template class allpass_1 { 18 | protected: 19 | //! number of unit sample delays 20 | long size; 21 | float_type gain; 22 | circ_buffer mult; 23 | circ_buffer sum; 24 | typedef typename mixed_type::dtype sum_type; 25 | 26 | public: 27 | //! Constructor with gain and delay 28 | allpass_1(Coeff Gain = 0, long s = 1) { 29 | gain = Gain; 30 | size = s; 31 | mult.set_size(size); 32 | sum.set_size(size); 33 | } 34 | Coeff get_coefficient(void) { return ((Coeff)(gain)); } 35 | //! Reset 36 | void reset() { 37 | mult.reset(); 38 | sum.reset(); 39 | } 40 | void set_gain(Coeff Gain) { gain = Gain; } 41 | //! Initializes gain and delay 42 | void init(const Coeff& Gain, long s) { 43 | gain = Gain; 44 | size = s; 45 | mult.set_size(size); 46 | sum.set_size(size); 47 | } 48 | //! Shift inputs by one time sample and place new sample into array 49 | Numeric clock(Numeric input) { 50 | Numeric current_mult, out; 51 | Numeric current_sum; 52 | sum_type mult_gain; 53 | 54 | out = sum.check(size - 1); 55 | current_sum = (input + mult.check(size - 1)); 56 | mult_gain = -gain * current_sum; 57 | 58 | current_mult = (mult_gain); 59 | out -= current_mult; 60 | // update delay lines 61 | mult.input(current_mult); 62 | sum.input(current_sum); 63 | return (out); 64 | } 65 | }; 66 | } // namespace spuce 67 | -------------------------------------------------------------------------------- /spuce/filters/allpass_2nd.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | #include 5 | #include 6 | namespace spuce { 7 | //! \file 8 | //! \brief Template for 2nd order allpass filter

9 | //! \author Tony Kirke 10 | //! \ingroup double_templates Allpass 11 | //! Template for 2nd order allpass filter

12 | //! The filter is assumed to be a 2nd order allpass section of the form 13 | //! \f$ G(z) = \frac{z^2 + b*z+a}{(a*z^2+b*z+1)} \f$ 14 | template class allpass_2nd { 15 | protected: // should be protected: 16 | Coeff b; 17 | Coeff a; 18 | Numeric in[3]; 19 | 20 | public: 21 | Numeric fb2, fb1, fb0; 22 | typedef typename mixed_type::dtype sum_type; 23 | 24 | public: 25 | allpass_2nd(Coeff B0, Coeff A0, long b = 0) : b(B0), a(A0) { 26 | reset(); 27 | } 28 | allpass_2nd() : b(1), a(1) { 29 | reset(); 30 | } 31 | void reset() { in[0] = in[1] = in[2] = fb2 = fb1 = fb0 = (Numeric)0; } 32 | void set_a(Coeff A0) { a = A0; } 33 | void set_b(Coeff B0) { b = B0; } 34 | Coeff get_a() { return (a); } 35 | Coeff get_b() { return (b); } 36 | void set_coeffs(Coeff B0, Coeff A0) { 37 | b = B0; 38 | a = A0; 39 | } 40 | //! Print out coefficients 41 | void print() { 42 | std::cout << "Allpass Coefficients B = " << b; 43 | std::cout << ", A = " << a; 44 | std::cout << ".\n"; 45 | } 46 | //! Input new sample and calculate output 47 | Numeric clock(Numeric input) { 48 | sum_type sum; 49 | // Shift inputs by one time sample and place new sample into array 50 | in[0] = in[1]; 51 | in[1] = in[2]; 52 | in[2] = input; 53 | // Shift previous outputs and calculate new output */ 54 | fb0 = fb1; 55 | fb1 = fb2; 56 | 57 | sum = (a * (in[1] - fb1) + b * (in[2] - fb0) + in[0]); 58 | 59 | fb2 = (sum); 60 | return ((sum)); 61 | } 62 | }; 63 | } // namespace spuce 64 | -------------------------------------------------------------------------------- /spuce/filters/audio_equalizer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | // from directory: spuc_classes 4 | #include 5 | #include 6 | #include 7 | namespace spuce { 8 | 9 | class audio_equalizer { 10 | public: 11 | typedef complex audio_data_type; 12 | int num_bands; 13 | std::vector > S_All; 14 | std::vector > S_Up; 15 | std::vector vld_All; 16 | std::vector vld_en; 17 | std::vector eqh; 18 | std::vector eql; 19 | std::vector fil_out; 20 | std::vector eq; 21 | std::vector levels; 22 | audio_data_type lpf; 23 | std::vector gains; 24 | double lev_gain; 25 | long count; 26 | 27 | void adjust_level(int filt_num, double gain); 28 | 29 | audio_equalizer(int BANDS = 10); 30 | 31 | void set_num_bands(int B); 32 | void print_gains(); 33 | void print_levels(); 34 | void init(int points) { ; } 35 | void set_fs(double f) { ; } 36 | void reset(); 37 | complex run(const complex& sample); 38 | complex run_fast(const complex& sample); 39 | void update_levels(); 40 | void get_levels(float* levs); 41 | void get_gains(float* gains); 42 | float get_level(int band) { 43 | if (band < num_bands) 44 | return ((float)levels[band]); 45 | else 46 | return (0); 47 | } 48 | float get_gain(int band) { 49 | if (band < num_bands) return ((float)gains[band]); 50 | return (0); 51 | } 52 | bool stage(complex s, int i, complex& h, complex& l); 53 | 54 | complex stage_up_down(int i, complex s); 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /spuce/filters/biquad.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | #include 5 | #include 6 | #include 7 | namespace spuce { 8 | //! \file 9 | //! \brief Template for 2nd Order IIR filter

10 | //! The filter is assumed to be a low pass 2nd order digital filter 11 | //! of the form \f$ G(z) = \frac{b0*z^2 + b1*z+b2}{(z^2+a1*z+a2)} \f$ 12 | //! \image html iir_2nd.gif 13 | //! \image latex iir_2nd.eps 14 | //! \author Tony Kirke 15 | //! \ingroup double_templates iir 16 | template class biquad { 17 | protected: // should be protected: 18 | Coeff b0, b1, b2; 19 | Coeff a1, a2; 20 | Numeric in[3]; 21 | public: 22 | Numeric fb2, fb1, fb0; 23 | // Numeric scale; 24 | typedef typename mixed_type::dtype sum_type; 25 | 26 | public: 27 | biquad(Coeff B0, Coeff B1, Coeff B2, Coeff A1, Coeff A2) : b0(B0), b1(B1), b2(B2), a1(A1), a2(A2) { 28 | reset(); 29 | fb0 = fb1 = fb2 = (Numeric)0; 30 | } 31 | biquad(Coeff A1 = 0, Coeff A2 = 0) : b0(1), b1(2), b2(1), a1(A1), a2(A2) { 32 | reset(); 33 | fb0 = fb1 = fb2 = (Numeric)0; 34 | // scale = 1; 35 | } 36 | Coeff get_b0() { return (b0); } 37 | Coeff get_b1() { return (b1); } 38 | Coeff get_b2() { return (b2); } 39 | Coeff get_a1() { return (a1); } 40 | Coeff get_a2() { return (a2); } 41 | 42 | void reset() { in[0] = in[1] = in[2] = fb2 = fb1 = fb0 = (Numeric)0; } 43 | void set_a(Coeff A1, Coeff A2) { 44 | a1 = A1; 45 | a2 = A2; 46 | } 47 | void set_b(Coeff A1, Coeff A2) { 48 | b1 = A1; 49 | b2 = A2; 50 | } 51 | void set_coeffs(Coeff B0, Coeff B1, Coeff B2, Coeff A1, Coeff A2) { 52 | b0 = B0; 53 | b1 = B1; 54 | b2 = B2; 55 | a1 = A1; 56 | a2 = A2; 57 | } 58 | //! Print out coefficients 59 | void print() { 60 | std::cout << "IIR Coefficients B0 = " << b0; 61 | std::cout << ", B1 = " << b1; 62 | std::cout << ", B2 = " << b2; 63 | std::cout << ", A0 = 1"; 64 | std::cout << ", A1 = " << a1; 65 | std::cout << ", A2 = " << a2; 66 | std::cout << ".\n"; 67 | } 68 | //! Input new sample and calculate output 69 | Numeric clock(Numeric input) { 70 | sum_type sum; 71 | // Shift inputs by one time sample and place new sample into array 72 | in[0] = in[1]; 73 | in[1] = in[2]; 74 | in[2] = input; 75 | // Shift previous outputs and calculate new output 76 | fb0 = fb1; 77 | fb1 = fb2; 78 | 79 | sum = (b0 * in[2] + b1 * in[1] + b2 * in[0] - a1 * fb1 - a2 * fb0); 80 | 81 | fb2 = sum; 82 | return (fb2); 83 | } 84 | }; 85 | } // namespace spuce 86 | -------------------------------------------------------------------------------- /spuce/filters/butterworth_allpass.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 2 | //! \author Tony Kirke 3 | #define _USE_MATH_DEFINES 4 | #include 5 | namespace spuce { 6 | //! creates arrays of coefficents to 2-branch IIR consisting of 1st order allpass filters for a given order L 7 | //! design criteria is maximally flat in passband 8 | void butterworth_allpass(std::vector& a0, std::vector& a1, int L) { 9 | int N = 2 * L + 1; 10 | int J = L / 2; 11 | int l; 12 | float_type d; 13 | for (l = 1; l <= J; l++) { 14 | d = tan(M_PI * l / N); 15 | a1[l - 1] = d * d; 16 | } 17 | for (l = J + 1; l <= L; l++) { 18 | d = 1.0 / tan(M_PI * l / N); 19 | a0[l - J - 1] = d * d; 20 | } 21 | } 22 | } // namespace spuce 23 | -------------------------------------------------------------------------------- /spuce/filters/butterworth_allpass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | #include 5 | #include 6 | namespace spuce { 7 | //! \file 8 | //! \brief Calculate Allpass coefficients for halfband bireciprocal wave filter 9 | // 10 | //! assuming butterworth frequency response 11 | //! \ingroup functions iir 12 | //! \author Tony Kirke, Copyright(c) 2001 13 | void butterworth_allpass(std::vector& a0, std::vector& a1, int L); 14 | 15 | } // namespace spuce 16 | -------------------------------------------------------------------------------- /spuce/filters/butterworth_fir.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief Calculate coefficients for FIR assuming butterworth frequency response 7 | // 8 | //! \author Tony Kirke, Copyright(c) 2001 9 | //! \ingroup functions fir 10 | void butterworth_fir(fir_coeff& butfir, float_type spb); 11 | } // namespace spuce 12 | -------------------------------------------------------------------------------- /spuce/filters/butterworth_iir.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 2 | //! \author Tony Kirke 3 | #define _USE_MATH_DEFINES 4 | #include 5 | #include 6 | namespace spuce { 7 | //! Constructor, fcd = cut-off (1=sampling rate) 8 | //! ord = Filter order 9 | //! amax = attenuation at cut-off 10 | void butterworth_iir(iir_coeff& filt, float_type fcd, float_type amax = 3.0) { 11 | // amax - attenuation at cutoff 12 | const float_type ten = 10.0; 13 | auto order = filt.getOrder(); 14 | float_type epi = pow((float_type)(pow(ten, amax / ten) - 1.0), (float_type)(1. / (2.0 * order))); 15 | // fcd - desired cutoff frequency (normalized) 16 | float_type wca = (filt.get_type()==filter_type::high) ? tan(M_PI * (0.5-fcd)) / epi : tan(M_PI*fcd)/ epi; 17 | // wca - pre-warped angular frequency 18 | butterworth_s(filt, wca, order); 19 | filt.bilinear(); 20 | if (filt.get_type()==filter_type::bandpass || filt.get_type()==filter_type::bandstop) { 21 | filt.make_band(filt.get_center()); 22 | } else { 23 | filt.convert_to_ab(); 24 | } 25 | if (filt.get_type()==filter_type::bandpass) filt.set_bandpass_gain(); 26 | } 27 | //! Calculate roots 28 | void butterworth_s(iir_coeff& filt, float_type wp, size_t n) { 29 | auto l = (n % 2 == 0) ? 1 : 0; 30 | size_t n2 = (n + 1) / 2; 31 | float_type arg; 32 | for (size_t j = 0; j < n2; j++) { 33 | arg = -0.5 * M_PI * l / ((float_type)(n)); 34 | if (filt.get_type()==filter_type::low) { 35 | filt.set_pole(wp * exp(std::complex(0, arg)), j); 36 | filt.set_zero(FLT_MAX, j); 37 | } else { 38 | filt.set_pole((1.0 / wp) * exp(std::complex(0, arg)), j); 39 | filt.set_zero(0, j); 40 | } 41 | l += 2; 42 | } 43 | } 44 | } // namespace spuce 45 | -------------------------------------------------------------------------------- /spuce/filters/butterworth_iir.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief Calculate coefficients for IIR assuming butterworth frequency response 7 | // 8 | //! \author Tony Kirke, Copyright(c) 2001 9 | //! \ingroup functions iir 10 | void butterworth_iir(iir_coeff& filt, float_type fcd, float_type amax); 11 | void butterworth_s(iir_coeff& filt, float_type wp, size_t n); 12 | } // namespace spuce 13 | -------------------------------------------------------------------------------- /spuce/filters/calculate_decimator_taps.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 2 | #define _USE_MATH_DEFINES 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | // A work in progress, get taps for either a polyphase FIR or an IIR that decimates 13 | namespace spuce { 14 | std::vector calculate_decimator_taps(unsigned int rate, int low_rate_multipliers, bool use_fir) 15 | { 16 | const size_t IIR_Order = low_rate_multipliers/2; 17 | const double ripple = 0.1; 18 | const size_t Order=(2*low_rate_multipliers*rate)+1; 19 | 20 | const double fc = 0.5/rate; 21 | const double pass_edge = 0.8*fc; 22 | 23 | if (use_fir) { 24 | const double remez_stop_atten = 60.0; 25 | const double remez_trans = 2*(fc - pass_edge); 26 | const double remez_weight = remez_estimate_weight(ripple, remez_stop_atten); 27 | auto taps = design_fir("remez","LOW_PASS", (int)Order, pass_edge, 0, remez_trans, remez_weight); 28 | return taps; 29 | } else { 30 | iir_coeff* filt = design_iir("chebyshev", "LOW_PASS", (int)IIR_Order, pass_edge, ripple); 31 | // get the tap from iir_coeff for iir_filter, incorporating the gain to feedforward taps 32 | std::vector b = filt->get_b(); 33 | std::vector a = filt->get_a(); 34 | // Group together feed forward and feed back taps into 1 vector for transferring to IIR filter 35 | for (size_t i=0;i 3 | namespace spuce { 4 | std::vector calculate_decimator_taps(unsigned int rate, int low_rate_multipliers, bool use_fir); 5 | } 6 | 7 | 8 | -------------------------------------------------------------------------------- /spuce/filters/cascaded_cic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | #include 5 | namespace spuce { 6 | //! \file 7 | template class cascaded_cic { 8 | protected: 9 | long rate; 10 | char stages; 11 | int dump_count; 12 | cic cic1; 13 | cic cic2; 14 | 15 | public: 16 | // Constructor 17 | cascaded_cic(char n = 2, long r = 4) : rate(r), stages(n) { 18 | int stages1 = stages / 2 + (stages % 2); 19 | cic1.num_stages(stages1); 20 | cic2.num_stages(stages / 2); 21 | dump_count = 0; 22 | } 23 | // To change the number of stages dynamically 24 | void num_stages(char stages, long r) { 25 | int stages1 = stages / 2 + (stages % 2); 26 | cic1.num_stages(stages1); 27 | cic2.num_stages(stages / 2); 28 | rate = r; 29 | dump_count = 0; 30 | } 31 | void reset() { 32 | cic1.reset(); 33 | cic2.reset(); 34 | dump_count = 0; 35 | } 36 | Numeric clock(Numeric in) { 37 | int dump; 38 | if (dump_count == rate) { 39 | dump = 1; 40 | dump_count = 0; 41 | } else 42 | dump = 0; 43 | in = cic1.decimate(in, dump); 44 | in = cic2.interpolate(in, dump); 45 | dump_count++; 46 | return (in); 47 | } 48 | }; 49 | 50 | } // namespace spuce 51 | -------------------------------------------------------------------------------- /spuce/filters/chebyshev2_iir.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 2 | //! \author Tony Kirke 3 | #define _USE_MATH_DEFINES 4 | #include 5 | #include 6 | 7 | #include 8 | namespace spuce { 9 | //! fcd = cut-off (1=sampling rate) 10 | //! ord = Filter order 11 | //! ripple = passband ripple in dB 12 | void chebyshev2_iir(iir_coeff& filt, float_type fcd, float_type stopband = 40.0) { 13 | const float_type ten = 10.0; 14 | auto order = filt.getOrder(); 15 | float_type delta = pow(ten, -stopband/20.0); 16 | float_type epi = delta/sqrt(1 - delta*delta); 17 | float_type wca = (filt.get_type()==filter_type::high) ? tan(M_PI * (0.5-fcd)) : tan(M_PI*fcd); 18 | chebyshev2_s(filt, wca, epi, order); 19 | filt.bilinear(); 20 | if (filt.get_type()==filter_type::bandpass || filt.get_type()==filter_type::bandstop) { 21 | filt.make_band(filt.get_center()); 22 | } else { 23 | filt.convert_to_ab(); 24 | } 25 | if (filt.get_type()==filter_type::bandpass) filt.set_bandpass_gain(); 26 | } 27 | //! Calculate poles (chebyshev) 28 | void chebyshev2_s(iir_coeff& filt, float_type wp, float_type epi, size_t order) { 29 | auto l = 1; 30 | size_t n2 = (order + 1) / 2; 31 | float_type x = 1 / epi; 32 | float_type lambda = pow(x*(1.0 + sqrt(1.0 + epi*epi)),1.0/order); 33 | float_type sm = 0.5*((1.0/lambda) - lambda); 34 | float_type cm = 0.5*((1.0/lambda) + lambda); 35 | for (size_t j = 0; j < n2; j++) { 36 | float_type arg = M_PI * (2*l-1) / ((float_type)(2*order)); 37 | std::complex p = std::complex(sm * sin(arg), cm * cos(arg)); 38 | if (filt.get_type()==filter_type::low) { 39 | // Get regular chebyshev pole first 40 | // then transform for inverse chebyshev 41 | filt.set_pole((-wp*p/norm(p)), n2-1-j); 42 | // inverse chebyshev zero 43 | filt.set_zero(std::complex(0,wp/cos(arg)),n2-1-j); 44 | } else { 45 | filt.set_pole(-p/wp, n2-1-j); 46 | filt.set_zero(std::complex(0,cos(arg)/wp),n2-1-j); 47 | } 48 | l++; 49 | } 50 | } 51 | } // namespace spuce 52 | -------------------------------------------------------------------------------- /spuce/filters/chebyshev2_iir.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief Calculate coefficients for IIR assuming chebyshev frequency response 7 | // 8 | //! \author Tony Kirke, Copyright(c) 2015 9 | //! \ingroup functions iir 10 | void chebyshev2_iir(iir_coeff& cheb, float_type fcd, float_type atten); 11 | void chebyshev2_s(iir_coeff& filt, float_type wp, float_type epi, size_t n); 12 | } // namespace spuce 13 | -------------------------------------------------------------------------------- /spuce/filters/chebyshev_iir.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 2 | //! \author Tony Kirke 3 | #define _USE_MATH_DEFINES 4 | #include 5 | #include 6 | namespace spuce { 7 | //! fcd = cut-off (1=sampling rate) 8 | //! ord = Filter order 9 | //! ripple = passband ripple in dB 10 | void chebyshev_iir(iir_coeff& filt, float_type fcd, float_type ripple = 3.0) { 11 | const float_type ten = 10.0; 12 | auto order = filt.getOrder(); 13 | float_type rlin = pow(ten, ripple/ten); 14 | float_type epi = sqrt(rlin - 1.0); 15 | //! wca - pre-warped angular frequency 16 | float_type wca = (filt.get_type()==filter_type::high) ? tan(M_PI * (0.5-fcd)) : tan(M_PI*fcd); 17 | chebyshev_s(filt, wca, epi, order); 18 | filt.bilinear(); 19 | if (filt.get_type()==filter_type::bandpass || filt.get_type()==filter_type::bandstop) { 20 | filt.make_band(filt.get_center()); 21 | } else { 22 | filt.convert_to_ab(); 23 | } 24 | if (filt.get_type()==filter_type::bandpass) filt.set_bandpass_gain(); 25 | // Must scale even order filter by this factor 26 | float_type gain = 1.0/sqrt(rlin); 27 | if (!filt.isOdd()) filt.apply_gain(gain); 28 | } 29 | //! Calculate poles (chebyshev) 30 | void chebyshev_s(iir_coeff& filt, float_type wp, float_type epi, size_t n) { 31 | auto l = 1; 32 | size_t n2 = (n + 1) / 2; 33 | float_type arg; 34 | float_type x = 1 / epi; 35 | float_type lambda = pow(x*(1.0 + sqrt(1.0 + epi*epi)),1.0/n); 36 | float_type sm = 0.5*((1.0/lambda) - lambda); 37 | float_type cm = 0.5*((1.0/lambda) + lambda); 38 | for (size_t j = 0; j < n2; j++) { 39 | arg = 0.5 * M_PI * (2*l-1) / ((float_type)(n)); 40 | if (filt.get_type()==filter_type::low) { 41 | filt.set_pole(-wp * std::complex(sm * sin(arg), cm * cos(arg)), n2-1-j); 42 | filt.set_zero(FLT_MAX, n2-1-j); 43 | } else { 44 | filt.set_pole(-1.0 / (wp * std::complex(sm * sin(arg), cm * cos(arg))), n2-1-j); 45 | filt.set_zero(0, n2-1-j); 46 | } 47 | l++; 48 | } 49 | } 50 | } // namespace spuce 51 | -------------------------------------------------------------------------------- /spuce/filters/chebyshev_iir.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief Calculate coefficients for IIR assuming chebyshev frequency response 7 | // 8 | //! \author Tony Kirke, Copyright(c) 2015 9 | //! \ingroup functions iir 10 | void chebyshev_iir(iir_coeff& cheb, float_type fcd, float_type ripple); 11 | void chebyshev_s(iir_coeff& filt, float_type wp, float_type epi, size_t n); 12 | } // namespace spuce 13 | -------------------------------------------------------------------------------- /spuce/filters/cic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | #include 5 | #include 6 | namespace spuce { 7 | //! \file 8 | //! \brief class for CIC digital filter 9 | //! Implementation for cascaded integrator comb filters 10 | //! This implementation provides for both decimation and 11 | //! interpolation filtering. Registers are signed long and 12 | //! the default number of stages is 3. 13 | //! \author Tony Kirke 14 | //! \ingroup templates fir interpolation 15 | //! \image html cic.gif 16 | //! \image latex cic.eps 17 | template class cic { 18 | protected: 19 | std::vector diff; //! Differentiators 20 | std::vector nacc; //! Accumulators 21 | std::vector prev; //! Previous values 22 | size_t stages; //! Number of stages 23 | public: 24 | //! Constructor 25 | cic(size_t n = 3) : diff(n), nacc(n), prev(n), stages(n) { 26 | assert(n < 1); 27 | for (size_t i = 0; i < stages; i++) nacc[i] = diff[i] = prev[i] = (Numeric)0; 28 | } 29 | //! Reset 30 | void reset() { 31 | for (size_t i = 0; i < stages; i++) nacc[i] = diff[i] = prev[i] = (Numeric)0; 32 | } 33 | //! To change the number of stages dynamically 34 | void num_stages(size_t n) { 35 | assert(n < 1); 36 | stages = n; 37 | nacc.resize(n); 38 | diff.resize(n); 39 | prev.resize(n); 40 | for (size_t i = 0; i < stages; i++) nacc[i] = diff[i] = prev[i] = (Numeric)0; 41 | } 42 | //! For CIC interpolation, non-zero dump implies new input 43 | Numeric interpolate(Numeric in = 0, bool dump = 0) { 44 | if (dump) { 45 | diff[0] = in - prev[0]; 46 | prev[0] = in; 47 | for (size_t i = 1; i < stages; i++) { 48 | diff[i] = diff[i - 1] - prev[i]; 49 | prev[i] = diff[i - 1]; 50 | } 51 | nacc[0] += diff[stages - 1]; 52 | } 53 | for (size_t i = 0; i < (stages - 1); i++) nacc[i + 1] += nacc[i]; 54 | return (nacc[stages - 1]); 55 | } 56 | //! For CIC decimation, non-zero dump implies output required 57 | Numeric decimate(Numeric in, bool dump) { 58 | nacc[0] += in; 59 | for (size_t i = 0; i < (stages - 1); i++) nacc[i + 1] += nacc[i]; 60 | if (dump) { 61 | diff[0] = nacc[stages - 1] - prev[0]; 62 | prev[0] = nacc[stages - 1]; 63 | for (size_t i = 1; i < stages; i++) { 64 | diff[i] = diff[i - 1] - prev[i]; 65 | prev[i] = diff[i - 1]; 66 | } 67 | } 68 | return (diff[stages - 1]); 69 | } 70 | }; 71 | } // namespace spuce 72 | -------------------------------------------------------------------------------- /spuce/filters/create_remez_fir.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 2 | //! \author Tony Kirke 3 | // from directory: src 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | namespace spuce { 10 | void create_remez_fir(fir_coeff& remezfir, int jtype, int nbands, std::vector& edge, 11 | std::vector& fx, std::vector& wtx) { 12 | bool ok; 13 | long nfilt = remezfir.number_of_taps(); 14 | remez_fir Remz; 15 | std::vector fir_coef(nfilt); 16 | ok = Remz.remez(fir_coef, nfilt, nbands, edge, fx, wtx, jtype); 17 | if (!ok) { 18 | for (int i = 0; i < nfilt; i++) remezfir.settap(i, 0); 19 | remezfir.settap(0, 1); 20 | } else { 21 | for (int i = 0; i < nfilt; i++) remezfir.settap(i, fir_coef[i]); 22 | } 23 | } 24 | } // namespace spuce 25 | -------------------------------------------------------------------------------- /spuce/filters/create_remez_lpfir.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 2 | //! \author Tony Kirke 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | namespace spuce { 9 | //! \brief calculates the coefficients for lowpass FIR based on Remez constraints 10 | void create_remez_lpfir(fir_coeff& remezfir, float_type pass_edge, float_type stop_edge, 11 | float_type stop_weight) { 12 | bool ok = true; 13 | std::vector e1(4); 14 | std::vector f1(4); 15 | std::vector w1(4); 16 | size_t nfilt = remezfir.number_of_taps(); 17 | remez_fir Remz; 18 | w1[0] = 1.0; 19 | w1[1] = stop_weight; 20 | e1[0] = 0; 21 | e1[1] = pass_edge / 2.0; 22 | e1[2] = stop_edge / 2.0; 23 | e1[3] = 0.5; 24 | f1[0] = 1.0; 25 | f1[1] = 0.0; 26 | std::vector fir_coef(nfilt); 27 | ok = Remz.remez(fir_coef, (int)nfilt, 2, e1, f1, w1, remez_type::BANDPASS); 28 | if (ok) { 29 | for (size_t i = 0; i < nfilt; i++) remezfir.settap(i, fir_coef[i]); 30 | } else { 31 | for (size_t i = 0; i < nfilt; i++) remezfir.settap(i, 0); 32 | remezfir.settap(0, 1); 33 | } 34 | } 35 | } // namespace spuce 36 | -------------------------------------------------------------------------------- /spuce/filters/create_remez_lpfir.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief Calculate coefficients for lowpass FIR assuming equiripple frequency response 7 | //! \author Tony Kirke, Copyright(c) 2001 8 | //! \ingroup functions fir 9 | void create_remez_lpfir(fir_coeff& remezfir, float_type edge, float_type fx, float_type wtx); 10 | } // namespace spuce 11 | -------------------------------------------------------------------------------- /spuce/filters/cutboost.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | #include 5 | namespace spuce { 6 | //! \file 7 | //! \brief IIR structure that can cut or boost signals at a programmed frequency 8 | //! This has independent controls for notch frequency and depth of notch 9 | //! \author Tony Kirke 10 | //! \image html cutboost.png 11 | //! \ingroup double_templates iir 12 | template class cutboost { 13 | public: 14 | allpass_2nd ap; 15 | float_type k; 16 | float_type g; 17 | float_type a; 18 | 19 | cutboost() : ap(0.1, -cos(2.0*M_PI * 0.2) * (1 + 0.1)) { 20 | a = 0.9; 21 | k = 1.0; 22 | g = 0.50; 23 | } 24 | cutboost(float_type fp, float_type k2, float_type k0) : ap(k2, -cos(2.0*M_PI * fp) * (1 + k2)) { 25 | a = k2; 26 | k = (1 - k0) / (1 + k0); 27 | g = 0.5 * (1 + k0); 28 | } 29 | cutboost(float_type fp, float_type k0) : ap(0.9, -cos(2.0*M_PI * fp) * (1 + 0.9)), k(1) { 30 | a = 0.9; 31 | k = (1 - k0) / (1 + k0); 32 | g = 0.5 * (1 + k0); 33 | } 34 | void reset() { ap.reset(); } 35 | Numeric clock(Numeric x) { 36 | Numeric sum = (Numeric)(g * (x + k * ap.clock(x))); 37 | return (sum); 38 | } 39 | void set_coeffs(float_type fp, float_type k2, float_type k0) { 40 | ap.set_coeffs(k2, -cos(2.0*M_PI * fp) * (1 + k2)); 41 | a = k2; 42 | k = (1 - k0) / (1 + k0); 43 | g = 0.5 * (1 + k0); 44 | } 45 | void set_depth(float_type k0) { 46 | k = (1 - k0) / (1 + k0); 47 | g = 0.5 * (1 + k0); 48 | } 49 | void set_freq(float_type fp) { ap.set_coeffs(a, -cos(2.0*M_PI * fp) * (1 + a)); } 50 | }; 51 | // template_instantiations: float_type 52 | } // namespace SPUC 53 | -------------------------------------------------------------------------------- /spuce/filters/decimator.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 2 | #pragma once 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace spuce { 10 | 11 | template class decimator { 12 | 13 | private: 14 | bool m_use_fir; 15 | int m_rate; 16 | int m_phase; 17 | spuce::fir_decim m_if_fir; 18 | spuce::iir_df m_if_iir; 19 | 20 | public: 21 | decimator() {;} 22 | decimator(unsigned int rate, int low_rate_multipliers, bool use_fir=true) { 23 | setup(rate,low_rate_multipliers, use_fir); 24 | } 25 | void setup(unsigned int rate, int low_rate_multipliers, bool use_fir=true) 26 | { 27 | m_use_fir = use_fir; 28 | m_rate = rate; 29 | m_phase = 0; 30 | auto taps = calculate_decimator_taps(m_rate,low_rate_multipliers,m_use_fir); 31 | if (m_use_fir) { 32 | m_if_fir.set_rate(m_rate); 33 | m_if_fir.set_taps(taps); 34 | } else { 35 | m_if_iir.set_taps(taps); 36 | } 37 | } 38 | 39 | void process(const std::vector& samples_in, 40 | std::vector& if_out) 41 | { 42 | if (m_use_fir) { 43 | m_if_fir.process(samples_in, if_out); 44 | } else { 45 | std::vector iir_out; 46 | if_out.resize((samples_in.size() - m_phase + m_rate - 1 )/ m_rate); 47 | m_if_iir.process(samples_in, iir_out); 48 | for (size_t i=0;i 4 | #include 5 | #include 6 | namespace spuce { 7 | //! \file 8 | //! \brief Design functions for fir filters 9 | //! \author Tony Kirke 10 | //! \ingroup functions fir 11 | std::vector design_fir(const std::string& fir_type, 12 | const std::string& band_type, 13 | int order, float_type fl, float_type fu, 14 | float_type alpha_beta_stop_edge=0.1, 15 | float_type weight=100.0); 16 | 17 | std::vector > design_complex_fir(const std::string& fir_type, 18 | const std::string& band_type, 19 | int order, float_type fl, float_type fu, 20 | float_type alpha_beta_stop_edge=0.1, 21 | float_type weight=100.0); 22 | 23 | } // namespace spuce 24 | -------------------------------------------------------------------------------- /spuce/filters/design_iir.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 2 | #define _USE_MATH_DEFINES 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | namespace spuce { 10 | //! \file 11 | //! \brief Design functions for iir filters 12 | //! \author Tony Kirke 13 | //! \ingroup functions iir 14 | iir_coeff* design_iir(const std::string& iir_type, const std::string& filt_type, 15 | int order, float_type fcd, 16 | float_type ripple, float_type stopattn, 17 | float_type center_freq) { 18 | iir_coeff* filt = new iir_coeff(order); 19 | if (filt_type == "LOW_PASS") { 20 | filt->set_type(filter_type::low); 21 | } else if (filt_type == "HIGH_PASS") { 22 | filt->set_type(filter_type::high); 23 | } else if (filt_type == "BAND_PASS") { 24 | filt->set_type(filter_type::bandpass); 25 | } else if (filt_type == "BAND_STOP") { 26 | filt->set_type(filter_type::bandstop); 27 | } else { 28 | std::cout << "Unsupported band type :" << filt_type << "\n"; 29 | } 30 | 31 | // Only used by bandpass/bandstop 32 | filt->set_center(center_freq); 33 | 34 | if (iir_type == "butterworth") { 35 | butterworth_iir(*filt, fcd, 3.0); 36 | } else if (iir_type == "chebyshev") { 37 | chebyshev_iir(*filt, fcd, ripple); 38 | } else if (iir_type == "chebyshev2") { 39 | chebyshev2_iir(*filt, fcd, stopattn); 40 | } else if (iir_type == "elliptic") { 41 | elliptic_iir(*filt, fcd, ripple, stopattn); 42 | } else { 43 | std::cout << "Unknown iir type\n"; 44 | } 45 | 46 | return filt; 47 | } 48 | } // namespace spuce 49 | -------------------------------------------------------------------------------- /spuce/filters/design_iir.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | #include 5 | #include 6 | namespace spuce { 7 | //! \file 8 | //! \brief Design functions for iir filters 9 | //! \author Tony Kirke 10 | //! \ingroup functions iir 11 | iir_coeff* design_iir(const std::string& iir_type, const std::string& filt_type, 12 | int order, float_type fcd, 13 | float_type ripple = 0.1, float_type stopattn = 60, 14 | float_type center_freq = 0.25); 15 | } // namespace spuce 16 | -------------------------------------------------------------------------------- /spuce/filters/design_window.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 2 | #define _USE_MATH_DEFINES 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief Design functions for window functions 7 | //! \author Tony Kirke 8 | //! \ingroup functions fir 9 | std::vector design_window(const std::string& fir_type, int order, float_type beta) { 10 | 11 | std::vector win; 12 | if (fir_type == "hamming") { 13 | win = hamming(order); 14 | } else if (fir_type == "hanning") { 15 | win = hanning(order); 16 | } else if (fir_type == "hann") { 17 | win = hann(order); 18 | } else if (fir_type == "blackman") { 19 | win = blackman(order); 20 | } else if (fir_type == "kaiser") { 21 | win = kaiser(order, beta); 22 | } else if (fir_type == "bartlett") { 23 | win = bartlett(order); 24 | } else if (fir_type == "chebyshev") { 25 | win = cheby(order, beta); 26 | } else if (fir_type == "flattop") { 27 | win = flattop(order); 28 | } else { 29 | win = rectangular(order); 30 | } 31 | 32 | return win; 33 | } 34 | } // namespace spuce 35 | -------------------------------------------------------------------------------- /spuce/filters/design_window.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief Design functions for window functions 7 | //! \author Tony Kirke 8 | //! \ingroup functions fir 9 | std::vector design_window(const std::string& fir_type, int order, float_type beta=4); 10 | } // namespace spuce 11 | -------------------------------------------------------------------------------- /spuce/filters/elliptic_allpass.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 2 | //! \author Tony Kirke 3 | #define _USE_MATH_DEFINES 4 | #include 5 | #include 6 | #include 7 | #define MINFP 0.005 8 | namespace spuce { 9 | //! creates arrays of coefficents to 2-branch IIR consisting of 1st order allpass filters for a given order L 10 | //! design criteria is elliptic shaping for maximal stopband attenuation 11 | //! fp controls the amount of attenuation 12 | void elliptic_allpass(std::vector& a0, std::vector& a1, float_type fp, int L) { 13 | int N = 2 * L + 1; 14 | int l; 15 | int i = 0; 16 | int j = 0; 17 | int odd; 18 | float_type lambda = 1.0; 19 | float_type d, sn, cn, dn, sn2, beta; 20 | float_type k, k2, zeta, zeta2; 21 | 22 | if (fp < MINFP) fp = MINFP; 23 | k = 2 * fp; 24 | zeta = 1.0 / k; 25 | zeta2 = zeta * zeta; 26 | ; 27 | k2 = k * k; 28 | 29 | odd = (L % 2); 30 | for (l = 1; l <= L; l++) { 31 | d = ellik(M_PI / 2.0, k); 32 | d = ((2.0 * l - 1.0) / N + 1.0) * d; 33 | ellpj(d, k2, sn, cn, dn); 34 | sn2 = sn * sn; 35 | beta = (zeta + sn2 - lambda * sqrt((1 - sn2) * (zeta2 - sn2))) / 36 | (zeta + sn2 + lambda * sqrt((1 - sn2) * (zeta2 - sn2))); 37 | if (l % 2 != odd) 38 | a1[i++] = beta; 39 | else 40 | a0[j++] = beta; 41 | } 42 | } 43 | } // namespace spuce 44 | -------------------------------------------------------------------------------- /spuce/filters/elliptic_allpass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | #include 5 | #include 6 | namespace spuce { 7 | //! \file 8 | //! \brief Calculate Allpass coefficients for halfband bireciprocal wave filter 9 | //! assuming elliptic frequency response 10 | //! \ingroup functions iir 11 | //! \author Tony Kirke, Copyright(c) 2015 12 | void elliptic_allpass(std::vector& a0, std::vector& a1, float_type fp, int L); 13 | 14 | } // namespace spuce 15 | -------------------------------------------------------------------------------- /spuce/filters/elliptic_iir.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief Calculate coefficients for IIR assuming elliptic frequency response 7 | // 8 | //! \author Tony Kirke, Copyright(c) 2001 9 | //! \ingroup functions iir 10 | void elliptic_iir(iir_coeff& filt, float_type fcd, float_type ripple, float_type stopattn); 11 | //! get roots in Lamda plane 12 | float_type lamda_plane(float_type m, int n, float_type eps); 13 | //! calculate s plane poles and zeros 14 | void s_plane(iir_coeff& filt, int n, float_type u, float_type m, float_type k, float_type Kk, float_type wc); 15 | float_type ellik(float_type phi, float_type k); 16 | float_type ellpk(float_type k); 17 | int ellpj(float_type u, float_type m, float_type& sn, float_type& cn, float_type& dn); 18 | float_type msqrt(float_type u); 19 | } // namespace spuce 20 | -------------------------------------------------------------------------------- /spuce/filters/farrow_upsampler.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 2 | //! \author Tony Kirke 3 | #include 4 | namespace spuce { 5 | farrow_upsampler::farrow_upsampler(int order) : INTERP(order) { time_offset = 0; } 6 | int farrow_upsampler::need_sample(float_type t_inc, float_type x) { 7 | if (time_offset + t_inc >= 1.0) { 8 | INTERP.input(x); 9 | return (1); 10 | } else { 11 | return (0); 12 | } 13 | } 14 | float_type farrow_upsampler::output(float_type t_inc) { 15 | time_offset += t_inc; 16 | if (time_offset >= 1.0) { time_offset -= 1.0; } 17 | return (INTERP.rephase(time_offset)); 18 | } 19 | } // namespace spuce 20 | -------------------------------------------------------------------------------- /spuce/filters/farrow_upsampler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief Upsampler/interpolator using farrow structure 7 | // 8 | //! Essentially a wrapper around farrow to allow one to 9 | //! upsample by specifing a fractional time increment 10 | //! input should always be available, need_sample returns 11 | //! 1 when the input needs to be update for next call 12 | //! \author Tony Kirke 13 | //! \ingroup classes examples interpolators 14 | class farrow_upsampler { 15 | public: 16 | float_type time_offset; 17 | farrow INTERP; 18 | 19 | int need_sample(float_type t_inc, float_type x); 20 | float_type output(float_type t_inc); 21 | farrow_upsampler(int order = 4); 22 | }; 23 | } // namespace spuce 24 | -------------------------------------------------------------------------------- /spuce/filters/find_roots.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | #include 5 | #include 6 | namespace spuce { 7 | //! \file 8 | //! \brief Calculate the std::complex roots of a polynomial equation 9 | // 10 | //! \author Tony Kirke 11 | //! \ingroup functions misc 12 | std::vector > find_roots(const std::vector& a, long n); 13 | } // namespace spuce 14 | -------------------------------------------------------------------------------- /spuce/filters/fir_adapt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | #include 5 | namespace spuce { 6 | //! \file 7 | //! \brief template class fir_adapt Based on FIR class, created to support LMS adaptive filtering 8 | //! \author Tony Kirke 9 | //! \ingroup double_utemplates equalizers fir 10 | //! \image html fir_adapt.gif 11 | //! \image latex fir_adapt.eps 12 | template class fir_adapt : public fir { 13 | public: 14 | typedef typename base_type::btype real_type; 15 | //! Adaptation gain 16 | real_type u; 17 | 18 | public: 19 | //! Constructor 20 | fir_adapt(void) : fir(), u(0) {} 21 | //! Constructor with size 22 | fir_adapt(long n, real_type gain) : fir(n), u(gain) {} 23 | //! Reset both history and coefficients! 24 | void reset() { 25 | fir::reset(); 26 | for (int i = 0; i < fir::num_taps; i++) fir::coeff[i] = (Coeff)0; 27 | } 28 | //! Set adaptation gain 29 | void set_gain(real_type gain) { u = gain; } 30 | //! Calculate updated taps using LMS algorithm 31 | void update_lms(Numeric err) { 32 | Numeric m = u * err; 33 | for (int i = 0; i < fir::num_taps; i++) 34 | fir::coeff[i] = fir::coeff[i] + m * signbit(conj(fir::z[i])); 35 | } 36 | //! Calculate updated taps using LMS algorithm and sign of input 37 | void update_lms_sign_coeff(Numeric err) { 38 | Numeric m = u * err; 39 | for (int i = 0; i < fir::num_taps; i++) 40 | fir::coeff[i] = fir::coeff[i] + m * signbit(conj(fir::z[i])); 41 | } 42 | }; 43 | } // namespace spuce 44 | -------------------------------------------------------------------------------- /spuce/filters/fir_coeff.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | #include 5 | #include 6 | namespace spuce { 7 | //! \file 8 | //! \brief Template Class for Modeling a Finite Impulse Response filter. 9 | // 10 | //! Template works for double, long, std::complex, etc 11 | //! Taps initialized to zeros. 12 | //! \author Tony Kirke 13 | //! \ingroup templates fir 14 | //! \image html fir.gif 15 | //! \image latex fir.eps 16 | template class fir_coeff { 17 | public: 18 | //! Set tap weights 19 | void settap(size_t i, Numeric tap) { coeff[i] = tap; } 20 | Numeric gettap(size_t i) { return (coeff[i]); } 21 | size_t number_of_taps() const { return (num_taps); } 22 | //! Get sum of coefficients 23 | Numeric coeff_sum() { 24 | Numeric s(0); 25 | for (size_t i = 0; i < num_taps; i++) s += coeff[i]; 26 | return (s); 27 | } 28 | //! Constructor 29 | ~fir_coeff(void) {} 30 | //! Constructor 31 | fir_coeff(void) { ; } 32 | //! Constructor 33 | fir_coeff(size_t n) : coeff(n), num_taps(n) { set_size(n); } 34 | //! Set size of Filter 35 | void set_size(size_t n) { 36 | num_taps = n; 37 | if (n > 0) { 38 | coeff.resize(n); 39 | for (size_t i = 0; i < n; i++) coeff[i] = (Numeric)0; 40 | } 41 | } 42 | size_t get_size(void) { return (num_taps); } 43 | //! Constructor that gets coefficients from file (requires fir_coeff.cpp) 44 | fir_coeff(const char* file) { read_taps(file); } 45 | int read_taps(const char* file) { return (0); } 46 | void make_hpf() { 47 | bool inv = true; 48 | for (size_t i = 0; i < num_taps; i++) { 49 | if (inv) coeff[i] *= -1; 50 | inv = !inv; 51 | } 52 | } 53 | void print(void) { 54 | std::cout << "coeff[] = "; 55 | for (size_t i = 0; i < num_taps; i++) std::cout << coeff[i] << ","; 56 | std::cout << "\n"; 57 | } 58 | template friend std::vector get_taps(fir_coeff x); 59 | void set_taps(const std::vector& taps) { 60 | for (size_t i = 0; i < num_taps; i++) coeff[i] = taps[i]; 61 | } 62 | // Get frequency response at freq 63 | float_type freqz_mag(float_type freq) { 64 | std::complex z(1, 0); 65 | std::complex z_inc = std::complex(cos(freq), sin(freq)); 66 | std::complex nom(0); 67 | for (size_t i = 0; i < num_taps; i++) { 68 | nom += z * (std::complex(coeff[i])); 69 | z *= z_inc; 70 | } 71 | return sqrt(std::norm(nom)); 72 | } 73 | 74 | private: 75 | std::vector coeff; 76 | size_t num_taps; 77 | }; 78 | 79 | template std::vector get_taps(fir_coeff f) { 80 | size_t N = f.num_taps; 81 | std::vector V(N); 82 | for (size_t i = 0; i < N; i++) V[i] = f.coeff[i]; 83 | return (V); 84 | } 85 | } // namespace spuce 86 | -------------------------------------------------------------------------------- /spuce/filters/fir_decim.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief template class for fir decimation based on FIR class 7 | //! created to support polyphase FIR decimation 8 | //! \author Tony Kirke 9 | //! \ingroup double_templates fir 10 | template class fir_decim : public fir { 11 | using spuce::fir::coeff; 12 | using spuce::fir::z; 13 | using spuce::fir::read_taps; 14 | using spuce::fir::number_of_taps; 15 | typedef typename base_type::btype Numeric_base; 16 | typedef typename mixed_type::dtype sum_type; 17 | int rate; 18 | int phase; 19 | 20 | public: 21 | //! Constructor 22 | fir_decim(void) {} 23 | fir_decim(long n) : fir(n) {} 24 | fir_decim(const char* file) { read_taps(file); } 25 | fir_decim(fir_coeff C) : fir(C) { 26 | size_t n = C.number_of_taps(); 27 | if (n > 0) { 28 | coeff.resize(n); 29 | z.resize(n); 30 | for (size_t i = 0; i < n; i++) z[i] = (Numeric)0; 31 | coeff = get_taps(C); 32 | } 33 | phase = 0; 34 | } 35 | fir_decim(const std::vector& C) : fir(C.size()) { 36 | size_t n = C.size(); 37 | if (n > 0) { 38 | coeff.resize(n); 39 | z.resize(n); 40 | for (size_t i = 0; i < n; i++) z[i] = (Numeric)0; 41 | for (size_t i = 0; i < n; i++) coeff[i] = C[i]; 42 | } 43 | } 44 | 45 | void skip() { 46 | phase++; 47 | phase = phase % rate; 48 | } 49 | //! Set interpolation rate 50 | void set_rate(long r) { 51 | rate = r; 52 | } 53 | void set_manual(int def_phase = 0) { 54 | phase = def_phase; 55 | } 56 | 57 | 58 | void input(Numeric in) { 59 | // Update history of inputs 60 | for (size_t i = number_of_taps() - 1; i > 0; i--) z[i] = z[i - 1]; 61 | // Add new input 62 | z[0] = in; 63 | } 64 | //! Phase increments when in automatic mode 65 | //! Otherwise phase does not change 66 | Numeric decim(void) { 67 | sum_type sum(0); 68 | // Perform FIR 69 | Numeric output; 70 | for (size_t i = 0; i < number_of_taps(); i++) sum += coeff[i] * z[i]; 71 | output = Numeric(sum); 72 | return (output); 73 | } 74 | void process(const std::vector& in, std::vector& out) { 75 | out.resize((in.size() - phase + rate - 1 )/ rate); 76 | size_t j = 0; 77 | for (size_t i = 0; i < in.size(); i++) { 78 | input(in[i]); 79 | phase = (phase + 1) % rate; 80 | if (phase == 0) { 81 | out[j++] = decim(); 82 | } 83 | } 84 | } 85 | }; 86 | } // namespace spuce 87 | -------------------------------------------------------------------------------- /spuce/filters/fir_interp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief template class fir_decim based on FIR class 7 | //! created to support polyphase FIR interpolation 8 | //! \author Tony Kirke 9 | //! \ingroup double_templates fir interpolation 10 | template class fir_interp : public fir { 11 | using fir::num_taps; 12 | using fir::coeff; 13 | using fir::z; 14 | using fir::read_taps; 15 | typedef typename base_type::btype Numeric_base; 16 | typedef typename mixed_type::dtype sum_type; 17 | 18 | public: 19 | long num_low; 20 | long rate; //! upsampling rate 21 | long phase; //! current polyphase phase 22 | long auto_mode; //! if set, automaticaly increment phase 23 | 24 | public: 25 | //! Skip output sample but increment phase 26 | void skip() { 27 | phase++; 28 | phase = phase % rate; 29 | } 30 | //! Set interpolation rate 31 | void set_rate(long r) { 32 | rate = r; 33 | num_low = (num_taps / r); 34 | } 35 | void set_automatic(void) { auto_mode = 1; } 36 | void set_manual(int def_phase = 0) { 37 | auto_mode = 0; 38 | phase = def_phase; 39 | } 40 | 41 | //! Constructor 42 | fir_interp(const char* i) : fir(i), phase(0), auto_mode(1) {} 43 | fir_interp(void) : phase(0), auto_mode(1) {} 44 | fir_interp(long n) : fir(n), phase(0), auto_mode(1) {} 45 | void reset() { 46 | fir::reset(); 47 | phase = 0; 48 | } 49 | Coeff coeff_sum() { return (fir::coeff_sum()); } 50 | void input(Numeric in) { 51 | int i; 52 | // Update history of inputs 53 | for (i = num_low; i > 0; i--) z[i] = z[i - 1]; 54 | // Add new input 55 | z[0] = in; 56 | } 57 | //! Explicitly set the phase 58 | Numeric clock(long set_phase) { 59 | phase = set_phase; 60 | return (clock()); 61 | } 62 | //! Phase increments when in automatic mode 63 | //! Otherwise phase does not change 64 | Numeric clock(void) { 65 | // Perform FIR 66 | Numeric output; 67 | int i; 68 | sum_type sum(0); 69 | for (i = 0; i < num_low; i++) sum = sum + coeff[i * rate + phase] * z[i]; 70 | 71 | output = (sum); 72 | // Increment to next polyphase filter 73 | if (auto_mode) phase++; 74 | phase = phase % rate; 75 | return (output); 76 | } 77 | }; 78 | } // namespace spuce 79 | -------------------------------------------------------------------------------- /spuce/filters/fir_inv_dft.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 2 | //! \author Tony Kirke 3 | #define _USE_MATH_DEFINES 4 | #include 5 | #include 6 | namespace spuce { 7 | //! \file 8 | //! \brief calculates fir filter coefficients based on frequency sampling design using IDFT 9 | std::vector inv_dft_symmetric(const std::vector& A, int N) { 10 | std::vector h(N); 11 | float_type x, val; 12 | float_type M = (N - 1.0) / 2.0; 13 | int END = (N % 2 != 0) ? (int)M : (N / 2 - 1); 14 | for (int n = 0; n < N; n++) { 15 | val = A[0]; 16 | x = 2.0*M_PI * (n - M) / N; 17 | for (int k = 1; k <= END; k++) val += 2.0 * A[k] * cos(x * k); 18 | h[n] = val / N; 19 | } 20 | return h; 21 | } 22 | //! \brief calculates fir filter coefficients based on frequency sampling design using IDFT 23 | std::vector inv_dft(const std::vector& A, int N) { 24 | std::vector h(N); 25 | float_type x, val; 26 | float_type M = (N - 1.0) / 2.0; 27 | int END = (N % 2 != 0) ? (int)M : (N / 2 - 1); 28 | for (int n = 0; n < N; n++) { 29 | val = (N % 2 != 0) ? 0 : A[N / 2] * sin(M_PI * (n - M)); 30 | x = 2.0*M_PI * (n - M) / N; 31 | for (int k = 1; k <= END; k++) val += 2.0 * A[k] * sin(x * k); 32 | h[n] = val / N; 33 | } 34 | return h; 35 | } 36 | } // namespace spuce 37 | -------------------------------------------------------------------------------- /spuce/filters/fir_inv_dft.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief Calculate coefficients for FIR using frequency sampling IDFT 7 | //! \author Tony Kirke 8 | //! \ingroup functions fir 9 | std::vector inv_dft_symmetric(const std::vector& A, int N); 10 | std::vector inv_dft(const std::vector& A, int N); 11 | } // namespace spuce 12 | -------------------------------------------------------------------------------- /spuce/filters/gaussian_fir.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 2 | //! \author Tony Kirke 3 | #define _USE_MATH_DEFINES 4 | #include 5 | #include 6 | #include 7 | #include 8 | namespace spuce { 9 | //! \file 10 | //! \brief calculates the sampled Gaussian filter impulse response 11 | void gaussian_fir(fir_coeff& gaussf, float_type bt) { 12 | // generate the sampled Gaussian filter impulse response 13 | // and transfer coefficients to "gaussf". 14 | // spb = samples per bit (at full rate) 15 | // BT = filter bandwidth 16 | float_type s, t0, ts, gsum; 17 | size_t nir = gaussf.number_of_taps(); 18 | float_type* gf = new float_type[nir]; 19 | s = 1.0 / (sqrt(log(2.0)) / (2.0 * M_PI * bt)); 20 | t0 = -0.5 * nir; 21 | gsum = 0.0; // std::normalize to unit sum 22 | for (size_t i = 0; i < nir; i++) { 23 | t0++; 24 | ts = s * t0; 25 | gf[i] = ::exp(-0.5 * ts * ts); 26 | gsum += gf[i]; 27 | } 28 | // Unity DC gain 29 | gsum = 1.0 / gsum; 30 | for (size_t i = 0; i < nir; i++) gaussf.settap(i,gf[i] * gsum); 31 | } 32 | } // namespace spuce 33 | -------------------------------------------------------------------------------- /spuce/filters/gaussian_fir.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief Calculate coefficients for FIR assuming gaussian frequency response 7 | //! \author Tony Kirke, Copyright(c) 2001 8 | //! \ingroup functions fir 9 | void gaussian_fir(fir_coeff& gaussf, float_type bt); 10 | } // namespace spuce 11 | -------------------------------------------------------------------------------- /spuce/filters/iir_1st.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | #include 5 | #include 6 | #include 7 | namespace spuce { 8 | //! \file 9 | //! \brief Template Class for 1st Order iir filter 10 | //! The filter is the first order low pass digital filter given by 11 | //! \f$ G(z) = \frac{1+z^-1}{1-az^-1} \f$

where a is real and |a| < 1 12 | //! \author Tony Kirke 13 | //! \ingroup double_templates iir 14 | template class iir_1st { 15 | protected: 16 | Coeff a; 17 | Coeff b; 18 | Numeric out; 19 | Numeric previous_out; 20 | Numeric previous_in; 21 | 22 | public: 23 | iir_1st(Coeff A = 0, Coeff B = 0) : a(A), b(B) { previous_in = previous_out = out = (Numeric)0; } 24 | void set_coeffs(Coeff A, Coeff B) { 25 | a = A; 26 | b = B; 27 | } 28 | //! Print out coefficients 29 | void print() { std::cout << "IIR Coefficient gains = " << a << " " << b << "\n"; } 30 | //! Input new sample and calculate output 31 | Numeric clock(Numeric input) { 32 | typename mixed_type::dtype sum; 33 | // Shift previous outputs and calculate new output 34 | sum = (b * previous_in + input - a * previous_out); 35 | out = sum; 36 | previous_out = out; 37 | previous_in = input; 38 | return (out); 39 | } 40 | //! Reset 41 | void reset() { previous_in = previous_out = out = (Numeric)0; } 42 | }; 43 | } // namespace spuce 44 | -------------------------------------------------------------------------------- /spuce/filters/iir_coeff.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | #include 5 | namespace spuce { 6 | //! \file 7 | //! \brief Class for iir filter design 8 | //! \author Tony Kirke 9 | //! \ingroup classes iir 10 | 11 | // Only low and high are implemented so far 12 | enum class filter_type {low,high,bandpass,bandstop}; 13 | 14 | class iir_coeff { 15 | public: 16 | //! ord = Filter order 17 | iir_coeff(size_t ord = 1, filter_type lp = filter_type::low); 18 | void resize(size_t ord); 19 | //! Destructor 20 | ~iir_coeff(); 21 | //! Do bilinear transformation 22 | void bilinear(); 23 | void make_band(float_type center); 24 | void convert_to_ab(); 25 | void z_root_to_ab(std::vector >& z); 26 | void pz_to_ap(); 27 | void ab_to_tf(); 28 | std::vector p2_to_poly(const std::vector >& ab); 29 | std::vector pz_to_poly(const std::vector >& z); 30 | void set_zero(const std::complex& z, size_t i) { zeros[i] = z; } 31 | void set_pole(const std::complex& z, size_t i) { poles[i] = z; } 32 | std::complex get_zero(size_t i); 33 | std::complex get_pole(size_t i); 34 | float_type get_a(size_t i) const; 35 | float_type get_b(size_t i) const; 36 | float_type get_coeff_a(size_t i) const; 37 | float_type get_coeff_b(size_t i) const; 38 | float_type max_abs_coeff(); 39 | void apply_gain(float_type g); 40 | float_type freqz_mag(float_type freq); 41 | float_type getGain(void) const; 42 | size_t getOrder(void) const; 43 | size_t getN2(void) const; 44 | bool calculate_biquad_coefficents(); 45 | size_t isOdd(void) const; 46 | std::vector get_a() const; 47 | std::vector get_b() const; 48 | filter_type get_type(void) const { return lpf; } 49 | void set_type(filter_type t) { lpf = t; } 50 | void set_center(float_type c) { center_freq = c; c0 = cos(2*M_PI*c); } 51 | void set_bandpass_gain(); 52 | float_type get_center() { return center_freq;} 53 | void print() const; 54 | void print_pz() const; 55 | 56 | private: 57 | enum class filter_state {start,z_domain,z_domain_ab,z_domain_allpass}; 58 | std::vector > poles; 59 | std::vector > zeros; 60 | float_type gain; 61 | float_type c0; 62 | float_type center_freq; 63 | float_type hpf_gain; 64 | size_t n2; 65 | size_t odd; 66 | size_t order; 67 | filter_state state; 68 | //long tf_state; 69 | //long ap_state; 70 | std::vector a_tf; 71 | std::vector b_tf; 72 | filter_type lpf; 73 | }; 74 | // template_instantiations: float_type, std::complex 75 | } // namespace spuce 76 | -------------------------------------------------------------------------------- /spuce/filters/iir_comb.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | #include 5 | #include 6 | namespace spuce { 7 | //! \file 8 | //! \brief Template for IIR comb type filter with programmable delay and gain 9 | //! \author Tony Kirke 10 | //! \ingroup double_templates iir 11 | template class iir_comb { 12 | protected: 13 | Coeff acc_gain; 14 | Coeff in_gain; 15 | Numeric out; 16 | delay dly; 17 | long delay_size; 18 | Numeric previous_out; 19 | Numeric previous_in; 20 | 21 | public: 22 | iir_comb(Coeff A = 0, long delay = 2) : acc_gain(A), in_gain(1 - A), delay_size(delay) { 23 | dly.set_size(delay); 24 | previous_in = previous_out = out = (Numeric)0; 25 | } 26 | void init(Coeff A, long delay) { 27 | in_gain = 1 - A; 28 | acc_gain = A; 29 | delay_size = delay; 30 | dly.set_size(delay); 31 | } 32 | 33 | void set_coeff(Coeff A) { 34 | in_gain = 1 - A; 35 | acc_gain = A; 36 | } 37 | //! Input new sample and calculate output 38 | Numeric clock(Numeric input) { 39 | typename mixed_type::dtype sum; 40 | // Shift previous outputs and calculate new output 41 | sum = acc_gain * previous_out + in_gain * input; 42 | out = (sum); 43 | previous_out = dly.input(out); 44 | return (out); 45 | } 46 | //! Reset 47 | void reset() { 48 | previous_in = previous_out = out = (Numeric)0; 49 | dly.reset(); 50 | } 51 | }; 52 | } // namespace spuce 53 | -------------------------------------------------------------------------------- /spuce/filters/iir_df.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | #include 5 | namespace spuce { 6 | //! \file 7 | //! \brief Template Class for Modeling a Direct Form IIR 8 | // 9 | //! Template works for float_type, long, std::complex, etc 10 | //! Implemented as cascade of FIR part followed by IIR part 11 | //! IIR function implemented with FIR class using special iir function 12 | //! \author Tony Kirke 13 | //! \ingroup double_templates iir 14 | template class iir_df { 15 | public: 16 | // iir_df() { ; } 17 | iir_df(const size_t order=1) : poles(order), zeros(order + 1) { 18 | for (size_t i = 0; i < order + 1; i++) zeros.settap(i,1.0); 19 | for (size_t i = 0; i < order; i++) poles.settap(i,0.0); 20 | } 21 | 22 | iir_df(const iir_df& cp) : poles(a_size()), zeros(b_size()) { 23 | for (size_t i = 0; i < a_size(); i++) poles.settap(i, cp.poles.get_coeff(i)); 24 | for (size_t i = 0; i < b_size(); i++) zeros.settap(i, cp.zeros.get_coeff(i)); 25 | } 26 | 27 | iir_df(const iir_coeff& filt) : poles(filt.getOrder()), zeros(filt.getOrder() + 1) { 28 | // Apply gain to feedforward taps to normalize 29 | for (size_t i = 0; i < filt.getOrder() + 1; i++) zeros.settap(i, filt.get_b(i)); 30 | // For feedback, skip a[0] which is 1 and used negative of remaining coefficients 31 | // for `iir` part 32 | for (size_t i = 0; i < filt.getOrder(); i++) poles.settap(i, -filt.get_a(i + 1)); 33 | } 34 | ~iir_df(void) {} 35 | //! Reset 36 | void reset() { 37 | poles.reset(); 38 | zeros.reset(); 39 | } 40 | void set_taps(const std::vector& taps) { 41 | // Divide vector in half, 1st half are feedforward, 2nd half feedback 42 | assert(taps.size() != 0); 43 | auto size = taps.size()/2; 44 | zeros.set_size(size); 45 | poles.set_size(size-1); 46 | for (size_t i = 0; i < size; i++) { zeros.settap(i, taps[i]); } 47 | // Skip 1st feedback and negate the rest 48 | for (size_t i = 0; i < size-1; i++) { poles.settap(i, -taps[i+size+1]); } 49 | } 50 | size_t order(void) { return zeros.number_of_taps(); } 51 | Numeric clock(Numeric in) { return (update(in)); } 52 | Numeric update(Numeric in) { 53 | Numeric output = zeros.update(in); 54 | output = poles.iir(output); 55 | return (output); 56 | } 57 | void process(const std::vector& samples_in, 58 | std::vector& if_out) 59 | { 60 | if_out.resize(samples_in.size()); 61 | for (size_t i=0;i poles; 76 | fir zeros; 77 | }; 78 | } // namespace spuce 79 | -------------------------------------------------------------------------------- /spuce/filters/iir_shelf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | #include 5 | #include 6 | #include 7 | namespace spuce { 8 | //! \file 9 | //! \brief Template Class for shelf filter 10 | //! Template for shelving filter 11 | //!

The filter is assumed of the form 12 | //! \f$ H(s) = \frac{s+A}{s+B} \f$ 13 | //! which becomes 14 | //! \f$ H(z) = \frac{(A+1)+(A-1)*z^-1}{(B+1)+(B-1)*z^-1} \f$ 15 | //! \author Tony Kirke 16 | //! \ingroup double_templates iir 17 | template class iir_shelf { 18 | protected: 19 | Coeff b; 20 | Coeff a0; 21 | Coeff a1; 22 | Numeric out; 23 | Numeric previous_out; 24 | Numeric previous_in; 25 | 26 | public: 27 | // Constructor specifying coefficients 28 | iir_shelf(Coeff A0, Coeff A1, Coeff B) : b(B), a0(A0), a1(A1) { reset(); } 29 | // Constructor specifying lower & upper frequencies rather than coefficients 30 | iir_shelf(float_type ca, float_type cb) 31 | : b((1.0 - cb) / (1.0 + cb)), a0((ca + 1.0) / (cb + 1.0)), a1((1.0 - ca) / (1.0 + b)) { 32 | reset(); 33 | } 34 | void set(float_type ca, float_type cb) { 35 | a0 = ((ca + 1.0) / (cb + 1.0)); 36 | a1 = ((1.0 - ca) / (1.0 + b)); 37 | b = ((1.0 - cb) / (1.0 + cb)); 38 | reset(); 39 | } 40 | Coeff get_a0() { return (a0); } 41 | Coeff get_a1() { return (a1); } 42 | Coeff get_b() { return (b); } 43 | //! Input new sample and calculate output 44 | Numeric clock(Numeric input) { 45 | typename mixed_type::dtype sum; 46 | // Shift previous outputs and calculate new output */ 47 | sum = b * previous_out + a0 * input - a1 * previous_in; 48 | out = (sum); 49 | previous_out = out; 50 | previous_in = input; 51 | return (out); 52 | } 53 | //! Reset 54 | void reset() { previous_in = previous_out = out = (Numeric)0; } 55 | }; 56 | } // namespace spuce 57 | -------------------------------------------------------------------------------- /spuce/filters/notch_allpass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #define _USE_MATH_DEFINES 3 | #include 4 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 5 | #include 6 | namespace spuce { 7 | //! \file 8 | //! \brief IIR notch filter based on 2nd order allpass structure 9 | //! \author Tony Kirke 10 | //! \ingroup double_templates iir 11 | template class notch_allpass { 12 | public: 13 | allpass_2nd ap; 14 | 15 | notch_allpass(float_type fp, float_type k2) : ap(k2, -cos(2.0*M_PI * fp) * (1 + k2)) {} 16 | notch_allpass(float_type fp) : ap(0.9, -cos(2.0*M_PI * fp) * (1 + 0.9)) {} 17 | notch_allpass() : ap(0.9, -cos(2.0*M_PI * 0.2) * (1 + 0.9)) {} 18 | void set_coeffs(float_type fp, float_type k2) { ap.set_coeffs(k2, -cos(2.0*M_PI * fp) * (1 + k2)); } 19 | 20 | void reset() { ap.reset(); } 21 | Numeric clock(Numeric x) { 22 | Numeric sum = 0.5 * (x + ap.clock(x)); 23 | return (sum); 24 | } 25 | }; 26 | } // namespace spuce 27 | -------------------------------------------------------------------------------- /spuce/filters/notch_comb.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \author Tony Kirke 7 | //! \ingroup double_templates double_templates iir 8 | template class notch_comb { 9 | public: 10 | allpass_1 ap; 11 | 12 | notch_comb(float_type fp, int dly) : ap(fp, dly) {} 13 | notch_comb(float_type fp) : ap(fp, 1) {} 14 | notch_comb() : ap(0.5, 1) {} 15 | void set_coeffs(float_type fp, int dly) { ap.init(fp, dly); } 16 | 17 | void reset() { ap.reset(); } 18 | Numeric clock(Numeric x) { 19 | Numeric sum = 0.5 * (x + ap.clock(x)); 20 | return (sum); 21 | } 22 | }; 23 | 24 | } // namespace spuce 25 | -------------------------------------------------------------------------------- /spuce/filters/notch_iir.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief IIR notch filter based on 2nd order biquad 7 | //! Independent frequency and depth control 8 | //! \author Tony Kirke 9 | //! \ingroup double_templates iir 10 | template class notch_iir { 11 | public: 12 | biquad filter; 13 | Coeff gain; 14 | 15 | notch_iir(Coeff B, Coeff Y) : filter(1, Y * (1 + B), B, 2 * Y, 1) { gain = (1 + B) * (Coeff)(0.5); } 16 | void set_coeffs(Coeff B, Coeff Y) { 17 | filter.set_coeffs(1, Y * (1 + B), B, 2 * Y, 1); 18 | gain = (1 + B) * (Coeff)(0.5); 19 | } 20 | void set_freq(Coeff B) { 21 | Coeff Y = 0.5 * filter.get_a1(); 22 | filter.set_coeffs(1, Y * (1 + B), B, 2 * Y, 1); 23 | gain = (1 + B) * (Coeff)(0.5); 24 | } 25 | void set_depth(Coeff Y) { 26 | Coeff B = 0.5 * filter.get_b2(); 27 | filter.set_coeffs(1, Y * (1 + B), B, 2 * Y, 1); 28 | gain = (1 + B) * (Coeff)(0.5); 29 | } 30 | 31 | // force gain*x to be Numeric? 32 | Numeric clock(Numeric x) { return (filter.clock(Numeric(gain * x))); } 33 | }; 34 | } // namespace spuce 35 | -------------------------------------------------------------------------------- /spuce/filters/raised_cosine.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | #include 5 | #include 6 | namespace spuce { 7 | //! \file 8 | //! \brief Raised Cosine functions 9 | //! \author Tony Kirke 10 | //! \ingroup template_functions comm 11 | template void raised_cosine(fir_coeff& rcfir, float_type alpha, float_type rate) { 12 | size_t num_taps = rcfir.number_of_taps(); 13 | float_type sum = 0; 14 | for (size_t i = 0; i < num_taps; i++) { 15 | sum += (float_type)raised_cosine_imp(alpha, float_type(i), rate, num_taps); 16 | } 17 | // Normalize impulse response 18 | for (size_t i = 0; i < num_taps; i++) { 19 | rcfir.settap(i,(T)((1.0/sum)*raised_cosine_imp(alpha, float_type(i), rate, num_taps))); 20 | } 21 | } 22 | 23 | } // namespace spuce 24 | -------------------------------------------------------------------------------- /spuce/filters/raised_cosine_imp.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 2 | //! \author Tony Kirke 3 | #define _USE_MATH_DEFINES 4 | #include 5 | #include 6 | #include 7 | namespace spuce { 8 | float_type raised_cosine_imp(float_type alpha, float_type xin, float_type r, size_t num_taps) 9 | //------------------------------------------------------------------------------------------------ 10 | // Calculates the raised cosine pulse shape given the excess bandwidth value alpha and the index. 11 | //------------------------------------------------------------------------------------------------ 12 | { 13 | float_type x1, x2, rc1; 14 | float_type rate = 0.5*r; 15 | float_type xindx = xin - num_taps / 2; 16 | x1 = M_PI * xindx / rate; 17 | x2 = 1 - (4 * alpha * alpha * (xindx / rate) * (xindx / rate)); 18 | if (x1 == 0) return (1); 19 | if (x2 == 0) { 20 | x2 = 8 * alpha * (xindx / rate) * (xindx / rate); 21 | rc1 = sin(x1) * sin(alpha * x1) / x2; 22 | } else { 23 | rc1 = (sin(x1) * cos(alpha * x1)) / (x1 * x2); 24 | } 25 | return (rc1); 26 | } 27 | } // namespace spuce 28 | -------------------------------------------------------------------------------- /spuce/filters/raised_cosine_imp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | // from directory: functions 4 | 5 | #include 6 | namespace spuce { 7 | float_type raised_cosine_imp(float_type alpha, float_type xin, float_type rate, size_t num_taps); 8 | 9 | } // namespace spuce 10 | -------------------------------------------------------------------------------- /spuce/filters/remez_estimate.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 2 | //! \author Tony Kirke 3 | #include 4 | #include 5 | namespace spuce { 6 | 7 | float_type remez_estimate_atten(size_t num_taps, float_type trans_bw, float_type ripple); 8 | float_type remez_estimate_bw(size_t num_taps, float_type ripple, float_type atten); 9 | float_type remez_estimate_weight(float_type pass_ripple_db, float_type stop_atten_db); 10 | /* Estimate the number of taps for a Remez FIR for the input params */ 11 | size_t remez_estimate_num_taps(float_type trans_bw, float_type ripple, float_type atten); 12 | 13 | } // namespace spuce 14 | -------------------------------------------------------------------------------- /spuce/filters/remez_fir.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | #include 5 | #include 6 | namespace spuce { 7 | 8 | enum class remez_type {BANDPASS,DIFFERENTIATOR,HILBERT}; 9 | enum class remez_symmetry {POSITIVE,NEGATIVE}; 10 | //!------------------------------------------------- 11 | //! \file 12 | //! \brief template Remez_fir class 13 | // 14 | //!

Calculates the optimal (in the Chebyshev/minimax sense) 15 | //! FIR filter impulse response given a set of band edges, 16 | //! the desired reponse on those bands, and the weight given to 17 | //! the error in those bands. 18 | //! 19 | //!

Inputs: 20 | //!

int numtaps - Number of filter coefficients

21 | //!

int numband - Number of bands in filter specification 22 | //!

float_type[] bands - User-specified band edges [2 * numband] 23 | //!

float_type[] des - User-specified band responses [numband] 24 | //!

float_type[] weight - User-specified error weights [numband] 25 | //!

int type - Type of filter 26 | //! 27 | //!

Output: 28 | //!

float_type[] h - Impulse response of final filter [numtaps] 29 | //! 30 | //! \author Tony Kirke 31 | //! \ingroup classes fir 32 | class remez_fir { 33 | public: 34 | remez_fir() {} 35 | 36 | private: 37 | static void createDenseGrid(int r, int numtaps, int numband, std::vector& bands, 38 | const std::vector& des, const std::vector& weight, int gridSize, 39 | std::vector& grid, std::vector& d, std::vector& w, 40 | remez_symmetry symmetry); 41 | 42 | static std::vector calc_d(int r, const std::vector& x); 43 | static std::vector calc_y(int r, const std::vector& ext, const std::vector& des, 44 | const std::vector& w, const std::vector& d); 45 | static float_type gee(float_type freq, int r, const std::vector& ad, const std::vector& x, 46 | const std::vector& y); 47 | static void search(int r, std::vector& ext, int gridSize, const std::vector& e); 48 | static bool isDone(int r, const std::vector& ext, const std::vector& e); 49 | 50 | public: 51 | static bool remez(std::vector& filt, int n, int numband, std::vector& bands, 52 | const std::vector& des, const std::vector& weight, remez_type type); 53 | }; 54 | } // namespace spuce 55 | -------------------------------------------------------------------------------- /spuce/filters/root_raised_cosine.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | #include 5 | namespace spuce { 6 | //! \file 7 | //! \brief Root Raised Cosine functions 8 | //! \author Tony Kirke 9 | //! \ingroup template_functions comm 10 | template 11 | void root_raised_cosine_quantized(fir_coeff& rcfir, float_type alpha, int rate, int bits, float_type scale); 12 | template void root_raised_cosine(fir_coeff& rcfir, float_type alpha, float_type rate) { 13 | size_t num_taps = rcfir.number_of_taps(); 14 | float_type gain = 1.0 / rate; 15 | float_type sum = 0; 16 | for (size_t i = 0; i < num_taps; i++) { 17 | sum += (T)(gain * root_raised_cosine_imp(alpha, float_type(i), rate, num_taps)); 18 | } 19 | gain /= sum; 20 | for (size_t i = 0; i < num_taps; i++) { 21 | rcfir.settap(i,(T)(gain * root_raised_cosine_imp(alpha, float_type(i), rate, num_taps))); 22 | } 23 | } 24 | } // namespace spuce 25 | -------------------------------------------------------------------------------- /spuce/filters/root_raised_cosine_imp.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 2 | //! \author Tony Kirke 3 | #define _USE_MATH_DEFINES 4 | #include 5 | #include 6 | #include 7 | namespace spuce { 8 | float_type root_raised_cosine_imp(float_type alpha, float_type xin, float_type r, size_t num_taps) 9 | //---------------------------------------------------------------------------------------------------- 10 | // Calculates the square root raised cosine pulse shape given the bandwidth value alpha and the index. 11 | //---------------------------------------------------------------------------------------------------- 12 | { 13 | float_type x1, x2, x3; 14 | float_type nom, denom; 15 | float_type rate = 0.5*r; 16 | float_type xindx = xin - num_taps / 2; 17 | x1 = M_PI * xindx / rate; 18 | x2 = 4 * alpha * xindx / rate; 19 | x3 = x2 * x2 - 1; 20 | if (x3 != 0) { 21 | if (x1 != 0) { 22 | nom = cos((1 + alpha) * x1); 23 | nom += sin((1 - alpha) * x1) / (4 * alpha * xindx / rate); 24 | } else { 25 | nom = cos((1 + alpha) * x1); 26 | nom += (1 - alpha) * M_PI / (4 * alpha); 27 | } 28 | denom = x3 * M_PI; 29 | } else { 30 | if (alpha == 1) return (-1); 31 | x3 = (1 - alpha) * x1; 32 | x2 = (1 + alpha) * x1; 33 | nom = sin(x2) * (1 + alpha) * M_PI - cos(x3) * ((1 - alpha) * M_PI * rate) / (4 * alpha * xindx) + 34 | sin(x3) * rate * rate / (4 * alpha * xindx * xindx); 35 | denom = -32 * M_PI * alpha * alpha * xindx / rate; 36 | } 37 | return (4 * alpha * nom / denom); 38 | } 39 | 40 | } // namespace spuce 41 | -------------------------------------------------------------------------------- /spuce/filters/root_raised_cosine_imp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | // from directory: functions 4 | 5 | #include 6 | namespace spuce { 7 | float_type root_raised_cosine_imp(float_type alpha, float_type xin, float_type rate, size_t num_taps); 8 | } // namespace spuce 9 | -------------------------------------------------------------------------------- /spuce/filters/running_average.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief template class running average filter consisting of a delay line, adder and subtractor 7 | // 8 | //! \ingroup templates templates fir 9 | //! \image html running_average.png 10 | //! \image html running_average.gif 11 | //! \image latex running_average.eps 12 | //! \author Tony Kirke 13 | template class running_average { 14 | protected: 15 | Numeric result; 16 | delay z; 17 | long size; 18 | float_type inv_size; 19 | 20 | public: 21 | //!/ Constructor 22 | running_average(long n = 0) : z() { 23 | size = n; 24 | inv_size = 1.0 / (float_type)size; 25 | if (n > 1) { 26 | z.set_size(n - 1); 27 | z.reset(); 28 | } 29 | result = (Numeric)0; 30 | } 31 | //! Assignment 32 | running_average& operator=(const running_average& rhs) { 33 | z = rhs.z; 34 | result = rhs.result; 35 | return (*this); 36 | } 37 | //! 38 | void set_size(long n) { 39 | z.set_size(n - 1); 40 | result = (Numeric)0; 41 | size = n; 42 | inv_size = 1.0 / (float_type)size; 43 | } 44 | //! destructor 45 | ~running_average(void) {} 46 | //! Reset/clear 47 | void reset(void) { 48 | z.reset(); 49 | result = (Numeric)0; 50 | } 51 | Numeric update(Numeric in) { 52 | result -= z.last(); 53 | z.input(in); 54 | result += in; 55 | return (((Numeric)inv_size * update(in))); 56 | } 57 | }; 58 | } // namespace spuce 59 | -------------------------------------------------------------------------------- /spuce/filters/running_sum.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | namespace spuce { 5 | //! \file 6 | //! \brief template class running average filter consisting of a delay line, adder and subtractor 7 | //! \author Tony Kirke 8 | //! \ingroup templates fir 9 | //! \image html running_sum.gif 10 | //! \image latex running_sum.eps 11 | template class running_sum { 12 | protected: 13 | Numeric result; 14 | delay z; 15 | long size; 16 | float_type inv_size; 17 | 18 | public: 19 | //!/ Constructor 20 | running_sum(long n = 0) : z() { 21 | size = n; 22 | inv_size = 1.0 / (float_type)size; 23 | if (n > 1) { 24 | z.set_size(n - 1); 25 | z.reset(); 26 | } 27 | result = (Numeric)0; 28 | } 29 | //! Assignment 30 | running_sum& operator=(const running_sum& rhs) { 31 | z = rhs.z; 32 | result = rhs.result; 33 | return (*this); 34 | } 35 | //! 36 | void set_size(long n) { 37 | z.set_size(n - 1); 38 | result = (Numeric)0; 39 | size = n; 40 | inv_size = 1.0 / (float_type)size; 41 | } 42 | //! destructor 43 | ~running_sum(void) {} 44 | //! Reset/clear 45 | void reset(void) { 46 | z.reset(); 47 | result = (Numeric)0; 48 | } 49 | //! return result 50 | Numeric get_result() { return (result); } 51 | //! Clock in new input sample 52 | Numeric update(Numeric in) { 53 | result -= z.last(); 54 | z.input(in); 55 | result += in; 56 | return (result); 57 | } 58 | Numeric average(Numeric in) { return (((Numeric)inv_size * update(in))); } 59 | }; 60 | } // namespace spuce 61 | -------------------------------------------------------------------------------- /spuce/filters/scic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | #include 5 | namespace spuce { 6 | //! \file 7 | //! \brief Implementation for sharped cascaded integrator comb filter 8 | //! Registers are signed long and default number of stages is 2. 9 | //! \author Tony Kirke 10 | //! \ingroup templates fir 11 | template class scic { 12 | protected: 13 | long max_rate; 14 | size_t stages; 15 | cic main; 16 | cic sub; 17 | delay dly; 18 | 19 | public: 20 | // Constructor 21 | scic(size_t n = 2, long r = 4) : max_rate(r), stages(3 * n), 22 | main(3 * n), sub(2 * n) { 23 | dly.set_size(max_rate); 24 | } 25 | // To change the number of stages dynamically 26 | void num_stages(size_t n, long r) { 27 | stages = 3 * n; 28 | max_rate = r; 29 | main.num_stages(3 * n); 30 | sub.num_stages(2 * n); 31 | dly.set_size(max_rate); 32 | } 33 | // For SCIC decimation 34 | Numeric decimate(Numeric in, long rate, bool dump) { 35 | Numeric result; 36 | dly.input(in); 37 | result = (Numeric)2 * main.decimate(in, dump) - (Numeric)3 * sub.decimate(dly.check(rate - 2), dump); 38 | return (result); 39 | } 40 | }; 41 | } // namespace spuce 42 | -------------------------------------------------------------------------------- /spuce/filters/shelf_allpass1.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 2 | //! \author Tony Kirke 3 | #define _USE_MATH_DEFINES 4 | #include 5 | #include 6 | using std::polar; 7 | 8 | namespace spuce { 9 | double z_freqz_db(bool hpf, double f, double a, double h, double l) { 10 | double wf = f * M_PI; 11 | std::complex hf; 12 | if (!hpf) { 13 | hf = h + l * (1 + (1.0 + polar(a, -wf)) / (a + polar(1.0, -wf))); 14 | } else { 15 | a = 1.0 / a; 16 | hf = h + l * (1 - (1.0 + polar(a, -wf)) / (a + polar(1.0, -wf))); 17 | } 18 | double db = 10.0 * log(std::norm(hf)) / log(10.0); 19 | return (db); 20 | } 21 | double find_a(bool hpf, double f, double des_gain, double h, double l) { 22 | // Need to check starting with low values of "l".... 23 | double a = 0.0001; 24 | double a_inc = -0.1; 25 | const double tol = 0.1; // error tolerance in dBs 26 | double g = z_freqz_db(hpf, f, a, h, l); 27 | double new_error = (g - des_gain); 28 | double prev_error; 29 | int count = 0; 30 | // std::cout << " a = " << a << " db = " << g << " " << new_error << "\n"; 31 | while ((fabs(new_error) > tol) && (count < 100)) { 32 | prev_error = new_error; 33 | a = a + a_inc; 34 | g = z_freqz_db(hpf, f, a, h, l); 35 | new_error = (g - des_gain); 36 | if (((new_error < 0) && (prev_error > 0)) || ((new_error > 0) && (prev_error < 0))) { 37 | // sign change in error 38 | a_inc = -a_inc / 2; 39 | } else if (fabs(new_error) > fabs(prev_error)) { 40 | // error is growing 41 | a_inc = -a_inc / 2; 42 | } 43 | if (a >= 0) { 44 | a = 0.0001; 45 | a_inc = -fabs(a_inc / 2); 46 | } 47 | if (a < -1.01) { 48 | a = -0.1001; 49 | a_inc = fabs(a_inc / 2); 50 | } 51 | count++; 52 | } 53 | // force val 54 | if (count == 100) { 55 | if (hpf) 56 | return (0.0); 57 | else 58 | return (-1); 59 | } 60 | return (a); 61 | } 62 | 63 | } // namespace spuce 64 | -------------------------------------------------------------------------------- /spuce/filters/shelf_allpass1.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 3 | #include 4 | namespace spuce { 5 | 6 | double z_freqz_db(bool hpf, double f, double a, double h, double l); 7 | double find_a(bool hpf, double f, double des_gain, double h, double l); 8 | 9 | //! \file 10 | //! \brief IIR zolzer filter based on 2nd order allpass structure 11 | //! \author Tony Kirke 12 | //! \image html zolzer_allpass.png 13 | //! \author Tony Kirke 14 | //! \ingroup double_templates double_templates iir 15 | template class shelf_allpass1 { 16 | public: 17 | allpass_1 ap; 18 | Coeff low_gain; 19 | Coeff high_gain; 20 | bool high_boost; // high-pass sum case 21 | 22 | // zolzer_allpass(float_type a, float_type g) : ap(a) { gain=g; } 23 | shelf_allpass1() : ap(0) {} 24 | 25 | void set_coeffs(float_type fc, float_type low_g_db, float_type high_g_db) { 26 | high_boost = (low_g_db < 0); 27 | // Convert from dB to gain values 28 | low_gain = pow(10.0, low_g_db / 20.0); 29 | high_gain = pow(10.0, high_g_db / 20.0); 30 | if (high_boost) { 31 | high_gain = (high_gain - low_gain) / 2.0; 32 | } else { 33 | low_gain = (low_gain - high_gain) / 2.0; 34 | } 35 | double a = find_a(high_boost, fc, 0.0, high_gain, low_gain); 36 | ap.init(a, 1); 37 | reset(); 38 | } 39 | 40 | void reset() { ap.reset(); } 41 | 42 | Numeric clock(Numeric x) { 43 | Numeric sum; 44 | if (high_boost) { 45 | sum = low_gain * x + high_gain * (x - ap.clock(x)); 46 | } else { 47 | sum = high_gain * x + low_gain * (x + ap.clock(x)); 48 | } 49 | return (sum); 50 | } 51 | }; 52 | 53 | } // namespace spuce 54 | -------------------------------------------------------------------------------- /spuce/filters/sinc_fir.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 2 | //! \author Tony Kirke 3 | #define _USE_MATH_DEFINES 4 | #include 5 | #include 6 | #include 7 | #include 8 | namespace spuce { 9 | void sinc_fir(fir_coeff& sincf, float_type f) { 10 | size_t len = sincf.number_of_taps(); 11 | std::vector taps(len); 12 | float_type sum=0; 13 | for (size_t i = 0; i < len; i++) { 14 | double x = i - (len - 1.0) / 2.0; 15 | if( x == 0.0 ) taps[i] = f; 16 | else taps[i] = sin( x * f * 2.0*M_PI) / (x * 2.0*M_PI); 17 | sum += taps[i]; 18 | } 19 | for (size_t i = 0; i 4 | namespace spuce { 5 | //! \file 6 | //! \brief Calculate coefficients for FIR assuming box-car filter defined by sinc function 7 | //! \ingroup functions fir 8 | void sinc_fir(fir_coeff& sinc, float_type f); 9 | } // namespace spuce 10 | -------------------------------------------------------------------------------- /spuce/filters/sinc_helper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | //! Band pass: sample rate, lower frequency, upper frequency, window 4 | std::vector sincBPF(const size_t numTaps, const double Fl, const double Fu); 5 | //! Band stop: sample rate, lower frequency, upper frequency, window 6 | std::vector sincBSF(const size_t numTaps, const double Fl, const double Fu); 7 | -------------------------------------------------------------------------------- /spuce/filters/transform_fir.cpp: -------------------------------------------------------------------------------- 1 | #define _USE_MATH_DEFINES 2 | #include 3 | #include 4 | #include 5 | #include 6 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 7 | namespace spuce { 8 | //! \author Tony Kirke 9 | //! \ingroup functions fir 10 | std::vector transform_fir(const std::string& band_type, const std::vector& taps, float_type f) { 11 | std::vector out(taps.size()); 12 | if (band_type == "LOW_PASS") { 13 | // just copy 14 | for (size_t i=0;i> transform_complex_fir(const std::string& band_type, const std::vector& taps, float_type f) { 47 | std::vector> out(taps.size()); 48 | if (band_type == "COMPLEX_BAND_PASS") { 49 | // Modulate taps up to band center frequency 50 | for (size_t i=0;i 3 | #include 4 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 5 | namespace spuce { 6 | //! \author Tony Kirke 7 | //! \ingroup functions fir 8 | std::vector transform_fir(const std::string& band_type, const std::vector& taps, float_type f); 9 | std::vector > transform_complex_fir(const std::string& band_type, const std::vector& taps, float_type f); 10 | } // namespace spuce 11 | -------------------------------------------------------------------------------- /spuce/filters/window.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #include 4 | #include 5 | namespace spuce { 6 | //! \file 7 | //! \brief Various FIR window functions: hamming,hanning,blackman,kaiser, chebyshev 8 | // 9 | //! \brief rectangular window \f$ w(n) = 1;\f$ 10 | //! \ingroup functions fir 11 | std::vector rectangular(long nf); 12 | //! \ingroup functions fir 13 | std::vector flattop(long nf); 14 | //! \brief hamming window \f$ w(n) = 0.54 - 0.46*cos( 2*\pi*n/(nf-1) )\f$ 15 | //! \ingroup functions fir 16 | std::vector hamming(long nf); 17 | //! \brief hanning window \f$ w(n) = 0.5( 1 - cos( 2*\pi*n/(nf-1) )\f$ 18 | //! \ingroup functions fir 19 | std::vector hann(long nf); 20 | //! \ingroup functions fir 21 | std::vector hanning(long nf); 22 | //! \brief Blackman Window \f$ w[x] = 0.42 - 0.5*cos(2*\pi*x/nf) + 0.08*cos(2*\pi*x/nf)\f$ 23 | //! \ingroup functions fir 24 | std::vector blackman(long nf); 25 | //! \brief kaiser window 26 | //! \ingroup functions fir 27 | std::vector kaiser(long nf, float_type beta); 28 | //! \brief dolph chebyshev window design 29 | //! \ingroup functions fir 30 | std::vector cheby(int nf, float_type alpha); 31 | //! \brief bartlett window design 32 | //! \ingroup functions fir 33 | std::vector bartlett(long nf); 34 | //! \brief calculate beta for kaiser window for a given ripple 35 | float_type kaiser_beta(float_type beta); 36 | //! \brief bessel function for kaiser window 37 | float_type io(float_type x); 38 | 39 | } // namespace spuce 40 | -------------------------------------------------------------------------------- /spuce/typedefs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | #define _USE_MATH_DEFINES 4 | #include 5 | // Putting std::complex here allows possible replacement with custom complex type later 6 | #include 7 | #include "complex_operators.h" 8 | 9 | namespace spuce { 10 | // if defined USE_FLOAT, default to float type 11 | #ifndef USE_FLOAT 12 | typedef double float_type; 13 | #else 14 | typedef float float_type; 15 | #endif 16 | 17 | } // namespace spuce 18 | 19 | // Copyright (c) 2015 Tony Kirke. License MIT (http://www.opensource.org/licenses/mit-license.php) 20 | //! \author = Tony Kirke 21 | // 22 | /*! \mainpage 23 |

SPUCE

24 |

This Class Library

25 |
  • 1) basic building blocks such as complex data types, Fixed-bit width integer classes, pure-delay 26 | blocks, etc. 27 |
  • 2) Basic DSP building blocks such as FIR, IIR, Allpass, farrow and lagrange interpolation filters 28 |
  • 3) Ability to design several types of FIR and IIR filters 29 |
30 |

The classes are designed so that they can be used in a simple straight forward manner. For example, a FIR 31 | would be initialized with its tap weights and then simply a member function would be called every time a sample is input or an output is required.

32 | 33 | */ 34 | //! \namespace spuce - SPUCE using C++ - A DSP library 35 | //! \author Tony Kirke, Copyright(c) 2015 36 | //! \defgroup base Base classes and functions 37 | //! \defgroup traits Traits classes and functions 38 | //! \defgroup base Base classes and functions 39 | //! \defgroup Allpass Allpass filters 40 | //! \defgroup fir FIR filters 41 | //! \defgroup iir IIR filters 42 | //! \defgroup interpolation Interpolation filters 43 | //! \defgroup misc Miscellaneous DSP 44 | //! \defgroup equalizers Equalization classes And functions 45 | //! \defgroup windfunc Windows 46 | //! \defgroup classes spuce non-template classes 47 | //! \defgroup complex_templates spuce complex templates 48 | //! \defgroup double_templates spuce double templates 49 | //! \defgroup double_utemplates spuce double templates restricted 50 | //! \defgroup functions spuce functions 51 | //! \defgroup misc spuce misc stuff 52 | //! \defgroup n_templates spuce templates with numeric parameters 53 | //! \defgroup real_double_templates spuce double templates with real parameters 54 | //! \defgroup real_templates spuce templates with real parameters 55 | //! \defgroup templates spuce templates 56 | //! \defgroup template_functions spuce templates functions 57 | //! \defgroup types spuce basic types 58 | -------------------------------------------------------------------------------- /test_spuce/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | 3 | PROJECT("spuce tests") 4 | message("Project spuce_tests") 5 | 6 | if (${CMAKE_SYSTEM_NAME} MATCHES "Windows") 7 | add_definitions(-D_CRT_SECURE_NO_WARNINGS) 8 | add_definitions("/WX") 9 | endif() 10 | 11 | FIND_PACKAGE(PythonLibs REQUIRED) 12 | include_directories(${PYTHON_INCLUDE_DIRS}) 13 | 14 | add_library(spuce_debug plot_fft.cpp cfft.cpp gen_iir_df) 15 | set_property(TARGET spuce_debug PROPERTY CXX_STANDARD 11) 16 | set_property(TARGET spuce_debug PROPERTY POSITION_INDEPENDENT_CODE TRUE) 17 | 18 | SET(PLOT_TARGETS 19 | chebyshev_iir chebyshev_iir_hpf 20 | chebyshev2_iir chebyshev2_iir_hpf 21 | elliptic_iir elliptic_iir_hpf 22 | butterworth_iir butterworth_iir_hpf 23 | butterworth_iir_bp butterworth_iir_bs 24 | elliptic_iir_bp iir iir_df iir_df2 25 | # fir 26 | fir maxflat remez kaiser sinc 27 | # window 28 | window 29 | # FIR bandpass/stop 30 | rc_bsf 31 | transform_bpf transform_hpf transform_bsf 32 | transform_complex_bpf transform_complex_bsf 33 | sinc_bsf 34 | # special filters 35 | iir_allpass1 36 | notch 37 | cic 38 | interp 39 | # other 40 | decimate 41 | decimate2 42 | ) 43 | 44 | FOREACH(mod ${PLOT_TARGETS}) 45 | SET(SRC test_${mod}.cpp) 46 | ADD_EXECUTABLE(spuce_plot_${mod} ${SRC}) 47 | TARGET_LINK_LIBRARIES(spuce_plot_${mod} spuce spuce_debug ${PYTHON_LIBRARY}) 48 | set_property(TARGET spuce_plot_${mod} PROPERTY CXX_STANDARD 11) 49 | set_property(TARGET spuce_plot_${mod} PROPERTY POSITION_INDEPENDENT_CODE TRUE) 50 | ENDFOREACH(mod ${EXTS}) 51 | 52 | SET(UNIT_TARGETS 53 | remez_estimate 54 | ) 55 | 56 | FOREACH(mod ${UNIT_TARGETS}) 57 | SET(SRC test_${mod}.cpp) 58 | ADD_EXECUTABLE(spuce_${mod} ${SRC}) 59 | TARGET_LINK_LIBRARIES(spuce_${mod} spuce spuce_debug ${PYTHON_LIBRARY}) 60 | set_property(TARGET spuce_${mod} PROPERTY CXX_STANDARD 11) 61 | set_property(TARGET spuce_${mod} PROPERTY POSITION_INDEPENDENT_CODE TRUE) 62 | ENDFOREACH(mod ${EXTS}) 63 | 64 | -------------------------------------------------------------------------------- /test_spuce/cfft.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) 2015 Tony Kirke. Boost Software License - Version 1.0 (http://www.opensource.org/licenses/BSL-1.0) 3 | // from directory: classes 4 | 5 | #include 6 | #include // for sin and cos 7 | namespace spuce { 8 | //! \file 9 | //! \brief General Purpose C++ complex FFT Transform 10 | // 11 | //! \brief General Purpose C++ complex FFT Transform 12 | // 13 | //! This is a general-purpose C++ complex FFT transform class. 14 | //! it is defined as a template over a complex type. For instance, 15 | //! if using gnu gcc, the complex type is 16 | //! complex 17 | //! And you declare the cfft class as 18 | //! cfft> 19 | //! 20 | //! The underlying CPLX type requires: 21 | //! CPLX() 22 | //! operator = , CPLX(CPLX const&) 23 | //! CPLX(float_type,float_type) [used on cos/sin] 24 | //! CPLX operator*( CPLX , float_type ) 25 | //! CPLX conj(CPLX const &); [conjugate] 26 | //! ComPlex::operator @ (CPLX , CPLX ) [ where @ =* + - ] 27 | //! \author Tony Kirke 28 | //! \ingroup classes misc 29 | typedef std::complex CPLX; 30 | class cfft { 31 | size_t N, log2N; //! these define size of FFT buffer 32 | CPLX *w; //! array [N/2] of cos/sin values 33 | int *bitrev; //! bit-reversing table, in 0..N 34 | float_type fscales[2]; //! f-transform scalings 35 | float_type iscales[2]; //! i-transform scales 36 | void fft_func(CPLX *buf, int iflag); 37 | 38 | public: 39 | cfft(size_t size, // size is power of 2 40 | float_type scalef1 = 0.5, float_type scalef2 = 1.0, // fwd transform scalings 41 | float_type scalei1 = 1.0, float_type scalei2 = 1.0 // rev xform 42 | ); 43 | ~cfft(); 44 | inline void fft(CPLX *buf) //! perform forward fft on buffer 45 | { 46 | fft_func(buf, 0); 47 | } 48 | inline void ifft(CPLX *buf) //! perform reverse fft on buffer 49 | { 50 | fft_func(buf, 1); 51 | } 52 | inline size_t length() const { return N; } 53 | //! used to fill in last half of complex spectrum of real signal 54 | //! when the first half is already there. 55 | void hermitian(CPLX *buf); 56 | 57 | }; // class cfft 58 | } // namespace spuce 59 | -------------------------------------------------------------------------------- /test_spuce/gen_iir_df.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using std::complex; 3 | // Test instantiation of various combinations of template parameters 4 | 5 | namespace spuce { 6 | template class iir_df ,float_type >; 7 | template class iir_df ,float_type >; 8 | template class iir_df ,float_type >; 9 | template class iir_df; 10 | 11 | template class iir_df ,float_type >; 12 | template class iir_df; 13 | 14 | template class iir_df ,float_type >; 15 | template class iir_df; 16 | 17 | } // namespace SPUC 18 | -------------------------------------------------------------------------------- /test_spuce/plot_fft.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "plot_fft.h" 3 | #include "MPLPlot.h" 4 | #include 5 | #include "cfft.h" 6 | using namespace spuce; 7 | #include 8 | 9 | void plot_fft(std::vector& data) { 10 | const size_t N = data.size(); 11 | Dictionary d; 12 | d.add("lw", 3.1); 13 | 14 | std::unique_ptr[]> z(new std::complex[N]); 15 | for (size_t i = 0; i < N; i++) z[i] = data[i]; 16 | 17 | cfft F(N); 18 | F.fft(z.get()); 19 | 20 | std::vector fft(N/2); 21 | std::vector x(N/2); 22 | 23 | for (size_t i = 0; i < N/2; i++) { 24 | double val = norm((double)N * z[i]); 25 | if (val < 1e-6) val = 1e-6; 26 | fft[i] = 10.0 * log10(val); 27 | x[i] = (double)i/N; 28 | } 29 | PyPlotter plt; 30 | plt.init(); 31 | plt.plot(x,fft, &d); 32 | plt.load(); 33 | plt.show(); 34 | } 35 | void plot_fft(std::vector>& data) { 36 | const size_t N = data.size(); 37 | Dictionary d; 38 | d.add("lw", 3.1); 39 | 40 | std::unique_ptr[]> z(new std::complex[N]); 41 | for (size_t i = 0; i < N; i++) z[i] = data[i]; 42 | 43 | cfft F(N); 44 | F.fft(z.get()); 45 | 46 | std::vector fft(N); 47 | std::vector x(N); 48 | 49 | for (size_t i = 0; i < N; i++) { 50 | double val = norm((double)N * z[i]); 51 | if (val < 1e-6) val = 1e-6; 52 | fft[i] = 10.0 * log10(val); 53 | x[i] = (double)(-(signed)N/2.0 + i)/N; 54 | } 55 | PyPlotter plt; 56 | plt.init(); 57 | plt.plot(x,fft, &d); 58 | plt.load(); 59 | plt.show(); 60 | } 61 | 62 | void plot_data(std::vector& data) { 63 | Dictionary d; 64 | d.add("lw", 3.1); 65 | PyPlotter plt; 66 | plt.init(); 67 | plt.plot_data(data, &d); 68 | plt.load_data(); 69 | plt.show_data(); 70 | } 71 | 72 | void compare_fft(std::vector& data1, std::vector& data2) 73 | { 74 | const size_t N=data1.size(); 75 | Dictionary d; 76 | d.add("lw", 3.1); 77 | 78 | std::unique_ptr []> z(new std::complex[N]); 79 | for (size_t i = 0; i < N; i++) z[i] = data1[i]; 80 | 81 | spuce::cfft F(N); 82 | F.fft(z.get()); 83 | 84 | std::vector fft(N/2); 85 | 86 | for (size_t i=0;i 3 | #include 4 | void plot_fft(std::vector& data); 5 | void plot_fft(std::vector>& data); 6 | void plot_data(std::vector& data); 7 | void compare_fft(std::vector& data1, std::vector& data2); 8 | -------------------------------------------------------------------------------- /test_spuce/test_butterworth_iir.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "plot_fft.h" 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | using namespace spuce; 10 | //! \brief testing various types for IIR 11 | //! \ingroup examples 12 | 13 | int main(int argc, char* argv[]) { 14 | const long N = 1024; 15 | long O = 2; 16 | float_type imp; 17 | float_type f_cutoff = 0.1; 18 | 19 | if (argc > 1) { 20 | f_cutoff = atof(argv[1]); 21 | std::cout << "Order used = " << O << " cut-off = " << f_cutoff << "\n"; 22 | 23 | } 24 | 25 | iir_coeff BPF(O); 26 | butterworth_iir(BPF, f_cutoff, 3.0); 27 | BPF.print(); 28 | 29 | iir_df LPF(BPF); 30 | 31 | std::vector y(N, 0); 32 | 33 | imp = 1.0; 34 | double sum = 0; 35 | for (unsigned int i = 0; i < N; i++) { 36 | y[i] = LPF.clock(imp); 37 | imp = 0; 38 | sum += y[i]; 39 | } 40 | 41 | std::cout << "Impulse response sum = " << sum << "\n"; 42 | plot_fft(y); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /test_spuce/test_butterworth_iir_bp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | #include 6 | #include 7 | #include 8 | #include "plot_fft.h" 9 | 10 | using namespace spuce; 11 | //! \brief testing various types for IIR 12 | //! \ingroup examples 13 | 14 | int main(int argc, char* argv[]) { 15 | const long N = 1024; 16 | long O = 3; 17 | float_type imp; 18 | float_type f_cutoff = 0.05; 19 | float_type f_center = 0.14158; 20 | // Approximately same params as octave 21 | // [z0,p0,g0] = butter(3,[0.10015 0.20015]); 22 | // sqrt(0.10015 * 0.20015) = 0.14158 23 | // cos(0.14158*pi) = 0.9027 24 | 25 | if (argc > 1) { 26 | f_cutoff = atof(argv[1]); 27 | } 28 | std::cout << "Order used = " << O << " cut-off = " << f_cutoff << "\n"; 29 | 30 | iir_coeff BPF(O,filter_type::bandpass); 31 | BPF.set_center(f_center); 32 | butterworth_iir(BPF, f_cutoff, 3.0); 33 | BPF.print(); 34 | 35 | iir_df LPF(BPF); 36 | 37 | std::vector y(N, 0); 38 | 39 | imp = 1.0; 40 | double sum = 0; 41 | for (unsigned int i = 0; i < N; i++) { 42 | y[i] = LPF.clock(imp); 43 | imp = 0; 44 | sum += y[i]; 45 | } 46 | 47 | std::cout << "Impulse response sum = " << sum << "\n"; 48 | plot_fft(y); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /test_spuce/test_butterworth_iir_bs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | #include 6 | #include 7 | #include 8 | #include "plot_fft.h" 9 | 10 | using namespace spuce; 11 | //! \brief testing various types for IIR 12 | //! \ingroup examples 13 | 14 | int main(int argc, char* argv[]) { 15 | const long N = 1024; 16 | long O = 2; 17 | float_type imp; 18 | float_type f_cutoff = 0.1; 19 | 20 | if (argc > 1) { 21 | f_cutoff = atof(argv[1]); 22 | std::cout << "Order used = " << O << " cut-off = " << f_cutoff << "\n"; 23 | 24 | } 25 | 26 | iir_coeff BPF(O,filter_type::bandstop); 27 | butterworth_iir(BPF, f_cutoff, 3.0); 28 | BPF.print(); 29 | 30 | iir_df LPF(BPF); 31 | 32 | std::vector y(N, 0); 33 | 34 | imp = 1.0; 35 | double sum = 0; 36 | for (unsigned int i = 0; i < N; i++) { 37 | y[i] = LPF.clock(imp); 38 | imp = 0; 39 | sum += y[i]; 40 | } 41 | 42 | std::cout << "Impulse response sum = " << sum << "\n"; 43 | plot_fft(y); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /test_spuce/test_butterworth_iir_hpf.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | #include 6 | #include 7 | #include 8 | #include "plot_fft.h" 9 | 10 | using namespace spuce; 11 | //! \brief testing various types for IIR 12 | //! \ingroup examples 13 | 14 | int main(int argc, char* argv[]) { 15 | const long N = 1024; 16 | long O = 2; 17 | float_type imp; 18 | float_type f_cutoff = 0.4; 19 | 20 | if (argc > 1) { 21 | f_cutoff = atof(argv[1]); 22 | std::cout << "Order used = " << O << " cut-off = " << f_cutoff << "\n"; 23 | 24 | } 25 | 26 | iir_coeff BPF(O,filter_type::high); 27 | butterworth_iir(BPF, f_cutoff, 3.0); 28 | 29 | BPF.print(); 30 | 31 | iir_df LPF(BPF); 32 | 33 | std::vector y(N, 0); 34 | 35 | imp = 1.0; 36 | double sum = 0; 37 | for (unsigned int i = 0; i < N; i++) { 38 | y[i] = LPF.clock(imp); 39 | imp = 0; 40 | sum += y[i]; 41 | } 42 | 43 | std::cout << "Impulse response sum = " << sum << "\n"; 44 | plot_fft(y); 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /test_spuce/test_chebyshev2_iir.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | #include 6 | #include 7 | #include 8 | #include "plot_fft.h" 9 | 10 | using namespace spuce; 11 | //! \brief testing various types for IIR 12 | //! \ingroup examples 13 | 14 | int main(int argc, char* argv[]) { 15 | const long N = 1024; 16 | long O = 6; 17 | float_type imp; 18 | float_type f_cutoff=0.2; 19 | float_type atten = 40.0; 20 | 21 | if (argc > 1) { 22 | f_cutoff = atof(argv[1]); 23 | std::cout << "Order used = " << O << " cut-off = " << f_cutoff << " atten = " << atten << "\n"; 24 | } 25 | 26 | iir_coeff BPF(O); 27 | chebyshev2_iir(BPF, f_cutoff, atten); 28 | BPF.print(); 29 | 30 | iir_df LPF(BPF); 31 | std::vector y(N, 0); 32 | 33 | imp = 1.0; 34 | double sum = 0; 35 | for (unsigned int i = 0; i < N; i++) { 36 | y[i] = LPF.clock(imp); 37 | imp = 0; 38 | sum += y[i]; 39 | } 40 | 41 | std::cout << "Impulse response sum = " << sum << "\n"; 42 | plot_fft(y); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /test_spuce/test_chebyshev2_iir_hpf.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | #include 6 | #include 7 | #include 8 | #include "plot_fft.h" 9 | 10 | using namespace spuce; 11 | //! \brief testing various types for IIR 12 | //! \ingroup examples 13 | 14 | int main(int argc, char* argv[]) { 15 | const long N = 1024; 16 | long O = 6; 17 | float_type imp; 18 | float_type f_cutoff=0.2; 19 | float_type atten = 40.0; 20 | 21 | if (argc > 1) { 22 | f_cutoff = atof(argv[1]); 23 | std::cout << "Order used = " << O << " cut-off = " << f_cutoff << " atten = " << atten << "\n"; 24 | } 25 | 26 | iir_coeff BPF(O,filter_type::high); 27 | chebyshev2_iir(BPF, f_cutoff, atten); 28 | BPF.print(); 29 | 30 | iir_df LPF(BPF); 31 | std::vector y(N, 0); 32 | 33 | imp = 1.0; 34 | double sum = 0; 35 | for (unsigned int i = 0; i < N; i++) { 36 | y[i] = LPF.clock(imp); 37 | imp = 0; 38 | sum += y[i]; 39 | } 40 | 41 | std::cout << "Impulse response sum = " << sum << "\n"; 42 | plot_fft(y); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /test_spuce/test_chebyshev_iir.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | #include 6 | #include 7 | #include 8 | #include "plot_fft.h" 9 | 10 | using namespace spuce; 11 | //! \brief testing various types for IIR 12 | //! \ingroup examples 13 | 14 | int main(int argc, char* argv[]) { 15 | const long N = 1024; 16 | long O = 6; 17 | float_type imp; 18 | float_type f_cutoff=0.2; 19 | float_type ripple = 1.0; 20 | 21 | if (argc > 1) { 22 | f_cutoff = atof(argv[1]); 23 | std::cout << "Order used = " << O << " cut-off = " << f_cutoff << " ripple = " << ripple << "\n"; 24 | } 25 | 26 | iir_coeff BPF(O); 27 | chebyshev_iir(BPF, f_cutoff, ripple); 28 | BPF.print(); 29 | 30 | iir_df LPF(BPF); 31 | std::vector y(N, 0); 32 | 33 | imp = 1.0; 34 | double sum = 0; 35 | for (unsigned int i = 0; i < N; i++) { 36 | y[i] = LPF.clock(imp); 37 | imp = 0; 38 | sum += y[i]; 39 | } 40 | 41 | std::cout << "Impulse response sum = " << sum << "\n"; 42 | plot_fft(y); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /test_spuce/test_chebyshev_iir_hpf.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | #include 6 | #include 7 | #include 8 | #include "plot_fft.h" 9 | 10 | using namespace spuce; 11 | //! \brief testing various types for IIR 12 | //! \ingroup examples 13 | 14 | int main(int argc, char* argv[]) { 15 | const long N = 1024; 16 | long O = 6; 17 | float_type imp; 18 | float_type f_cutoff=0.2; 19 | float_type ripple = 1.0; 20 | 21 | if (argc > 1) { 22 | f_cutoff = atof(argv[1]); 23 | std::cout << "Order used = " << O << " cut-off = " << f_cutoff << " ripple = " << ripple << "\n"; 24 | } 25 | 26 | iir_coeff BPF(O,filter_type::high); 27 | chebyshev_iir(BPF, f_cutoff, ripple); 28 | BPF.print(); 29 | 30 | iir_df LPF(BPF); 31 | std::vector y(N, 0); 32 | 33 | imp = 1.0; 34 | double sum = 0; 35 | for (unsigned int i = 0; i < N; i++) { 36 | y[i] = LPF.clock(imp); 37 | imp = 0; 38 | sum += y[i]; 39 | } 40 | 41 | std::cout << "Impulse response sum = " << sum << "\n"; 42 | plot_fft(y); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /test_spuce/test_cic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | using namespace spuce; 8 | #include "plot_fft.h" 9 | int main(int argv, char* argc[]) { 10 | const int N=256; 11 | int i; 12 | int rate = 16; 13 | long imp; 14 | const long O=2; 15 | 16 | cic F(O); 17 | std::vector y(N); 18 | 19 | imp = 1; 20 | bool dump = true; 21 | for (i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | using namespace std; 11 | using namespace spuce; 12 | #include "plot_fft.h" 13 | /* 14 | Compare frequency responses of a FIR decimation filter 15 | with an IIR one. 16 | FIR order = 2*Rate*IIR_Order + 1 17 | */ 18 | int main(int argv, char* argc[]) { 19 | const int N=256; 20 | const size_t IIR_Order = 6; 21 | const int rate=6; 22 | 23 | auto iir_taps = calculate_decimator_taps(rate, IIR_Order, false); 24 | auto fir_taps = calculate_decimator_taps(rate, IIR_Order, true); 25 | 26 | iir_df IIR; 27 | IIR.set_taps(iir_taps); 28 | 29 | fir BFIR(fir_taps); 30 | 31 | std::vector x(N); 32 | std::vector y(N); 33 | 34 | double imp = 1; 35 | for (int i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | using namespace spuce; 8 | #include "plot_fft.h" 9 | /* 10 | Compare frequency responses of a FIR decimation filter 11 | with an IIR one. 12 | FIR order = 2*Rate*IIR_Order + 1 13 | */ 14 | int main(int argv, char* argc[]) { 15 | const size_t IIR_Order = 6; 16 | const int rate=6; 17 | const int N=256*rate; 18 | 19 | decimator IDEC(rate, IIR_Order, false); 20 | decimator FDEC(rate, IIR_Order, true); 21 | 22 | std::vector imp(N,0); 23 | std::vector x; 24 | std::vector y; 25 | 26 | imp[0] = 1.0; 27 | IDEC.process(imp, x); 28 | FDEC.process(imp, y); 29 | 30 | /* 31 | std::cout << "print x\n"; 32 | for (size_t i=0;i 0) && (y.size() > 0)) { 39 | std::cout << "Calling compare fft\n"; 40 | compare_fft(x,y); 41 | } 42 | 43 | return(1); 44 | } 45 | -------------------------------------------------------------------------------- /test_spuce/test_elliptic_iir.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | #include 6 | #include 7 | #include 8 | #include "plot_fft.h" 9 | 10 | using namespace spuce; 11 | //! \brief testing various types for IIR 12 | //! \ingroup examples 13 | 14 | int main(int argc, char* argv[]) { 15 | const long N = 1024; 16 | long O = 6; 17 | float_type imp; 18 | float_type f_cutoff=0.2; 19 | float_type ripple = 1.0; 20 | float_type stopband_atten = 40; 21 | 22 | if (argc > 1) { 23 | f_cutoff = atof(argv[1]); 24 | } 25 | std::cout << "Order used = " << O << ", cut-off = " << f_cutoff 26 | << ", stopband attenuation = " << stopband_atten 27 | << ", ripple = " << ripple << "\n"; 28 | 29 | iir_coeff BPF(O); 30 | elliptic_iir(BPF, f_cutoff, ripple, stopband_atten); 31 | iir_df LPF(BPF); 32 | 33 | BPF.print(); 34 | 35 | std::vector y(N, 0); 36 | 37 | imp = 1.0; 38 | double sum = 0; 39 | for (unsigned int i = 0; i < N; i++) { 40 | y[i] = LPF.clock(imp); 41 | imp = 0; 42 | sum += y[i]; 43 | } 44 | 45 | std::cout << "Impulse response sum = " << sum << "\n"; 46 | plot_fft(y); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /test_spuce/test_elliptic_iir_bp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | #include 6 | #include 7 | #include 8 | #include "plot_fft.h" 9 | 10 | using namespace spuce; 11 | //! \brief testing various types for IIR 12 | //! \ingroup examples 13 | 14 | int main(int argc, char* argv[]) { 15 | const long N = 1024; 16 | long O = 3; 17 | float_type imp; 18 | float_type f_cutoff=0.1; 19 | float_type ripple = 0.1; 20 | float_type stopband_atten = 40; 21 | 22 | if (argc > 1) { 23 | f_cutoff = atof(argv[1]); 24 | } 25 | std::cout << "Order used = " << O << ", cut-off = " << f_cutoff 26 | << ", stopband attenuation = " << stopband_atten 27 | << ", ripple = " << ripple << "\n"; 28 | 29 | iir_coeff BPF(O,filter_type::bandpass); 30 | elliptic_iir(BPF, f_cutoff, ripple, stopband_atten); 31 | iir_df LPF(BPF); 32 | 33 | BPF.print(); 34 | 35 | std::vector y(N, 0); 36 | 37 | imp = 1.0; 38 | double sum = 0; 39 | for (unsigned int i = 0; i < N; i++) { 40 | y[i] = LPF.clock(imp); 41 | imp = 0; 42 | sum += y[i]; 43 | } 44 | 45 | std::cout << "Impulse response sum = " << sum << "\n"; 46 | plot_fft(y); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /test_spuce/test_elliptic_iir_hpf.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | #include 6 | #include 7 | #include 8 | #include "plot_fft.h" 9 | 10 | using namespace spuce; 11 | //! \brief testing various types for IIR 12 | //! \ingroup examples 13 | 14 | int main(int argc, char* argv[]) { 15 | const long N = 1024; 16 | long O = 6; 17 | float_type imp; 18 | float_type f_cutoff=0.2; 19 | float_type ripple = 1.0; 20 | float_type stopband_atten = 40; 21 | 22 | if (argc > 1) { 23 | f_cutoff = atof(argv[1]); 24 | } 25 | std::cout << "Order used = " << O << ", cut-off = " << f_cutoff 26 | << ", stopband attenuation = " << stopband_atten 27 | << ", ripple = " << ripple << "\n"; 28 | 29 | iir_coeff BPF(O,filter_type::high); 30 | elliptic_iir(BPF, f_cutoff, ripple, stopband_atten); 31 | iir_df LPF(BPF); 32 | 33 | BPF.print(); 34 | 35 | std::vector y(N, 0); 36 | 37 | imp = 1.0; 38 | double sum = 0; 39 | for (unsigned int i = 0; i < N; i++) { 40 | y[i] = LPF.clock(imp); 41 | imp = 0; 42 | sum += y[i]; 43 | } 44 | 45 | std::cout << "Impulse response sum = " << sum << "\n"; 46 | plot_fft(y); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /test_spuce/test_fir.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | using namespace spuce; 9 | #include "plot_fft.h" 10 | int main(int argc, char* argv[]) { 11 | const int N=256; 12 | int i; 13 | float_type imp; 14 | int TAPS = 51; 15 | float_type alpha = 0.2; 16 | float_type fl = 0.1; 17 | float_type fu = 0.2; 18 | float_type weight = 100; 19 | int sel = 0; 20 | if (argc > 1) { 21 | sel = atoi(argv[1]); 22 | } 23 | std::string band_type = "LOW_PASS"; 24 | switch (sel) { 25 | case 0: band_type = "LOW_PASS"; break; 26 | case 1: band_type = "HIGH_PASS"; break; 27 | case 2: band_type = "BAND_PASS"; break; 28 | case 3: band_type = "BAND_STOP"; break; 29 | } 30 | std::cout << "Band type is " << band_type << "\n"; 31 | 32 | std::string filt_type = "remez"; 33 | auto taps = design_fir(filt_type, band_type, TAPS, fl, fu, alpha, weight); 34 | 35 | fir RFIR(taps); 36 | std::vector y(N); 37 | 38 | imp = 1; 39 | for (i=0;i 2 | #include 3 | #include 4 | using namespace std; 5 | #include 6 | #include 7 | #include "cfft.h" 8 | using namespace spuce; 9 | #include "plot_fft.h" 10 | 11 | //! \brief testing various types for IIR 12 | //! \ingroup examples 13 | 14 | int main(int argv, char* argc[]) { 15 | const long N = 256; 16 | const long O = 4; 17 | float_type imp; 18 | 19 | iir_coeff* coeff = design_iir("butterworth", "LOW_PASS", O, 0.1); 20 | iir_df LPF(*coeff); 21 | std::vector y(N, 0); 22 | 23 | imp = 1.0; 24 | for (unsigned int i = 0; i < N; i++) { 25 | y[i] = LPF.clock(imp); 26 | imp = 0; 27 | } 28 | 29 | plot_fft(y); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /test_spuce/test_iir_allpass1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | #include 6 | #include 7 | using namespace spuce; 8 | //! \brief testing various types of filters 9 | // 10 | //! \ingroup examples 11 | #include "plot_fft.h" 12 | int main(int argv, char* argc[]) { 13 | const int N=256; 14 | const int Order=4; 15 | const double ripple_factor = 0.4; 16 | float_type imp; 17 | iir_allpass1_sections AF1(ripple_factor,Order); 18 | std::vector y(N,0); 19 | 20 | imp = 1; 21 | for (int i=0;i 2 | #include 3 | #include 4 | using namespace std; 5 | #include 6 | #include 7 | #include "cfft.h" 8 | using namespace spuce; 9 | #include "plot_fft.h" 10 | 11 | //! \brief testing various types for IIR 12 | //! \ingroup examples 13 | 14 | typedef std::complex dtype; 15 | 16 | int main(int argv, char* argc[]) { 17 | const long N = 256; 18 | 19 | // First set as 1st order filter 20 | iir_coeff BPF(1); 21 | butterworth_iir(BPF, 0.4, 3.0); 22 | iir_df IIR(BPF); 23 | 24 | // Approximation , set directly, over-riding previous setup of a different order 25 | std::vector taps = {0.2,0.4,0.2,1,-0.3682,0.1956}; 26 | IIR.set_taps(taps); 27 | 28 | // Check taps 29 | IIR.print(); 30 | 31 | dtype imp; 32 | std::vector y(N, 0); 33 | 34 | imp = 1.0; 35 | double sum = 0; 36 | for (unsigned int i = 0; i < N; i++) { 37 | y[i] = std::real(IIR.clock(imp)); 38 | sum += y[i]; 39 | imp = 0; 40 | } 41 | 42 | std::cout << "Impulse response sum = " << sum << "\n"; 43 | plot_fft(y); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /test_spuce/test_iir_df2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | #include 6 | #include 7 | #include "cfft.h" 8 | using namespace spuce; 9 | #include "plot_fft.h" 10 | 11 | //! \brief testing how IIR filter in Pothos is being setup/used 12 | //! \ingroup examples 13 | typedef std::complex dtype; 14 | 15 | int main(int argv, char* argc[]) { 16 | const long N = 256; 17 | 18 | iir_coeff* filt = design_iir("butterworth", "LOW_PASS", 2, 0.2, 0.1, 60.0); 19 | // get the tap from iir_coeff for iir_filter, incorporating the gain to feedforward taps 20 | std::vector b = filt->get_b(); 21 | std::vector a = filt->get_a(); 22 | // Group together feed forward and feed back taps into 1 vector for transferring to IIR filter 23 | double gain = filt->getGain(); 24 | for (int i=0;i IIR; 30 | 31 | // Get taps from design 32 | IIR.set_taps(b); 33 | 34 | dtype imp; 35 | std::vector y(N, 0); 36 | 37 | imp = 1.0; 38 | double sum = 0; 39 | for (unsigned int i = 0; i < N; i++) { 40 | y[i] = std::real(IIR.clock(imp)); 41 | sum += y[i]; 42 | imp = 0; 43 | } 44 | 45 | std::cout << "Impulse response sum = " << sum << "\n"; 46 | plot_fft(y); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /test_spuce/test_interp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace spuce; 5 | using namespace std; 6 | #include "plot_fft.h" 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | const int N=64; 11 | std::vector y(N); 12 | farrow_upsampler INTERP(4); 13 | double time_inc = 19.0/41.0; 14 | double x = 1.0; 15 | int need=0; 16 | 17 | // Show how impulse response is spread out in time 18 | for (int i=0;i 2 | #include 3 | #include 4 | using namespace std; 5 | #include 6 | #include 7 | #include 8 | using namespace spuce; 9 | #include "plot_fft.h" 10 | //! \brief testing various types for IIR 11 | //! \ingroup examples 12 | 13 | int main(int argc, char* argv[]) { 14 | const long N = 1024; 15 | long O = 30; 16 | float_type imp; 17 | float_type ripple = 0.01; 18 | 19 | if (argc > 1) { 20 | ripple = atof(argv[1]); 21 | } 22 | 23 | float_type beta = kaiser_beta(ripple); 24 | std::cout << "Order used = " << O << " ripple = " << ripple << " beta = " << beta << "\n"; 25 | std::vector taps = design_window("kaiser", O, beta); 26 | 27 | float_type sum=0; 28 | for (int i=0;i y(N, 0); 32 | // Map from std::vector<> to fir_coeff<> and then to fir<> 33 | fir_coeff RF(taps.size()); 34 | for (int i=0;i RFIR(RF); 36 | 37 | imp = 1; 38 | for (int i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | using namespace spuce; 10 | #include "plot_fft.h" 11 | int main(int argv, char* argc[]) { 12 | const int N=256; 13 | int i; 14 | float_type imp; 15 | int TAPS = 51; 16 | float_type fc = 0.02; 17 | 18 | fir_coeff filt(TAPS); 19 | butterworth_fir(filt, fc); 20 | fir RFIR(filt); 21 | std::vector y(N); 22 | 23 | imp = 1; 24 | for (i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | using namespace spuce; 8 | //! \brief testing of notch filter based on allpass section 9 | //! \ingroup examples 10 | #include "plot_fft.h" 11 | 12 | int main(int argv, char* argc[]) { 13 | const int N=256; 14 | std::vector y(N); 15 | // Notch is at frequency 0.1 16 | notch_allpass Notch(0.1); 17 | 18 | double imp = 1.0; 19 | for (int i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | using namespace spuce; 10 | #include "plot_fft.h" 11 | int main(int argv, char* argc[]) { 12 | const int N=256; 13 | int i; 14 | float_type imp; 15 | int TAPS = 51; 16 | float_type alpha = 0.125; 17 | float_type spb = 0.125; 18 | 19 | auto filt = design_fir("raised_cosine", "LOW_PASS", TAPS, spb, alpha); 20 | auto tf_taps = transform_fir("BAND_STOP", filt, 0.125); 21 | fir BSFIR(tf_taps); 22 | std::vector y(N); 23 | 24 | imp = 1; 25 | for (i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | using namespace spuce; 10 | #include "plot_fft.h" 11 | int main(int argv, char* argc[]) { 12 | const int N=256; 13 | int i; 14 | float_type imp; 15 | int TAPS = 51; 16 | float_type stop_weight = 1.0; 17 | float_type pass_edge = 0.05; 18 | float_type stop_edge = 0.1; 19 | 20 | bool ok = true; 21 | std::vector e1(4); 22 | std::vector f1(4); 23 | std::vector w1(4); 24 | remez_fir Remz; 25 | w1[0] = 1.0; 26 | w1[1] = stop_weight; 27 | w1[2] = 0; 28 | w1[3] = 0; 29 | e1[0] = 0; 30 | e1[1] = pass_edge; 31 | e1[2] = stop_edge; 32 | e1[3] = 0.5; 33 | f1[0] = 1.0; 34 | f1[1] = 0.0; 35 | f1[2] = 0.0; 36 | f1[3] = 0.0; 37 | std::vector fir_coef(TAPS); 38 | ok = Remz.remez(fir_coef, TAPS, 2, e1, f1, w1, remez_type::BANDPASS); 39 | 40 | // Map from std::vector<> to fir_coeff<> and then to fir<> 41 | fir_coeff RF(TAPS); 42 | for (int i=0;i RFIR(RF); 44 | std::vector y(N); 45 | 46 | imp = 1; 47 | for (i=0;i 2 | #include 3 | using namespace std; 4 | using namespace spuce; 5 | int main(int argc, char* argv[]) { 6 | float_type atten = 60.0; // db 7 | float_type rip_db = 0.1; // db 8 | float_type trans_bw = 0.0625; 9 | std::cout << "For passband ripple = " << rip_db << " dB " 10 | << " and stopband attenuation = " 11 | << atten << " dB " 12 | << " and transition width = " << trans_bw << "\n"; 13 | float_type weight = remez_estimate_weight(rip_db, atten); 14 | std::cout << "weight = " << weight << "\n"; 15 | size_t num_taps = remez_estimate_num_taps(trans_bw, rip_db, atten); 16 | std::cout << "number of taps needed = " << num_taps << "\n"; 17 | 18 | float_type min_trans_bw = remez_estimate_bw(num_taps, rip_db, atten); 19 | std::cout << "We can handle trans_bw ~= " << min_trans_bw << " "; 20 | float_type min_atten = remez_estimate_atten(num_taps, trans_bw, rip_db); 21 | std::cout << "and attenuation of ~= " << min_atten << " dB\n"; 22 | 23 | 24 | return(1); 25 | } 26 | -------------------------------------------------------------------------------- /test_spuce/test_sinc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | using namespace spuce; 10 | #include "plot_fft.h" 11 | int main(int argv, char* argc[]) { 12 | const int N=256; 13 | int i; 14 | float_type imp; 15 | int TAPS = 33; 16 | float_type f = 0.1; 17 | 18 | fir_coeff RF(TAPS); 19 | sinc_fir(RF, f); 20 | fir RFIR(RF); 21 | std::vector y(N); 22 | 23 | imp = 1; 24 | for (i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | using namespace spuce; 11 | #include "plot_fft.h" 12 | int main(int argv, char* argc[]) { 13 | const int N=256; 14 | int i; 15 | float_type imp; 16 | int TAPS = 33; 17 | float_type f = 0.05; 18 | 19 | fir_coeff RF(TAPS); 20 | sinc_fir(RF, f); 21 | auto lp_taps = get_taps(RF); 22 | 23 | double center = 0.15; 24 | auto tf_taps = transform_fir("BAND_STOP", lp_taps, center); 25 | fir RFIR(tf_taps); 26 | 27 | std::vector y(N); 28 | 29 | imp = 1; 30 | for (i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | using namespace spuce; 11 | #include "plot_fft.h" 12 | int main(int argv, char* argc[]) { 13 | const int N=256; 14 | int i; 15 | float_type imp; 16 | int TAPS = 33; 17 | float_type stop_weight = 50.0; 18 | float_type pass_edge = 0.05; 19 | float_type stop_edge = 0.1; 20 | 21 | bool ok = true; 22 | std::vector e1(4); 23 | std::vector f1(4); 24 | std::vector w1(4); 25 | remez_fir Remz; 26 | w1[0] = 1.0; 27 | w1[1] = stop_weight; 28 | w1[2] = 0; 29 | w1[3] = 0; 30 | e1[0] = 0; 31 | e1[1] = pass_edge; 32 | e1[2] = stop_edge; 33 | e1[3] = 0.5; 34 | f1[0] = 1.0; 35 | f1[1] = 0.0; 36 | f1[2] = 0.0; 37 | f1[3] = 0.0; 38 | std::vector fir_coef(TAPS); 39 | ok = Remz.remez(fir_coef, TAPS, 2, e1, f1, w1, remez_type::BANDPASS); 40 | 41 | auto tf_taps = transform_fir("BAND_PASS", fir_coef, 0.125); 42 | 43 | // Map from std::vector<> to fir_coeff<> and then to fir<> 44 | fir_coeff RF(TAPS); 45 | for (int i=0;i RFIR(RF); 47 | std::vector y(N); 48 | 49 | imp = 1; 50 | for (i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | using namespace spuce; 11 | #include "plot_fft.h" 12 | int main(int argv, char* argc[]) { 13 | const int N=256; 14 | int i; 15 | float_type imp; 16 | int TAPS = 33; 17 | float_type stop_weight = 1.0; 18 | float_type pass_edge = 0.05; 19 | float_type stop_edge = 0.1; 20 | 21 | bool ok = true; 22 | std::vector e1(4); 23 | std::vector f1(4); 24 | std::vector w1(4); 25 | remez_fir Remz; 26 | w1[0] = 1.0; 27 | w1[1] = stop_weight; 28 | w1[2] = 0; 29 | w1[3] = 0; 30 | e1[0] = 0; 31 | e1[1] = pass_edge; 32 | e1[2] = stop_edge; 33 | e1[3] = 0.5; 34 | f1[0] = 1.0; 35 | f1[1] = 0.0; 36 | f1[2] = 0.0; 37 | f1[3] = 0.0; 38 | std::vector fir_coef(TAPS); 39 | ok = Remz.remez(fir_coef, TAPS, 2, e1, f1, w1, remez_type::BANDPASS); 40 | 41 | auto tf_taps = transform_fir("BAND_STOP", fir_coef, 0.125); 42 | 43 | // Map from std::vector<> to fir_coeff<> and then to fir<> 44 | fir_coeff RF(TAPS); 45 | for (int i=0;i RFIR(RF); 47 | std::vector y(N); 48 | 49 | imp = 1; 50 | for (i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | using namespace spuce; 11 | #include "plot_fft.h" 12 | int main(int argv, char* argc[]) { 13 | const int N=256; 14 | int i; 15 | float_type imp; 16 | int TAPS = 33; 17 | float_type stop_weight = 50.0; 18 | float_type pass_edge = 0.05; 19 | float_type stop_edge = 0.1; 20 | 21 | bool ok = true; 22 | std::vector e1(4); 23 | std::vector f1(4); 24 | std::vector w1(4); 25 | remez_fir Remz; 26 | w1[0] = 1.0; 27 | w1[1] = stop_weight; 28 | w1[2] = 0; 29 | w1[3] = 0; 30 | e1[0] = 0; 31 | e1[1] = pass_edge; 32 | e1[2] = stop_edge; 33 | e1[3] = 0.5; 34 | f1[0] = 1.0; 35 | f1[1] = 0.0; 36 | f1[2] = 0.0; 37 | f1[3] = 0.0; 38 | std::vector fir_coef(TAPS); 39 | ok = Remz.remez(fir_coef, TAPS, 2, e1, f1, w1, remez_type::BANDPASS); 40 | 41 | // Put at negative frequency 42 | auto tf_taps = transform_complex_fir("COMPLEX_BAND_PASS", fir_coef, -0.125); 43 | 44 | // Map from std::vector<> to fir_coeff<> and then to fir<> 45 | fir_coeff> RF(TAPS); 46 | for (int i=0;i,std::complex> RFIR(RF); 48 | std::vector> y(N); 49 | 50 | imp = 1; 51 | for (i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | using namespace spuce; 11 | #include "plot_fft.h" 12 | int main(int argv, char* argc[]) { 13 | const int N=256; 14 | int i; 15 | float_type imp; 16 | int TAPS = 33; 17 | float_type stop_weight = 50.0; 18 | float_type pass_edge = 0.05; 19 | float_type stop_edge = 0.1; 20 | 21 | bool ok = true; 22 | std::vector e1(4); 23 | std::vector f1(4); 24 | std::vector w1(4); 25 | remez_fir Remz; 26 | w1[0] = 1.0; 27 | w1[1] = stop_weight; 28 | w1[2] = 0; 29 | w1[3] = 0; 30 | e1[0] = 0; 31 | e1[1] = pass_edge; 32 | e1[2] = stop_edge; 33 | e1[3] = 0.5; 34 | f1[0] = 1.0; 35 | f1[1] = 0.0; 36 | f1[2] = 0.0; 37 | f1[3] = 0.0; 38 | std::vector fir_coef(TAPS); 39 | ok = Remz.remez(fir_coef, TAPS, 2, e1, f1, w1, remez_type::BANDPASS); 40 | 41 | // Put at negative frequency 42 | auto tf_taps = transform_complex_fir("COMPLEX_BAND_STOP", fir_coef, -0.125); 43 | 44 | // Map from std::vector<> to fir_coeff<> and then to fir<> 45 | fir_coeff> RF(TAPS); 46 | for (int i=0;i,std::complex> RFIR(RF); 48 | std::vector> y(N); 49 | 50 | imp = 1; 51 | for (i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | using namespace spuce; 11 | #include "plot_fft.h" 12 | int main(int argv, char* argc[]) { 13 | const int N=256; 14 | int i; 15 | float_type imp; 16 | int TAPS = 33; 17 | float_type stop_weight = 50.0; 18 | float_type pass_edge = 0.2; 19 | float_type stop_edge = 0.3; 20 | 21 | bool ok = true; 22 | std::vector e1(4); 23 | std::vector f1(4); 24 | std::vector w1(4); 25 | remez_fir Remz; 26 | w1[0] = 1.0; 27 | w1[1] = stop_weight; 28 | w1[2] = 0; 29 | w1[3] = 0; 30 | e1[0] = 0; 31 | e1[1] = pass_edge; 32 | e1[2] = stop_edge; 33 | e1[3] = 0.5; 34 | f1[0] = 1.0; 35 | f1[1] = 0.0; 36 | f1[2] = 0.0; 37 | f1[3] = 0.0; 38 | std::vector fir_coef(TAPS); 39 | ok = Remz.remez(fir_coef, TAPS, 2, e1, f1, w1, remez_type::BANDPASS); 40 | 41 | auto tf_taps = transform_fir("HIGH_PASS", fir_coef, 0); 42 | 43 | // Map from std::vector<> to fir_coeff<> and then to fir<> 44 | fir_coeff RF(TAPS); 45 | for (int i=0;i RFIR(RF); 47 | std::vector y(N); 48 | 49 | imp = 1; 50 | for (i=0;i 2 | #include 3 | using namespace std; 4 | using namespace spuce; 5 | int main(int argv, char* argc[]) { 6 | int order = 8; 7 | 8 | // hanning,hann,hamming,blackman,bartlett,kaiser, 9 | std::string win_type = "chebyshev"; 10 | float_type beta = 60.0; 11 | 12 | std::vector taps = design_window(win_type, order, beta); 13 | std::cout << "Taps[] = {"; 14 | for (size_t i=0;i