summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt12
-rw-r--r--cmake/Modules/GrMiscUtils.cmake25
-rw-r--r--cmake/Modules/GrSwig.cmake2
-rw-r--r--gnuradio-core/CMakeLists.txt3
-rw-r--r--gnuradio-core/src/lib/filter/CMakeLists.txt3
-rw-r--r--gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.c2
-rw-r--r--gnuradio-core/src/lib/filter/dotprod_fff_armv7_a.c2
-rw-r--r--gnuradio-core/src/lib/general/CMakeLists.txt5
-rw-r--r--gnuradio-core/src/lib/general/general.i4
-rw-r--r--gnuradio-core/src/lib/general/gr_annotator_raw.cc106
-rw-r--r--gnuradio-core/src/lib/general/gr_annotator_raw.h69
-rw-r--r--gnuradio-core/src/lib/general/gr_annotator_raw.i26
-rw-r--r--gnuradio-core/src/lib/general/gr_tag_debug.cc100
-rw-r--r--gnuradio-core/src/lib/general/gr_tag_debug.h85
-rw-r--r--gnuradio-core/src/lib/general/gr_tag_debug.i35
-rw-r--r--gnuradio-core/src/lib/gengen/CMakeLists.txt2
-rw-r--r--gnuradio-core/src/lib/gengen/gr_sig_source_X.cc.t7
-rw-r--r--gnuradio-core/src/lib/io/CMakeLists.txt1
-rw-r--r--gnuradio-core/src/lib/io/gr_message_burst_source.cc144
-rw-r--r--gnuradio-core/src/lib/io/gr_message_burst_source.h71
-rw-r--r--gnuradio-core/src/lib/io/gr_message_burst_source.i38
-rw-r--r--gnuradio-core/src/lib/io/gri_wavfile.cc136
-rw-r--r--gnuradio-core/src/lib/io/gri_wavfile.h27
-rw-r--r--gnuradio-core/src/lib/io/io.i2
-rw-r--r--gnuradio-core/src/lib/runtime/CMakeLists.txt23
-rw-r--r--gnuradio-core/src/python/build_utils.py34
-rwxr-xr-xgnuradio-core/src/python/gnuradio/gr/qa_tag_debug.py43
-rw-r--r--gr-audio/lib/CMakeLists.txt2
-rw-r--r--gr-digital/examples/CMakeLists.txt1
-rwxr-xr-xgr-digital/examples/berawgn.py104
-rw-r--r--gr-digital/examples/demod/ber_simulation.grc305
-rw-r--r--gr-digital/examples/demod/digital_freq_lock.grc806
-rw-r--r--gr-digital/examples/demod/dpsk_loopback.grc198
-rw-r--r--gr-digital/examples/demod/gfsk_loopback.grc646
-rw-r--r--gr-digital/examples/demod/mpsk_demod.grc10
-rw-r--r--gr-digital/examples/demod/pam_sync.grc1117
-rw-r--r--gr-digital/examples/demod/pam_timing.grc370
-rw-r--r--gr-digital/grc/digital_dxpsk_demod.xml14
-rw-r--r--gr-digital/grc/digital_dxpsk_mod.xml10
-rw-r--r--gr-digital/grc/digital_gfsk_demod.xml95
-rw-r--r--gr-digital/grc/digital_gfsk_mod.xml74
-rw-r--r--gr-digital/include/digital_fll_band_edge_cc.h40
-rw-r--r--gr-digital/lib/digital_fll_band_edge_cc.cc70
-rw-r--r--gr-digital/python/CMakeLists.txt1
-rw-r--r--gr-digital/python/__init__.py1
-rw-r--r--gr-digital/python/gfsk.py306
-rw-r--r--gr-fft/include/fft/fft.h6
-rw-r--r--gr-fft/lib/CMakeLists.txt11
-rw-r--r--gr-filter/CMakeLists.txt113
-rw-r--r--gr-filter/doc/CMakeLists.txt23
-rw-r--r--gr-filter/doc/README.filter13
-rw-r--r--gr-filter/doc/filter.dox27
-rw-r--r--gr-filter/examples/CMakeLists.txt39
-rwxr-xr-xgr-filter/examples/channelize.py195
-rwxr-xr-xgr-filter/examples/chirp_channelize.py205
-rwxr-xr-xgr-filter/examples/decimate.py181
-rwxr-xr-xgr-filter/examples/fft_filter_ccc.py98
-rwxr-xr-xgr-filter/examples/fir_filter_ccc.py92
-rwxr-xr-xgr-filter/examples/fir_filter_fff.py92
-rwxr-xr-xgr-filter/examples/fmtest.py226
-rwxr-xr-xgr-filter/examples/interpolate.py240
-rwxr-xr-xgr-filter/examples/reconstruction.py164
-rwxr-xr-xgr-filter/examples/resampler.py128
-rw-r--r--gr-filter/examples/resampler_demo.grc630
-rwxr-xr-xgr-filter/examples/synth_filter.py85
-rwxr-xr-xgr-filter/examples/synth_to_chan.py118
-rw-r--r--gr-filter/gnuradio-filter.pc.in11
-rw-r--r--gr-filter/grc/CMakeLists.txt41
-rw-r--r--gr-filter/grc/channel_model.xml61
-rw-r--r--gr-filter/grc/dc_blocker_xx.xml51
-rw-r--r--gr-filter/grc/fft_filter_xxx.xml59
-rw-r--r--gr-filter/grc/filter_block_tree.xml51
-rw-r--r--gr-filter/grc/filter_delay_fc.xml31
-rw-r--r--gr-filter/grc/fir_filter_xxx.xml80
-rw-r--r--gr-filter/grc/fractional_interpolator_xx.xml46
-rw-r--r--gr-filter/grc/freq_xlating_fir_filter_xxx.xml93
-rw-r--r--gr-filter/grc/hilbert_fc.xml26
-rw-r--r--gr-filter/grc/iir_filter_ffd.xml31
-rw-r--r--gr-filter/grc/interp_fir_filter_xxx.xml80
-rw-r--r--gr-filter/grc/pfb_arb_resampler.xml61
-rw-r--r--gr-filter/grc/pfb_channelizer.xml62
-rw-r--r--gr-filter/grc/pfb_decimator.xml43
-rw-r--r--gr-filter/grc/pfb_interpolator.xml36
-rw-r--r--gr-filter/grc/pfb_synthesizer.xml57
-rw-r--r--gr-filter/grc/rational_resampler_base_xxx.xml86
-rw-r--r--gr-filter/grc/single_pole_iir_filter_xx.xml51
-rw-r--r--gr-filter/include/filter/CMakeLists.txt116
-rw-r--r--gr-filter/include/filter/adaptive_fir_ccc.h85
-rw-r--r--gr-filter/include/filter/adaptive_fir_ccf.h81
-rw-r--r--gr-filter/include/filter/api.h33
-rw-r--r--gr-filter/include/filter/channel_model.h87
-rw-r--r--gr-filter/include/filter/dc_blocker_cc.h76
-rw-r--r--gr-filter/include/filter/dc_blocker_ff.h76
-rw-r--r--gr-filter/include/filter/fft_filter.h171
-rw-r--r--gr-filter/include/filter/fft_filter_ccc.h86
-rw-r--r--gr-filter/include/filter/fft_filter_fff.h86
-rw-r--r--gr-filter/include/filter/filter_delay_fc.h65
-rw-r--r--gr-filter/include/filter/fir_filter.h222
-rw-r--r--gr-filter/include/filter/fir_filter_XXX.h.t82
-rw-r--r--gr-filter/include/filter/fir_filter_with_buffer.h326
-rw-r--r--gr-filter/include/filter/firdes.h378
-rw-r--r--gr-filter/include/filter/fractional_interpolator_cc.h60
-rw-r--r--gr-filter/include/filter/fractional_interpolator_ff.h60
-rw-r--r--gr-filter/include/filter/freq_xlating_fir_filter_XXX.h.t90
-rw-r--r--gr-filter/include/filter/hilbert_fc.h53
-rw-r--r--gr-filter/include/filter/iir_filter.h183
-rw-r--r--gr-filter/include/filter/iir_filter_ffd.h82
-rw-r--r--gr-filter/include/filter/interp_fir_filter_XXX.h.t81
-rw-r--r--gr-filter/include/filter/interpolator_taps.h140
-rw-r--r--gr-filter/include/filter/mmse_fir_interpolator_cc.h79
-rw-r--r--gr-filter/include/filter/mmse_fir_interpolator_ff.h76
-rw-r--r--gr-filter/include/filter/pfb_arb_resampler_ccf.h151
-rw-r--r--gr-filter/include/filter/pfb_arb_resampler_fff.h152
-rw-r--r--gr-filter/include/filter/pfb_channelizer_ccf.h204
-rw-r--r--gr-filter/include/filter/pfb_decimator_ccf.h131
-rw-r--r--gr-filter/include/filter/pfb_interpolator_ccf.h118
-rw-r--r--gr-filter/include/filter/pfb_synthesizer_ccf.h107
-rw-r--r--gr-filter/include/filter/pm_remez.h72
-rw-r--r--gr-filter/include/filter/polyphase_filterbank.h148
-rw-r--r--gr-filter/include/filter/rational_resampler_base_XXX.h.t61
-rw-r--r--gr-filter/include/filter/single_pole_iir.h200
-rw-r--r--gr-filter/include/filter/single_pole_iir_filter_cc.h78
-rw-r--r--gr-filter/include/filter/single_pole_iir_filter_ff.h78
-rw-r--r--gr-filter/lib/CMakeLists.txt185
-rw-r--r--gr-filter/lib/adaptive_fir_ccc_impl.cc106
-rw-r--r--gr-filter/lib/adaptive_fir_ccc_impl.h61
-rw-r--r--gr-filter/lib/adaptive_fir_ccf_impl.cc106
-rw-r--r--gr-filter/lib/adaptive_fir_ccf_impl.h61
-rw-r--r--gr-filter/lib/channel_model_impl.cc135
-rw-r--r--gr-filter/lib/channel_model_impl.h74
-rw-r--r--gr-filter/lib/dc_blocker_cc_impl.cc144
-rw-r--r--gr-filter/lib/dc_blocker_cc_impl.h76
-rw-r--r--gr-filter/lib/dc_blocker_ff_impl.cc142
-rw-r--r--gr-filter/lib/dc_blocker_ff_impl.h76
-rw-r--r--gr-filter/lib/fft_filter.cc316
-rw-r--r--gr-filter/lib/fft_filter_ccc_impl.cc118
-rw-r--r--gr-filter/lib/fft_filter_ccc_impl.h61
-rw-r--r--gr-filter/lib/fft_filter_fff_impl.cc119
-rw-r--r--gr-filter/lib/fft_filter_fff_impl.h61
-rw-r--r--gr-filter/lib/filter_delay_fc_impl.cc112
-rw-r--r--gr-filter/lib/filter_delay_fc_impl.h56
-rw-r--r--gr-filter/lib/fir_filter.cc667
-rw-r--r--gr-filter/lib/fir_filter_XXX_impl.cc.t104
-rw-r--r--gr-filter/lib/fir_filter_XXX_impl.h.t56
-rw-r--r--gr-filter/lib/fir_filter_with_buffer.cc496
-rw-r--r--gr-filter/lib/firdes.cc855
-rw-r--r--gr-filter/lib/fractional_interpolator_cc_impl.cc125
-rw-r--r--gr-filter/lib/fractional_interpolator_cc_impl.h61
-rw-r--r--gr-filter/lib/fractional_interpolator_ff_impl.cc125
-rw-r--r--gr-filter/lib/fractional_interpolator_ff_impl.h61
-rw-r--r--gr-filter/lib/freq_xlating_fir_filter_XXX_impl.cc.t143
-rw-r--r--gr-filter/lib/freq_xlating_fir_filter_XXX_impl.h.t71
-rw-r--r--gr-filter/lib/hilbert_fc_impl.cc76
-rw-r--r--gr-filter/lib/hilbert_fc_impl.h52
-rw-r--r--gr-filter/lib/iir_filter_ffd_impl.cc85
-rw-r--r--gr-filter/lib/iir_filter_ffd_impl.h56
-rw-r--r--gr-filter/lib/interp_fir_filter_XXX_impl.cc.t151
-rw-r--r--gr-filter/lib/interp_fir_filter_XXX_impl.h.t62
-rw-r--r--gr-filter/lib/mmse_fir_interpolator_cc.cc77
-rw-r--r--gr-filter/lib/mmse_fir_interpolator_ff.cc77
-rw-r--r--gr-filter/lib/pfb_arb_resampler_ccf_impl.cc258
-rw-r--r--gr-filter/lib/pfb_arb_resampler_ccf_impl.h89
-rw-r--r--gr-filter/lib/pfb_arb_resampler_fff_impl.cc258
-rw-r--r--gr-filter/lib/pfb_arb_resampler_fff_impl.h88
-rw-r--r--gr-filter/lib/pfb_channelizer_ccf_impl.cc191
-rw-r--r--gr-filter/lib/pfb_channelizer_ccf_impl.h69
-rw-r--r--gr-filter/lib/pfb_decimator_ccf_impl.cc137
-rw-r--r--gr-filter/lib/pfb_decimator_ccf_impl.h65
-rw-r--r--gr-filter/lib/pfb_interpolator_ccf_impl.cc107
-rw-r--r--gr-filter/lib/pfb_interpolator_ccf_impl.h61
-rw-r--r--gr-filter/lib/pfb_synthesizer_ccf_impl.cc287
-rw-r--r--gr-filter/lib/pfb_synthesizer_ccf_impl.h85
-rw-r--r--gr-filter/lib/pm_remez.cc834
-rw-r--r--gr-filter/lib/polyphase_filterbank.cc114
-rw-r--r--gr-filter/lib/qa_filter.cc47
-rw-r--r--gr-filter/lib/qa_filter.h38
-rw-r--r--gr-filter/lib/qa_fir_filter_with_buffer.cc406
-rw-r--r--gr-filter/lib/qa_fir_filter_with_buffer.h94
-rw-r--r--gr-filter/lib/qa_firdes.cc621
-rw-r--r--gr-filter/lib/qa_firdes.h56
-rw-r--r--gr-filter/lib/qa_mmse_fir_interpolator_cc.cc126
-rw-r--r--gr-filter/lib/qa_mmse_fir_interpolator_cc.h48
-rw-r--r--gr-filter/lib/qa_mmse_fir_interpolator_ff.cc71
-rw-r--r--gr-filter/lib/qa_mmse_fir_interpolator_ff.h45
-rw-r--r--gr-filter/lib/rational_resampler_base_XXX_impl.cc.t174
-rw-r--r--gr-filter/lib/rational_resampler_base_XXX_impl.h.t72
-rw-r--r--gr-filter/lib/single_pole_iir_filter_cc_impl.cc89
-rw-r--r--gr-filter/lib/single_pole_iir_filter_cc_impl.h55
-rw-r--r--gr-filter/lib/single_pole_iir_filter_ff_impl.cc87
-rw-r--r--gr-filter/lib/single_pole_iir_filter_ff_impl.h54
-rw-r--r--gr-filter/lib/test_gr_filter.cc43
-rw-r--r--gr-filter/python/CMakeLists.txt50
-rw-r--r--gr-filter/python/__init__.py30
-rw-r--r--gr-filter/python/optfir.py339
-rw-r--r--gr-filter/python/pfb.py271
-rwxr-xr-xgr-filter/python/qa_adaptive_fir_filter.py159
-rwxr-xr-xgr-filter/python/qa_channel_model.py60
-rwxr-xr-xgr-filter/python/qa_dc_blocker.py109
-rwxr-xr-xgr-filter/python/qa_fft_filter.py380
-rwxr-xr-xgr-filter/python/qa_filter_delay_fc.py318
-rwxr-xr-xgr-filter/python/qa_fir_filter.py318
-rwxr-xr-xgr-filter/python/qa_firdes.py202
-rwxr-xr-xgr-filter/python/qa_fractional_interpolator.py89
-rwxr-xr-xgr-filter/python/qa_freq_xlating_fir_filter.py445
-rwxr-xr-xgr-filter/python/qa_hilbert.py117
-rwxr-xr-xgr-filter/python/qa_iir_filter.py157
-rwxr-xr-xgr-filter/python/qa_interp_fir_filter.py60
-rwxr-xr-xgr-filter/python/qa_pfb_arb_resampler.py95
-rwxr-xr-xgr-filter/python/qa_pfb_channelizer.py104
-rwxr-xr-xgr-filter/python/qa_pfb_decimator.py125
-rwxr-xr-xgr-filter/python/qa_pfb_interpolator.py71
-rwxr-xr-xgr-filter/python/qa_pfb_synthesizer.py87
-rwxr-xr-xgr-filter/python/qa_pm_remez.py188
-rwxr-xr-xgr-filter/python/qa_rational_resampler.py257
-rwxr-xr-xgr-filter/python/qa_single_pole_iir.py114
-rw-r--r--gr-filter/python/rational_resampler.py129
-rw-r--r--gr-filter/swig/CMakeLists.txt53
-rw-r--r--gr-filter/swig/filter_swig.i169
-rw-r--r--gr-uhd/include/gr_uhd_usrp_source.h6
-rw-r--r--gr-uhd/lib/gr_uhd_usrp_source.cc23
-rw-r--r--gr-wavelet/lib/CMakeLists.txt9
-rw-r--r--gr-wxgui/CMakeLists.txt2
-rw-r--r--grc/CMakeLists.txt2
-rw-r--r--grc/blocks/block_tree.xml2
-rw-r--r--grc/blocks/gr_message_burst_source.xml58
-rw-r--r--grc/blocks/gr_tag_debug.xml82
-rw-r--r--gruel/src/include/gruel/CMakeLists.txt20
-rw-r--r--gruel/src/include/gruel/inet.h.in100
-rw-r--r--gruel/src/lib/pmt/pmt-serial-tags.scm2
-rw-r--r--gruel/src/lib/pmt/pmt_serialize.cc56
-rw-r--r--gruel/src/swig/CMakeLists.txt2
-rw-r--r--volk/apps/volk_profile.cc4
-rw-r--r--volk/gen/machines.xml6
-rw-r--r--volk/include/volk/volk_16i_32fc_dot_prod_32fc_a.h122
-rw-r--r--volk/include/volk/volk_16u_byteswap_u.h63
-rw-r--r--volk/include/volk/volk_32f_x2_dot_prod_16i_a.h98
-rw-r--r--volk/include/volk/volk_32f_x2_dot_prod_32f_a.h169
-rw-r--r--volk/include/volk/volk_32f_x2_dot_prod_32f_u.h170
-rw-r--r--volk/include/volk/volk_32fc_32f_dot_prod_32fc_a.h111
-rw-r--r--volk/include/volk/volk_32fc_s32fc_x2_rotator_32fc_a.h4
-rw-r--r--volk/include/volk/volk_32fc_x2_dot_prod_32fc_a.h35
-rw-r--r--volk/lib/CMakeLists.txt8
-rw-r--r--volk/lib/testqa.cc6
243 files changed, 26914 insertions, 2214 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 19f6fedff..d4155ff3d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -41,8 +41,8 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)
# Set the version information here
set(VERSION_INFO_MAJOR_VERSION 3)
set(VERSION_INFO_API_COMPAT 6)
-set(VERSION_INFO_MINOR_VERSION 1)
-set(VERSION_INFO_MAINT_VERSION 0)
+set(VERSION_INFO_MINOR_VERSION 2)
+set(VERSION_INFO_MAINT_VERSION git)
include(GrVersion) #setup version info
# Append -O2 optimization flag for Debug builds
@@ -107,6 +107,8 @@ set(GR_PKG_CONF_DIR ${GR_CONF_DIR}/${CMAKE_PROJECT_NAME}/conf.d)
set(GR_LIBEXEC_DIR libexec)
set(GR_PKG_LIBEXEC_DIR ${GR_LIBEXEC_DIR}/${CMAKE_PROJECT_NAME})
set(GRC_BLOCKS_DIR ${GR_PKG_DATA_DIR}/grc/blocks)
+set(SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/${GR_CONF_DIR}" CACHE PATH "System configuration directory")
+set(GR_PREFSDIR ${SYSCONFDIR}/${CMAKE_PROJECT_NAME}/conf.d)
########################################################################
# Variables replaced when configuring the package config files
@@ -115,6 +117,8 @@ file(TO_NATIVE_PATH "${CMAKE_INSTALL_PREFIX}" prefix)
file(TO_NATIVE_PATH "\${prefix}" exec_prefix)
file(TO_NATIVE_PATH "\${exec_prefix}/${GR_LIBRARY_DIR}" libdir)
file(TO_NATIVE_PATH "\${prefix}/${GR_INCLUDE_DIR}" includedir)
+file(TO_NATIVE_PATH "${SYSCONFDIR}" SYSCONFDIR)
+file(TO_NATIVE_PATH "${GR_PREFSDIR}" GR_PREFSDIR)
########################################################################
# Create uninstall target
@@ -207,9 +211,6 @@ CPACK_COMPONENT("volk_devel"
add_subdirectory(volk)
endif(ENABLE_VOLK)
-
-GR_VMCIRCBUF()
-
########################################################################
# Distribute the README file
########################################################################
@@ -229,6 +230,7 @@ add_subdirectory(gnuradio-core)
add_subdirectory(grc)
add_subdirectory(gr-fft)
+add_subdirectory(gr-filter)
add_subdirectory(gr-atsc)
add_subdirectory(gr-audio)
add_subdirectory(gr-comedi)
diff --git a/cmake/Modules/GrMiscUtils.cmake b/cmake/Modules/GrMiscUtils.cmake
index 189e97c7e..a73e3e6d7 100644
--- a/cmake/Modules/GrMiscUtils.cmake
+++ b/cmake/Modules/GrMiscUtils.cmake
@@ -208,28 +208,3 @@ function(GR_GEN_TARGET_DEPS name var)
set(${var} "DEPENDS;${name};COMMAND;${name}" PARENT_SCOPE)
endif()
endfunction(GR_GEN_TARGET_DEPS)
-
-
-########################################################################
-# Control availability of vmcircbuf methods.
-# For now, only allows disabling of shm methods, which cause uncatchable
-# segmentation faults on Cygwin with gcc 4.x (x <= 5)
-# Usage:
-# GR_VMCIRCBUF()
-#
-# Will set TRY_SHM_VMCIRCBUF to 1 by default except on Windows machines.
-# Can manually set with -DTRY_SHM_VMCIRCBUF=0|1
-########################################################################
-function(GR_VMCIRCBUF)
- if(WIN32)
- OPTION(TRY_SHM_VMCIRCBUF "Try SHM VMCIRCBUF" OFF)
- else(WIN32)
- OPTION(TRY_SHM_VMCIRCBUF "Try SHM VMCIRCBUF" ON)
- endif(WIN32)
-
- message(STATUS "TRY_SHM_VMCIRCBUF set to ${TRY_SHM_VMCIRCBUF}.")
-
- if(TRY_SHM_VMCIRCBUF)
- add_definitions( -DTRY_SHM_VMCIRCBUF )
- endif(TRY_SHM_VMCIRCBUF)
-endfunction(GR_VMCIRCBUF)
diff --git a/cmake/Modules/GrSwig.cmake b/cmake/Modules/GrSwig.cmake
index ff56faa0d..175d0d759 100644
--- a/cmake/Modules/GrSwig.cmake
+++ b/cmake/Modules/GrSwig.cmake
@@ -67,7 +67,6 @@ function(GR_SWIG_MAKE_DOCS output_file)
#call doxygen on the Doxyfile + input headers
add_custom_command(
OUTPUT ${OUTPUT_DIRECTORY}/xml/index.xml
- ${OUTPUT_DIRECTORY}/xml/combine.xslt
DEPENDS ${input_files} ${GR_SWIG_DOCS_SOURCE_DEPS} ${tag_deps}
COMMAND ${DOXYGEN_EXECUTABLE} ${OUTPUT_DIRECTORY}/Doxyfile
COMMENT "Generating doxygen xml for ${name} docs"
@@ -81,6 +80,7 @@ function(GR_SWIG_MAKE_DOCS output_file)
${CMAKE_SOURCE_DIR}/docs/doxygen/swig_doc.py
${OUTPUT_DIRECTORY}/xml
${output_file}
+ COMMENT "Generating python docstrings for ${name}"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs/doxygen
)
diff --git a/gnuradio-core/CMakeLists.txt b/gnuradio-core/CMakeLists.txt
index 022710844..4e76b3c5a 100644
--- a/gnuradio-core/CMakeLists.txt
+++ b/gnuradio-core/CMakeLists.txt
@@ -64,6 +64,7 @@ GR_SET_GLOBAL(GNURADIO_CORE_INCLUDE_DIRS
GR_SET_GLOBAL(GNURADIO_CORE_SWIG_INCLUDE_DIRS
${CMAKE_SOURCE_DIR}/gruel/src/swig
+ ${CMAKE_BINARY_DIR}/gruel/src/swig/
${CMAKE_CURRENT_SOURCE_DIR}/src/lib/swig
${GNURADIO_CORE_INCLUDE_DIRS}
)
@@ -109,7 +110,7 @@ CPACK_COMPONENT("core_swig"
install(
FILES gnuradio-core.conf
- DESTINATION ${GR_PKG_CONF_DIR}
+ DESTINATION ${GR_PREFSDIR}
COMPONENT "core_runtime"
)
diff --git a/gnuradio-core/src/lib/filter/CMakeLists.txt b/gnuradio-core/src/lib/filter/CMakeLists.txt
index facaff764..088d3376d 100644
--- a/gnuradio-core/src/lib/filter/CMakeLists.txt
+++ b/gnuradio-core/src/lib/filter/CMakeLists.txt
@@ -210,6 +210,9 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
${CMAKE_CURRENT_SOURCE_DIR}/qa_dotprod_powerpc.cc
)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
+ if(have_mfpu_neon)
+ add_definitions(-DHAVE_MFPU_NEON)
+ endif()
list(APPEND gnuradio_core_sources
${CMAKE_CURRENT_SOURCE_DIR}/sysconfig_armv7_a.cc
${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_sysconfig_armv7_a.cc
diff --git a/gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.c b/gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.c
index e7c6b266e..c125b49b3 100644
--- a/gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.c
+++ b/gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.c
@@ -37,7 +37,7 @@ gr_p2_round_down(size_t x, size_t pow2)
}
-#if 0
+#ifndef HAVE_MFPU_NEON
void
dotprod_ccf_armv7_a(const float *a, const float *b, float *res, size_t n)
diff --git a/gnuradio-core/src/lib/filter/dotprod_fff_armv7_a.c b/gnuradio-core/src/lib/filter/dotprod_fff_armv7_a.c
index 68c448b35..23bbef033 100644
--- a/gnuradio-core/src/lib/filter/dotprod_fff_armv7_a.c
+++ b/gnuradio-core/src/lib/filter/dotprod_fff_armv7_a.c
@@ -37,7 +37,7 @@ gr_p2_round_down(size_t x, size_t pow2)
}
-#if 0
+#ifndef HAVE_MFPU_NEON
float
dotprod_fff_armv7_a(const float *a, const float *b, size_t n)
diff --git a/gnuradio-core/src/lib/general/CMakeLists.txt b/gnuradio-core/src/lib/general/CMakeLists.txt
index e97644ffa..5c7b0f374 100644
--- a/gnuradio-core/src/lib/general/CMakeLists.txt
+++ b/gnuradio-core/src/lib/general/CMakeLists.txt
@@ -52,9 +52,6 @@ message(STATUS "Loading build date ${BUILD_DATE} into gr_constants...")
message(STATUS "Loading version ${VERSION} into gr_constants...")
-file(TO_NATIVE_PATH "${CMAKE_INSTALL_PREFIX}/${GR_CONF_DIR}" SYSCONFDIR)
-file(TO_NATIVE_PATH "${CMAKE_INSTALL_PREFIX}/${GR_PKG_CONF_DIR}" GR_PREFSDIR)
-
#double escape for windows backslash path separators
string(REPLACE "\\" "\\\\" prefix ${prefix})
string(REPLACE "\\" "\\\\" SYSCONFDIR ${SYSCONFDIR})
@@ -296,8 +293,10 @@ set(gr_core_general_triple_threats
gr_probe_density_b
gr_annotator_alltoall
gr_annotator_1to1
+ gr_annotator_raw
gr_burst_tagger
gr_correlate_access_code_tag_bb
+ gr_tag_debug
)
foreach(file_tt ${gr_core_general_triple_threats})
diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i
index 0696addbd..c0ce65527 100644
--- a/gnuradio-core/src/lib/general/general.i
+++ b/gnuradio-core/src/lib/general/general.i
@@ -135,11 +135,13 @@
#include <complex_vec_test.h>
#include <gr_annotator_alltoall.h>
#include <gr_annotator_1to1.h>
+#include <gr_annotator_raw.h>
#include <gr_burst_tagger.h>
#include <gr_cpm.h>
#include <gr_correlate_access_code_tag_bb.h>
#include <gr_add_ff.h>
#include <gr_vector_map.h>
+#include <gr_tag_debug.h>
%}
%include "gri_control_loop.i"
@@ -255,8 +257,10 @@
%include "complex_vec_test.i"
%include "gr_annotator_alltoall.i"
%include "gr_annotator_1to1.i"
+%include "gr_annotator_raw.i"
%include "gr_burst_tagger.i"
%include "gr_cpm.i"
%include "gr_correlate_access_code_tag_bb.i"
%include "gr_add_ff.i"
%include "gr_vector_map.i"
+%include "gr_tag_debug.i"
diff --git a/gnuradio-core/src/lib/general/gr_annotator_raw.cc b/gnuradio-core/src/lib/general/gr_annotator_raw.cc
new file mode 100644
index 000000000..e1ae73efb
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_annotator_raw.cc
@@ -0,0 +1,106 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_annotator_raw.h>
+#include <gr_io_signature.h>
+#include <string.h>
+#include <iostream>
+#include <iomanip>
+#include <stdexcept>
+
+using namespace pmt;
+
+gr_annotator_raw_sptr
+gr_make_annotator_raw(size_t sizeof_stream_item)
+{
+ return gnuradio::get_initial_sptr(new gr_annotator_raw
+ (sizeof_stream_item));
+}
+
+gr_annotator_raw::gr_annotator_raw(size_t sizeof_stream_item)
+ : gr_sync_block("annotator_raw",
+ gr_make_io_signature(1, 1, sizeof_stream_item),
+ gr_make_io_signature(1, 1, sizeof_stream_item)),
+ d_itemsize(sizeof_stream_item)
+{
+ set_tag_propagation_policy(TPP_ONE_TO_ONE);
+ set_relative_rate(1.0);
+}
+
+void gr_annotator_raw::add_tag(uint64_t offset, pmt_t key, pmt_t val)
+{
+ gruel::scoped_lock l(d_mutex);
+
+ gr_tag_t tag;
+ tag.srcid = pmt::pmt_intern(d_name);
+ tag.key = key;
+ tag.value = val;
+ tag.offset = offset;
+
+ // add our new tag
+ d_queued_tags.push_back(tag);
+ // make sure our tags are in offset order
+ std::sort(d_queued_tags.begin(), d_queued_tags.end(),
+ gr_tag_t::offset_compare);
+ // make sure we are not adding an item in the past!
+ if(tag.offset > nitems_read(0)) {
+ throw std::runtime_error("gr_annotator_raw::add_tag: item added too far in the past\n.");
+ }
+}
+
+gr_annotator_raw::~gr_annotator_raw()
+{
+}
+
+int
+gr_annotator_raw::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ gruel::scoped_lock l(d_mutex);
+
+ const char *in = (const char*)input_items[0];
+ char *out = (char*)output_items[0];
+
+ uint64_t start_N = nitems_read(0);
+ uint64_t end_N = start_N + (uint64_t)(noutput_items);
+
+ // locate queued tags that fall in this range and insert them when appropriate
+ std::vector<gr_tag_t>::iterator i = d_queued_tags.begin();
+ while( i != d_queued_tags.end() ) {
+ if( (*i).offset >= start_N && (*i).offset < end_N) {
+ add_item_tag(0, (*i).offset,(*i).key, (*i).value, (*i).srcid);
+ i = d_queued_tags.erase(i);
+ }
+ else {
+ break;
+ }
+ }
+
+ // copy data across
+ memcpy(out, in, noutput_items*d_itemsize);
+ return noutput_items;
+}
diff --git a/gnuradio-core/src/lib/general/gr_annotator_raw.h b/gnuradio-core/src/lib/general/gr_annotator_raw.h
new file mode 100644
index 000000000..8a6c3f6c0
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_annotator_raw.h
@@ -0,0 +1,69 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_ANNOTATOR_RAW_H
+#define INCLUDED_GR_ANNOTATOR_RAW_H
+
+#include <gr_core_api.h>
+#include <gr_sync_block.h>
+#include <gruel/pmt.h>
+#include <gruel/thread.h>
+
+class gr_annotator_raw;
+typedef boost::shared_ptr<gr_annotator_raw> gr_annotator_raw_sptr;
+
+// public constructor
+GR_CORE_API gr_annotator_raw_sptr
+gr_make_annotator_raw(size_t sizeof_stream_item);
+
+/*!
+ * \brief raw stream annotator testing block.
+ *
+ * This block creates arbitrary tags to be sent downstream
+ * blocks to be sent are set manually via accessor methods and are sent only once.
+ *
+ * This block is intended for testing of tag related blocks
+ */
+class GR_CORE_API gr_annotator_raw : public gr_sync_block
+{
+ public:
+ ~gr_annotator_raw();
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ // insert a tag to be added
+ void add_tag(uint64_t offset, pmt::pmt_t key, pmt::pmt_t val);
+
+protected:
+ gr_annotator_raw(size_t sizeof_stream_item);
+
+ private:
+ size_t d_itemsize;
+ std::vector<gr_tag_t> d_queued_tags;
+ gruel::mutex d_mutex;
+
+ friend GR_CORE_API gr_annotator_raw_sptr
+ gr_make_annotator_raw(size_t sizeof_stream_item);
+};
+
+#endif
diff --git a/gnuradio-core/src/lib/general/gr_annotator_raw.i b/gnuradio-core/src/lib/general/gr_annotator_raw.i
new file mode 100644
index 000000000..85777ef5d
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_annotator_raw.i
@@ -0,0 +1,26 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010-2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,annotator_raw);
+
+%include <pmt_swig.i>
+%include <gr_annotator_raw.h>
diff --git a/gnuradio-core/src/lib/general/gr_tag_debug.cc b/gnuradio-core/src/lib/general/gr_tag_debug.cc
new file mode 100644
index 000000000..c4031f438
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_tag_debug.cc
@@ -0,0 +1,100 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_tag_debug.h>
+#include <gr_io_signature.h>
+#include <iostream>
+#include <iomanip>
+
+gr_tag_debug_sptr
+gr_make_tag_debug(size_t sizeof_stream_item, const std::string &name)
+{
+ return gnuradio::get_initial_sptr
+ (new gr_tag_debug(sizeof_stream_item, name));
+}
+
+gr_tag_debug::gr_tag_debug(size_t sizeof_stream_item, const std::string &name)
+ : gr_sync_block("tag_debug",
+ gr_make_io_signature(1, -1, sizeof_stream_item),
+ gr_make_io_signature(0, 0, 0)),
+ d_name(name), d_display(true)
+{
+}
+
+std::vector<gr_tag_t>
+gr_tag_debug::current_tags()
+{
+ gruel::scoped_lock l(d_mutex);
+ return d_tags;
+}
+
+void
+gr_tag_debug::set_display(bool d)
+{
+ gruel::scoped_lock l(d_mutex);
+ d_display = d;
+}
+
+int
+gr_tag_debug::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ gruel::scoped_lock l(d_mutex);
+
+ if(d_display) {
+ std::cout << std::endl
+ << "----------------------------------------------------------------------";
+ std::cout << std::endl << "Tag Debug: " << d_name << std::endl;
+ }
+
+ uint64_t abs_N, end_N;
+ for(size_t i = 0; i < input_items.size(); i++) {
+ abs_N = nitems_read(i);
+ end_N = abs_N + (uint64_t)(noutput_items);
+
+ d_tags.clear();
+ get_tags_in_range(d_tags, i, abs_N, end_N);
+
+ if(d_display) {
+ std::cout << "Input Stream: " << i << std::endl;
+ for(d_tags_itr = d_tags.begin(); d_tags_itr != d_tags.end(); d_tags_itr++) {
+ std::cout << std::setw(10) << "Offset: " << d_tags_itr->offset
+ << std::setw(10) << "Source: " << pmt::pmt_symbol_to_string(d_tags_itr->srcid)
+ << std::setw(10) << "Key: " << pmt::pmt_symbol_to_string(d_tags_itr->key)
+ << std::setw(10) << "Value: ";
+ pmt::pmt_print(d_tags_itr->value);
+ }
+ }
+ }
+
+ if(d_display) {
+ std::cout << "----------------------------------------------------------------------";
+ std::cout << std::endl;
+ }
+
+ return noutput_items;
+}
diff --git a/gnuradio-core/src/lib/general/gr_tag_debug.h b/gnuradio-core/src/lib/general/gr_tag_debug.h
new file mode 100644
index 000000000..57578884a
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_tag_debug.h
@@ -0,0 +1,85 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_TAG_DEBUG_H
+#define INCLUDED_GR_TAG_DEBUG_H
+
+#include <gr_core_api.h>
+#include <gr_sync_block.h>
+#include <gruel/thread.h>
+#include <stddef.h>
+
+class gr_tag_debug;
+typedef boost::shared_ptr<gr_tag_debug> gr_tag_debug_sptr;
+
+GR_CORE_API gr_tag_debug_sptr
+gr_make_tag_debug(size_t sizeof_stream_item, const std::string &name);
+
+/*!
+ * \brief Bit bucket that prints out any tag received.
+ * \ingroup sink_blk
+ *
+ * This block collects all tags sent to it on all input ports and
+ * displays them to stdout in a formatted way. The \p name parameter
+ * is used to identify which debug sink generated the tag, so when
+ * connecting a block to this debug sink, an appropriate name is
+ * something that identifies the input block.
+ *
+ * This block otherwise acts as a NULL sink in that items from the
+ * input stream are ignored. It is designed to be able to attach to
+ * any block and watch all tags streaming out of that block for
+ * debugging purposes.
+ *
+ * The tags from the last call to this work function are stored and
+ * can be retrieved using the function 'current_tags'.
+ */
+class GR_CORE_API gr_tag_debug : public gr_sync_block
+{
+ private:
+ friend GR_CORE_API gr_tag_debug_sptr
+ gr_make_tag_debug(size_t sizeof_stream_item, const std::string &name);
+ gr_tag_debug(size_t sizeof_stream_item, const std::string &name);
+
+ std::string d_name;
+ std::vector<gr_tag_t> d_tags;
+ std::vector<gr_tag_t>::iterator d_tags_itr;
+ bool d_display;
+ gruel::mutex d_mutex;
+
+ public:
+ /*!
+ * \brief Returns a vector of gr_tag_t items as of the last call to
+ * work.
+ */
+ std::vector<gr_tag_t> current_tags();
+
+ /*!
+ * \brief Set the display of tags to stdout on/off.
+ */
+ void set_display(bool d);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif /* INCLUDED_GR_TAG_DEBUG_H */
diff --git a/gnuradio-core/src/lib/general/gr_tag_debug.i b/gnuradio-core/src/lib/general/gr_tag_debug.i
new file mode 100644
index 000000000..3af1bdcfe
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_tag_debug.i
@@ -0,0 +1,35 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,tag_debug)
+
+%include <gr_tags.i>
+
+gr_tag_debug_sptr
+gr_make_tag_debug(size_t sizeof_stream_item, const std::string &name);
+
+class gr_tag_debug : public gr_sync_block
+{
+public:
+ std::vector<gr_tag_t> current_tags();
+ void set_display(bool d);
+};
diff --git a/gnuradio-core/src/lib/gengen/CMakeLists.txt b/gnuradio-core/src/lib/gengen/CMakeLists.txt
index 22ac1bc58..b44a47075 100644
--- a/gnuradio-core/src/lib/gengen/CMakeLists.txt
+++ b/gnuradio-core/src/lib/gengen/CMakeLists.txt
@@ -89,7 +89,7 @@ expand_h_cc_i(gr_sig_source_X s i f c)
expand_h_cc_i(gr_probe_signal_X b s i f c)
expand_h_cc_i(gr_probe_signal_vX b s i f c)
-expand_h_cc_i(gr_add_const_XX ss ii ff cc sf)
+expand_h_cc_i(gr_add_const_XX bb ss ii ff cc sf)
expand_h_cc_i(gr_multiply_const_XX ss ii)
expand_h_cc_i(gr_add_XX ss ii cc)
expand_h_cc_i(gr_sub_XX ss ii ff cc)
diff --git a/gnuradio-core/src/lib/gengen/gr_sig_source_X.cc.t b/gnuradio-core/src/lib/gengen/gr_sig_source_X.cc.t
index bdd0e810a..6959eac82 100644
--- a/gnuradio-core/src/lib/gengen/gr_sig_source_X.cc.t
+++ b/gnuradio-core/src/lib/gengen/gr_sig_source_X.cc.t
@@ -29,6 +29,7 @@
#include <algorithm>
#include <gr_io_signature.h>
#include <stdexcept>
+#include <algorithm>
#include <gr_complex.h>
@@ -64,8 +65,7 @@ int
case GR_CONST_WAVE:
t = (gr_complex) d_ampl + d_offset;
- for (int i = 0; i < noutput_items; i++) // FIXME unroll
- optr[i] = t;
+ std::fill_n(optr, noutput_items, t);
break;
case GR_SIN_WAVE:
@@ -142,8 +142,7 @@ int
case GR_CONST_WAVE:
t = (@TYPE@) d_ampl + d_offset;
- for (int i = 0; i < noutput_items; i++) // FIXME unroll
- optr[i] = t;
+ std::fill_n(optr, noutput_items, t);
break;
case GR_SIN_WAVE:
diff --git a/gnuradio-core/src/lib/io/CMakeLists.txt b/gnuradio-core/src/lib/io/CMakeLists.txt
index af9d7583c..3dea13396 100644
--- a/gnuradio-core/src/lib/io/CMakeLists.txt
+++ b/gnuradio-core/src/lib/io/CMakeLists.txt
@@ -87,6 +87,7 @@ set(gr_core_io_triple_threats
gr_file_descriptor_source
gr_message_sink
gr_message_source
+ gr_message_burst_source
microtune_xxxx_eval_board
microtune_4702_eval_board
microtune_4937_eval_board
diff --git a/gnuradio-core/src/lib/io/gr_message_burst_source.cc b/gnuradio-core/src/lib/io/gr_message_burst_source.cc
new file mode 100644
index 000000000..e9e2dfd4d
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_message_burst_source.cc
@@ -0,0 +1,144 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_message_burst_source.h>
+#include <gr_io_signature.h>
+#include <cstdio>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdexcept>
+#include <string.h>
+#include <gr_tags.h>
+
+// public constructor that returns a shared_ptr
+
+gr_message_burst_source_sptr
+gr_make_message_burst_source(size_t itemsize, int msgq_limit)
+{
+ return gnuradio::get_initial_sptr(new gr_message_burst_source(itemsize, msgq_limit));
+}
+
+// public constructor that takes existing message queue
+gr_message_burst_source_sptr
+gr_make_message_burst_source(size_t itemsize, gr_msg_queue_sptr msgq)
+{
+ return gnuradio::get_initial_sptr(new gr_message_burst_source(itemsize, msgq));
+}
+
+gr_message_burst_source::gr_message_burst_source (size_t itemsize, int msgq_limit)
+ : gr_sync_block("message_burst_source",
+ gr_make_io_signature(0, 0, 0),
+ gr_make_io_signature(1, 1, itemsize)),
+ d_itemsize(itemsize), d_msgq(gr_make_msg_queue(msgq_limit)), d_msg_offset(0), d_eof(false)
+{
+ std::stringstream id;
+ id << name() << unique_id();
+ d_me = pmt::pmt_string_to_symbol(id.str());
+}
+
+gr_message_burst_source::gr_message_burst_source (size_t itemsize, gr_msg_queue_sptr msgq)
+ : gr_sync_block("message_burst_source",
+ gr_make_io_signature(0, 0, 0),
+ gr_make_io_signature(1, 1, itemsize)),
+ d_itemsize(itemsize), d_msgq(msgq), d_msg_offset(0), d_eof(false)
+{
+ std::stringstream id;
+ id << name() << unique_id();
+ d_me = pmt::pmt_string_to_symbol(id.str());
+}
+
+gr_message_burst_source::~gr_message_burst_source()
+{
+}
+
+int
+gr_message_burst_source::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ char *out = (char *) output_items[0];
+ int nn = 0;
+
+ uint64_t abs_sample_count = nitems_written(0);
+
+ while (nn < noutput_items){
+ if (d_msg){
+ //
+ // Consume whatever we can from the current message
+ //
+
+ int mm = std::min(noutput_items - nn, (int)((d_msg->length() - d_msg_offset) / d_itemsize));
+ memcpy (out, &(d_msg->msg()[d_msg_offset]), mm * d_itemsize);
+
+ nn += mm;
+ out += mm * d_itemsize;
+ d_msg_offset += mm * d_itemsize;
+ assert(d_msg_offset <= d_msg->length());
+
+ if (d_msg_offset == d_msg->length()){
+ if (d_msg->type() == 1) // type == 1 sets EOF
+ d_eof = true;
+ d_msg.reset();
+ //tag end of burst
+ add_item_tag(0, //stream ID
+ abs_sample_count+nn-1, //sample number
+ pmt::pmt_string_to_symbol("tx_eob"),
+ pmt::pmt_from_bool(1),
+ d_me //block src id
+ );
+ }
+ }
+ else {
+ //
+ // No current message
+ //
+ if (d_msgq->empty_p() && nn > 0){ // no more messages in the queue, return what we've got
+ break;
+ }
+
+ if (d_eof)
+ return -1;
+
+ d_msg = d_msgq->delete_head(); // block, waiting for a message
+ d_msg_offset = 0;
+ //tag start of burst
+ add_item_tag(0, //stream ID
+ abs_sample_count+nn, //sample number
+ pmt::pmt_string_to_symbol("tx_sob"),
+ pmt::pmt_from_bool(1),
+ d_me //block src id
+ );
+
+
+ if ((d_msg->length() % d_itemsize) != 0)
+ throw std::runtime_error("msg length is not a multiple of d_itemsize");
+ }
+ }
+
+ return nn;
+}
diff --git a/gnuradio-core/src/lib/io/gr_message_burst_source.h b/gnuradio-core/src/lib/io/gr_message_burst_source.h
new file mode 100644
index 000000000..63e220113
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_message_burst_source.h
@@ -0,0 +1,71 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_MESSAGE_BURST_SOURCE_H
+#define INCLUDED_GR_MESSAGE_BURST_SOURCE_H
+
+#include <gr_core_api.h>
+#include <gr_sync_block.h>
+#include <gr_message.h>
+#include <gr_msg_queue.h>
+
+class gr_message_burst_source;
+typedef boost::shared_ptr<gr_message_burst_source> gr_message_burst_source_sptr;
+
+GR_CORE_API gr_message_burst_source_sptr gr_make_message_burst_source (size_t itemsize, int msgq_limit=0);
+GR_CORE_API gr_message_burst_source_sptr gr_make_message_burst_source (size_t itemsize, gr_msg_queue_sptr msgq);
+
+/*!
+ * \brief Turn received messages into a stream and tag them for UHD to send.
+ * \ingroup source_blk
+ */
+class GR_CORE_API gr_message_burst_source : public gr_sync_block
+{
+ private:
+ size_t d_itemsize;
+ gr_msg_queue_sptr d_msgq;
+ gr_message_sptr d_msg;
+ unsigned d_msg_offset;
+ bool d_eof;
+
+ pmt::pmt_t d_me;
+
+ friend GR_CORE_API gr_message_burst_source_sptr
+ gr_make_message_burst_source(size_t itemsize, int msgq_limit);
+ friend GR_CORE_API gr_message_burst_source_sptr
+ gr_make_message_burst_source(size_t itemsize, gr_msg_queue_sptr msgq);
+
+ protected:
+ gr_message_burst_source (size_t itemsize, int msgq_limit);
+ gr_message_burst_source (size_t itemsize, gr_msg_queue_sptr msgq);
+
+ public:
+ ~gr_message_burst_source ();
+
+ gr_msg_queue_sptr msgq() const { return d_msgq; }
+
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif /* INCLUDED_gr_message_burst_source_H */
diff --git a/gnuradio-core/src/lib/io/gr_message_burst_source.i b/gnuradio-core/src/lib/io/gr_message_burst_source.i
new file mode 100644
index 000000000..f7ad840c2
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_message_burst_source.i
@@ -0,0 +1,38 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,message_burst_source);
+
+gr_message_burst_source_sptr gr_make_message_burst_source (size_t itemsize, int msgq_limit=0);
+gr_message_burst_source_sptr gr_make_message_burst_source (size_t itemsize, gr_msg_queue_sptr msgq);
+
+class gr_message_burst_source : public gr_sync_block
+{
+ protected:
+ gr_message_burst_source (size_t itemsize, int msgq_limit);
+ gr_message_burst_source (size_t itemsize, gr_msg_queue_sptr msgq);
+
+ public:
+ ~gr_message_burst_source ();
+
+ gr_msg_queue_sptr msgq() const;
+};
diff --git a/gnuradio-core/src/lib/io/gri_wavfile.cc b/gnuradio-core/src/lib/io/gri_wavfile.cc
index e316a0825..277e6b7b0 100644
--- a/gnuradio-core/src/lib/io/gri_wavfile.cc
+++ b/gnuradio-core/src/lib/io/gri_wavfile.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2008 Free Software Foundation, Inc.
+ * Copyright 2004,2008,2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -27,110 +27,45 @@
#include <gri_wavfile.h>
#include <cstring>
#include <stdint.h>
+#include <boost/detail/endian.hpp> //BOOST_BIG_ENDIAN
# define VALID_COMPRESSION_TYPE 0x0001
-// WAV files are always little-endian, so we need some byte switching macros
-
-// FIXME: Use libgruel versions
-
-#ifdef WORDS_BIGENDIAN
-
-#ifdef HAVE_BYTESWAP_H
-#include <byteswap.h>
-#else
-#warning Using non-portable code (likely wrong other than ILP32).
-
-static inline short int
-bswap_16 (unsigned short int x)
-{
- return ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8));
-}
-
-static inline unsigned int
-bswap_32 (unsigned int x)
-{
- return ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \
- | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24));
-}
-#endif // HAVE_BYTESWAP_H
-
-static inline uint32_t
-host_to_wav(uint32_t x)
-{
- return bswap_32(x);
-}
-
-static inline uint16_t
-host_to_wav(uint16_t x)
-{
- return bswap_16(x);
-}
-
-static inline int16_t
-host_to_wav(int16_t x)
-{
- return bswap_16(x);
-}
+// Basically, this is the opposite of htonx() and ntohx()
+// Define host to/from worknet (little endian) short and long
+#ifdef BOOST_BIG_ENDIAN
-static inline uint32_t
-wav_to_host(uint32_t x)
-{
- return bswap_32(x);
-}
+ static inline uint16_t __gri_wav_bs16(uint16_t x)
+ {
+ return (x>>8) | (x<<8);
+ }
-static inline uint16_t
-wav_to_host(uint16_t x)
-{
- return bswap_16(x);
-}
+ static inline uint32_t __gri_wav_bs32(uint32_t x)
+ {
+ return (uint32_t(__gri_wav_bs16(uint16_t(x&0xfffful)))<<16) | (__gri_wav_bs16(uint16_t(x>>16)));
+ }
-static inline int16_t
-wav_to_host(int16_t x)
-{
- return bswap_16(x);
-}
+ #define htowl(x) __gri_wav_bs32(x)
+ #define wtohl(x) __gri_wav_bs32(x)
+ #define htows(x) __gri_wav_bs16(x)
+ #define wtohs(x) __gri_wav_bs16(x)
#else
-static inline uint32_t
-host_to_wav(uint32_t x)
-{
- return x;
-}
-
-static inline uint16_t
-host_to_wav(uint16_t x)
-{
- return x;
-}
-
-static inline int16_t
-host_to_wav(int16_t x)
-{
- return x;
-}
-
-static inline uint32_t
-wav_to_host(uint32_t x)
-{
- return x;
-}
-
-static inline uint16_t
-wav_to_host(uint16_t x)
-{
- return x;
-}
-
-static inline int16_t
-wav_to_host(int16_t x)
-{
- return x;
-}
+ #define htowl(x) uint32_t(x)
+ #define wtohl(x) uint32_t(x)
+ #define htows(x) uint16_t(x)
+ #define wtohs(x) uint16_t(x)
-#endif // WORDS_BIGENDIAN
+#endif // BOOST_BIG_ENDIAN
+// WAV files are always little-endian, so we need some byte switching macros
+static inline uint32_t host_to_wav(uint32_t x) { return htowl(x); }
+static inline uint16_t host_to_wav(uint16_t x) { return htows(x); }
+static inline int16_t host_to_wav(int16_t x) { return htows(x); }
+static inline uint32_t wav_to_host(uint32_t x) { return wtohl(x); }
+static inline uint16_t wav_to_host(uint16_t x) { return wtohs(x); }
+static inline int16_t wav_to_host(int16_t x) { return wtohs(x); }
bool
gri_wavheader_parse(FILE *fp,
@@ -225,12 +160,15 @@ gri_wavheader_parse(FILE *fp,
short int
gri_wav_read_sample(FILE *fp, int bytes_per_sample)
{
- int16_t buf = 0;
- size_t fresult;
+ int16_t buf_16bit;
- fresult = fread(&buf, bytes_per_sample, 1, fp);
-
- return (short) wav_to_host(buf);
+ if(!fread(&buf_16bit, bytes_per_sample, 1, fp)) {
+ return 0;
+ }
+ if(bytes_per_sample == 1) {
+ return (short) buf_16bit;
+ }
+ return (short)wav_to_host(buf_16bit);
}
diff --git a/gnuradio-core/src/lib/io/gri_wavfile.h b/gnuradio-core/src/lib/io/gri_wavfile.h
index c757be26b..16280e34a 100644
--- a/gnuradio-core/src/lib/io/gri_wavfile.h
+++ b/gnuradio-core/src/lib/io/gri_wavfile.h
@@ -29,20 +29,15 @@
/*!
* \brief Read signal information from a given WAV file.
*
- * \p fp File pointer to an opened, empty file.
- * \p sample_rate Stores the sample rate [S/s]
- * \p nchans Number of channels
- * \p bytes_per_sample Bytes per sample, can either be 1 or 2 (corresponding to
- * 8 or 16 bit samples, respectively)
- * \p first_sample_pos Number of the first byte containing a sample. Use this
- * with fseek() to jump from the end of the file to the first sample
- * when in repeat mode.
- * \p samples_per_chan Number of samples per channel
- * \p normalize_fac The normalization factor with which you need to divide the
- * integer values of the samples to get them within [-1;1]
- * \p normalize_shift The value by which the sample values need to be shifted
- * after normalization (reason being, 8-bit WAV files store samples as
- * unsigned char and 16-bit as signed short int)
+ * \param[in] fp File pointer to an opened, empty file.
+ * \param[out] sample_rate Stores the sample rate [S/s]
+ * \param[out] nchans Number of channels
+ * \param[out] bytes_per_sample Bytes per sample, can either be 1 or 2 (corresponding o
+ * 8 or 16 bit samples, respectively)
+ * \param[out] first_sample_pos Number of the first byte containing a sample. Use this
+ * with fseek() to jump from the end of the file to the
+ * first sample when in repeat mode.
+ * \param[out] samples_per_chan Number of samples per channel
* \return True on a successful read, false if the file could not be read or is
* not a valid WAV file.
*/
@@ -94,8 +89,8 @@ gri_wav_write_sample(FILE *fp, short int sample, int bytes_per_sample);
* shouldn't happen), you need to fseek() to the end of the file (or
* whereever).
*
- * \p fp File pointer to an open WAV file with a blank header
- * \p byte_count Length of all samples written to the file in bytes.
+ * \param[in] fp File pointer to an open WAV file with a blank header
+ * \param[in] byte_count Length of all samples written to the file in bytes.
*/
bool
gri_wavheader_complete(FILE *fp, unsigned int byte_count);
diff --git a/gnuradio-core/src/lib/io/io.i b/gnuradio-core/src/lib/io/io.i
index eab1346f1..5cd352905 100644
--- a/gnuradio-core/src/lib/io/io.i
+++ b/gnuradio-core/src/lib/io/io.i
@@ -38,6 +38,7 @@
#include <gr_oscope_sink_f.h>
#include <ppio.h>
#include <gr_message_source.h>
+#include <gr_message_burst_source.h>
#include <gr_message_sink.h>
#include <gr_udp_sink.h>
#include <gr_udp_source.h>
@@ -59,6 +60,7 @@
%include "gr_oscope_sink.i"
%include "ppio.i"
%include "gr_message_source.i"
+%include "gr_message_burst_source.i"
%include "gr_message_sink.i"
%include "gr_udp_sink.i"
%include "gr_udp_source.i"
diff --git a/gnuradio-core/src/lib/runtime/CMakeLists.txt b/gnuradio-core/src/lib/runtime/CMakeLists.txt
index 1415ff4c6..5f3672dde 100644
--- a/gnuradio-core/src/lib/runtime/CMakeLists.txt
+++ b/gnuradio-core/src/lib/runtime/CMakeLists.txt
@@ -22,6 +22,29 @@
########################################################################
########################################################################
+# Control availability of vmcircbuf methods.
+# For now, only allows disabling of shm methods, which cause uncatchable
+# segmentation faults on Cygwin with gcc 4.x (x <= 5)
+# Usage:
+# GR_VMCIRCBUF()
+#
+# Will set TRY_SHM_VMCIRCBUF to 1 by default except on Windows machines.
+# Can manually set with -DTRY_SHM_VMCIRCBUF=0|1
+########################################################################
+
+ if(WIN32)
+ OPTION(TRY_SHM_VMCIRCBUF "Try SHM VMCIRCBUF" OFF)
+ else(WIN32)
+ OPTION(TRY_SHM_VMCIRCBUF "Try SHM VMCIRCBUF" ON)
+ endif(WIN32)
+
+ message(STATUS "TRY_SHM_VMCIRCBUF set to ${TRY_SHM_VMCIRCBUF}.")
+
+ if(TRY_SHM_VMCIRCBUF)
+ add_definitions( -DTRY_SHM_VMCIRCBUF )
+ endif(TRY_SHM_VMCIRCBUF)
+
+########################################################################
# Append gnuradio-core library sources
########################################################################
list(APPEND gnuradio_core_sources
diff --git a/gnuradio-core/src/python/build_utils.py b/gnuradio-core/src/python/build_utils.py
index ce0757912..77bf0607a 100644
--- a/gnuradio-core/src/python/build_utils.py
+++ b/gnuradio-core/src/python/build_utils.py
@@ -182,7 +182,7 @@ def standard_dict (name, code3, package='gr'):
d['GUARD_NAME'] = 'INCLUDED_%s_H' % name.upper ()
d['BASE_NAME'] = re.sub ('^' + package + '_', '', name)
d['SPTR_NAME'] = '%s_sptr' % name
- d['WARNING'] = 'WARNING: this file is machine generated. Edits will be over written'
+ d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten'
d['COPYRIGHT'] = copyright
d['TYPE'] = i_type (code3)
d['I_TYPE'] = i_type (code3)
@@ -190,3 +190,35 @@ def standard_dict (name, code3, package='gr'):
d['TAP_TYPE'] = tap_type (code3)
d['IS_COMPLEX'] = is_complex (code3)
return d
+
+
+def standard_dict2 (name, code3, package):
+ d = {}
+ d['NAME'] = name
+ d['BASE_NAME'] = name
+ d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper())
+ d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten'
+ d['COPYRIGHT'] = copyright
+ d['TYPE'] = i_type (code3)
+ d['I_TYPE'] = i_type (code3)
+ d['O_TYPE'] = o_type (code3)
+ d['TAP_TYPE'] = tap_type (code3)
+ d['IS_COMPLEX'] = is_complex (code3)
+ return d
+
+def standard_impl_dict2 (name, code3, package):
+ d = {}
+ d['NAME'] = name
+ d['IMPL_NAME'] = name
+ d['BASE_NAME'] = name.rstrip("_impl")
+ d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper())
+ d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten'
+ d['COPYRIGHT'] = copyright
+ d['FIR_TYPE'] = "fir_filter_" + code3
+ d['CFIR_TYPE'] = "fir_filter_" + code3[0:2] + 'c'
+ d['TYPE'] = i_type (code3)
+ d['I_TYPE'] = i_type (code3)
+ d['O_TYPE'] = o_type (code3)
+ d['TAP_TYPE'] = tap_type (code3)
+ d['IS_COMPLEX'] = is_complex (code3)
+ return d
diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_tag_debug.py b/gnuradio-core/src/python/gnuradio/gr/qa_tag_debug.py
new file mode 100755
index 000000000..81babca04
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/gr/qa_tag_debug.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+
+class test_tag_debug(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_001(self):
+ # Just run some data through and make sure it doesn't puke.
+ src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ src = gr.vector_source_i(src_data)
+ op = gr.tag_debug(gr.sizeof_int, "tag QA")
+ self.tb.connect(src, op)
+ self.tb.run()
+ x = op.current_tags()
+
+if __name__ == '__main__':
+ gr_unittest.run(test_tag_debug, "test_tag_debug.xml")
diff --git a/gr-audio/lib/CMakeLists.txt b/gr-audio/lib/CMakeLists.txt
index 7e0252a8b..c1781af79 100644
--- a/gr-audio/lib/CMakeLists.txt
+++ b/gr-audio/lib/CMakeLists.txt
@@ -150,4 +150,4 @@ add_library(gnuradio-audio SHARED ${gr_audio_sources})
target_link_libraries(gnuradio-audio ${gr_audio_libs})
GR_LIBRARY_FOO(gnuradio-audio RUNTIME_COMPONENT "audio_runtime" DEVEL_COMPONENT "audio_devel")
-install(FILES ${gr_audio_confs} DESTINATION ${GR_PKG_CONF_DIR} COMPONENT "audio_runtime")
+install(FILES ${gr_audio_confs} DESTINATION ${GR_PREFSDIR} COMPONENT "audio_runtime")
diff --git a/gr-digital/examples/CMakeLists.txt b/gr-digital/examples/CMakeLists.txt
index 33d257e59..63e1eba4e 100644
--- a/gr-digital/examples/CMakeLists.txt
+++ b/gr-digital/examples/CMakeLists.txt
@@ -71,6 +71,7 @@ install(
demod/pam_timing.grc
demod/ber_simulation.grc
demod/dpsk_loopback.grc
+ demod/gfsk_loopback.grc
DESTINATION ${GR_PKG_DIGITAL_EXAMPLES_DIR}/demod
COMPONENT "digital_python"
)
diff --git a/gr-digital/examples/berawgn.py b/gr-digital/examples/berawgn.py
new file mode 100755
index 000000000..d58dfbaae
--- /dev/null
+++ b/gr-digital/examples/berawgn.py
@@ -0,0 +1,104 @@
+#!/usr/bin/env python
+"""
+BER simulation for QPSK signals, compare to theoretical values.
+Change the N_BITS value to simulate more bits per Eb/N0 value,
+thus allowing to check for lower BER values.
+
+Lower values will work faster, higher values will use a lot of RAM.
+Also, this app isn't highly optimized--the flow graph is completely
+reinstantiated for every Eb/N0 value.
+Of course, expect the maximum value for BER to be one order of
+magnitude below what you chose for N_BITS.
+"""
+
+
+import math
+import numpy
+from scipy.special import erfc
+import pylab
+from gnuradio import gr, digital
+
+# Best to choose powers of 10
+N_BITS = 1e7
+RAND_SEED = 42
+
+def berawgn(EbN0):
+ """ Calculates theoretical bit error rate in AWGN (for BPSK and given Eb/N0) """
+ return 0.5 * erfc(math.sqrt(10**(float(EbN0)/10)))
+
+class BitErrors(gr.hier_block2):
+ """ Two inputs: true and received bits. We compare them and
+ add up the number of incorrect bits. Because integrate_ff()
+ can only add up a certain number of values, the output is
+ not a scalar, but a sequence of values, the sum of which is
+ the BER. """
+ def __init__(self, bits_per_byte):
+ gr.hier_block2.__init__(self, "BitErrors",
+ gr.io_signature(2, 2, gr.sizeof_char),
+ gr.io_signature(1, 1, gr.sizeof_int))
+
+ # Bit comparison
+ comp = gr.xor_bb()
+ intdump_decim = 100000
+ if N_BITS < intdump_decim:
+ intdump_decim = int(N_BITS)
+ self.connect(self,
+ comp,
+ gr.unpack_k_bits_bb(bits_per_byte),
+ gr.uchar_to_float(),
+ gr.integrate_ff(intdump_decim),
+ gr.multiply_const_ff(1.0/N_BITS),
+ self)
+ self.connect((self, 1), (comp, 1))
+
+class BERAWGNSimu(gr.top_block):
+ " This contains the simulation flow graph "
+ def __init__(self, EbN0):
+ gr.top_block.__init__(self)
+ self.const = digital.qpsk_constellation()
+ # Source is N_BITS bits, non-repeated
+ data = map(int, numpy.random.randint(0, self.const.arity(), N_BITS/self.const.bits_per_symbol()))
+ src = gr.vector_source_b(data, False)
+ mod = gr.chunks_to_symbols_bc((self.const.points()), 1)
+ add = gr.add_vcc()
+ noise = gr.noise_source_c(gr.GR_GAUSSIAN,
+ self.EbN0_to_noise_voltage(EbN0),
+ RAND_SEED)
+ demod = digital.constellation_decoder_cb(self.const.base())
+ ber = BitErrors(self.const.bits_per_symbol())
+ self.sink = gr.vector_sink_f()
+ self.connect(src, mod, add, demod, ber, self.sink)
+ self.connect(noise, (add, 1))
+ self.connect(src, (ber, 1))
+
+ def EbN0_to_noise_voltage(self, EbN0):
+ """ Converts Eb/N0 to a single-sided noise voltage (assuming unit symbol power) """
+ return 1.0 / math.sqrt(2.0 * self.const.bits_per_symbol() * 10**(float(EbN0)/10))
+
+
+def simulate_ber(EbN0):
+ """ All the work's done here: create flow graph, run, read out BER """
+ print "Eb/N0 = %d dB" % EbN0
+ fg = BERAWGNSimu(EbN0)
+ fg.run()
+ return numpy.sum(fg.sink.data())
+
+if __name__ == "__main__":
+ EbN0_min = 0
+ EbN0_max = 15
+ EbN0_range = range(EbN0_min, EbN0_max+1)
+ ber_theory = [berawgn(x) for x in EbN0_range]
+ print "Simulating..."
+ ber_simu = [simulate_ber(x) for x in EbN0_range]
+
+ f = pylab.figure()
+ s = f.add_subplot(1,1,1)
+ s.semilogy(EbN0_range, ber_theory, 'g-.', label="Theoretical")
+ s.semilogy(EbN0_range, ber_simu, 'b-o', label="Simulated")
+ s.set_title('BER Simulation')
+ s.set_xlabel('Eb/N0 (dB)')
+ s.set_ylabel('BER')
+ s.legend()
+ s.grid()
+ pylab.show()
+
diff --git a/gr-digital/examples/demod/ber_simulation.grc b/gr-digital/examples/demod/ber_simulation.grc
index 6a9361ed1..b7c6a624b 100644
--- a/gr-digital/examples/demod/ber_simulation.grc
+++ b/gr-digital/examples/demod/ber_simulation.grc
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='ASCII'?>
<flow_graph>
- <timestamp>Tue Apr 3 18:11:51 2012</timestamp>
+ <timestamp>Thu Jul 5 15:57:06 2012</timestamp>
<block>
<key>options</key>
<param>
@@ -44,6 +44,10 @@
<value>True</value>
</param>
<param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
<key>realtime_scheduling</key>
<value></value>
</param>
@@ -57,10 +61,41 @@
</param>
</block>
<block>
- <key>gr_noise_source_x</key>
+ <key>gr_throttle</key>
<param>
<key>id</key>
- <value>gr_noise_source_x</value>
+ <value>gr_throttle</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(284, 24)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_add_xx</key>
+ <param>
+ <key>id</key>
+ <value>gr_add_xx</value>
</param>
<param>
<key>_enabled</key>
@@ -71,20 +106,39 @@
<value>complex</value>
</param>
<param>
- <key>noise_type</key>
- <value>gr.GR_GAUSSIAN</value>
+ <key>num_inputs</key>
+ <value>2</value>
</param>
<param>
- <key>amp</key>
- <value>noise</value>
+ <key>vlen</key>
+ <value>1</value>
</param>
<param>
- <key>seed</key>
- <value>42</value>
+ <key>_coordinate</key>
+ <value>(486, 151)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_constellation_decoder_cb</key>
+ <param>
+ <key>id</key>
+ <value>digital_constellation_decoder_cb_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>constellation</key>
+ <value>const.base()</value>
</param>
<param>
<key>_coordinate</key>
- <value>(235, 379)</value>
+ <value>(618, 164)</value>
</param>
<param>
<key>_rotation</key>
@@ -171,38 +225,30 @@
</param>
<param>
<key>_coordinate</key>
- <value>(1062, 11)</value>
+ <value>(791, 228)</value>
</param>
<param>
<key>_rotation</key>
- <value>0</value>
+ <value>180</value>
</param>
</block>
<block>
- <key>gr_throttle</key>
+ <key>import</key>
<param>
<key>id</key>
- <value>gr_throttle</value>
+ <value>import</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>byte</value>
- </param>
- <param>
- <key>samples_per_second</key>
- <value>samp_rate</value>
- </param>
- <param>
- <key>vlen</key>
- <value>1</value>
+ <key>import</key>
+ <value>import math</value>
</param>
<param>
<key>_coordinate</key>
- <value>(397, 27)</value>
+ <value>(18, 373)</value>
</param>
<param>
<key>_rotation</key>
@@ -213,7 +259,7 @@
<key>variable</key>
<param>
<key>id</key>
- <value>samp_rate</value>
+ <value>const</value>
</param>
<param>
<key>_enabled</key>
@@ -221,11 +267,11 @@
</param>
<param>
<key>value</key>
- <value>50e3</value>
+ <value>digital.qpsk_constellation()</value>
</param>
<param>
<key>_coordinate</key>
- <value>(20, 168)</value>
+ <value>(116, 310)</value>
</param>
<param>
<key>_rotation</key>
@@ -233,22 +279,22 @@
</param>
</block>
<block>
- <key>import</key>
+ <key>variable</key>
<param>
<key>id</key>
- <value>import</value>
+ <value>samp_rate</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>import</key>
- <value>import math</value>
+ <key>value</key>
+ <value>100e3</value>
</param>
<param>
<key>_coordinate</key>
- <value>(138, 168)</value>
+ <value>(16, 308)</value>
</param>
<param>
<key>_rotation</key>
@@ -271,7 +317,7 @@
</param>
<param>
<key>title</key>
- <value>"Constellation: "+str(const)</value>
+ <value>"Constellation: "+str(const.arity()) + "-PSK"</value>
</param>
<param>
<key>samp_rate</key>
@@ -323,7 +369,7 @@
</param>
<param>
<key>_coordinate</key>
- <value>(828, 368)</value>
+ <value>(623, 228)</value>
</param>
<param>
<key>_rotation</key>
@@ -331,10 +377,10 @@
</param>
</block>
<block>
- <key>gr_add_xx</key>
+ <key>blks2_error_rate</key>
<param>
<key>id</key>
- <value>gr_add_xx</value>
+ <value>blks2_error_rate</value>
</param>
<param>
<key>_enabled</key>
@@ -342,42 +388,19 @@
</param>
<param>
<key>type</key>
- <value>complex</value>
- </param>
- <param>
- <key>num_inputs</key>
- <value>2</value>
- </param>
- <param>
- <key>vlen</key>
- <value>1</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(652, 395)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>digital_constellation_decoder_cb</key>
- <param>
- <key>id</key>
- <value>digital_constellation_decoder_cb_0</value>
+ <value>'BER'</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>win_size</key>
+ <value>int(1e7)</value>
</param>
<param>
- <key>constellation</key>
- <value>const.base()</value>
+ <key>bits_per_symbol</key>
+ <value>const.bits_per_symbol()</value>
</param>
<param>
<key>_coordinate</key>
- <value>(693, 205)</value>
+ <value>(720, 25)</value>
</param>
<param>
<key>_rotation</key>
@@ -385,45 +408,34 @@
</param>
</block>
<block>
- <key>variable</key>
+ <key>gr_noise_source_x</key>
<param>
<key>id</key>
- <value>const</value>
+ <value>gr_noise_source_x</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>value</key>
- <value>digital.qpsk_constellation()</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(16, 461)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
+ <key>type</key>
+ <value>complex</value>
</param>
- </block>
- <block>
- <key>variable</key>
<param>
- <key>id</key>
- <value>const_points</value>
+ <key>noise_type</key>
+ <value>gr.GR_GAUSSIAN</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>amp</key>
+ <value>1.0 / math.sqrt(2.0 * const.bits_per_symbol() * 10**(EbN0/10))</value>
</param>
<param>
- <key>value</key>
- <value>const.points()</value>
+ <key>seed</key>
+ <value>42</value>
</param>
<param>
<key>_coordinate</key>
- <value>(17, 532)</value>
+ <value>(16, 224)</value>
</param>
<param>
<key>_rotation</key>
@@ -431,38 +443,38 @@
</param>
</block>
<block>
- <key>random_source_x</key>
+ <key>gr_chunks_to_symbols_xx</key>
<param>
<key>id</key>
- <value>random_source_x</value>
+ <value>gr_chunks_to_symbols_xx</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
+ <key>in_type</key>
<value>byte</value>
</param>
<param>
- <key>min</key>
- <value>0</value>
+ <key>out_type</key>
+ <value>complex</value>
</param>
<param>
- <key>max</key>
- <value>len(const_points)</value>
+ <key>symbol_table</key>
+ <value>const.points()</value>
</param>
<param>
- <key>num_samps</key>
- <value>1000000</value>
+ <key>dimension</key>
+ <value>1</value>
</param>
<param>
- <key>repeat</key>
- <value>False</value>
+ <key>num_ports</key>
+ <value>1</value>
</param>
<param>
<key>_coordinate</key>
- <value>(15, 244)</value>
+ <value>(240, 140)</value>
</param>
<param>
<key>_rotation</key>
@@ -470,69 +482,54 @@
</param>
</block>
<block>
- <key>gr_chunks_to_symbols_xx</key>
+ <key>variable_slider</key>
<param>
<key>id</key>
- <value>gr_chunks_to_symbols_xx</value>
+ <value>EbN0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>in_type</key>
- <value>byte</value>
- </param>
- <param>
- <key>out_type</key>
- <value>complex</value>
- </param>
- <param>
- <key>symbol_table</key>
- <value>const_points</value>
- </param>
- <param>
- <key>dimension</key>
- <value>1</value>
+ <key>label</key>
+ <value>Eb/N0 (dB)</value>
</param>
<param>
- <key>num_ports</key>
- <value>1</value>
+ <key>value</key>
+ <value>10</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(367, 260)</value>
+ <key>min</key>
+ <value>-10</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>max</key>
+ <value>200</value>
</param>
- </block>
- <block>
- <key>blks2_error_rate</key>
<param>
- <key>id</key>
- <value>blks2_error_rate</value>
+ <key>num_steps</key>
+ <value>211</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
</param>
<param>
- <key>type</key>
- <value>'BER'</value>
+ <key>converver</key>
+ <value>float_converter</value>
</param>
<param>
- <key>win_size</key>
- <value>1000000</value>
+ <key>grid_pos</key>
+ <value></value>
</param>
<param>
- <key>bits_per_symbol</key>
- <value>int(math.log(len(const_points))/math.log(2))</value>
+ <key>notebook</key>
+ <value></value>
</param>
<param>
<key>_coordinate</key>
- <value>(670, 41)</value>
+ <value>(311, 309)</value>
</param>
<param>
<key>_rotation</key>
@@ -540,22 +537,18 @@
</param>
</block>
<block>
- <key>variable_slider</key>
+ <key>random_source_x</key>
<param>
<key>id</key>
- <value>noise</value>
+ <value>random_source_x</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>label</key>
- <value>AWGN Noise</value>
- </param>
- <param>
- <key>value</key>
- <value>0.10</value>
+ <key>type</key>
+ <value>byte</value>
</param>
<param>
<key>min</key>
@@ -563,31 +556,19 @@
</param>
<param>
<key>max</key>
- <value>1</value>
- </param>
- <param>
- <key>num_steps</key>
- <value>100</value>
+ <value>const.arity()</value>
</param>
<param>
- <key>style</key>
- <value>wx.SL_HORIZONTAL</value>
- </param>
- <param>
- <key>converver</key>
- <value>float_converter</value>
- </param>
- <param>
- <key>grid_pos</key>
- <value></value>
+ <key>num_samps</key>
+ <value>10000000</value>
</param>
<param>
- <key>notebook</key>
- <value></value>
+ <key>repeat</key>
+ <value>True</value>
</param>
<param>
<key>_coordinate</key>
- <value>(268, 481)</value>
+ <value>(17, 125)</value>
</param>
<param>
<key>_rotation</key>
diff --git a/gr-digital/examples/demod/digital_freq_lock.grc b/gr-digital/examples/demod/digital_freq_lock.grc
index 36037febb..df105dd7f 100644
--- a/gr-digital/examples/demod/digital_freq_lock.grc
+++ b/gr-digital/examples/demod/digital_freq_lock.grc
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='ASCII'?>
<flow_graph>
- <timestamp>Sat Mar 6 17:17:12 2010</timestamp>
+ <timestamp>Thu Jul 5 18:11:22 2012</timestamp>
<block>
<key>options</key>
<param>
@@ -44,12 +44,16 @@
<value>True</value>
</param>
<param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
<key>realtime_scheduling</key>
<value></value>
</param>
<param>
<key>_coordinate</key>
- <value>(10, 10)</value>
+ <value>(-1, 0)</value>
</param>
<param>
<key>_rotation</key>
@@ -57,37 +61,38 @@
</param>
</block>
<block>
- <key>gr_uchar_to_float</key>
+ <key>random_source_x</key>
<param>
<key>id</key>
- <value>gr_uchar_to_float_0</value>
+ <value>random_source_x</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(217, 108)</value>
+ <key>type</key>
+ <value>byte</value>
</param>
<param>
- <key>_rotation</key>
+ <key>min</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>gr_uchar_to_float</key>
<param>
- <key>id</key>
- <value>gr_uchar_to_float_0_0</value>
+ <key>max</key>
+ <value>256</value>
</param>
<param>
- <key>_enabled</key>
+ <key>num_samps</key>
+ <value>10000000</value>
+ </param>
+ <param>
+ <key>repeat</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
- <value>(216, 273)</value>
+ <value>(-2, 111)</value>
</param>
<param>
<key>_rotation</key>
@@ -95,54 +100,30 @@
</param>
</block>
<block>
- <key>variable_slider</key>
+ <key>gr_throttle</key>
<param>
<key>id</key>
- <value>freq_offset</value>
+ <value>gr_throttle_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>label</key>
- <value>Frequency Offset</value>
- </param>
- <param>
- <key>value</key>
- <value>0</value>
- </param>
- <param>
- <key>min</key>
- <value>-0.5</value>
- </param>
- <param>
- <key>max</key>
- <value>0.5</value>
- </param>
- <param>
- <key>num_steps</key>
- <value>1000</value>
- </param>
- <param>
- <key>style</key>
- <value>wx.SL_HORIZONTAL</value>
- </param>
- <param>
- <key>converver</key>
- <value>float_converter</value>
+ <key>type</key>
+ <value>complex</value>
</param>
<param>
- <key>grid_pos</key>
- <value></value>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
</param>
<param>
- <key>notebook</key>
- <value></value>
+ <key>vlen</key>
+ <value>1</value>
</param>
<param>
<key>_coordinate</key>
- <value>(293, 684)</value>
+ <value>(456, 134)</value>
</param>
<param>
<key>_rotation</key>
@@ -150,38 +131,22 @@
</param>
</block>
<block>
- <key>random_source_x</key>
+ <key>variable</key>
<param>
<key>id</key>
- <value>random_source_x_0</value>
+ <value>sps</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>byte</value>
- </param>
- <param>
- <key>min</key>
- <value>0</value>
- </param>
- <param>
- <key>max</key>
- <value>pam_amp</value>
- </param>
- <param>
- <key>num_samps</key>
- <value>10000</value>
- </param>
- <param>
- <key>repeat</key>
- <value>True</value>
+ <key>value</key>
+ <value>4</value>
</param>
<param>
<key>_coordinate</key>
- <value>(13, 80)</value>
+ <value>(166, -2)</value>
</param>
<param>
<key>_rotation</key>
@@ -189,38 +154,22 @@
</param>
</block>
<block>
- <key>random_source_x</key>
+ <key>variable</key>
<param>
<key>id</key>
- <value>random_source_x_0_0</value>
+ <value>rolloff</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>byte</value>
- </param>
- <param>
- <key>min</key>
- <value>0</value>
- </param>
- <param>
- <key>max</key>
- <value>pam_amp</value>
- </param>
- <param>
- <key>num_samps</key>
- <value>10000</value>
- </param>
- <param>
- <key>repeat</key>
- <value>True</value>
+ <key>value</key>
+ <value>0.35</value>
</param>
<param>
<key>_coordinate</key>
- <value>(15, 245)</value>
+ <value>(231, 0)</value>
</param>
<param>
<key>_rotation</key>
@@ -228,10 +177,10 @@
</param>
</block>
<block>
- <key>const_source_x</key>
+ <key>digital_fll_band_edge_cc</key>
<param>
<key>id</key>
- <value>const_source_x_0</value>
+ <value>digital_fll_band_edge_cc_0</value>
</param>
<param>
<key>_enabled</key>
@@ -239,42 +188,27 @@
</param>
<param>
<key>type</key>
- <value>float</value>
- </param>
- <param>
- <key>const</key>
- <value>-0.5*(pam_amp-1)</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(213, 197)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
+ <value>cc</value>
</param>
- </block>
- <block>
- <key>const_source_x</key>
<param>
- <key>id</key>
- <value>const_source_x_0_0</value>
+ <key>samps_per_sym</key>
+ <value>sps</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>rolloff</key>
+ <value>rolloff</value>
</param>
<param>
- <key>type</key>
- <value>float</value>
+ <key>filter_size</key>
+ <value>44</value>
</param>
<param>
- <key>const</key>
- <value>-0.5*(pam_amp-1)</value>
+ <key>w</key>
+ <value>freq_bw</value>
</param>
<param>
<key>_coordinate</key>
- <value>(200, 360)</value>
+ <value>(81, 248)</value>
</param>
<param>
<key>_rotation</key>
@@ -282,61 +216,54 @@
</param>
</block>
<block>
- <key>gr_add_xx</key>
+ <key>variable_slider</key>
<param>
<key>id</key>
- <value>gr_add_xx_0</value>
+ <value>freq_bw</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>float</value>
+ <key>label</key>
+ <value>FLL Loop Bandwidth</value>
</param>
<param>
- <key>num_inputs</key>
- <value>2</value>
+ <key>value</key>
+ <value>0</value>
</param>
<param>
- <key>vlen</key>
- <value>1</value>
+ <key>min</key>
+ <value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(440, 167)</value>
+ <key>max</key>
+ <value>0.1</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>gr_add_xx</key>
- <param>
- <key>id</key>
- <value>gr_add_xx_0_1</value>
+ <key>num_steps</key>
+ <value>1000</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
</param>
<param>
- <key>type</key>
- <value>float</value>
+ <key>converver</key>
+ <value>float_converter</value>
</param>
<param>
- <key>num_inputs</key>
- <value>2</value>
+ <key>grid_pos</key>
+ <value></value>
</param>
<param>
- <key>vlen</key>
- <value>1</value>
+ <key>notebook</key>
+ <value></value>
</param>
<param>
<key>_coordinate</key>
- <value>(430, 330)</value>
+ <value>(80, 382)</value>
</param>
<param>
<key>_rotation</key>
@@ -347,7 +274,7 @@
<key>variable</key>
<param>
<key>id</key>
- <value>nfilts</value>
+ <value>samp_rate</value>
</param>
<param>
<key>_enabled</key>
@@ -355,11 +282,11 @@
</param>
<param>
<key>value</key>
- <value>32</value>
+ <value>32000</value>
</param>
<param>
<key>_coordinate</key>
- <value>(435, 686)</value>
+ <value>(439, -1)</value>
</param>
<param>
<key>_rotation</key>
@@ -414,7 +341,7 @@
</param>
<param>
<key>_coordinate</key>
- <value>(168, 684)</value>
+ <value>(553, 0)</value>
</param>
<param>
<key>_rotation</key>
@@ -422,91 +349,54 @@
</param>
</block>
<block>
- <key>variable</key>
+ <key>variable_slider</key>
<param>
<key>id</key>
- <value>spb_gen</value>
+ <value>freq_offset</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>value</key>
- <value>4</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(119, 841)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>variable</key>
- <param>
- <key>id</key>
- <value>pam_amp</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
+ <key>label</key>
+ <value>Frequency Offset</value>
</param>
<param>
<key>value</key>
- <value>2</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(223, 9)</value>
- </param>
- <param>
- <key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>variable</key>
- <param>
- <key>id</key>
- <value>spb</value>
- </param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>min</key>
+ <value>-0.5</value>
</param>
<param>
- <key>value</key>
- <value>4.1</value>
+ <key>max</key>
+ <value>0.5</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(32, 842)</value>
+ <key>num_steps</key>
+ <value>1000</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
</param>
- </block>
- <block>
- <key>gr_float_to_complex</key>
<param>
- <key>id</key>
- <value>gr_float_to_complex_0</value>
+ <key>converver</key>
+ <value>float_converter</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>grid_pos</key>
+ <value></value>
</param>
<param>
- <key>vlen</key>
- <value>1</value>
+ <key>notebook</key>
+ <value></value>
</param>
<param>
<key>_coordinate</key>
- <value>(590, 184)</value>
+ <value>(673, -1)</value>
</param>
<param>
<key>_rotation</key>
@@ -514,65 +404,38 @@
</param>
</block>
<block>
- <key>gr_throttle</key>
+ <key>gr_channel_model</key>
<param>
<key>id</key>
- <value>gr_throttle_0</value>
+ <value>gr_channel_model_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
- </param>
- <param>
- <key>samples_per_second</key>
- <value>samp_rate</value>
- </param>
- <param>
- <key>vlen</key>
- <value>1</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(788, 197)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>notebook</key>
- <param>
- <key>id</key>
- <value>notebook_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
+ <key>noise_voltage</key>
+ <value>noise_amp</value>
</param>
<param>
- <key>style</key>
- <value>wx.NB_TOP</value>
+ <key>freq_offset</key>
+ <value>freq_offset</value>
</param>
<param>
- <key>labels</key>
- <value>['Freq', 'Time']</value>
+ <key>epsilon</key>
+ <value>1.0</value>
</param>
<param>
- <key>grid_pos</key>
- <value></value>
+ <key>taps</key>
+ <value>1.0</value>
</param>
<param>
- <key>notebook</key>
- <value></value>
+ <key>seed</key>
+ <value>42</value>
</param>
<param>
<key>_coordinate</key>
- <value>(216, 845)</value>
+ <value>(649, 104)</value>
</param>
<param>
<key>_rotation</key>
@@ -638,8 +501,16 @@
<value>notebook_0,1</value>
</param>
<param>
+ <key>trig_mode</key>
+ <value>gr.gr_TRIG_MODE_AUTO</value>
+ </param>
+ <param>
+ <key>y_axis_label</key>
+ <value>Counts</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(1123, 392)</value>
+ <value>(875, 0)</value>
</param>
<param>
<key>_rotation</key>
@@ -725,8 +596,59 @@
<value>notebook_0,0</value>
</param>
<param>
+ <key>freqvar</key>
+ <value>None</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(1122, 473)</value>
+ <value>(875, 108)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_psk_mod</key>
+ <param>
+ <key>id</key>
+ <value>digital_psk_mod_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>constellation_points</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>mod_code</key>
+ <value>"gray"</value>
+ </param>
+ <param>
+ <key>differential</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>samples_per_symbol</key>
+ <value>sps</value>
+ </param>
+ <param>
+ <key>excess_bw</key>
+ <value>0.35</value>
+ </param>
+ <param>
+ <key>verbose</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>log</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(194, 104)</value>
</param>
<param>
<key>_rotation</key>
@@ -792,8 +714,16 @@
<value>notebook_0,1</value>
</param>
<param>
+ <key>trig_mode</key>
+ <value>gr.gr_TRIG_MODE_AUTO</value>
+ </param>
+ <param>
+ <key>y_axis_label</key>
+ <value>Counts</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(1122, 680)</value>
+ <value>(439, 289)</value>
</param>
<param>
<key>_rotation</key>
@@ -879,233 +809,12 @@
<value>notebook_0,0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(1121, 762)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>variable</key>
- <param>
- <key>id</key>
- <value>samp_rate</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>value</key>
- <value>32000</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(128, 9)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>variable</key>
- <param>
- <key>id</key>
- <value>sig_amp</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>value</key>
- <value>1</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(315, 9)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>variable</key>
- <param>
- <key>id</key>
- <value>rolloff</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>value</key>
- <value>0.35</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(398, 12)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>variable</key>
- <param>
- <key>id</key>
- <value>rrctaps</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>value</key>
- <value>firdes.root_raised_cosine(nfilts,1.0,1.0/(spb*nfilts), .35, int(11*spb*nfilts))</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(826, 61)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>root_raised_cosine_filter</key>
- <param>
- <key>id</key>
- <value>root_raised_cosine_filter_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>type</key>
- <value>interp_fir_filter_ccf</value>
- </param>
- <param>
- <key>decim</key>
- <value>1</value>
- </param>
- <param>
- <key>interp</key>
- <value>spb_gen</value>
- </param>
- <param>
- <key>gain</key>
- <value>2*spb_gen</value>
- </param>
- <param>
- <key>samp_rate</key>
- <value>1.0</value>
- </param>
- <param>
- <key>sym_rate</key>
- <value>1./spb_gen</value>
- </param>
- <param>
- <key>alpha</key>
- <value>rolloff</value>
- </param>
- <param>
- <key>ntaps</key>
- <value>44</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(978, 157)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>gr_fll_band_edge_cc</key>
- <param>
- <key>id</key>
- <value>gr_fll_band_edge_cc_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>type</key>
- <value>cc</value>
- </param>
- <param>
- <key>samps_per_sym</key>
- <value>spb_gen</value>
- </param>
- <param>
- <key>rolloff</key>
- <value>rolloff</value>
- </param>
- <param>
- <key>filter_size</key>
- <value>44</value>
- </param>
- <param>
- <key>alpha</key>
- <value>alpha</value>
- </param>
- <param>
- <key>beta</key>
- <value>beta</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(874, 664)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>gr_channel_model</key>
- <param>
- <key>id</key>
- <value>gr_channel_model_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>noise_voltage</key>
- <value>noise_amp</value>
- </param>
- <param>
- <key>freq_offset</key>
- <value>freq_offset</value>
- </param>
- <param>
- <key>epsilon</key>
- <value>1.0</value>
- </param>
- <param>
- <key>taps</key>
- <value>1.0</value>
- </param>
- <param>
- <key>seed</key>
- <value>42</value>
+ <key>freqvar</key>
+ <value>None</value>
</param>
<param>
<key>_coordinate</key>
- <value>(618, 376)</value>
+ <value>(439, 423)</value>
</param>
<param>
<key>_rotation</key>
@@ -1113,97 +822,22 @@
</param>
</block>
<block>
- <key>variable_slider</key>
- <param>
- <key>id</key>
- <value>beta</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>label</key>
- <value>Freq Beta</value>
- </param>
- <param>
- <key>value</key>
- <value>0</value>
- </param>
- <param>
- <key>min</key>
- <value>0.0</value>
- </param>
- <param>
- <key>max</key>
- <value>0.01</value>
- </param>
- <param>
- <key>num_steps</key>
- <value>1000</value>
- </param>
- <param>
- <key>style</key>
- <value>wx.SL_HORIZONTAL</value>
- </param>
- <param>
- <key>converver</key>
- <value>float_converter</value>
- </param>
- <param>
- <key>grid_pos</key>
- <value></value>
- </param>
- <param>
- <key>notebook</key>
- <value></value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(668, 5)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>180</value>
- </param>
- </block>
- <block>
- <key>variable_slider</key>
+ <key>notebook</key>
<param>
<key>id</key>
- <value>alpha</value>
+ <value>notebook_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>label</key>
- <value>Freq Alpha</value>
- </param>
- <param>
- <key>value</key>
- <value>0</value>
- </param>
- <param>
- <key>min</key>
- <value>0</value>
- </param>
- <param>
- <key>max</key>
- <value>0.1</value>
- </param>
- <param>
- <key>num_steps</key>
- <value>1000</value>
- </param>
- <param>
<key>style</key>
- <value>wx.SL_HORIZONTAL</value>
+ <value>wx.NB_TOP</value>
</param>
<param>
- <key>converver</key>
- <value>float_converter</value>
+ <key>labels</key>
+ <value>['Freq', 'Time']</value>
</param>
<param>
<key>grid_pos</key>
@@ -1215,7 +849,7 @@
</param>
<param>
<key>_coordinate</key>
- <value>(552, 4)</value>
+ <value>(114, 521)</value>
</param>
<param>
<key>_rotation</key>
@@ -1223,97 +857,49 @@
</param>
</block>
<connection>
- <source_block_id>random_source_x_0</source_block_id>
- <sink_block_id>gr_uchar_to_float_0</sink_block_id>
- <source_key>0</source_key>
- <sink_key>0</sink_key>
- </connection>
- <connection>
- <source_block_id>gr_uchar_to_float_0</source_block_id>
- <sink_block_id>gr_add_xx_0</sink_block_id>
- <source_key>0</source_key>
- <sink_key>0</sink_key>
- </connection>
- <connection>
- <source_block_id>const_source_x_0</source_block_id>
- <sink_block_id>gr_add_xx_0</sink_block_id>
- <source_key>0</source_key>
- <sink_key>1</sink_key>
- </connection>
- <connection>
- <source_block_id>gr_uchar_to_float_0_0</source_block_id>
- <sink_block_id>gr_add_xx_0_1</sink_block_id>
+ <source_block_id>gr_channel_model_0</source_block_id>
+ <sink_block_id>wxgui_scopesink2_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>const_source_x_0_0</source_block_id>
- <sink_block_id>gr_add_xx_0_1</sink_block_id>
- <source_key>0</source_key>
- <sink_key>1</sink_key>
- </connection>
- <connection>
- <source_block_id>random_source_x_0_0</source_block_id>
- <sink_block_id>gr_uchar_to_float_0_0</sink_block_id>
+ <source_block_id>gr_channel_model_0</source_block_id>
+ <sink_block_id>wxgui_fftsink2_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>gr_add_xx_0</source_block_id>
- <sink_block_id>gr_float_to_complex_0</sink_block_id>
+ <source_block_id>random_source_x</source_block_id>
+ <sink_block_id>digital_psk_mod_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>gr_add_xx_0_1</source_block_id>
- <sink_block_id>gr_float_to_complex_0</sink_block_id>
- <source_key>0</source_key>
- <sink_key>1</sink_key>
- </connection>
- <connection>
- <source_block_id>gr_float_to_complex_0</source_block_id>
+ <source_block_id>digital_psk_mod_0</source_block_id>
<sink_block_id>gr_throttle_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>gr_throttle_0</source_block_id>
- <sink_block_id>root_raised_cosine_filter_0</sink_block_id>
- <source_key>0</source_key>
- <sink_key>0</sink_key>
- </connection>
- <connection>
- <source_block_id>gr_channel_model_0</source_block_id>
- <sink_block_id>wxgui_scopesink2_0</sink_block_id>
- <source_key>0</source_key>
- <sink_key>0</sink_key>
- </connection>
- <connection>
- <source_block_id>root_raised_cosine_filter_0</source_block_id>
<sink_block_id>gr_channel_model_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>gr_channel_model_0</source_block_id>
- <sink_block_id>wxgui_fftsink2_0</sink_block_id>
- <source_key>0</source_key>
- <sink_key>0</sink_key>
- </connection>
- <connection>
- <source_block_id>gr_channel_model_0</source_block_id>
- <sink_block_id>gr_fll_band_edge_cc_0</sink_block_id>
+ <sink_block_id>digital_fll_band_edge_cc_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>gr_fll_band_edge_cc_0</source_block_id>
+ <source_block_id>digital_fll_band_edge_cc_0</source_block_id>
<sink_block_id>wxgui_scopesink2_0_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>gr_fll_band_edge_cc_0</source_block_id>
+ <source_block_id>digital_fll_band_edge_cc_0</source_block_id>
<sink_block_id>wxgui_fftsink2_0_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
diff --git a/gr-digital/examples/demod/dpsk_loopback.grc b/gr-digital/examples/demod/dpsk_loopback.grc
index aef6a7738..c9867bea2 100644
--- a/gr-digital/examples/demod/dpsk_loopback.grc
+++ b/gr-digital/examples/demod/dpsk_loopback.grc
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='ASCII'?>
<flow_graph>
- <timestamp>Tue Apr 3 18:03:52 2012</timestamp>
+ <timestamp>Thu Jul 5 16:26:53 2012</timestamp>
<block>
<key>options</key>
<param>
@@ -17,11 +17,11 @@
</param>
<param>
<key>author</key>
- <value>Example</value>
+ <value>GNU Radio</value>
</param>
<param>
<key>description</key>
- <value>gnuradio flow graph</value>
+ <value>Encode a signal into a packet, modulate, demodulate, decode and show it's the same data.</value>
</param>
<param>
<key>window_size</key>
@@ -44,6 +44,10 @@
<value>True</value>
</param>
<param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
<key>realtime_scheduling</key>
<value></value>
</param>
@@ -72,7 +76,7 @@
</param>
<param>
<key>_coordinate</key>
- <value>(10, 170)</value>
+ <value>(11, 120)</value>
</param>
<param>
<key>_rotation</key>
@@ -127,7 +131,7 @@
</param>
<param>
<key>_coordinate</key>
- <value>(12, 257)</value>
+ <value>(13, 188)</value>
</param>
<param>
<key>_rotation</key>
@@ -135,10 +139,10 @@
</param>
</block>
<block>
- <key>gr_throttle</key>
+ <key>gr_sig_source_x</key>
<param>
<key>id</key>
- <value>gr_throttle_0_0</value>
+ <value>gr_sig_source_x_0</value>
</param>
<param>
<key>_enabled</key>
@@ -149,16 +153,28 @@
<value>float</value>
</param>
<param>
- <key>samples_per_second</key>
+ <key>samp_rate</key>
<value>samp_rate</value>
</param>
<param>
- <key>vlen</key>
+ <key>waveform</key>
+ <value>gr.GR_COS_WAVE</value>
+ </param>
+ <param>
+ <key>freq</key>
+ <value>freq</value>
+ </param>
+ <param>
+ <key>amp</key>
<value>1</value>
</param>
<param>
+ <key>offset</key>
+ <value>0</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(225, 174)</value>
+ <value>(184, 9)</value>
</param>
<param>
<key>_rotation</key>
@@ -166,10 +182,10 @@
</param>
</block>
<block>
- <key>gr_sig_source_x</key>
+ <key>digital_dxpsk_mod</key>
<param>
<key>id</key>
- <value>gr_sig_source_x_0</value>
+ <value>digital_dxpsk_mod_1</value>
</param>
<param>
<key>_enabled</key>
@@ -177,31 +193,31 @@
</param>
<param>
<key>type</key>
- <value>float</value>
+ <value>dbpsk</value>
</param>
<param>
- <key>samp_rate</key>
- <value>samp_rate</value>
+ <key>samples_per_symbol</key>
+ <value>2</value>
</param>
<param>
- <key>waveform</key>
- <value>gr.GR_COS_WAVE</value>
+ <key>excess_bw</key>
+ <value>0.35</value>
</param>
<param>
- <key>freq</key>
- <value>freq</value>
+ <key>gray_coded</key>
+ <value>True</value>
</param>
<param>
- <key>amp</key>
- <value>1</value>
+ <key>verbose</key>
+ <value>False</value>
</param>
<param>
- <key>offset</key>
- <value>0</value>
+ <key>log</key>
+ <value>False</value>
</param>
<param>
<key>_coordinate</key>
- <value>(203, 8)</value>
+ <value>(745, 16)</value>
</param>
<param>
<key>_rotation</key>
@@ -209,10 +225,10 @@
</param>
</block>
<block>
- <key>blks2_packet_decoder</key>
+ <key>gr_throttle</key>
<param>
<key>id</key>
- <value>blks2_packet_decoder_0</value>
+ <value>gr_throttle_0_0</value>
</param>
<param>
<key>_enabled</key>
@@ -223,16 +239,16 @@
<value>float</value>
</param>
<param>
- <key>access_code</key>
- <value></value>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
</param>
<param>
- <key>threshold</key>
- <value>-1</value>
+ <key>vlen</key>
+ <value>1</value>
</param>
<param>
<key>_coordinate</key>
- <value>(551, 65)</value>
+ <value>(358, 39)</value>
</param>
<param>
<key>_rotation</key>
@@ -240,10 +256,10 @@
</param>
</block>
<block>
- <key>digital_dxpsk_demod</key>
+ <key>blks2_packet_encoder</key>
<param>
<key>id</key>
- <value>digital_dxpsk_demod_0</value>
+ <value>blks2_packet_encoder_0</value>
</param>
<param>
<key>_enabled</key>
@@ -251,51 +267,31 @@
</param>
<param>
<key>type</key>
- <value>dbpsk</value>
+ <value>float</value>
</param>
<param>
<key>samples_per_symbol</key>
<value>2</value>
</param>
<param>
- <key>excess_bw</key>
- <value>0.35</value>
- </param>
- <param>
- <key>freq_bw</key>
- <value>6.28/100.0</value>
- </param>
- <param>
- <key>phase_bw</key>
- <value>6.28/100.0</value>
- </param>
- <param>
- <key>timing_bw</key>
- <value>6.28/100.0</value>
+ <key>bits_per_symbol</key>
+ <value>1</value>
</param>
<param>
- <key>omega_relative_limit</key>
- <value>0.005</value>
+ <key>access_code</key>
+ <value></value>
</param>
<param>
- <key>gray_coded</key>
+ <key>pad_for_usrp</key>
<value>True</value>
</param>
<param>
- <key>verbose</key>
- <value>False</value>
- </param>
- <param>
- <key>log</key>
- <value>False</value>
- </param>
- <param>
- <key>sync_out</key>
- <value>False</value>
+ <key>payload_length</key>
+ <value>0</value>
</param>
<param>
<key>_coordinate</key>
- <value>(639, 254)</value>
+ <value>(541, 9)</value>
</param>
<param>
<key>_rotation</key>
@@ -303,10 +299,10 @@
</param>
</block>
<block>
- <key>digital_dxpsk_mod</key>
+ <key>digital_dxpsk_demod</key>
<param>
<key>id</key>
- <value>digital_dxpsk_mod_0</value>
+ <value>digital_dxpsk_demod_1</value>
</param>
<param>
<key>_enabled</key>
@@ -325,6 +321,22 @@
<value>0.35</value>
</param>
<param>
+ <key>freq_bw</key>
+ <value>6.28/100.0</value>
+ </param>
+ <param>
+ <key>phase_bw</key>
+ <value>6.28/100.0</value>
+ </param>
+ <param>
+ <key>timing_bw</key>
+ <value>6.28/100.0</value>
+ </param>
+ <param>
+ <key>omega_relative_limit</key>
+ <value>0.005</value>
+ </param>
+ <param>
<key>gray_coded</key>
<value>True</value>
</param>
@@ -337,19 +349,23 @@
<value>False</value>
</param>
<param>
+ <key>sync_out</key>
+ <value>False</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(421, 294)</value>
+ <value>(746, 135)</value>
</param>
<param>
<key>_rotation</key>
- <value>0</value>
+ <value>180</value>
</param>
</block>
<block>
- <key>blks2_packet_encoder</key>
+ <key>blks2_packet_decoder</key>
<param>
<key>id</key>
- <value>blks2_packet_encoder_0</value>
+ <value>blks2_packet_decoder_0</value>
</param>
<param>
<key>_enabled</key>
@@ -360,32 +376,20 @@
<value>float</value>
</param>
<param>
- <key>samples_per_symbol</key>
- <value>2</value>
- </param>
- <param>
- <key>bits_per_symbol</key>
- <value>1</value>
- </param>
- <param>
<key>access_code</key>
<value></value>
</param>
<param>
- <key>pad_for_usrp</key>
- <value>True</value>
- </param>
- <param>
- <key>payload_length</key>
- <value>0</value>
+ <key>threshold</key>
+ <value>-1</value>
</param>
<param>
<key>_coordinate</key>
- <value>(216, 286)</value>
+ <value>(545, 187)</value>
</param>
<param>
<key>_rotation</key>
- <value>0</value>
+ <value>180</value>
</param>
</block>
<block>
@@ -456,46 +460,46 @@
</param>
<param>
<key>_coordinate</key>
- <value>(760, 41)</value>
+ <value>(184, 165)</value>
</param>
<param>
<key>_rotation</key>
- <value>0</value>
+ <value>180</value>
</param>
</block>
<connection>
- <source_block_id>gr_sig_source_x_0</source_block_id>
- <sink_block_id>gr_throttle_0_0</sink_block_id>
+ <source_block_id>blks2_packet_decoder_0</source_block_id>
+ <sink_block_id>wxgui_scopesink2_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>gr_throttle_0_0</source_block_id>
- <sink_block_id>blks2_packet_encoder_0</sink_block_id>
+ <source_block_id>blks2_packet_encoder_0</source_block_id>
+ <sink_block_id>digital_dxpsk_mod_1</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>blks2_packet_decoder_0</source_block_id>
- <sink_block_id>wxgui_scopesink2_0</sink_block_id>
+ <source_block_id>digital_dxpsk_mod_1</source_block_id>
+ <sink_block_id>digital_dxpsk_demod_1</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>digital_dxpsk_demod_0</source_block_id>
+ <source_block_id>digital_dxpsk_demod_1</source_block_id>
<sink_block_id>blks2_packet_decoder_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>digital_dxpsk_mod_0</source_block_id>
- <sink_block_id>digital_dxpsk_demod_0</sink_block_id>
+ <source_block_id>gr_throttle_0_0</source_block_id>
+ <sink_block_id>blks2_packet_encoder_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>blks2_packet_encoder_0</source_block_id>
- <sink_block_id>digital_dxpsk_mod_0</sink_block_id>
+ <source_block_id>gr_sig_source_x_0</source_block_id>
+ <sink_block_id>gr_throttle_0_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
diff --git a/gr-digital/examples/demod/gfsk_loopback.grc b/gr-digital/examples/demod/gfsk_loopback.grc
new file mode 100644
index 000000000..f74a83526
--- /dev/null
+++ b/gr-digital/examples/demod/gfsk_loopback.grc
@@ -0,0 +1,646 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+ <timestamp>Sun Jul 8 16:56:18 2012</timestamp>
+ <block>
+ <key>variable_slider</key>
+ <param>
+ <key>id</key>
+ <value>freq</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Frequency (Hz)</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>500</value>
+ </param>
+ <param>
+ <key>min</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>max</key>
+ <value>samp_rate/2</value>
+ </param>
+ <param>
+ <key>num_steps</key>
+ <value>100</value>
+ </param>
+ <param>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
+ </param>
+ <param>
+ <key>converver</key>
+ <value>float_converter</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(34, 241)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_sig_source_x</key>
+ <param>
+ <key>id</key>
+ <value>gr_sig_source_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>waveform</key>
+ <value>gr.GR_COS_WAVE</value>
+ </param>
+ <param>
+ <key>freq</key>
+ <value>freq</value>
+ </param>
+ <param>
+ <key>amp</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>offset</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(215, 26)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_throttle</key>
+ <param>
+ <key>id</key>
+ <value>gr_throttle_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(272.5, 142.0)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blks2_packet_encoder</key>
+ <param>
+ <key>id</key>
+ <value>blks2_packet_encoder_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>samples_per_symbol</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>bits_per_symbol</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>access_code</key>
+ <value></value>
+ </param>
+ <param>
+ <key>pad_for_usrp</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>payload_length</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(261, 227)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>10000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 170)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_gfsk_demod</key>
+ <param>
+ <key>id</key>
+ <value>digital_gfsk_demod_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>samples_per_symbol</key>
+ <value>sps</value>
+ </param>
+ <param>
+ <key>sensitivity</key>
+ <value>fm_sensitivity</value>
+ </param>
+ <param>
+ <key>gain_mu</key>
+ <value>0.175</value>
+ </param>
+ <param>
+ <key>mu</key>
+ <value>0.5</value>
+ </param>
+ <param>
+ <key>omega_relative_limit</key>
+ <value>0.005</value>
+ </param>
+ <param>
+ <key>freq_error</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>verbose</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>log</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(669, 257)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>sps</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>8</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(47, 445)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_gfsk_mod</key>
+ <param>
+ <key>id</key>
+ <value>digital_gfsk_mod_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>samples_per_symbol</key>
+ <value>sps</value>
+ </param>
+ <param>
+ <key>sensitivity</key>
+ <value>fm_sensitivity</value>
+ </param>
+ <param>
+ <key>bt</key>
+ <value>0.35</value>
+ </param>
+ <param>
+ <key>verbose</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>log</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(456, 277)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>fm_sensitivity</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(40, 366)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blks2_packet_decoder</key>
+ <param>
+ <key>id</key>
+ <value>blks2_packet_decoder_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>access_code</key>
+ <value></value>
+ </param>
+ <param>
+ <key>threshold</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(705, 130)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_quadrature_demod_cf</key>
+ <param>
+ <key>id</key>
+ <value>gr_quadrature_demod_cf_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>gain</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(627, 417)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>gfsk_loopback</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></value>
+ </param>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>wx_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 10)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>wxgui_scopesink2</key>
+ <param>
+ <key>id</key>
+ <value>wxgui_scopesink2_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>Scope Plot</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>v_scale</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>v_offset</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>t_scale</key>
+ <value>1./freq</value>
+ </param>
+ <param>
+ <key>ac_couple</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>xy_mode</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>win_size</key>
+ <value></value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>trig_mode</key>
+ <value>gr.gr_TRIG_MODE_AUTO</value>
+ </param>
+ <param>
+ <key>y_axis_label</key>
+ <value>Counts</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(907, 59)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>wxgui_scopesink2</key>
+ <param>
+ <key>id</key>
+ <value>wxgui_scopesink2_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>Scope Plot</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>v_scale</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>v_offset</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>t_scale</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ac_couple</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>xy_mode</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>win_size</key>
+ <value></value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>trig_mode</key>
+ <value>gr.gr_TRIG_MODE_AUTO</value>
+ </param>
+ <param>
+ <key>y_axis_label</key>
+ <value>Counts</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(853, 400)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>digital_gfsk_mod_0</source_block_id>
+ <sink_block_id>digital_gfsk_demod_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_sig_source_x_0</source_block_id>
+ <sink_block_id>gr_throttle_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_throttle_0_0</source_block_id>
+ <sink_block_id>blks2_packet_encoder_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blks2_packet_encoder_0</source_block_id>
+ <sink_block_id>digital_gfsk_mod_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_gfsk_demod_0</source_block_id>
+ <sink_block_id>blks2_packet_decoder_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blks2_packet_decoder_0</source_block_id>
+ <sink_block_id>wxgui_scopesink2_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_gfsk_mod_0</source_block_id>
+ <sink_block_id>gr_quadrature_demod_cf_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_quadrature_demod_cf_0</source_block_id>
+ <sink_block_id>wxgui_scopesink2_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gr-digital/examples/demod/mpsk_demod.grc b/gr-digital/examples/demod/mpsk_demod.grc
index d7cca9661..b718fb68a 100644
--- a/gr-digital/examples/demod/mpsk_demod.grc
+++ b/gr-digital/examples/demod/mpsk_demod.grc
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='ASCII'?>
<flow_graph>
- <timestamp>Tue Apr 3 18:01:57 2012</timestamp>
+ <timestamp>Thu Jul 5 16:28:45 2012</timestamp>
<block>
<key>options</key>
<param>
@@ -44,6 +44,10 @@
<value>True</value>
</param>
<param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
<key>realtime_scheduling</key>
<value></value>
</param>
@@ -405,6 +409,10 @@
<value>notebook, 1</value>
</param>
<param>
+ <key>freqvar</key>
+ <value>None</value>
+ </param>
+ <param>
<key>_coordinate</key>
<value>(847, 10)</value>
</param>
diff --git a/gr-digital/examples/demod/pam_sync.grc b/gr-digital/examples/demod/pam_sync.grc
index 8571995a5..f870a0b06 100644
--- a/gr-digital/examples/demod/pam_sync.grc
+++ b/gr-digital/examples/demod/pam_sync.grc
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='ASCII'?>
<flow_graph>
- <timestamp>Sat Mar 6 17:17:22 2010</timestamp>
+ <timestamp>Thu Jul 5 17:54:54 2012</timestamp>
<block>
<key>options</key>
<param>
@@ -44,12 +44,16 @@
<value>True</value>
</param>
<param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
<key>realtime_scheduling</key>
<value></value>
</param>
<param>
<key>_coordinate</key>
- <value>(10, 10)</value>
+ <value>(-1, 0)</value>
</param>
<param>
<key>_rotation</key>
@@ -57,37 +61,22 @@
</param>
</block>
<block>
- <key>gr_uchar_to_float</key>
+ <key>variable</key>
<param>
<key>id</key>
- <value>gr_uchar_to_float_0</value>
+ <value>const</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(217, 108)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>gr_uchar_to_float</key>
- <param>
- <key>id</key>
- <value>gr_uchar_to_float_0_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
+ <key>value</key>
+ <value>digital.qpsk_constellation()</value>
</param>
<param>
<key>_coordinate</key>
- <value>(216, 273)</value>
+ <value>(336, -2)</value>
</param>
<param>
<key>_rotation</key>
@@ -98,7 +87,7 @@
<key>variable</key>
<param>
<key>id</key>
- <value>samp_rate</value>
+ <value>rrctaps</value>
</param>
<param>
<key>_enabled</key>
@@ -106,11 +95,11 @@
</param>
<param>
<key>value</key>
- <value>32000</value>
+ <value>firdes.root_raised_cosine(nfilts,1.0,1.0/(spb*nfilts), rolloff, int(11*spb*nfilts))</value>
</param>
<param>
<key>_coordinate</key>
- <value>(128, 9)</value>
+ <value>(686, -1)</value>
</param>
<param>
<key>_rotation</key>
@@ -118,54 +107,22 @@
</param>
</block>
<block>
- <key>variable_slider</key>
+ <key>variable</key>
<param>
<key>id</key>
- <value>freq_offset</value>
+ <value>rolloff</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>label</key>
- <value>Frequency Offset</value>
- </param>
- <param>
<key>value</key>
- <value>0</value>
- </param>
- <param>
- <key>min</key>
- <value>-0.5</value>
- </param>
- <param>
- <key>max</key>
- <value>0.5</value>
- </param>
- <param>
- <key>num_steps</key>
- <value>1000</value>
- </param>
- <param>
- <key>style</key>
- <value>wx.SL_HORIZONTAL</value>
- </param>
- <param>
- <key>converver</key>
- <value>float_converter</value>
- </param>
- <param>
- <key>grid_pos</key>
- <value></value>
- </param>
- <param>
- <key>notebook</key>
- <value></value>
+ <value>0.35</value>
</param>
<param>
<key>_coordinate</key>
- <value>(293, 684)</value>
+ <value>(607, -1)</value>
</param>
<param>
<key>_rotation</key>
@@ -173,38 +130,22 @@
</param>
</block>
<block>
- <key>random_source_x</key>
+ <key>variable</key>
<param>
<key>id</key>
- <value>random_source_x_0</value>
+ <value>spb</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>byte</value>
- </param>
- <param>
- <key>min</key>
- <value>0</value>
- </param>
- <param>
- <key>max</key>
- <value>pam_amp</value>
- </param>
- <param>
- <key>num_samps</key>
- <value>10000</value>
- </param>
- <param>
- <key>repeat</key>
- <value>True</value>
+ <key>value</key>
+ <value>4.0</value>
</param>
<param>
<key>_coordinate</key>
- <value>(13, 80)</value>
+ <value>(542, -1)</value>
</param>
<param>
<key>_rotation</key>
@@ -212,38 +153,22 @@
</param>
</block>
<block>
- <key>random_source_x</key>
+ <key>variable</key>
<param>
<key>id</key>
- <value>random_source_x_0_0</value>
+ <value>sig_amp</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>byte</value>
- </param>
- <param>
- <key>min</key>
- <value>0</value>
- </param>
- <param>
- <key>max</key>
- <value>pam_amp</value>
- </param>
- <param>
- <key>num_samps</key>
- <value>10000</value>
- </param>
- <param>
- <key>repeat</key>
- <value>True</value>
+ <key>value</key>
+ <value>1.0</value>
</param>
<param>
<key>_coordinate</key>
- <value>(15, 245)</value>
+ <value>(861, 0)</value>
</param>
<param>
<key>_rotation</key>
@@ -251,26 +176,22 @@
</param>
</block>
<block>
- <key>const_source_x</key>
+ <key>virtual_sink</key>
<param>
<key>id</key>
- <value>const_source_x_0</value>
+ <value>virtual_sink_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>float</value>
- </param>
- <param>
- <key>const</key>
- <value>-0.5*(pam_amp-1)</value>
+ <key>stream_id</key>
+ <value>input_signal_probe</value>
</param>
<param>
<key>_coordinate</key>
- <value>(213, 197)</value>
+ <value>(330, 183)</value>
</param>
<param>
<key>_rotation</key>
@@ -278,10 +199,10 @@
</param>
</block>
<block>
- <key>const_source_x</key>
+ <key>gr_pfb_clock_sync_xxx</key>
<param>
<key>id</key>
- <value>const_source_x_0_0</value>
+ <value>gr_pfb_clock_sync_xxx_0</value>
</param>
<param>
<key>_enabled</key>
@@ -289,46 +210,43 @@
</param>
<param>
<key>type</key>
- <value>float</value>
+ <value>ccf</value>
</param>
<param>
- <key>const</key>
- <value>-0.5*(pam_amp-1)</value>
+ <key>sps</key>
+ <value>spb</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(200, 360)</value>
+ <key>alpha</key>
+ <value>time_alpha</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>beta</key>
+ <value>time_beta</value>
</param>
- </block>
- <block>
- <key>gr_add_xx</key>
<param>
- <key>id</key>
- <value>gr_add_xx_0</value>
+ <key>taps</key>
+ <value>rrctaps</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>filter_size</key>
+ <value>nfilts</value>
</param>
<param>
- <key>type</key>
- <value>float</value>
+ <key>init_phase</key>
+ <value>16</value>
</param>
<param>
- <key>num_inputs</key>
- <value>2</value>
+ <key>max_dev</key>
+ <value>1.5</value>
</param>
<param>
- <key>vlen</key>
+ <key>osps</key>
<value>1</value>
</param>
<param>
<key>_coordinate</key>
- <value>(440, 167)</value>
+ <value>(598, 241)</value>
</param>
<param>
<key>_rotation</key>
@@ -336,10 +254,10 @@
</param>
</block>
<block>
- <key>gr_add_xx</key>
+ <key>digital_fll_band_edge_cc</key>
<param>
<key>id</key>
- <value>gr_add_xx_0_1</value>
+ <value>digital_fll_band_edge_cc_0</value>
</param>
<param>
<key>_enabled</key>
@@ -347,19 +265,27 @@
</param>
<param>
<key>type</key>
- <value>float</value>
+ <value>cc</value>
</param>
<param>
- <key>num_inputs</key>
- <value>2</value>
+ <key>samps_per_sym</key>
+ <value>spb</value>
</param>
<param>
- <key>vlen</key>
- <value>1</value>
+ <key>rolloff</key>
+ <value>rolloff</value>
+ </param>
+ <param>
+ <key>filter_size</key>
+ <value>44</value>
+ </param>
+ <param>
+ <key>w</key>
+ <value>freq_bw</value>
</param>
<param>
<key>_coordinate</key>
- <value>(430, 330)</value>
+ <value>(331, 239)</value>
</param>
<param>
<key>_rotation</key>
@@ -382,7 +308,7 @@
</param>
<param>
<key>_coordinate</key>
- <value>(435, 686)</value>
+ <value>(598, 186)</value>
</param>
<param>
<key>_rotation</key>
@@ -390,54 +316,22 @@
</param>
</block>
<block>
- <key>variable_slider</key>
+ <key>variable</key>
<param>
<key>id</key>
- <value>noise_amp</value>
+ <value>samp_rate</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>label</key>
- <value>Channel Noise</value>
- </param>
- <param>
<key>value</key>
- <value>0</value>
- </param>
- <param>
- <key>min</key>
- <value>0</value>
- </param>
- <param>
- <key>max</key>
- <value>1.0</value>
- </param>
- <param>
- <key>num_steps</key>
- <value>1000</value>
- </param>
- <param>
- <key>style</key>
- <value>wx.SL_HORIZONTAL</value>
- </param>
- <param>
- <key>converver</key>
- <value>float_converter</value>
- </param>
- <param>
- <key>grid_pos</key>
- <value></value>
- </param>
- <param>
- <key>notebook</key>
- <value></value>
+ <value>128000</value>
</param>
<param>
<key>_coordinate</key>
- <value>(168, 684)</value>
+ <value>(193, -1)</value>
</param>
<param>
<key>_rotation</key>
@@ -445,77 +339,38 @@
</param>
</block>
<block>
- <key>variable_slider</key>
+ <key>random_source_x</key>
<param>
<key>id</key>
- <value>interpratio</value>
+ <value>random_source_x</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>label</key>
- <value>Timing Offset</value>
- </param>
- <param>
- <key>value</key>
- <value>1.00</value>
+ <key>type</key>
+ <value>byte</value>
</param>
<param>
<key>min</key>
- <value>0.99</value>
+ <value>0</value>
</param>
<param>
<key>max</key>
- <value>1.01</value>
- </param>
- <param>
- <key>num_steps</key>
- <value>1000</value>
- </param>
- <param>
- <key>style</key>
- <value>wx.SL_HORIZONTAL</value>
+ <value>const.arity()</value>
</param>
<param>
- <key>converver</key>
- <value>float_converter</value>
- </param>
- <param>
- <key>grid_pos</key>
- <value></value>
- </param>
- <param>
- <key>notebook</key>
- <value></value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(40, 684)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>180</value>
- </param>
- </block>
- <block>
- <key>variable</key>
- <param>
- <key>id</key>
- <value>pam_amp</value>
+ <key>num_samps</key>
+ <value>10000000</value>
</param>
<param>
- <key>_enabled</key>
+ <key>repeat</key>
<value>True</value>
</param>
<param>
- <key>value</key>
- <value>2</value>
- </param>
- <param>
<key>_coordinate</key>
- <value>(223, 9)</value>
+ <value>(0, 72)</value>
</param>
<param>
<key>_rotation</key>
@@ -523,45 +378,38 @@
</param>
</block>
<block>
- <key>variable</key>
+ <key>gr_chunks_to_symbols_xx</key>
<param>
<key>id</key>
- <value>sig_amp</value>
+ <value>gr_chunks_to_symbols_xx</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>value</key>
- <value>1</value>
+ <key>in_type</key>
+ <value>byte</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(315, 9)</value>
+ <key>out_type</key>
+ <value>complex</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>symbol_table</key>
+ <value>const.points()</value>
</param>
- </block>
- <block>
- <key>variable</key>
<param>
- <key>id</key>
- <value>rolloff</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
+ <key>dimension</key>
+ <value>1</value>
</param>
<param>
- <key>value</key>
- <value>0.35</value>
+ <key>num_ports</key>
+ <value>1</value>
</param>
<param>
<key>_coordinate</key>
- <value>(397, 9)</value>
+ <value>(196, 87)</value>
</param>
<param>
<key>_rotation</key>
@@ -569,30 +417,30 @@
</param>
</block>
<block>
- <key>gr_throttle</key>
+ <key>blks2_pfb_arb_resampler_ccf</key>
<param>
<key>id</key>
- <value>gr_throttle_0</value>
+ <value>blks2_pfb_arb_resampler_ccf_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
+ <key>rate</key>
+ <value>spb</value>
</param>
<param>
- <key>samples_per_second</key>
- <value>samp_rate</value>
+ <key>taps</key>
+ <value>firdes.root_raised_cosine(32, 32, 1.0, 0.35, 44*32)</value>
</param>
<param>
- <key>vlen</key>
- <value>1</value>
+ <key>size</key>
+ <value>32</value>
</param>
<param>
<key>_coordinate</key>
- <value>(253, 575)</value>
+ <value>(435, 80)</value>
</param>
<param>
<key>_rotation</key>
@@ -600,109 +448,69 @@
</param>
</block>
<block>
- <key>variable_slider</key>
+ <key>gr_channel_model</key>
<param>
<key>id</key>
- <value>time_beta</value>
+ <value>gr_channel_model_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>label</key>
- <value>Timing Beta</value>
- </param>
- <param>
- <key>value</key>
- <value>0</value>
- </param>
- <param>
- <key>min</key>
- <value>0.0</value>
- </param>
- <param>
- <key>max</key>
- <value>0.1</value>
- </param>
- <param>
- <key>num_steps</key>
- <value>1000</value>
+ <key>noise_voltage</key>
+ <value>noise_amp</value>
</param>
<param>
- <key>style</key>
- <value>wx.SL_HORIZONTAL</value>
+ <key>freq_offset</key>
+ <value>freq_offset</value>
</param>
<param>
- <key>converver</key>
- <value>float_converter</value>
+ <key>epsilon</key>
+ <value>interpratio</value>
</param>
<param>
- <key>grid_pos</key>
- <value></value>
+ <key>taps</key>
+ <value>1.0</value>
</param>
<param>
- <key>notebook</key>
- <value></value>
+ <key>seed</key>
+ <value>42</value>
</param>
<param>
<key>_coordinate</key>
- <value>(606, 8)</value>
+ <value>(46, 183)</value>
</param>
<param>
<key>_rotation</key>
- <value>180</value>
+ <value>0</value>
</param>
</block>
<block>
- <key>variable_slider</key>
+ <key>gr_multiply_const_vxx</key>
<param>
<key>id</key>
- <value>time_alpha</value>
+ <value>gr_multiply_const_vxx_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>label</key>
- <value>Timing Alpha</value>
- </param>
- <param>
- <key>value</key>
- <value>0</value>
+ <key>type</key>
+ <value>complex</value>
</param>
<param>
- <key>min</key>
- <value>0</value>
+ <key>const</key>
+ <value>sig_amp</value>
</param>
<param>
- <key>max</key>
+ <key>vlen</key>
<value>1</value>
</param>
<param>
- <key>num_steps</key>
- <value>1000</value>
- </param>
- <param>
- <key>style</key>
- <value>wx.SL_HORIZONTAL</value>
- </param>
- <param>
- <key>converver</key>
- <value>float_converter</value>
- </param>
- <param>
- <key>grid_pos</key>
- <value></value>
- </param>
- <param>
- <key>notebook</key>
- <value></value>
- </param>
- <param>
<key>_coordinate</key>
- <value>(490, 8)</value>
+ <value>(659, 95)</value>
</param>
<param>
<key>_rotation</key>
@@ -710,54 +518,30 @@
</param>
</block>
<block>
- <key>variable_slider</key>
+ <key>gr_throttle</key>
<param>
<key>id</key>
- <value>phase_alpha</value>
+ <value>gr_throttle_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>label</key>
- <value>Phase Alpha</value>
- </param>
- <param>
- <key>value</key>
- <value>0</value>
- </param>
- <param>
- <key>min</key>
- <value>0</value>
- </param>
- <param>
- <key>max</key>
- <value>0.1</value>
- </param>
- <param>
- <key>num_steps</key>
- <value>1000</value>
- </param>
- <param>
- <key>style</key>
- <value>wx.SL_HORIZONTAL</value>
- </param>
- <param>
- <key>converver</key>
- <value>float_converter</value>
+ <key>type</key>
+ <value>complex</value>
</param>
<param>
- <key>grid_pos</key>
- <value></value>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
</param>
<param>
- <key>notebook</key>
- <value></value>
+ <key>vlen</key>
+ <value>1</value>
</param>
<param>
<key>_coordinate</key>
- <value>(953, 8)</value>
+ <value>(857, 95)</value>
</param>
<param>
<key>_rotation</key>
@@ -765,85 +549,41 @@
</param>
</block>
<block>
- <key>variable_slider</key>
+ <key>virtual_source</key>
<param>
<key>id</key>
- <value>phase_beta</value>
+ <value>virtual_source_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>label</key>
- <value>Phase Beta</value>
- </param>
- <param>
- <key>value</key>
- <value>0</value>
- </param>
- <param>
- <key>min</key>
- <value>0.0</value>
- </param>
- <param>
- <key>max</key>
- <value>0.01</value>
- </param>
- <param>
- <key>num_steps</key>
- <value>1000</value>
- </param>
- <param>
- <key>style</key>
- <value>wx.SL_HORIZONTAL</value>
- </param>
- <param>
- <key>converver</key>
- <value>float_converter</value>
- </param>
- <param>
- <key>grid_pos</key>
- <value></value>
- </param>
- <param>
- <key>notebook</key>
- <value></value>
+ <key>stream_id</key>
+ <value>input_signal_probe</value>
</param>
<param>
<key>_coordinate</key>
- <value>(1066, 8)</value>
+ <value>(835, 562)</value>
</param>
<param>
<key>_rotation</key>
- <value>180</value>
+ <value>0</value>
</param>
</block>
<block>
- <key>gr_costas_loop_cc</key>
+ <key>digital_costas_loop_cc</key>
<param>
<key>id</key>
- <value>gr_costas_loop_cc_0</value>
+ <value>digital_costas_loop_cc_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>alpha</key>
- <value>phase_alpha</value>
- </param>
- <param>
- <key>beta</key>
- <value>phase_beta</value>
- </param>
- <param>
- <key>max_freq</key>
- <value>0.2</value>
- </param>
- <param>
- <key>min_freq</key>
- <value>-0.2</value>
+ <key>w</key>
+ <value>phase_bw</value>
</param>
<param>
<key>order</key>
@@ -851,7 +591,7 @@
</param>
<param>
<key>_coordinate</key>
- <value>(915, 560)</value>
+ <value>(866, 246)</value>
</param>
<param>
<key>_rotation</key>
@@ -862,7 +602,7 @@
<key>wxgui_scopesink2</key>
<param>
<key>id</key>
- <value>wxgui_scopesink2_0</value>
+ <value>wxgui_scopesink2_0_0_1</value>
</param>
<param>
<key>_enabled</key>
@@ -874,7 +614,7 @@
</param>
<param>
<key>title</key>
- <value>Input Signal</value>
+ <value>Pre-sync Signal</value>
</param>
<param>
<key>samp_rate</key>
@@ -882,7 +622,7 @@
</param>
<param>
<key>v_scale</key>
- <value>0</value>
+ <value>.5</value>
</param>
<param>
<key>v_offset</key>
@@ -914,34 +654,19 @@
</param>
<param>
<key>notebook</key>
- <value>notebook_0,0</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(1116, 559)</value>
+ <value>notebook_0,1</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>trig_mode</key>
+ <value>gr.gr_TRIG_MODE_AUTO</value>
</param>
- </block>
- <block>
- <key>variable</key>
<param>
- <key>id</key>
- <value>rrctaps</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>value</key>
- <value>firdes.root_raised_cosine(nfilts,1.0,1.0/(spb*nfilts), rolloff, int(11*spb*nfilts))</value>
+ <key>y_axis_label</key>
+ <value>Counts</value>
</param>
<param>
<key>_coordinate</key>
- <value>(436, 755)</value>
+ <value>(1081, 439)</value>
</param>
<param>
<key>_rotation</key>
@@ -949,85 +674,70 @@
</param>
</block>
<block>
- <key>notebook</key>
+ <key>wxgui_fftsink2</key>
<param>
<key>id</key>
- <value>notebook_0</value>
+ <value>wxgui_fftsink2_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>style</key>
- <value>wx.NB_TOP</value>
- </param>
- <param>
- <key>labels</key>
- <value>['Output Signal', 'Input Signal']</value>
- </param>
- <param>
- <key>grid_pos</key>
- <value></value>
+ <key>type</key>
+ <value>complex</value>
</param>
<param>
- <key>notebook</key>
- <value></value>
+ <key>title</key>
+ <value>Received spectrum</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(203, 823)</value>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
</param>
<param>
- <key>_rotation</key>
+ <key>baseband_freq</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>wxgui_scopesink2</key>
- <param>
- <key>id</key>
- <value>wxgui_scopesink2_0_0_1</value>
- </param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>y_per_div</key>
+ <value>10</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
+ <key>y_divs</key>
+ <value>10</value>
</param>
<param>
- <key>title</key>
- <value>Input Signal</value>
+ <key>ref_level</key>
+ <value>10</value>
</param>
<param>
- <key>samp_rate</key>
- <value>samp_rate</value>
+ <key>ref_scale</key>
+ <value>2.0</value>
</param>
<param>
- <key>v_scale</key>
- <value>.5</value>
+ <key>fft_size</key>
+ <value>1024</value>
</param>
<param>
- <key>v_offset</key>
- <value>0</value>
+ <key>fft_rate</key>
+ <value>30</value>
</param>
<param>
- <key>t_scale</key>
- <value>0</value>
+ <key>peak_hold</key>
+ <value>False</value>
</param>
<param>
- <key>ac_couple</key>
+ <key>average</key>
<value>False</value>
</param>
<param>
- <key>xy_mode</key>
- <value>False</value>
+ <key>avg_alpha</key>
+ <value>0</value>
</param>
<param>
- <key>num_inputs</key>
- <value>1</value>
+ <key>win</key>
+ <value>None</value>
</param>
<param>
<key>win_size</key>
@@ -1042,8 +752,12 @@
<value>notebook_0,1</value>
</param>
<param>
+ <key>freqvar</key>
+ <value>None</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(975, 312)</value>
+ <value>(1081, 563)</value>
</param>
<param>
<key>_rotation</key>
@@ -1054,7 +768,7 @@
<key>wxgui_fftsink2</key>
<param>
<key>id</key>
- <value>wxgui_fftsink2_0</value>
+ <value>wxgui_fftsink2_0_0</value>
</param>
<param>
<key>_enabled</key>
@@ -1066,7 +780,7 @@
</param>
<param>
<key>title</key>
- <value>Input Frequency</value>
+ <value>Post-sync spectrum</value>
</param>
<param>
<key>samp_rate</key>
@@ -1126,195 +840,200 @@
</param>
<param>
<key>notebook</key>
- <value>notebook_0,1</value>
+ <value>notebook_0,0</value>
+ </param>
+ <param>
+ <key>freqvar</key>
+ <value>None</value>
</param>
<param>
<key>_coordinate</key>
- <value>(1116, 355)</value>
+ <value>(347, 516)</value>
</param>
<param>
<key>_rotation</key>
- <value>0</value>
+ <value>180</value>
</param>
</block>
<block>
- <key>virtual_source</key>
+ <key>wxgui_scopesink2</key>
<param>
<key>id</key>
- <value>virtual_source_0</value>
+ <value>wxgui_scopesink2_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>stream_id</key>
- <value>input_signal_probe</value>
+ <key>type</key>
+ <value>complex</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(801, 453)</value>
+ <key>title</key>
+ <value>Post-sync Signal</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
</param>
- </block>
- <block>
- <key>virtual_sink</key>
<param>
- <key>id</key>
- <value>virtual_sink_0</value>
+ <key>v_scale</key>
+ <value>0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>v_offset</key>
+ <value>0</value>
</param>
<param>
- <key>stream_id</key>
- <value>input_signal_probe</value>
+ <key>t_scale</key>
+ <value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(280, 475)</value>
+ <key>ac_couple</key>
+ <value>False</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>xy_mode</key>
+ <value>True</value>
</param>
- </block>
- <block>
- <key>wxgui_fftsink2</key>
<param>
- <key>id</key>
- <value>wxgui_fftsink2_0_0</value>
+ <key>num_inputs</key>
+ <value>1</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>win_size</key>
+ <value></value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
+ <key>grid_pos</key>
+ <value></value>
</param>
<param>
- <key>title</key>
- <value>Output Frequency</value>
+ <key>notebook</key>
+ <value>notebook_0,0</value>
</param>
<param>
- <key>samp_rate</key>
- <value>samp_rate</value>
+ <key>trig_mode</key>
+ <value>gr.gr_TRIG_MODE_AUTO</value>
</param>
<param>
- <key>baseband_freq</key>
- <value>0</value>
+ <key>y_axis_label</key>
+ <value>Counts</value>
</param>
<param>
- <key>y_per_div</key>
- <value>10</value>
+ <key>_coordinate</key>
+ <value>(1085, 213)</value>
</param>
<param>
- <key>y_divs</key>
- <value>10</value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
+ </block>
+ <block>
+ <key>variable_slider</key>
<param>
- <key>ref_level</key>
- <value>10</value>
+ <key>id</key>
+ <value>freq_bw</value>
</param>
<param>
- <key>ref_scale</key>
- <value>2.0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>fft_size</key>
- <value>1024</value>
+ <key>label</key>
+ <value>FLL Bandwidth</value>
</param>
<param>
- <key>fft_rate</key>
- <value>30</value>
+ <key>value</key>
+ <value>0</value>
</param>
<param>
- <key>peak_hold</key>
- <value>False</value>
+ <key>min</key>
+ <value>0.0</value>
</param>
<param>
- <key>average</key>
- <value>False</value>
+ <key>max</key>
+ <value>0.05</value>
</param>
<param>
- <key>avg_alpha</key>
- <value>0</value>
+ <key>num_steps</key>
+ <value>1000</value>
</param>
<param>
- <key>win</key>
- <value>None</value>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
</param>
<param>
- <key>win_size</key>
- <value></value>
+ <key>converver</key>
+ <value>float_converter</value>
</param>
<param>
<key>grid_pos</key>
- <value></value>
+ <value>(4,2,1,1)</value>
</param>
<param>
<key>notebook</key>
- <value>notebook_0,0</value>
+ <value></value>
</param>
<param>
<key>_coordinate</key>
- <value>(663, 687)</value>
+ <value>(341, 373)</value>
</param>
<param>
<key>_rotation</key>
- <value>0</value>
+ <value>180</value>
</param>
</block>
<block>
- <key>gr_pfb_clock_sync_xxx</key>
+ <key>variable_slider</key>
<param>
<key>id</key>
- <value>gr_pfb_clock_sync_xxx_0</value>
+ <value>time_alpha</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>ccf</value>
+ <key>label</key>
+ <value>Timing Alpha</value>
</param>
<param>
- <key>sps</key>
- <value>spb</value>
+ <key>value</key>
+ <value>0</value>
</param>
<param>
- <key>alpha</key>
- <value>time_alpha</value>
+ <key>min</key>
+ <value>0</value>
</param>
<param>
- <key>beta</key>
- <value>time_beta</value>
+ <key>max</key>
+ <value>1</value>
</param>
<param>
- <key>taps</key>
- <value>rrctaps</value>
+ <key>num_steps</key>
+ <value>1000</value>
</param>
<param>
- <key>filter_size</key>
- <value>nfilts</value>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
</param>
<param>
- <key>init_phase</key>
- <value>16</value>
+ <key>converver</key>
+ <value>float_converter</value>
</param>
<param>
- <key>max_dev</key>
- <value>1.5</value>
+ <key>grid_pos</key>
+ <value>(5,2,1,1)</value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
</param>
<param>
<key>_coordinate</key>
- <value>(662, 527)</value>
+ <value>(598, 388)</value>
</param>
<param>
<key>_rotation</key>
@@ -1322,92 +1041,109 @@
</param>
</block>
<block>
- <key>gr_float_to_complex</key>
+ <key>variable_slider</key>
<param>
<key>id</key>
- <value>gr_float_to_complex_0</value>
+ <value>time_beta</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>vlen</key>
- <value>1</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(592, 184)</value>
+ <key>label</key>
+ <value>Timing Beta</value>
</param>
<param>
- <key>_rotation</key>
+ <key>value</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>gr_channel_model</key>
<param>
- <key>id</key>
- <value>gr_channel_model_0</value>
+ <key>min</key>
+ <value>0.0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>max</key>
+ <value>0.1</value>
</param>
<param>
- <key>noise_voltage</key>
- <value>noise_amp</value>
+ <key>num_steps</key>
+ <value>1000</value>
</param>
<param>
- <key>freq_offset</key>
- <value>freq_offset</value>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
</param>
<param>
- <key>epsilon</key>
- <value>interpratio</value>
+ <key>converver</key>
+ <value>float_converter</value>
</param>
<param>
- <key>taps</key>
- <value>1.0</value>
+ <key>grid_pos</key>
+ <value>(6,2,1,1)</value>
</param>
<param>
- <key>seed</key>
- <value>42</value>
+ <key>notebook</key>
+ <value></value>
</param>
<param>
<key>_coordinate</key>
- <value>(60, 443)</value>
+ <value>(708, 388)</value>
</param>
<param>
<key>_rotation</key>
- <value>0</value>
+ <value>180</value>
</param>
</block>
<block>
- <key>gr_multiply_const_vxx</key>
+ <key>variable_slider</key>
<param>
<key>id</key>
- <value>gr_multiply_const_vxx_0</value>
+ <value>phase_bw</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
+ <key>label</key>
+ <value>Costas Loop (Phase) Bandwidth</value>
</param>
<param>
- <key>const</key>
- <value>sig_amp</value>
+ <key>value</key>
+ <value>0</value>
</param>
<param>
- <key>vlen</key>
- <value>1</value>
+ <key>min</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>max</key>
+ <value>0.1</value>
+ </param>
+ <param>
+ <key>num_steps</key>
+ <value>1000</value>
+ </param>
+ <param>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
+ </param>
+ <param>
+ <key>converver</key>
+ <value>float_converter</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value>(7,2,1,1)</value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
</param>
<param>
<key>_coordinate</key>
- <value>(670, 322)</value>
+ <value>(866, 313)</value>
</param>
<param>
<key>_rotation</key>
@@ -1415,30 +1151,34 @@
</param>
</block>
<block>
- <key>blks2_pfb_arb_resampler_ccf</key>
+ <key>notebook</key>
<param>
<key>id</key>
- <value>blks2_pfb_arb_resampler_ccf_0</value>
+ <value>notebook_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>rate</key>
- <value>spb</value>
+ <key>style</key>
+ <value>wx.NB_TOP</value>
</param>
<param>
- <key>taps</key>
- <value>firdes.root_raised_cosine(32, 32, 1.0, 0.35, 44*32)</value>
+ <key>labels</key>
+ <value>['Synched Signal', 'Received Signal']</value>
</param>
<param>
- <key>size</key>
- <value>32</value>
+ <key>grid_pos</key>
+ <value>(1,1,8,1)</value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
</param>
<param>
<key>_coordinate</key>
- <value>(778, 180)</value>
+ <value>(9, 601)</value>
</param>
<param>
<key>_rotation</key>
@@ -1446,76 +1186,65 @@
</param>
</block>
<block>
- <key>gr_fll_band_edge_cc</key>
+ <key>variable_slider</key>
<param>
<key>id</key>
- <value>gr_fll_band_edge_cc_0</value>
+ <value>interpratio</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>cc</value>
- </param>
- <param>
- <key>samps_per_sym</key>
- <value>spb</value>
- </param>
- <param>
- <key>rolloff</key>
- <value>rolloff</value>
+ <key>label</key>
+ <value>Timing Offset</value>
</param>
<param>
- <key>filter_size</key>
- <value>44</value>
+ <key>value</key>
+ <value>1.00</value>
</param>
<param>
- <key>alpha</key>
- <value>freq_alpha</value>
+ <key>min</key>
+ <value>0.99</value>
</param>
<param>
- <key>beta</key>
- <value>freq_beta</value>
+ <key>max</key>
+ <value>1.01</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(429, 528)</value>
+ <key>num_steps</key>
+ <value>1000</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
</param>
- </block>
- <block>
- <key>variable</key>
<param>
- <key>id</key>
- <value>spb</value>
+ <key>converver</key>
+ <value>float_converter</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>grid_pos</key>
+ <value>(3,2,1,1)</value>
</param>
<param>
- <key>value</key>
- <value>4.0</value>
+ <key>notebook</key>
+ <value></value>
</param>
<param>
<key>_coordinate</key>
- <value>(40, 829)</value>
+ <value>(60, 407)</value>
</param>
<param>
<key>_rotation</key>
- <value>0</value>
+ <value>180</value>
</param>
</block>
<block>
<key>variable_slider</key>
<param>
<key>id</key>
- <value>freq_alpha</value>
+ <value>noise_amp</value>
</param>
<param>
<key>_enabled</key>
@@ -1523,7 +1252,7 @@
</param>
<param>
<key>label</key>
- <value>Freq Alpha</value>
+ <value>Channel Noise</value>
</param>
<param>
<key>value</key>
@@ -1535,7 +1264,7 @@
</param>
<param>
<key>max</key>
- <value>0.1</value>
+ <value>1.0</value>
</param>
<param>
<key>num_steps</key>
@@ -1551,7 +1280,7 @@
</param>
<param>
<key>grid_pos</key>
- <value></value>
+ <value>(1,2,1,1)</value>
</param>
<param>
<key>notebook</key>
@@ -1559,7 +1288,7 @@
</param>
<param>
<key>_coordinate</key>
- <value>(734, 10)</value>
+ <value>(125, 284)</value>
</param>
<param>
<key>_rotation</key>
@@ -1570,7 +1299,7 @@
<key>variable_slider</key>
<param>
<key>id</key>
- <value>freq_beta</value>
+ <value>freq_offset</value>
</param>
<param>
<key>_enabled</key>
@@ -1578,7 +1307,7 @@
</param>
<param>
<key>label</key>
- <value>Freq Beta</value>
+ <value>Frequency Offset</value>
</param>
<param>
<key>value</key>
@@ -1586,11 +1315,11 @@
</param>
<param>
<key>min</key>
- <value>0.0</value>
+ <value>-0.5</value>
</param>
<param>
<key>max</key>
- <value>0.01</value>
+ <value>0.5</value>
</param>
<param>
<key>num_steps</key>
@@ -1606,7 +1335,7 @@
</param>
<param>
<key>grid_pos</key>
- <value></value>
+ <value>(2,2,1,1)</value>
</param>
<param>
<key>notebook</key>
@@ -1614,130 +1343,88 @@
</param>
<param>
<key>_coordinate</key>
- <value>(836, 9)</value>
+ <value>(6, 284)</value>
</param>
<param>
<key>_rotation</key>
- <value>180</value>
+ <value>0</value>
</param>
</block>
<connection>
- <source_block_id>random_source_x_0</source_block_id>
- <sink_block_id>gr_uchar_to_float_0</sink_block_id>
- <source_key>0</source_key>
- <sink_key>0</sink_key>
- </connection>
- <connection>
- <source_block_id>gr_uchar_to_float_0_0</source_block_id>
- <sink_block_id>gr_add_xx_0_1</sink_block_id>
- <source_key>0</source_key>
- <sink_key>0</sink_key>
- </connection>
- <connection>
- <source_block_id>const_source_x_0_0</source_block_id>
- <sink_block_id>gr_add_xx_0_1</sink_block_id>
- <source_key>0</source_key>
- <sink_key>1</sink_key>
- </connection>
- <connection>
- <source_block_id>random_source_x_0_0</source_block_id>
- <sink_block_id>gr_uchar_to_float_0_0</sink_block_id>
- <source_key>0</source_key>
- <sink_key>0</sink_key>
- </connection>
- <connection>
<source_block_id>gr_channel_model_0</source_block_id>
- <sink_block_id>gr_throttle_0</sink_block_id>
+ <sink_block_id>virtual_sink_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>gr_add_xx_0</source_block_id>
- <sink_block_id>gr_float_to_complex_0</sink_block_id>
+ <source_block_id>digital_fll_band_edge_cc_0</source_block_id>
+ <sink_block_id>gr_pfb_clock_sync_xxx_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>gr_add_xx_0_1</source_block_id>
- <sink_block_id>gr_float_to_complex_0</sink_block_id>
- <source_key>0</source_key>
- <sink_key>1</sink_key>
- </connection>
- <connection>
- <source_block_id>gr_uchar_to_float_0</source_block_id>
- <sink_block_id>gr_add_xx_0</sink_block_id>
+ <source_block_id>gr_pfb_clock_sync_xxx_0</source_block_id>
+ <sink_block_id>digital_costas_loop_cc_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>const_source_x_0</source_block_id>
- <sink_block_id>gr_add_xx_0</sink_block_id>
- <source_key>0</source_key>
- <sink_key>1</sink_key>
- </connection>
- <connection>
- <source_block_id>gr_throttle_0</source_block_id>
- <sink_block_id>gr_fll_band_edge_cc_0</sink_block_id>
+ <source_block_id>digital_costas_loop_cc_0</source_block_id>
+ <sink_block_id>wxgui_scopesink2_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>gr_fll_band_edge_cc_0</source_block_id>
- <sink_block_id>gr_pfb_clock_sync_xxx_0</sink_block_id>
+ <source_block_id>blks2_pfb_arb_resampler_ccf_0</source_block_id>
+ <sink_block_id>gr_multiply_const_vxx_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>gr_pfb_clock_sync_xxx_0</source_block_id>
- <sink_block_id>gr_costas_loop_cc_0</sink_block_id>
+ <source_block_id>gr_chunks_to_symbols_xx</source_block_id>
+ <sink_block_id>blks2_pfb_arb_resampler_ccf_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>gr_costas_loop_cc_0</source_block_id>
- <sink_block_id>wxgui_scopesink2_0</sink_block_id>
+ <source_block_id>gr_channel_model_0</source_block_id>
+ <sink_block_id>digital_fll_band_edge_cc_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>gr_fll_band_edge_cc_0</source_block_id>
+ <source_block_id>digital_fll_band_edge_cc_0</source_block_id>
<sink_block_id>wxgui_fftsink2_0_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>virtual_source_0</source_block_id>
- <sink_block_id>wxgui_scopesink2_0_0_1</sink_block_id>
- <source_key>0</source_key>
- <sink_key>0</sink_key>
- </connection>
- <connection>
- <source_block_id>virtual_source_0</source_block_id>
<sink_block_id>wxgui_fftsink2_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>gr_channel_model_0</source_block_id>
- <sink_block_id>virtual_sink_0</sink_block_id>
+ <source_block_id>virtual_source_0</source_block_id>
+ <sink_block_id>wxgui_scopesink2_0_0_1</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>gr_float_to_complex_0</source_block_id>
- <sink_block_id>blks2_pfb_arb_resampler_ccf_0</sink_block_id>
+ <source_block_id>random_source_x</source_block_id>
+ <sink_block_id>gr_chunks_to_symbols_xx</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>blks2_pfb_arb_resampler_ccf_0</source_block_id>
- <sink_block_id>gr_multiply_const_vxx_0</sink_block_id>
+ <source_block_id>gr_throttle_0</source_block_id>
+ <sink_block_id>gr_channel_model_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>gr_multiply_const_vxx_0</source_block_id>
- <sink_block_id>gr_channel_model_0</sink_block_id>
+ <sink_block_id>gr_throttle_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
diff --git a/gr-digital/examples/demod/pam_timing.grc b/gr-digital/examples/demod/pam_timing.grc
index 02130f481..14a7d403e 100644
--- a/gr-digital/examples/demod/pam_timing.grc
+++ b/gr-digital/examples/demod/pam_timing.grc
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='ASCII'?>
<flow_graph>
- <timestamp>Mon Feb 1 18:54:46 2010</timestamp>
+ <timestamp>Thu Jul 5 17:55:51 2012</timestamp>
<block>
<key>options</key>
<param>
@@ -44,6 +44,10 @@
<value>True</value>
</param>
<param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
<key>realtime_scheduling</key>
<value></value>
</param>
@@ -749,6 +753,14 @@
<value></value>
</param>
<param>
+ <key>trig_mode</key>
+ <value>gr.gr_TRIG_MODE_AUTO</value>
+ </param>
+ <param>
+ <key>y_axis_label</key>
+ <value>Counts</value>
+ </param>
+ <param>
<key>_coordinate</key>
<value>(1116, 500)</value>
</param>
@@ -792,7 +804,7 @@
<key>wxgui_scopesink2</key>
<param>
<key>id</key>
- <value>wxgui_scopesink2_0_0</value>
+ <value>wxgui_scopesink2_0_0_0</value>
</param>
<param>
<key>_enabled</key>
@@ -804,7 +816,7 @@
</param>
<param>
<key>title</key>
- <value>Error</value>
+ <value>Scope Plot</value>
</param>
<param>
<key>samp_rate</key>
@@ -812,7 +824,7 @@
</param>
<param>
<key>v_scale</key>
- <value>3</value>
+ <value>9</value>
</param>
<param>
<key>v_offset</key>
@@ -844,11 +856,42 @@
</param>
<param>
<key>notebook</key>
- <value>notebook_0,0</value>
+ <value>notebook_0,1</value>
+ </param>
+ <param>
+ <key>trig_mode</key>
+ <value>gr.gr_TRIG_MODE_AUTO</value>
+ </param>
+ <param>
+ <key>y_axis_label</key>
+ <value>Counts</value>
</param>
<param>
<key>_coordinate</key>
- <value>(1110, 651)</value>
+ <value>(1112, 881)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>rrctaps</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>firdes.root_raised_cosine(nfilts,1.0,1.0/(spb*nfilts), .35, int(11*spb*nfilts))</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(513, 679)</value>
</param>
<param>
<key>_rotation</key>
@@ -859,7 +902,7 @@
<key>wxgui_scopesink2</key>
<param>
<key>id</key>
- <value>wxgui_scopesink2_0_0_0</value>
+ <value>wxgui_scopesink2_0_0_1</value>
</param>
<param>
<key>_enabled</key>
@@ -867,11 +910,11 @@
</param>
<param>
<key>type</key>
- <value>float</value>
+ <value>complex</value>
</param>
<param>
<key>title</key>
- <value>Scope Plot</value>
+ <value>Error</value>
</param>
<param>
<key>samp_rate</key>
@@ -879,7 +922,7 @@
</param>
<param>
<key>v_scale</key>
- <value>9</value>
+ <value>.5</value>
</param>
<param>
<key>v_offset</key>
@@ -911,11 +954,19 @@
</param>
<param>
<key>notebook</key>
- <value>notebook_0,1</value>
+ <value>notebook_0,3</value>
+ </param>
+ <param>
+ <key>trig_mode</key>
+ <value>gr.gr_TRIG_MODE_AUTO</value>
+ </param>
+ <param>
+ <key>y_axis_label</key>
+ <value>Counts</value>
</param>
<param>
<key>_coordinate</key>
- <value>(1112, 881)</value>
+ <value>(1115, 358)</value>
</param>
<param>
<key>_rotation</key>
@@ -923,22 +974,22 @@
</param>
</block>
<block>
- <key>variable</key>
+ <key>gr_float_to_complex</key>
<param>
<key>id</key>
- <value>rrctaps</value>
+ <value>gr_float_to_complex_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>value</key>
- <value>firdes.root_raised_cosine(nfilts,1.0,1.0/(spb*nfilts), .35, int(11*spb*nfilts))</value>
+ <key>vlen</key>
+ <value>1</value>
</param>
<param>
<key>_coordinate</key>
- <value>(513, 679)</value>
+ <value>(590, 184)</value>
</param>
<param>
<key>_rotation</key>
@@ -946,50 +997,69 @@
</param>
</block>
<block>
- <key>gr_pfb_clock_sync_xxx</key>
+ <key>blks2_pfb_arb_resampler_ccf</key>
<param>
<key>id</key>
- <value>gr_pfb_clock_sync_xxx_0</value>
+ <value>blks2_pfb_arb_resampler_ccf_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>ccf</value>
+ <key>rate</key>
+ <value>spb</value>
</param>
<param>
- <key>sps</key>
- <value>spb</value>
+ <key>taps</key>
+ <value>firdes.root_raised_cosine(32, 32, 1.0, 0.35, 44*32)</value>
</param>
<param>
- <key>alpha</key>
- <value>alpha</value>
+ <key>size</key>
+ <value>32</value>
</param>
<param>
- <key>beta</key>
- <value>beta</value>
+ <key>_coordinate</key>
+ <value>(816, 181)</value>
</param>
<param>
- <key>taps</key>
- <value>rrctaps</value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
+ </block>
+ <block>
+ <key>gr_channel_model</key>
<param>
- <key>filter_size</key>
- <value>nfilts</value>
+ <key>id</key>
+ <value>gr_channel_model_0</value>
</param>
<param>
- <key>init_phase</key>
- <value>16</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>max_dev</key>
- <value>1.5</value>
+ <key>noise_voltage</key>
+ <value>noise_amp</value>
+ </param>
+ <param>
+ <key>freq_offset</key>
+ <value>freq_offset</value>
+ </param>
+ <param>
+ <key>epsilon</key>
+ <value>interpratio</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>seed</key>
+ <value>42</value>
</param>
<param>
<key>_coordinate</key>
- <value>(512, 527)</value>
+ <value>(59, 543)</value>
</param>
<param>
<key>_rotation</key>
@@ -997,10 +1067,10 @@
</param>
</block>
<block>
- <key>wxgui_scopesink2</key>
+ <key>gr_multiply_const_vxx</key>
<param>
<key>id</key>
- <value>wxgui_scopesink2_0_0_0_0</value>
+ <value>gr_multiply_const_vxx_0</value>
</param>
<param>
<key>_enabled</key>
@@ -1008,55 +1078,97 @@
</param>
<param>
<key>type</key>
- <value>float</value>
+ <value>complex</value>
</param>
<param>
- <key>title</key>
- <value>Scope Plot</value>
+ <key>const</key>
+ <value>sig_amp</value>
</param>
<param>
- <key>samp_rate</key>
- <value>samp_rate</value>
+ <key>vlen</key>
+ <value>1</value>
</param>
<param>
- <key>v_scale</key>
- <value>1.25</value>
+ <key>_coordinate</key>
+ <value>(714, 382)</value>
</param>
<param>
- <key>v_offset</key>
+ <key>_rotation</key>
<value>0</value>
</param>
+ </block>
+ <block>
+ <key>variable</key>
<param>
- <key>t_scale</key>
+ <key>id</key>
+ <value>spb</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>4.2563</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(42, 840)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
<value>0</value>
</param>
+ </block>
+ <block>
+ <key>gr_pfb_clock_sync_xxx</key>
<param>
- <key>ac_couple</key>
- <value>False</value>
+ <key>id</key>
+ <value>gr_pfb_clock_sync_xxx_0</value>
</param>
<param>
- <key>xy_mode</key>
- <value>False</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>num_inputs</key>
- <value>1</value>
+ <key>type</key>
+ <value>ccf</value>
</param>
<param>
- <key>win_size</key>
- <value></value>
+ <key>sps</key>
+ <value>spb</value>
</param>
<param>
- <key>grid_pos</key>
- <value></value>
+ <key>alpha</key>
+ <value>alpha</value>
</param>
<param>
- <key>notebook</key>
- <value>notebook_0,2</value>
+ <key>beta</key>
+ <value>beta</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value>rrctaps</value>
+ </param>
+ <param>
+ <key>filter_size</key>
+ <value>nfilts</value>
+ </param>
+ <param>
+ <key>init_phase</key>
+ <value>16</value>
+ </param>
+ <param>
+ <key>max_dev</key>
+ <value>1.5</value>
+ </param>
+ <param>
+ <key>osps</key>
+ <value>1</value>
</param>
<param>
<key>_coordinate</key>
- <value>(1111, 767)</value>
+ <value>(512, 527)</value>
</param>
<param>
<key>_rotation</key>
@@ -1067,7 +1179,7 @@
<key>wxgui_scopesink2</key>
<param>
<key>id</key>
- <value>wxgui_scopesink2_0_0_1</value>
+ <value>wxgui_scopesink2_0_0</value>
</param>
<param>
<key>_enabled</key>
@@ -1075,7 +1187,7 @@
</param>
<param>
<key>type</key>
- <value>complex</value>
+ <value>float</value>
</param>
<param>
<key>title</key>
@@ -1087,7 +1199,7 @@
</param>
<param>
<key>v_scale</key>
- <value>.5</value>
+ <value>3</value>
</param>
<param>
<key>v_offset</key>
@@ -1119,34 +1231,19 @@
</param>
<param>
<key>notebook</key>
- <value>notebook_0,3</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(1115, 358)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>gr_float_to_complex</key>
- <param>
- <key>id</key>
- <value>gr_float_to_complex_0</value>
+ <value>notebook_0,0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>trig_mode</key>
+ <value>gr.gr_TRIG_MODE_AUTO</value>
</param>
<param>
- <key>vlen</key>
- <value>1</value>
+ <key>y_axis_label</key>
+ <value>Counts</value>
</param>
<param>
<key>_coordinate</key>
- <value>(590, 184)</value>
+ <value>(1114, 615)</value>
</param>
<param>
<key>_rotation</key>
@@ -1154,123 +1251,74 @@
</param>
</block>
<block>
- <key>blks2_pfb_arb_resampler_ccf</key>
+ <key>wxgui_scopesink2</key>
<param>
<key>id</key>
- <value>blks2_pfb_arb_resampler_ccf_0</value>
+ <value>wxgui_scopesink2_0_0_0_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>rate</key>
- <value>spb</value>
+ <key>type</key>
+ <value>float</value>
</param>
<param>
- <key>taps</key>
- <value>firdes.root_raised_cosine(32, 32, 1.0, 0.35, 44*32)</value>
+ <key>title</key>
+ <value>Scope Plot</value>
</param>
<param>
- <key>size</key>
- <value>32</value>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(816, 181)</value>
+ <key>v_scale</key>
+ <value>1.25</value>
</param>
<param>
- <key>_rotation</key>
+ <key>v_offset</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>gr_channel_model</key>
- <param>
- <key>id</key>
- <value>gr_channel_model_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>noise_voltage</key>
- <value>noise_amp</value>
- </param>
<param>
- <key>freq_offset</key>
- <value>freq_offset</value>
- </param>
- <param>
- <key>epsilon</key>
- <value>interpratio</value>
- </param>
- <param>
- <key>taps</key>
- <value>1.0</value>
- </param>
- <param>
- <key>seed</key>
- <value>42</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(59, 543)</value>
- </param>
- <param>
- <key>_rotation</key>
+ <key>t_scale</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>gr_multiply_const_vxx</key>
<param>
- <key>id</key>
- <value>gr_multiply_const_vxx_0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>type</key>
- <value>complex</value>
+ <key>ac_couple</key>
+ <value>False</value>
</param>
<param>
- <key>const</key>
- <value>sig_amp</value>
+ <key>xy_mode</key>
+ <value>False</value>
</param>
<param>
- <key>vlen</key>
+ <key>num_inputs</key>
<value>1</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(714, 382)</value>
+ <key>win_size</key>
+ <value></value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>grid_pos</key>
+ <value></value>
</param>
- </block>
- <block>
- <key>variable</key>
<param>
- <key>id</key>
- <value>spb</value>
+ <key>notebook</key>
+ <value>notebook_0,2</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>trig_mode</key>
+ <value>gr.gr_TRIG_MODE_AUTO</value>
</param>
<param>
- <key>value</key>
- <value>4.2563</value>
+ <key>y_axis_label</key>
+ <value>Counts</value>
</param>
<param>
<key>_coordinate</key>
- <value>(42, 840)</value>
+ <value>(1080, 751)</value>
</param>
<param>
<key>_rotation</key>
diff --git a/gr-digital/grc/digital_dxpsk_demod.xml b/gr-digital/grc/digital_dxpsk_demod.xml
index 6366596d9..f3e9ee6fc 100644
--- a/gr-digital/grc/digital_dxpsk_demod.xml
+++ b/gr-digital/grc/digital_dxpsk_demod.xml
@@ -36,7 +36,7 @@
freq_bw=$freq_bw,
phase_bw=$phase_bw,
timing_bw=$timing_bw,
- mod_code=$mod_code,
+ gray_coded=$gray_coded,
verbose=$verbose,
log=$log
)</make>
@@ -86,23 +86,17 @@
<type>real</type>
</param>
<param>
- <name>Omega Relative Limit</name>
- <key>omega_relative_limit</key>
- <value>0.005</value>
- <type>real</type>
- </param>
- <param>
<name>Gray Code</name>
- <key>mod_code</key>
+ <key>gray_coded</key>
<value>True</value>
<type>enum</type>
<option>
<name>Yes</name>
- <key>"gray"</key>
+ <key>True</key>
</option>
<option>
<name>No</name>
- <key>"none"</key>
+ <key>False</key>
</option>
</param>
<param>
diff --git a/gr-digital/grc/digital_dxpsk_mod.xml b/gr-digital/grc/digital_dxpsk_mod.xml
index 58e30436d..93334d27d 100644
--- a/gr-digital/grc/digital_dxpsk_mod.xml
+++ b/gr-digital/grc/digital_dxpsk_mod.xml
@@ -33,7 +33,7 @@
<make>digital.$(type)_mod(
samples_per_symbol=$samples_per_symbol,
excess_bw=$excess_bw,
- mod_code=$mod_code,
+ gray_coded=$gray_coded,
verbose=$verbose,
log=$log)
</make>
@@ -68,16 +68,16 @@
</param>
<param>
<name>Gray Code</name>
- <key>mod_code</key>
- <value>"gray"</value>
+ <key>gray_coded</key>
+ <value>True</value>
<type>enum</type>
<option>
<name>Yes</name>
- <key>"gray"</key>
+ <key>True</key>
</option>
<option>
<name>No</name>
- <key>"none"</key>
+ <key>False</key>
</option>
</param>
<param>
diff --git a/gr-digital/grc/digital_gfsk_demod.xml b/gr-digital/grc/digital_gfsk_demod.xml
new file mode 100644
index 000000000..ce3024d89
--- /dev/null
+++ b/gr-digital/grc/digital_gfsk_demod.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##GFSK Demod
+###################################################
+ -->
+<block>
+ <name>GFSK Demod</name>
+ <key>digital_gfsk_demod</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.gfsk_demod(
+ samples_per_symbol=$samples_per_symbol,
+ sensitivity=$sensitivity,
+ gain_mu=$gain_mu,
+ mu=$mu,
+ omega_relative_limit=$omega_relative_limit,
+ freq_error=$freq_error,
+ verbose=$verbose,
+ log=$log,
+)</make>
+ <param>
+ <name>Samples/Symbol</name>
+ <key>samples_per_symbol</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Sensitivity</name>
+ <key>sensitivity</key>
+ <value>1.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Gain Mu</name>
+ <key>gain_mu</key>
+ <value>0.175</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Mu</name>
+ <key>mu</key>
+ <value>0.5</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Omega Relative Limit</name>
+ <key>omega_relative_limit</key>
+ <value>0.005</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Freq Error</name>
+ <key>freq_error</key>
+ <value>0.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Verbose</name>
+ <key>verbose</key>
+ <value>False</value>
+ <type>bool</type>
+ <hide>#if str($verbose) == 'False' then 'part' else 'none'#</hide>
+ <option>
+ <name>On</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Off</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Logging</name>
+ <key>log</key>
+ <value>False</value>
+ <type>bool</type>
+ <hide>#if str($log) == 'False' then 'part' else 'none'#</hide>
+ <option>
+ <name>On</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Off</name>
+ <key>False</key>
+ </option>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/gr-digital/grc/digital_gfsk_mod.xml b/gr-digital/grc/digital_gfsk_mod.xml
new file mode 100644
index 000000000..2d6cd1ea5
--- /dev/null
+++ b/gr-digital/grc/digital_gfsk_mod.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##GFSK Mod
+###################################################
+ -->
+<block>
+ <name>GFSK Mod</name>
+ <key>digital_gfsk_mod</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.gfsk_mod(
+ samples_per_symbol=$samples_per_symbol,
+ sensitivity=$sensitivity,
+ bt=$bt,
+ verbose=$verbose,
+ log=$log,
+)</make>
+ <param>
+ <name>Samples/Symbol</name>
+ <key>samples_per_symbol</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Sensitivity</name>
+ <key>sensitivity</key>
+ <value>1.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>BT</name>
+ <key>bt</key>
+ <value>0.35</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Verbose</name>
+ <key>verbose</key>
+ <value>False</value>
+ <type>bool</type>
+ <hide>#if str($verbose) == 'False' then 'part' else 'none'#</hide>
+ <option>
+ <name>On</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Off</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Logging</name>
+ <key>log</key>
+ <value>False</value>
+ <type>bool</type>
+ <hide>#if str($log) == 'False' then 'part' else 'none'#</hide>
+ <option>
+ <name>On</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Off</name>
+ <key>False</key>
+ </option>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/gr-digital/include/digital_fll_band_edge_cc.h b/gr-digital/include/digital_fll_band_edge_cc.h
index c70bfc86d..68083bbae 100644
--- a/gr-digital/include/digital_fll_band_edge_cc.h
+++ b/gr-digital/include/digital_fll_band_edge_cc.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2009,2011 Free Software Foundation, Inc.
+ * Copyright 2009,2011,2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -27,13 +27,19 @@
#include <digital_api.h>
#include <gr_sync_block.h>
#include <gri_control_loop.h>
+#include <gr_fir_util.h>
+#include <gr_fir_ccc.h>
+
+typedef gr_fir_ccc* (*fir_maker_t)(const std::vector<gr_complex> &taps);
+typedef gr_fir_ccc filter_t;
class digital_fll_band_edge_cc;
typedef boost::shared_ptr<digital_fll_band_edge_cc> digital_fll_band_edge_cc_sptr;
-DIGITAL_API digital_fll_band_edge_cc_sptr digital_make_fll_band_edge_cc (float samps_per_sym,
- float rolloff,
- int filter_size,
- float bandwidth);
+DIGITAL_API digital_fll_band_edge_cc_sptr
+digital_make_fll_band_edge_cc(float samps_per_sym,
+ float rolloff,
+ int filter_size,
+ float bandwidth);
/*!
* \class digital_fll_band_edge_cc
@@ -86,7 +92,8 @@ DIGITAL_API digital_fll_band_edge_cc_sptr digital_make_fll_band_edge_cc (float s
*
*/
-class DIGITAL_API digital_fll_band_edge_cc : public gr_sync_block, public gri_control_loop
+class DIGITAL_API digital_fll_band_edge_cc :
+ public gr_sync_block, public gri_control_loop
{
private:
/*!
@@ -96,10 +103,11 @@ class DIGITAL_API digital_fll_band_edge_cc : public gr_sync_block, public gri_co
* \param filter_size (int) Size (in taps) of the filter
* \param bandwidth (float) Loop bandwidth
*/
- friend DIGITAL_API digital_fll_band_edge_cc_sptr digital_make_fll_band_edge_cc (float samps_per_sym,
- float rolloff,
- int filter_size,
- float bandwidth);
+ friend DIGITAL_API digital_fll_band_edge_cc_sptr
+ digital_make_fll_band_edge_cc(float samps_per_sym,
+ float rolloff,
+ int filter_size,
+ float bandwidth);
float d_sps;
float d_rolloff;
@@ -108,6 +116,10 @@ class DIGITAL_API digital_fll_band_edge_cc : public gr_sync_block, public gri_co
std::vector<gr_complex> d_taps_lower;
std::vector<gr_complex> d_taps_upper;
bool d_updated;
+ filter_t* d_filter_lower;
+ filter_t* d_filter_upper;
+ std::vector<gr_complex> d_output_hist;
+ std::vector<gr_complex> d_fllbuffer;
/*!
* Build the FLL
@@ -130,7 +142,7 @@ class DIGITAL_API digital_fll_band_edge_cc : public gr_sync_block, public gri_co
void design_filter(float samps_per_sym, float rolloff, int filter_size);
public:
- ~digital_fll_band_edge_cc ();
+ ~digital_fll_band_edge_cc();
/*******************************************************************
SET FUNCTIONS
@@ -206,9 +218,9 @@ public:
*/
void print_taps();
- int work (int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
};
#endif
diff --git a/gr-digital/lib/digital_fll_band_edge_cc.cc b/gr-digital/lib/digital_fll_band_edge_cc.cc
index 05c092622..f2cfb1020 100644
--- a/gr-digital/lib/digital_fll_band_edge_cc.cc
+++ b/gr-digital/lib/digital_fll_band_edge_cc.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2009-2011 Free Software Foundation, Inc.
+ * Copyright 2009-2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -50,37 +50,38 @@ digital_make_fll_band_edge_cc (float samps_per_sym, float rolloff,
static int ios[] = {sizeof(gr_complex), sizeof(float), sizeof(float), sizeof(float)};
static std::vector<int> iosig(ios, ios+sizeof(ios)/sizeof(int));
-digital_fll_band_edge_cc::digital_fll_band_edge_cc (float samps_per_sym, float rolloff,
- int filter_size, float bandwidth)
- : gr_sync_block ("fll_band_edge_cc",
- gr_make_io_signature (1, 1, sizeof(gr_complex)),
- gr_make_io_signaturev (1, 4, iosig)),
+digital_fll_band_edge_cc::digital_fll_band_edge_cc(float samps_per_sym, float rolloff,
+ int filter_size, float bandwidth)
+ : gr_sync_block("fll_band_edge_cc",
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ gr_make_io_signaturev(1, 4, iosig)),
gri_control_loop(bandwidth, M_TWOPI*(2.0/samps_per_sym), -M_TWOPI*(2.0/samps_per_sym)),
- d_updated (false)
+ d_updated(false)
{
// Initialize samples per symbol
if(samps_per_sym <= 0) {
- throw std::out_of_range ("digital_fll_band_edge_cc: invalid number of sps. Must be > 0.");
+ throw std::out_of_range("digital_fll_band_edge_cc: invalid number of sps. Must be > 0.");
}
d_sps = samps_per_sym;
// Initialize rolloff factor
if(rolloff < 0 || rolloff > 1.0) {
- throw std::out_of_range ("digital_fll_band_edge_cc: invalid rolloff factor. Must be in [0,1].");
+ throw std::out_of_range("digital_fll_band_edge_cc: invalid rolloff factor. Must be in [0,1].");
}
d_rolloff = rolloff;
// Initialize filter length
if(filter_size <= 0) {
- throw std::out_of_range ("digital_fll_band_edge_cc: invalid filter size. Must be > 0.");
+ throw std::out_of_range("digital_fll_band_edge_cc: invalid filter size. Must be > 0.");
}
d_filter_size = filter_size;
// Build the band edge filters
design_filter(d_sps, d_rolloff, d_filter_size);
+ d_output_hist.resize(filter_size,0);
}
-digital_fll_band_edge_cc::~digital_fll_band_edge_cc ()
+digital_fll_band_edge_cc::~digital_fll_band_edge_cc()
{
}
@@ -93,7 +94,7 @@ void
digital_fll_band_edge_cc::set_samples_per_symbol(float sps)
{
if(sps <= 0) {
- throw std::out_of_range ("digital_fll_band_edge_cc: invalid number of sps. Must be > 0.");
+ throw std::out_of_range("digital_fll_band_edge_cc: invalid number of sps. Must be > 0.");
}
d_sps = sps;
design_filter(d_sps, d_rolloff, d_filter_size);
@@ -103,7 +104,7 @@ void
digital_fll_band_edge_cc::set_rolloff(float rolloff)
{
if(rolloff < 0 || rolloff > 1.0) {
- throw std::out_of_range ("digital_fll_band_edge_cc: invalid rolloff factor. Must be in [0,1].");
+ throw std::out_of_range("digital_fll_band_edge_cc: invalid rolloff factor. Must be in [0,1].");
}
d_rolloff = rolloff;
design_filter(d_sps, d_rolloff, d_filter_size);
@@ -113,7 +114,7 @@ void
digital_fll_band_edge_cc::set_filter_size(int filter_size)
{
if(filter_size <= 0) {
- throw std::out_of_range ("digital_fll_band_edge_cc: invalid filter size. Must be > 0.");
+ throw std::out_of_range("digital_fll_band_edge_cc: invalid filter size. Must be > 0.");
}
d_filter_size = filter_size;
design_filter(d_sps, d_rolloff, d_filter_size);
@@ -185,6 +186,8 @@ digital_fll_band_edge_cc::design_filter(float samps_per_sym,
// Set the history to ensure enough input items for each filter
set_history(filter_size+1);
+ d_filter_upper = gr_fir_util::create_gr_fir_ccc(d_taps_upper);
+ d_filter_lower = gr_fir_util::create_gr_fir_ccc(d_taps_lower);
}
void
@@ -206,23 +209,25 @@ digital_fll_band_edge_cc::print_taps()
}
int
-digital_fll_band_edge_cc::work (int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
+digital_fll_band_edge_cc::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
{
- const gr_complex *in = (const gr_complex *) input_items[0];
- gr_complex *out = (gr_complex *) output_items[0];
+ const gr_complex *in = (const gr_complex*)input_items[0];
+ gr_complex *out = (gr_complex*)output_items[0];
+ d_fllbuffer.reserve(d_filter_size+noutput_items);
+
float *frq = NULL;
float *phs = NULL;
float *err = NULL;
if(output_items.size() == 4) {
- frq = (float *) output_items[1];
- phs = (float *) output_items[2];
- err = (float *) output_items[3];
+ frq = (float*)output_items[1];
+ phs = (float*)output_items[2];
+ err = (float*)output_items[3];
}
- if (d_updated) {
+ if(d_updated) {
d_updated = false;
return 0; // history requirements may have changed.
}
@@ -231,17 +236,19 @@ digital_fll_band_edge_cc::work (int noutput_items,
float error;
gr_complex nco_out;
gr_complex out_upper, out_lower;
+ gr_complex out_uppersse, out_lowersse;
+ copy( d_output_hist.begin(), d_output_hist.end(), d_fllbuffer.begin());
+
for(i = 0; i < noutput_items; i++) {
nco_out = gr_expj(d_phase);
- out[i+d_filter_size-1] = in[i] * nco_out;
-
+ d_fllbuffer[i+d_filter_size] = in[i] * nco_out;
// Perform the dot product of the output with the filters
out_upper = 0;
out_lower = 0;
- for(int k = 0; k < d_filter_size; k++) {
- out_upper += d_taps_upper[k] * out[i+k];
- out_lower += d_taps_lower[k] * out[i+k];
- }
+
+ out_upper = d_filter_lower->filter(&d_fllbuffer[i]);
+ out_lower = d_filter_upper->filter(&d_fllbuffer[i]);
+
error = norm(out_lower) - norm(out_upper);
advance_loop(error);
@@ -255,5 +262,10 @@ digital_fll_band_edge_cc::work (int noutput_items,
}
}
+ copy(d_fllbuffer.begin(), d_fllbuffer.begin()+noutput_items, out);
+ copy(d_fllbuffer.begin()+noutput_items,
+ d_fllbuffer.begin()+noutput_items+d_filter_size,
+ d_output_hist.begin());
+
return noutput_items;
}
diff --git a/gr-digital/python/CMakeLists.txt b/gr-digital/python/CMakeLists.txt
index c786b5a14..6a9f10295 100644
--- a/gr-digital/python/CMakeLists.txt
+++ b/gr-digital/python/CMakeLists.txt
@@ -30,6 +30,7 @@ GR_PYTHON_INSTALL(
crc.py
generic_mod_demod.py
gmsk.py
+ gfsk.py
modulation_utils.py
ofdm.py
ofdm_packet_utils.py
diff --git a/gr-digital/python/__init__.py b/gr-digital/python/__init__.py
index 7c76183c9..3fdbca769 100644
--- a/gr-digital/python/__init__.py
+++ b/gr-digital/python/__init__.py
@@ -31,6 +31,7 @@ from qam import *
from bpsk import *
from qpsk import *
from gmsk import *
+from gfsk import *
from cpm import *
from pkt import *
from crc import *
diff --git a/gr-digital/python/gfsk.py b/gr-digital/python/gfsk.py
new file mode 100644
index 000000000..c85fdf0e0
--- /dev/null
+++ b/gr-digital/python/gfsk.py
@@ -0,0 +1,306 @@
+#
+# GFSK modulation and demodulation.
+#
+#
+# Copyright 2005,2006,2007 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+# See gnuradio-examples/python/digital for examples
+
+from gnuradio import gr
+import modulation_utils
+import digital_swig as digital
+from math import pi
+import numpy
+from pprint import pprint
+import inspect
+
+# default values (used in __init__ and add_options)
+_def_samples_per_symbol = 2
+_def_sensitivity = 1
+_def_bt = 0.35
+_def_verbose = False
+_def_log = False
+
+_def_gain_mu = None
+_def_mu = 0.5
+_def_freq_error = 0.0
+_def_omega_relative_limit = 0.005
+
+
+# FIXME: Figure out how to make GFSK work with pfb_arb_resampler_fff for both
+# transmit and receive so we don't require integer samples per symbol.
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# GFSK modulator
+# /////////////////////////////////////////////////////////////////////////////
+
+class gfsk_mod(gr.hier_block2):
+
+ def __init__(self,
+ samples_per_symbol=_def_samples_per_symbol,
+ sensitivity=_def_sensitivity,
+ bt=_def_bt,
+ verbose=_def_verbose,
+ log=_def_log):
+ """
+ Hierarchical block for Gaussian Frequency Shift Key (GFSK)
+ modulation.
+
+ The input is a byte stream (unsigned char) and the
+ output is the complex modulated signal at baseband.
+
+ @param samples_per_symbol: samples per baud >= 2
+ @type samples_per_symbol: integer
+ @param bt: Gaussian filter bandwidth * symbol time
+ @type bt: float
+ @param verbose: Print information about modulator?
+ @type verbose: bool
+ @param debug: Print modualtion data to files?
+ @type debug: bool
+ """
+
+ gr.hier_block2.__init__(self, "gfsk_mod",
+ gr.io_signature(1, 1, gr.sizeof_char), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
+
+ samples_per_symbol = int(samples_per_symbol)
+ self._samples_per_symbol = samples_per_symbol
+ self._bt = bt
+ self._differential = False
+
+ if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2:
+ raise TypeError, ("samples_per_symbol must be an integer >= 2, is %r" % (samples_per_symbol,))
+
+ ntaps = 4 * samples_per_symbol # up to 3 bits in filter at once
+ #sensitivity = (pi / 2) / samples_per_symbol # phase change per bit = pi / 2
+
+ # Turn it into NRZ data.
+ self.nrz = gr.bytes_to_syms()
+
+ # Form Gaussian filter
+ # Generate Gaussian response (Needs to be convolved with window below).
+ self.gaussian_taps = gr.firdes.gaussian(
+ 1.0, # gain
+ samples_per_symbol, # symbol_rate
+ bt, # bandwidth * symbol time
+ ntaps # number of taps
+ )
+
+ self.sqwave = (1,) * samples_per_symbol # rectangular window
+ self.taps = numpy.convolve(numpy.array(self.gaussian_taps),numpy.array(self.sqwave))
+ self.gaussian_filter = gr.interp_fir_filter_fff(samples_per_symbol, self.taps)
+
+ # FM modulation
+ self.fmmod = gr.frequency_modulator_fc(sensitivity)
+
+ # small amount of output attenuation to prevent clipping USRP sink
+ self.amp = gr.multiply_const_cc(0.999)
+
+ if verbose:
+ self._print_verbage()
+
+ if log:
+ self._setup_logging()
+
+ # Connect & Initialize base class
+ self.connect(self, self.nrz, self.gaussian_filter, self.fmmod, self.amp, self)
+
+ def samples_per_symbol(self):
+ return self._samples_per_symbol
+
+ def bits_per_symbol(self=None): # staticmethod that's also callable on an instance
+ return 1
+ bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method.
+
+
+ def _print_verbage(self):
+ print "bits per symbol = %d" % self.bits_per_symbol()
+ print "Gaussian filter bt = %.2f" % self._bt
+
+
+ def _setup_logging(self):
+ print "Modulation logging turned on."
+ self.connect(self.nrz,
+ gr.file_sink(gr.sizeof_float, "nrz.dat"))
+ self.connect(self.gaussian_filter,
+ gr.file_sink(gr.sizeof_float, "gaussian_filter.dat"))
+ self.connect(self.fmmod,
+ gr.file_sink(gr.sizeof_gr_complex, "fmmod.dat"))
+
+
+ def add_options(parser):
+ """
+ Adds GFSK modulation-specific options to the standard parser
+ """
+ parser.add_option("", "--bt", type="float", default=_def_bt,
+ help="set bandwidth-time product [default=%default] (GFSK)")
+ add_options=staticmethod(add_options)
+
+
+ def extract_kwargs_from_options(options):
+ """
+ Given command line options, create dictionary suitable for passing to __init__
+ """
+ return modulation_utils.extract_kwargs_from_options(gfsk_mod.__init__,
+ ('self',), options)
+ extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
+
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# GFSK demodulator
+# /////////////////////////////////////////////////////////////////////////////
+
+class gfsk_demod(gr.hier_block2):
+
+ def __init__(self,
+ samples_per_symbol=_def_samples_per_symbol,
+ sensitivity=_def_sensitivity,
+ gain_mu=_def_gain_mu,
+ mu=_def_mu,
+ omega_relative_limit=_def_omega_relative_limit,
+ freq_error=_def_freq_error,
+ verbose=_def_verbose,
+ log=_def_log):
+ """
+ Hierarchical block for Gaussian Minimum Shift Key (GFSK)
+ demodulation.
+
+ The input is the complex modulated signal at baseband.
+ The output is a stream of bits packed 1 bit per byte (the LSB)
+
+ @param samples_per_symbol: samples per baud
+ @type samples_per_symbol: integer
+ @param verbose: Print information about modulator?
+ @type verbose: bool
+ @param log: Print modualtion data to files?
+ @type log: bool
+
+ Clock recovery parameters. These all have reasonble defaults.
+
+ @param gain_mu: controls rate of mu adjustment
+ @type gain_mu: float
+ @param mu: fractional delay [0.0, 1.0]
+ @type mu: float
+ @param omega_relative_limit: sets max variation in omega
+ @type omega_relative_limit: float, typically 0.000200 (200 ppm)
+ @param freq_error: bit rate error as a fraction
+ @param float
+ """
+
+ gr.hier_block2.__init__(self, "gfsk_demod",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_char)) # Output signature
+
+ self._samples_per_symbol = samples_per_symbol
+ self._gain_mu = gain_mu
+ self._mu = mu
+ self._omega_relative_limit = omega_relative_limit
+ self._freq_error = freq_error
+ self._differential = False
+
+ if samples_per_symbol < 2:
+ raise TypeError, "samples_per_symbol >= 2, is %f" % samples_per_symbol
+
+ self._omega = samples_per_symbol*(1+self._freq_error)
+
+ if not self._gain_mu:
+ self._gain_mu = 0.175
+
+ self._gain_omega = .25 * self._gain_mu * self._gain_mu # critically damped
+
+ # Demodulate FM
+ #sensitivity = (pi / 2) / samples_per_symbol
+ self.fmdemod = gr.quadrature_demod_cf(1.0 / sensitivity)
+
+ # the clock recovery block tracks the symbol clock and resamples as needed.
+ # the output of the block is a stream of soft symbols (float)
+ self.clock_recovery = digital.clock_recovery_mm_ff(self._omega, self._gain_omega,
+ self._mu, self._gain_mu,
+ self._omega_relative_limit)
+
+ # slice the floats at 0, outputting 1 bit (the LSB of the output byte) per sample
+ self.slicer = digital.binary_slicer_fb()
+
+ if verbose:
+ self._print_verbage()
+
+ if log:
+ self._setup_logging()
+
+ # Connect & Initialize base class
+ self.connect(self, self.fmdemod, self.clock_recovery, self.slicer, self)
+
+ def samples_per_symbol(self):
+ return self._samples_per_symbol
+
+ def bits_per_symbol(self=None): # staticmethod that's also callable on an instance
+ return 1
+ bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method.
+
+
+ def _print_verbage(self):
+ print "bits per symbol = %d" % self.bits_per_symbol()
+ print "M&M clock recovery omega = %f" % self._omega
+ print "M&M clock recovery gain mu = %f" % self._gain_mu
+ print "M&M clock recovery mu = %f" % self._mu
+ print "M&M clock recovery omega rel. limit = %f" % self._omega_relative_limit
+ print "frequency error = %f" % self._freq_error
+
+
+ def _setup_logging(self):
+ print "Demodulation logging turned on."
+ self.connect(self.fmdemod,
+ gr.file_sink(gr.sizeof_float, "fmdemod.dat"))
+ self.connect(self.clock_recovery,
+ gr.file_sink(gr.sizeof_float, "clock_recovery.dat"))
+ self.connect(self.slicer,
+ gr.file_sink(gr.sizeof_char, "slicer.dat"))
+
+ def add_options(parser):
+ """
+ Adds GFSK demodulation-specific options to the standard parser
+ """
+ parser.add_option("", "--gain-mu", type="float", default=_def_gain_mu,
+ help="M&M clock recovery gain mu [default=%default] (GFSK/PSK)")
+ parser.add_option("", "--mu", type="float", default=_def_mu,
+ help="M&M clock recovery mu [default=%default] (GFSK/PSK)")
+ parser.add_option("", "--omega-relative-limit", type="float", default=_def_omega_relative_limit,
+ help="M&M clock recovery omega relative limit [default=%default] (GFSK/PSK)")
+ parser.add_option("", "--freq-error", type="float", default=_def_freq_error,
+ help="M&M clock recovery frequency error [default=%default] (GFSK)")
+ add_options=staticmethod(add_options)
+
+ def extract_kwargs_from_options(options):
+ """
+ Given command line options, create dictionary suitable for passing to __init__
+ """
+ return modulation_utils.extract_kwargs_from_options(gfsk_demod.__init__,
+ ('self',), options)
+ extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
+
+
+#
+# Add these to the mod/demod registry
+#
+modulation_utils.add_type_1_mod('gfsk', gfsk_mod)
+modulation_utils.add_type_1_demod('gfsk', gfsk_demod)
diff --git a/gr-fft/include/fft/fft.h b/gr-fft/include/fft/fft.h
index 5cc2e21e8..e3fd3f278 100644
--- a/gr-fft/include/fft/fft.h
+++ b/gr-fft/include/fft/fft.h
@@ -37,15 +37,15 @@ namespace gr {
/*! \brief Helper function for allocating complex fft buffers
*/
- gr_complex* malloc_complex(int size);
+ FFT_API gr_complex* malloc_complex(int size);
/*! \brief Helper function for allocating float fft buffers
*/
- float* malloc_float(int size);
+ FFT_API float* malloc_float(int size);
/*! \brief Helper function for freeing fft buffers
*/
- void free(void *b);
+ FFT_API void free(void *b);
/*!
* \brief Export reference to planner mutex for those apps that
diff --git a/gr-fft/lib/CMakeLists.txt b/gr-fft/lib/CMakeLists.txt
index e2f17a183..ea1248fba 100644
--- a/gr-fft/lib/CMakeLists.txt
+++ b/gr-fft/lib/CMakeLists.txt
@@ -21,19 +21,16 @@
# Setup the include and linker paths
########################################################################
include_directories(
- ${GNURADIO_CORE_INCLUDE_DIRS}
- ${GR_FFT_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
+ ${GNURADIO_CORE_INCLUDE_DIRS}
+ ${GR_FFT_INCLUDE_DIRS}
+ ${Boost_INCLUDE_DIRS}
+ ${FFTW3F_INCLUDE_DIRS}
)
-include_directories(${FFT_INCLUDE_DIRS})
link_directories(${FFT_LIBRARY_DIRS})
-
-include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
-
-include_directories(${FFTW3F_INCLUDE_DIRS})
link_directories(${FFTW3F_LIBRARY_DIRS})
########################################################################
diff --git a/gr-filter/CMakeLists.txt b/gr-filter/CMakeLists.txt
new file mode 100644
index 000000000..b77a3d9d4
--- /dev/null
+++ b/gr-filter/CMakeLists.txt
@@ -0,0 +1,113 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+# Setup dependencies
+########################################################################
+include(GrBoost)
+
+########################################################################
+# Register component
+########################################################################
+include(GrComponent)
+
+GR_REGISTER_COMPONENT("gr-filter" ENABLE_GR_FILTER
+ ENABLE_GRUEL
+ ENABLE_VOLK
+ Boost_FOUND
+ ENABLE_GR_CORE
+ ENABLE_GR_FFT
+)
+
+GR_SET_GLOBAL(GR_FILTER_INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR}/lib
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+ ${CMAKE_CURRENT_BINARY_DIR}/lib
+ ${CMAKE_CURRENT_BINARY_DIR}/include
+)
+
+SET(GR_PKG_FILTER_EXAMPLES_DIR ${GR_PKG_DATA_DIR}/examples/filter)
+
+########################################################################
+# Begin conditional configuration
+########################################################################
+if(ENABLE_GR_FILTER)
+
+########################################################################
+# Setup CPack components
+########################################################################
+include(GrPackage)
+CPACK_SET(CPACK_COMPONENT_GROUP_FILTER_DESCRIPTION "GNU Radio Filter Blocks")
+
+CPACK_COMPONENT("filter_runtime"
+ GROUP "Filter"
+ DISPLAY_NAME "Runtime"
+ DESCRIPTION "Runtime"
+ DEPENDS "core_runtime"
+)
+
+CPACK_COMPONENT("filter_devel"
+ GROUP "Filter"
+ DISPLAY_NAME "Development"
+ DESCRIPTION "C++ headers, package config, import libraries"
+ DEPENDS "core_devel"
+)
+
+CPACK_COMPONENT("filter_python"
+ GROUP "Filter"
+ DISPLAY_NAME "Python"
+ DESCRIPTION "Python modules for runtime; GRC xml files"
+ DEPENDS "core_python;filter_runtime"
+)
+
+CPACK_COMPONENT("filter_swig"
+ GROUP "Filter"
+ DISPLAY_NAME "SWIG"
+ DESCRIPTION "SWIG development .i files"
+ DEPENDS "core_swig;filter_python;filter_devel"
+)
+
+########################################################################
+# Add subdirectories
+########################################################################
+add_subdirectory(include/filter)
+add_subdirectory(lib)
+if(ENABLE_PYTHON)
+ add_subdirectory(swig)
+ add_subdirectory(python)
+ add_subdirectory(grc)
+endif(ENABLE_PYTHON)
+add_subdirectory(examples)
+add_subdirectory(doc)
+
+########################################################################
+# Create Pkg Config File
+########################################################################
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/gnuradio-filter.pc.in
+ ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-filter.pc
+@ONLY)
+
+install(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-filter.pc
+ DESTINATION ${GR_LIBRARY_DIR}/pkgconfig
+ COMPONENT "filter_devel"
+)
+
+endif(ENABLE_GR_FILTER)
diff --git a/gr-filter/doc/CMakeLists.txt b/gr-filter/doc/CMakeLists.txt
new file mode 100644
index 000000000..63447ed2c
--- /dev/null
+++ b/gr-filter/doc/CMakeLists.txt
@@ -0,0 +1,23 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+install(
+ FILES README.filter
+ DESTINATION ${GR_PKG_DOC_DIR}
+)
diff --git a/gr-filter/doc/README.filter b/gr-filter/doc/README.filter
new file mode 100644
index 000000000..776acd46c
--- /dev/null
+++ b/gr-filter/doc/README.filter
@@ -0,0 +1,13 @@
+This is the gr-filter package. It contains signal processing blocks to
+perform filtering operations.
+
+The Python namespace is in gnuradio.filter, which would be normally
+imported as:
+
+ from gnuradio import filter
+
+See the Doxygen documentation for details about the blocks available
+in this package. A quick listing of the details can be found in Python
+after importing by using:
+
+ help(filter)
diff --git a/gr-filter/doc/filter.dox b/gr-filter/doc/filter.dox
new file mode 100644
index 000000000..fc3b52e91
--- /dev/null
+++ b/gr-filter/doc/filter.dox
@@ -0,0 +1,27 @@
+/*! \page page_filter filter Signal Processing Blocks
+
+\section Introduction
+
+This is the gr-filter package. It contains signal processing blocks to
+perform filtering operations.
+
+The Python namespace is in gnuradio.filter, which would be normally
+imported as:
+
+\code
+ from gnuradio import filter
+\endcode
+
+See the Doxygen documentation for details about the blocks available
+in this package. A quick listing of the details can be found in Python
+after importing by using:
+
+\code
+ help(filter)
+\endcode
+
+\section Dependencies
+
+The filter blocks depend on \ref page_fft.
+
+*/
diff --git a/gr-filter/examples/CMakeLists.txt b/gr-filter/examples/CMakeLists.txt
new file mode 100644
index 000000000..d94e5c16e
--- /dev/null
+++ b/gr-filter/examples/CMakeLists.txt
@@ -0,0 +1,39 @@
+# Copyright 2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+include(GrPython)
+
+# Base stuff
+GR_PYTHON_INSTALL(PROGRAMS
+ channelize.py
+ chirp_channelize.py
+ decimate.py
+ fft_filter_ccc.py
+ fir_filter_ccc.py
+ fir_filter_fff.py
+ fmtest.py
+ interpolate.py
+ reconstruction.py
+ resampler.py
+ resampler_demo.grc
+ synth_filter.py
+ synth_to_chan.py
+ DESTINATION ${GR_PKG_FILTER_EXAMPLES_DIR}
+ COMPONENT "filter_python"
+)
diff --git a/gr-filter/examples/channelize.py b/gr-filter/examples/channelize.py
new file mode 100755
index 000000000..1f784d9b0
--- /dev/null
+++ b/gr-filter/examples/channelize.py
@@ -0,0 +1,195 @@
+#!/usr/bin/env python
+#
+# Copyright 2009,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, blks2
+from gnuradio import filter
+import sys, time
+
+try:
+ import scipy
+ from scipy import fftpack
+except ImportError:
+ print "Error: Program requires scipy (see: www.scipy.org)."
+ sys.exit(1)
+
+try:
+ import pylab
+ from pylab import mlab
+except ImportError:
+ print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)."
+ sys.exit(1)
+
+class pfb_top_block(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ self._N = 2000000 # number of samples to use
+ self._fs = 1000 # initial sampling rate
+ self._M = M = 9 # Number of channels to channelize
+ self._ifs = M*self._fs # initial sampling rate
+
+ # Create a set of taps for the PFB channelizer
+ self._taps = filter.firdes.low_pass_2(1, self._ifs, 475.50, 50,
+ attenuation_dB=100,
+ window=filter.firdes.WIN_BLACKMAN_hARRIS)
+
+ # Calculate the number of taps per channel for our own information
+ tpc = scipy.ceil(float(len(self._taps)) / float(self._M))
+ print "Number of taps: ", len(self._taps)
+ print "Number of channels: ", self._M
+ print "Taps per channel: ", tpc
+
+ # Create a set of signals at different frequencies
+ # freqs lists the frequencies of the signals that get stored
+ # in the list "signals", which then get summed together
+ self.signals = list()
+ self.add = gr.add_cc()
+ freqs = [-70, -50, -30, -10, 10, 20, 40, 60, 80]
+ for i in xrange(len(freqs)):
+ f = freqs[i] + (M/2-M+i+1)*self._fs
+ self.signals.append(gr.sig_source_c(self._ifs, gr.GR_SIN_WAVE, f, 1))
+ self.connect(self.signals[i], (self.add,i))
+
+ self.head = gr.head(gr.sizeof_gr_complex, self._N)
+
+ # Construct the channelizer filter
+ self.pfb = filter.pfb.channelizer_ccf(self._M, self._taps, 1)
+
+ # Construct a vector sink for the input signal to the channelizer
+ self.snk_i = gr.vector_sink_c()
+
+ # Connect the blocks
+ self.connect(self.add, self.head, self.pfb)
+ self.connect(self.add, self.snk_i)
+
+ # Use this to play with the channel mapping
+ #self.pfb.set_channel_map([5,6,7,8,0,1,2,3,4])
+
+ # Create a vector sink for each of M output channels of the filter and connect it
+ self.snks = list()
+ for i in xrange(self._M):
+ self.snks.append(gr.vector_sink_c())
+ self.connect((self.pfb, i), self.snks[i])
+
+
+def main():
+ tstart = time.time()
+
+ tb = pfb_top_block()
+ tb.run()
+
+ tend = time.time()
+ print "Run time: %f" % (tend - tstart)
+
+ if 1:
+ fig_in = pylab.figure(1, figsize=(16,9), facecolor="w")
+ fig1 = pylab.figure(2, figsize=(16,9), facecolor="w")
+ fig2 = pylab.figure(3, figsize=(16,9), facecolor="w")
+
+ Ns = 1000
+ Ne = 10000
+
+ fftlen = 8192
+ winfunc = scipy.blackman
+ fs = tb._ifs
+
+ # Plot the input signal on its own figure
+ d = tb.snk_i.data()[Ns:Ne]
+ spin_f = fig_in.add_subplot(2, 1, 1)
+
+ X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs,
+ window = lambda d: d*winfunc(fftlen),
+ scale_by_freq=True)
+ X_in = 10.0*scipy.log10(abs(X))
+ f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size))
+ pin_f = spin_f.plot(f_in, X_in, "b")
+ spin_f.set_xlim([min(f_in), max(f_in)+1])
+ spin_f.set_ylim([-200.0, 50.0])
+
+ spin_f.set_title("Input Signal", weight="bold")
+ spin_f.set_xlabel("Frequency (Hz)")
+ spin_f.set_ylabel("Power (dBW)")
+
+
+ Ts = 1.0/fs
+ Tmax = len(d)*Ts
+
+ t_in = scipy.arange(0, Tmax, Ts)
+ x_in = scipy.array(d)
+ spin_t = fig_in.add_subplot(2, 1, 2)
+ pin_t = spin_t.plot(t_in, x_in.real, "b")
+ pin_t = spin_t.plot(t_in, x_in.imag, "r")
+
+ spin_t.set_xlabel("Time (s)")
+ spin_t.set_ylabel("Amplitude")
+
+ Ncols = int(scipy.floor(scipy.sqrt(tb._M)))
+ Nrows = int(scipy.floor(tb._M / Ncols))
+ if(tb._M % Ncols != 0):
+ Nrows += 1
+
+ # Plot each of the channels outputs. Frequencies on Figure 2 and
+ # time signals on Figure 3
+ fs_o = tb._fs
+ Ts_o = 1.0/fs_o
+ Tmax_o = len(d)*Ts_o
+ for i in xrange(len(tb.snks)):
+ # remove issues with the transients at the beginning
+ # also remove some corruption at the end of the stream
+ # this is a bug, probably due to the corner cases
+ d = tb.snks[i].data()[Ns:Ne]
+
+ sp1_f = fig1.add_subplot(Nrows, Ncols, 1+i)
+ X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o,
+ window = lambda d: d*winfunc(fftlen),
+ scale_by_freq=True)
+ X_o = 10.0*scipy.log10(abs(X))
+ f_o = scipy.arange(-fs_o/2.0, fs_o/2.0, fs_o/float(X_o.size))
+ p2_f = sp1_f.plot(f_o, X_o, "b")
+ sp1_f.set_xlim([min(f_o), max(f_o)+1])
+ sp1_f.set_ylim([-200.0, 50.0])
+
+ sp1_f.set_title(("Channel %d" % i), weight="bold")
+ sp1_f.set_xlabel("Frequency (Hz)")
+ sp1_f.set_ylabel("Power (dBW)")
+
+ x_o = scipy.array(d)
+ t_o = scipy.arange(0, Tmax_o, Ts_o)
+ sp2_o = fig2.add_subplot(Nrows, Ncols, 1+i)
+ p2_o = sp2_o.plot(t_o, x_o.real, "b")
+ p2_o = sp2_o.plot(t_o, x_o.imag, "r")
+ sp2_o.set_xlim([min(t_o), max(t_o)+1])
+ sp2_o.set_ylim([-2, 2])
+
+ sp2_o.set_title(("Channel %d" % i), weight="bold")
+ sp2_o.set_xlabel("Time (s)")
+ sp2_o.set_ylabel("Amplitude")
+
+ pylab.show()
+
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-filter/examples/chirp_channelize.py b/gr-filter/examples/chirp_channelize.py
new file mode 100755
index 000000000..3638c55d1
--- /dev/null
+++ b/gr-filter/examples/chirp_channelize.py
@@ -0,0 +1,205 @@
+#!/usr/bin/env python
+#
+# Copyright 2009,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, blks2
+from gnuradio import filter
+import sys, time
+
+try:
+ import scipy
+ from scipy import fftpack
+except ImportError:
+ print "Error: Program requires scipy (see: www.scipy.org)."
+ sys.exit(1)
+
+try:
+ import pylab
+ from pylab import mlab
+except ImportError:
+ print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)."
+ sys.exit(1)
+
+class pfb_top_block(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ self._N = 200000 # number of samples to use
+ self._fs = 9000 # initial sampling rate
+ self._M = 9 # Number of channels to channelize
+
+ # Create a set of taps for the PFB channelizer
+ self._taps = filter.firdes.low_pass_2(1, self._fs, 500, 20,
+ attenuation_dB=10,
+ window=filter.firdes.WIN_BLACKMAN_hARRIS)
+
+ # Calculate the number of taps per channel for our own information
+ tpc = scipy.ceil(float(len(self._taps)) / float(self._M))
+ print "Number of taps: ", len(self._taps)
+ print "Number of channels: ", self._M
+ print "Taps per channel: ", tpc
+
+ repeated = True
+ if(repeated):
+ self.vco_input = gr.sig_source_f(self._fs, gr.GR_SIN_WAVE, 0.25, 110)
+ else:
+ amp = 100
+ data = scipy.arange(0, amp, amp/float(self._N))
+ self.vco_input = gr.vector_source_f(data, False)
+
+ # Build a VCO controlled by either the sinusoid or single chirp tone
+ # Then convert this to a complex signal
+ self.vco = gr.vco_f(self._fs, 225, 1)
+ self.f2c = gr.float_to_complex()
+
+ self.head = gr.head(gr.sizeof_gr_complex, self._N)
+
+ # Construct the channelizer filter
+ self.pfb = filter.pfb.channelizer_ccf(self._M, self._taps)
+
+ # Construct a vector sink for the input signal to the channelizer
+ self.snk_i = gr.vector_sink_c()
+
+ # Connect the blocks
+ self.connect(self.vco_input, self.vco, self.f2c)
+ self.connect(self.f2c, self.head, self.pfb)
+ self.connect(self.f2c, self.snk_i)
+
+ # Create a vector sink for each of M output channels of the filter and connect it
+ self.snks = list()
+ for i in xrange(self._M):
+ self.snks.append(gr.vector_sink_c())
+ self.connect((self.pfb, i), self.snks[i])
+
+
+def main():
+ tstart = time.time()
+
+ tb = pfb_top_block()
+ tb.run()
+
+ tend = time.time()
+ print "Run time: %f" % (tend - tstart)
+
+ if 1:
+ fig_in = pylab.figure(1, figsize=(16,9), facecolor="w")
+ fig1 = pylab.figure(2, figsize=(16,9), facecolor="w")
+ fig2 = pylab.figure(3, figsize=(16,9), facecolor="w")
+ fig3 = pylab.figure(4, figsize=(16,9), facecolor="w")
+
+ Ns = 650
+ Ne = 20000
+
+ fftlen = 8192
+ winfunc = scipy.blackman
+ fs = tb._fs
+
+ # Plot the input signal on its own figure
+ d = tb.snk_i.data()[Ns:Ne]
+ spin_f = fig_in.add_subplot(2, 1, 1)
+
+ X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs,
+ window = lambda d: d*winfunc(fftlen),
+ scale_by_freq=True)
+ X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X)))
+ f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size))
+ pin_f = spin_f.plot(f_in, X_in, "b")
+ spin_f.set_xlim([min(f_in), max(f_in)+1])
+ spin_f.set_ylim([-200.0, 50.0])
+
+ spin_f.set_title("Input Signal", weight="bold")
+ spin_f.set_xlabel("Frequency (Hz)")
+ spin_f.set_ylabel("Power (dBW)")
+
+
+ Ts = 1.0/fs
+ Tmax = len(d)*Ts
+
+ t_in = scipy.arange(0, Tmax, Ts)
+ x_in = scipy.array(d)
+ spin_t = fig_in.add_subplot(2, 1, 2)
+ pin_t = spin_t.plot(t_in, x_in.real, "b")
+ pin_t = spin_t.plot(t_in, x_in.imag, "r")
+
+ spin_t.set_xlabel("Time (s)")
+ spin_t.set_ylabel("Amplitude")
+
+ Ncols = int(scipy.floor(scipy.sqrt(tb._M)))
+ Nrows = int(scipy.floor(tb._M / Ncols))
+ if(tb._M % Ncols != 0):
+ Nrows += 1
+
+ # Plot each of the channels outputs. Frequencies on Figure 2 and
+ # time signals on Figure 3
+ fs_o = tb._fs / tb._M
+ Ts_o = 1.0/fs_o
+ Tmax_o = len(d)*Ts_o
+ for i in xrange(len(tb.snks)):
+ # remove issues with the transients at the beginning
+ # also remove some corruption at the end of the stream
+ # this is a bug, probably due to the corner cases
+ d = tb.snks[i].data()[Ns:Ne]
+
+ sp1_f = fig1.add_subplot(Nrows, Ncols, 1+i)
+ X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o,
+ window = lambda d: d*winfunc(fftlen),
+ scale_by_freq=True)
+ X_o = 10.0*scipy.log10(abs(X))
+ f_o = freq
+ p2_f = sp1_f.plot(f_o, X_o, "b")
+ sp1_f.set_xlim([min(f_o), max(f_o)+1])
+ sp1_f.set_ylim([-200.0, 50.0])
+
+ sp1_f.set_title(("Channel %d" % i), weight="bold")
+ sp1_f.set_xlabel("Frequency (Hz)")
+ sp1_f.set_ylabel("Power (dBW)")
+
+ x_o = scipy.array(d)
+ t_o = scipy.arange(0, Tmax_o, Ts_o)
+ sp2_o = fig2.add_subplot(Nrows, Ncols, 1+i)
+ p2_o = sp2_o.plot(t_o, x_o.real, "b")
+ p2_o = sp2_o.plot(t_o, x_o.imag, "r")
+ sp2_o.set_xlim([min(t_o), max(t_o)+1])
+ sp2_o.set_ylim([-2, 2])
+
+ sp2_o.set_title(("Channel %d" % i), weight="bold")
+ sp2_o.set_xlabel("Time (s)")
+ sp2_o.set_ylabel("Amplitude")
+
+
+ sp3 = fig3.add_subplot(1,1,1)
+ p3 = sp3.plot(t_o, x_o.real)
+ sp3.set_xlim([min(t_o), max(t_o)+1])
+ sp3.set_ylim([-2, 2])
+
+ sp3.set_title("All Channels")
+ sp3.set_xlabel("Time (s)")
+ sp3.set_ylabel("Amplitude")
+
+ pylab.show()
+
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-filter/examples/decimate.py b/gr-filter/examples/decimate.py
new file mode 100755
index 000000000..7f1f03d8f
--- /dev/null
+++ b/gr-filter/examples/decimate.py
@@ -0,0 +1,181 @@
+#!/usr/bin/env python
+#
+# Copyright 2009,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr
+from gnuradio import filter
+import sys, time
+
+try:
+ import scipy
+ from scipy import fftpack
+except ImportError:
+ print "Error: Program requires scipy (see: www.scipy.org)."
+ sys.exit(1)
+
+try:
+ import pylab
+ from pylab import mlab
+except ImportError:
+ print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)."
+ sys.exit(1)
+
+class pfb_top_block(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ self._N = 10000000 # number of samples to use
+ self._fs = 10000 # initial sampling rate
+ self._decim = 20 # Decimation rate
+
+ # Generate the prototype filter taps for the decimators with a 200 Hz bandwidth
+ self._taps = filter.firdes.low_pass_2(1, self._fs,
+ 200, 150,
+ attenuation_dB=120,
+ window=filter.firdes.WIN_BLACKMAN_hARRIS)
+
+ # Calculate the number of taps per channel for our own information
+ tpc = scipy.ceil(float(len(self._taps)) / float(self._decim))
+ print "Number of taps: ", len(self._taps)
+ print "Number of filters: ", self._decim
+ print "Taps per channel: ", tpc
+
+ # Build the input signal source
+ # We create a list of freqs, and a sine wave is generated and added to the source
+ # for each one of these frequencies.
+ self.signals = list()
+ self.add = gr.add_cc()
+ freqs = [10, 20, 2040]
+ for i in xrange(len(freqs)):
+ self.signals.append(gr.sig_source_c(self._fs, gr.GR_SIN_WAVE, freqs[i], 1))
+ self.connect(self.signals[i], (self.add,i))
+
+ self.head = gr.head(gr.sizeof_gr_complex, self._N)
+
+ # Construct a PFB decimator filter
+ self.pfb = filter.pfb.decimator_ccf(self._decim, self._taps, 0)
+
+ # Construct a standard FIR decimating filter
+ self.dec = filter.fir_filter_ccf(self._decim, self._taps)
+
+ self.snk_i = gr.vector_sink_c()
+
+ # Connect the blocks
+ self.connect(self.add, self.head, self.pfb)
+ self.connect(self.add, self.snk_i)
+
+ # Create the sink for the decimated siganl
+ self.snk = gr.vector_sink_c()
+ self.connect(self.pfb, self.snk)
+
+
+def main():
+ tb = pfb_top_block()
+
+ tstart = time.time()
+ tb.run()
+ tend = time.time()
+ print "Run time: %f" % (tend - tstart)
+
+ if 1:
+ fig1 = pylab.figure(1, figsize=(16,9))
+ fig2 = pylab.figure(2, figsize=(16,9))
+
+ Ns = 10000
+ Ne = 10000
+
+ fftlen = 8192
+ winfunc = scipy.blackman
+ fs = tb._fs
+
+ # Plot the input to the decimator
+
+ d = tb.snk_i.data()[Ns:Ns+Ne]
+ sp1_f = fig1.add_subplot(2, 1, 1)
+
+ X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs,
+ window = lambda d: d*winfunc(fftlen),
+ scale_by_freq=True)
+ X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X)))
+ f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size))
+ p1_f = sp1_f.plot(f_in, X_in, "b")
+ sp1_f.set_xlim([min(f_in), max(f_in)+1])
+ sp1_f.set_ylim([-200.0, 50.0])
+
+ sp1_f.set_title("Input Signal", weight="bold")
+ sp1_f.set_xlabel("Frequency (Hz)")
+ sp1_f.set_ylabel("Power (dBW)")
+
+ Ts = 1.0/fs
+ Tmax = len(d)*Ts
+
+ t_in = scipy.arange(0, Tmax, Ts)
+ x_in = scipy.array(d)
+ sp1_t = fig1.add_subplot(2, 1, 2)
+ p1_t = sp1_t.plot(t_in, x_in.real, "b")
+ p1_t = sp1_t.plot(t_in, x_in.imag, "r")
+ sp1_t.set_ylim([-tb._decim*1.1, tb._decim*1.1])
+
+ sp1_t.set_xlabel("Time (s)")
+ sp1_t.set_ylabel("Amplitude")
+
+
+ # Plot the output of the decimator
+ fs_o = tb._fs / tb._decim
+
+ sp2_f = fig2.add_subplot(2, 1, 1)
+ d = tb.snk.data()[Ns:Ns+Ne]
+ X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o,
+ window = lambda d: d*winfunc(fftlen),
+ scale_by_freq=True)
+ X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X)))
+ f_o = scipy.arange(-fs_o/2.0, fs_o/2.0, fs_o/float(X_o.size))
+ p2_f = sp2_f.plot(f_o, X_o, "b")
+ sp2_f.set_xlim([min(f_o), max(f_o)+1])
+ sp2_f.set_ylim([-200.0, 50.0])
+
+ sp2_f.set_title("PFB Decimated Signal", weight="bold")
+ sp2_f.set_xlabel("Frequency (Hz)")
+ sp2_f.set_ylabel("Power (dBW)")
+
+
+ Ts_o = 1.0/fs_o
+ Tmax_o = len(d)*Ts_o
+
+ x_o = scipy.array(d)
+ t_o = scipy.arange(0, Tmax_o, Ts_o)
+ sp2_t = fig2.add_subplot(2, 1, 2)
+ p2_t = sp2_t.plot(t_o, x_o.real, "b-o")
+ p2_t = sp2_t.plot(t_o, x_o.imag, "r-o")
+ sp2_t.set_ylim([-2.5, 2.5])
+
+ sp2_t.set_xlabel("Time (s)")
+ sp2_t.set_ylabel("Amplitude")
+
+ pylab.show()
+
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-filter/examples/fft_filter_ccc.py b/gr-filter/examples/fft_filter_ccc.py
new file mode 100755
index 000000000..45e241a6f
--- /dev/null
+++ b/gr-filter/examples/fft_filter_ccc.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, filter
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+try:
+ import scipy
+except ImportError:
+ print "Error: could not import scipy (http://www.scipy.org/)"
+ sys.exit(1)
+
+try:
+ import pylab
+except ImportError:
+ print "Error: could not import pylab (http://matplotlib.sourceforge.net/)"
+ sys.exit(1)
+
+class example_fft_filter_ccc(gr.top_block):
+ def __init__(self, N, fs, bw0, bw1, tw, atten, D):
+ gr.top_block.__init__(self)
+
+ self._nsamps = N
+ self._fs = fs
+ self._bw0 = bw0
+ self._bw1 = bw1
+ self._tw = tw
+ self._at = atten
+ self._decim = D
+ taps = filter.firdes.complex_band_pass_2(1, self._fs,
+ self._bw0, self._bw1,
+ self._tw, self._at)
+ print "Num. Taps: ", len(taps)
+
+ self.src = gr.noise_source_c(gr.GR_GAUSSIAN, 1)
+ self.head = gr.head(gr.sizeof_gr_complex, self._nsamps)
+
+ self.filt0 = filter.fft_filter_ccc(self._decim, taps)
+
+ self.vsnk_src = gr.vector_sink_c()
+ self.vsnk_out = gr.vector_sink_c()
+
+ self.connect(self.src, self.head, self.vsnk_src)
+ self.connect(self.head, self.filt0, self.vsnk_out)
+
+def main():
+ parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=10000,
+ help="Number of samples to process [default=%default]")
+ parser.add_option("-s", "--samplerate", type="eng_float", default=8000,
+ help="System sample rate [default=%default]")
+ parser.add_option("-S", "--start-pass", type="eng_float", default=1000,
+ help="Start of Passband [default=%default]")
+ parser.add_option("-E", "--end-pass", type="eng_float", default=2000,
+ help="End of Passband [default=%default]")
+ parser.add_option("-T", "--transition", type="eng_float", default=100,
+ help="Transition band [default=%default]")
+ parser.add_option("-A", "--attenuation", type="eng_float", default=80,
+ help="Stopband attenuation [default=%default]")
+ parser.add_option("-D", "--decimation", type="int", default=1,
+ help="Decmation factor [default=%default]")
+ (options, args) = parser.parse_args ()
+
+ put = example_fft_filter_ccc(options.nsamples,
+ options.samplerate,
+ options.start_pass,
+ options.end_pass,
+ options.transition,
+ options.attenuation,
+ options.decimation)
+ put.run()
+
+ data_src = scipy.array(put.vsnk_src.data())
+ data_snk = scipy.array(put.vsnk_out.data())
+
+ # Plot the signals PSDs
+ nfft = 1024
+ f1 = pylab.figure(1, figsize=(12,10))
+ s1 = f1.add_subplot(1,1,1)
+ s1.psd(data_src, NFFT=nfft, noverlap=nfft/4,
+ Fs=options.samplerate)
+ s1.psd(data_snk, NFFT=nfft, noverlap=nfft/4,
+ Fs=options.samplerate)
+
+ f2 = pylab.figure(2, figsize=(12,10))
+ s2 = f2.add_subplot(1,1,1)
+ s2.plot(data_src)
+ s2.plot(data_snk.real, 'g')
+
+ pylab.show()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-filter/examples/fir_filter_ccc.py b/gr-filter/examples/fir_filter_ccc.py
new file mode 100755
index 000000000..baa05eeb7
--- /dev/null
+++ b/gr-filter/examples/fir_filter_ccc.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, filter
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+try:
+ import scipy
+except ImportError:
+ print "Error: could not import scipy (http://www.scipy.org/)"
+ sys.exit(1)
+
+try:
+ import pylab
+except ImportError:
+ print "Error: could not import pylab (http://matplotlib.sourceforge.net/)"
+ sys.exit(1)
+
+class example_fir_filter_ccc(gr.top_block):
+ def __init__(self, N, fs, bw, tw, atten, D):
+ gr.top_block.__init__(self)
+
+ self._nsamps = N
+ self._fs = fs
+ self._bw = bw
+ self._tw = tw
+ self._at = atten
+ self._decim = D
+ taps = filter.firdes.low_pass_2(1, self._fs, self._bw, self._tw, self._at)
+ print "Num. Taps: ", len(taps)
+
+ self.src = gr.noise_source_c(gr.GR_GAUSSIAN, 1)
+ self.head = gr.head(gr.sizeof_gr_complex, self._nsamps)
+
+ self.filt0 = filter.fir_filter_ccc(self._decim, taps)
+
+ self.vsnk_src = gr.vector_sink_c()
+ self.vsnk_out = gr.vector_sink_c()
+
+ self.connect(self.src, self.head, self.vsnk_src)
+ self.connect(self.head, self.filt0, self.vsnk_out)
+
+def main():
+ parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=10000,
+ help="Number of samples to process [default=%default]")
+ parser.add_option("-s", "--samplerate", type="eng_float", default=8000,
+ help="System sample rate [default=%default]")
+ parser.add_option("-B", "--bandwidth", type="eng_float", default=1000,
+ help="Filter bandwidth [default=%default]")
+ parser.add_option("-T", "--transition", type="eng_float", default=100,
+ help="Transition band [default=%default]")
+ parser.add_option("-A", "--attenuation", type="eng_float", default=80,
+ help="Stopband attenuation [default=%default]")
+ parser.add_option("-D", "--decimation", type="int", default=1,
+ help="Decmation factor [default=%default]")
+ (options, args) = parser.parse_args ()
+
+ put = example_fir_filter_ccc(options.nsamples,
+ options.samplerate,
+ options.bandwidth,
+ options.transition,
+ options.attenuation,
+ options.decimation)
+ put.run()
+
+ data_src = scipy.array(put.vsnk_src.data())
+ data_snk = scipy.array(put.vsnk_out.data())
+
+ # Plot the signals PSDs
+ nfft = 1024
+ f1 = pylab.figure(1, figsize=(12,10))
+ s1 = f1.add_subplot(1,1,1)
+ s1.psd(data_src, NFFT=nfft, noverlap=nfft/4,
+ Fs=options.samplerate)
+ s1.psd(data_snk, NFFT=nfft, noverlap=nfft/4,
+ Fs=options.samplerate)
+
+ f2 = pylab.figure(2, figsize=(12,10))
+ s2 = f2.add_subplot(1,1,1)
+ s2.plot(data_src)
+ s2.plot(data_snk.real, 'g')
+
+ pylab.show()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-filter/examples/fir_filter_fff.py b/gr-filter/examples/fir_filter_fff.py
new file mode 100755
index 000000000..48769f00d
--- /dev/null
+++ b/gr-filter/examples/fir_filter_fff.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, filter
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+try:
+ import scipy
+except ImportError:
+ print "Error: could not import scipy (http://www.scipy.org/)"
+ sys.exit(1)
+
+try:
+ import pylab
+except ImportError:
+ print "Error: could not import pylab (http://matplotlib.sourceforge.net/)"
+ sys.exit(1)
+
+class example_fir_filter_fff(gr.top_block):
+ def __init__(self, N, fs, bw, tw, atten, D):
+ gr.top_block.__init__(self)
+
+ self._nsamps = N
+ self._fs = fs
+ self._bw = bw
+ self._tw = tw
+ self._at = atten
+ self._decim = D
+ taps = filter.firdes.low_pass_2(1, self._fs, self._bw, self._tw, self._at)
+ print "Num. Taps: ", len(taps)
+
+ self.src = gr.noise_source_f(gr.GR_GAUSSIAN, 1)
+ self.head = gr.head(gr.sizeof_float, self._nsamps)
+
+ self.filt0 = filter.fir_filter_fff(self._decim, taps)
+
+ self.vsnk_src = gr.vector_sink_f()
+ self.vsnk_out = gr.vector_sink_f()
+
+ self.connect(self.src, self.head, self.vsnk_src)
+ self.connect(self.head, self.filt0, self.vsnk_out)
+
+def main():
+ parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=10000,
+ help="Number of samples to process [default=%default]")
+ parser.add_option("-s", "--samplerate", type="eng_float", default=8000,
+ help="System sample rate [default=%default]")
+ parser.add_option("-B", "--bandwidth", type="eng_float", default=1000,
+ help="Filter bandwidth [default=%default]")
+ parser.add_option("-T", "--transition", type="eng_float", default=100,
+ help="Transition band [default=%default]")
+ parser.add_option("-A", "--attenuation", type="eng_float", default=80,
+ help="Stopband attenuation [default=%default]")
+ parser.add_option("-D", "--decimation", type="int", default=1,
+ help="Decmation factor [default=%default]")
+ (options, args) = parser.parse_args ()
+
+ put = example_fir_filter_fff(options.nsamples,
+ options.samplerate,
+ options.bandwidth,
+ options.transition,
+ options.attenuation,
+ options.decimation)
+ put.run()
+
+ data_src = scipy.array(put.vsnk_src.data())
+ data_snk = scipy.array(put.vsnk_out.data())
+
+ # Plot the signals PSDs
+ nfft = 1024
+ f1 = pylab.figure(1, figsize=(12,10))
+ s1 = f1.add_subplot(1,1,1)
+ s1.psd(data_src, NFFT=nfft, noverlap=nfft/4,
+ Fs=options.samplerate)
+ s1.psd(data_snk, NFFT=nfft, noverlap=nfft/4,
+ Fs=options.samplerate)
+
+ f2 = pylab.figure(2, figsize=(12,10))
+ s2 = f2.add_subplot(1,1,1)
+ s2.plot(data_src)
+ s2.plot(data_snk.real, 'g')
+
+ pylab.show()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-filter/examples/fmtest.py b/gr-filter/examples/fmtest.py
new file mode 100755
index 000000000..9b02526d9
--- /dev/null
+++ b/gr-filter/examples/fmtest.py
@@ -0,0 +1,226 @@
+#!/usr/bin/env python
+#
+# Copyright 2009,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, blks2
+from gnuradio import filter
+import sys, math, time
+
+try:
+ import scipy
+ from scipy import fftpack
+except ImportError:
+ print "Error: Program requires scipy (see: www.scipy.org)."
+ sys.exit(1)
+
+try:
+ import pylab
+except ImportError:
+ print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)."
+ sys.exit(1)
+
+
+class fmtx(gr.hier_block2):
+ def __init__(self, lo_freq, audio_rate, if_rate):
+
+ gr.hier_block2.__init__(self, "build_fm",
+ gr.io_signature(1, 1, gr.sizeof_float),
+ gr.io_signature(1, 1, gr.sizeof_gr_complex))
+
+ fmtx = blks2.nbfm_tx (audio_rate, if_rate, max_dev=5e3, tau=75e-6)
+
+ # Local oscillator
+ lo = gr.sig_source_c (if_rate, # sample rate
+ gr.GR_SIN_WAVE, # waveform type
+ lo_freq, #frequency
+ 1.0, # amplitude
+ 0) # DC Offset
+ mixer = gr.multiply_cc ()
+
+ self.connect (self, fmtx, (mixer, 0))
+ self.connect (lo, (mixer, 1))
+ self.connect (mixer, self)
+
+class fmtest(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ self._nsamples = 1000000
+ self._audio_rate = 8000
+
+ # Set up N channels with their own baseband and IF frequencies
+ self._N = 5
+ chspacing = 16000
+ freq = [10, 20, 30, 40, 50]
+ f_lo = [0, 1*chspacing, -1*chspacing, 2*chspacing, -2*chspacing]
+
+ self._if_rate = 4*self._N*self._audio_rate
+
+ # Create a signal source and frequency modulate it
+ self.sum = gr.add_cc ()
+ for n in xrange(self._N):
+ sig = gr.sig_source_f(self._audio_rate, gr.GR_SIN_WAVE, freq[n], 0.5)
+ fm = fmtx(f_lo[n], self._audio_rate, self._if_rate)
+ self.connect(sig, fm)
+ self.connect(fm, (self.sum, n))
+
+ self.head = gr.head(gr.sizeof_gr_complex, self._nsamples)
+ self.snk_tx = gr.vector_sink_c()
+ self.channel = blks2.channel_model(0.1)
+
+ self.connect(self.sum, self.head, self.channel, self.snk_tx)
+
+
+ # Design the channlizer
+ self._M = 10
+ bw = chspacing/2.0
+ t_bw = chspacing/10.0
+ self._chan_rate = self._if_rate / self._M
+ self._taps = filter.firdes.low_pass_2(1, self._if_rate, bw, t_bw,
+ attenuation_dB=100,
+ window=filter.firdes.WIN_BLACKMAN_hARRIS)
+ tpc = math.ceil(float(len(self._taps)) / float(self._M))
+
+ print "Number of taps: ", len(self._taps)
+ print "Number of channels: ", self._M
+ print "Taps per channel: ", tpc
+
+ self.pfb = filter.pfb.channelizer_ccf(self._M, self._taps)
+
+ self.connect(self.channel, self.pfb)
+
+ # Create a file sink for each of M output channels of the filter and connect it
+ self.fmdet = list()
+ self.squelch = list()
+ self.snks = list()
+ for i in xrange(self._M):
+ self.fmdet.append(blks2.nbfm_rx(self._audio_rate, self._chan_rate))
+ self.squelch.append(blks2.standard_squelch(self._audio_rate*10))
+ self.snks.append(gr.vector_sink_f())
+ self.connect((self.pfb, i), self.fmdet[i], self.squelch[i], self.snks[i])
+
+ def num_tx_channels(self):
+ return self._N
+
+ def num_rx_channels(self):
+ return self._M
+
+def main():
+
+ fm = fmtest()
+
+ tstart = time.time()
+ fm.run()
+ tend = time.time()
+
+ if 1:
+ fig1 = pylab.figure(1, figsize=(12,10), facecolor="w")
+ fig2 = pylab.figure(2, figsize=(12,10), facecolor="w")
+ fig3 = pylab.figure(3, figsize=(12,10), facecolor="w")
+
+ Ns = 10000
+ Ne = 100000
+
+ fftlen = 8192
+ winfunc = scipy.blackman
+
+ # Plot transmitted signal
+ fs = fm._if_rate
+
+ d = fm.snk_tx.data()[Ns:Ns+Ne]
+ sp1_f = fig1.add_subplot(2, 1, 1)
+
+ X,freq = sp1_f.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs,
+ window = lambda d: d*winfunc(fftlen),
+ visible=False)
+ X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X)))
+ f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size))
+ p1_f = sp1_f.plot(f_in, X_in, "b")
+ sp1_f.set_xlim([min(f_in), max(f_in)+1])
+ sp1_f.set_ylim([-120.0, 20.0])
+
+ sp1_f.set_title("Input Signal", weight="bold")
+ sp1_f.set_xlabel("Frequency (Hz)")
+ sp1_f.set_ylabel("Power (dBW)")
+
+ Ts = 1.0/fs
+ Tmax = len(d)*Ts
+
+ t_in = scipy.arange(0, Tmax, Ts)
+ x_in = scipy.array(d)
+ sp1_t = fig1.add_subplot(2, 1, 2)
+ p1_t = sp1_t.plot(t_in, x_in.real, "b-o")
+ #p1_t = sp1_t.plot(t_in, x_in.imag, "r-o")
+ sp1_t.set_ylim([-5, 5])
+
+ # Set up the number of rows and columns for plotting the subfigures
+ Ncols = int(scipy.floor(scipy.sqrt(fm.num_rx_channels())))
+ Nrows = int(scipy.floor(fm.num_rx_channels() / Ncols))
+ if(fm.num_rx_channels() % Ncols != 0):
+ Nrows += 1
+
+ # Plot each of the channels outputs. Frequencies on Figure 2 and
+ # time signals on Figure 3
+ fs_o = fm._audio_rate
+ for i in xrange(len(fm.snks)):
+ # remove issues with the transients at the beginning
+ # also remove some corruption at the end of the stream
+ # this is a bug, probably due to the corner cases
+ d = fm.snks[i].data()[Ns:Ne]
+
+ sp2_f = fig2.add_subplot(Nrows, Ncols, 1+i)
+ X,freq = sp2_f.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o,
+ window = lambda d: d*winfunc(fftlen),
+ visible=False)
+ #X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X)))
+ X_o = 10.0*scipy.log10(abs(X))
+ #f_o = scipy.arange(-fs_o/2.0, fs_o/2.0, fs_o/float(X_o.size))
+ f_o = scipy.arange(0, fs_o/2.0, fs_o/2.0/float(X_o.size))
+ p2_f = sp2_f.plot(f_o, X_o, "b")
+ sp2_f.set_xlim([min(f_o), max(f_o)+0.1])
+ sp2_f.set_ylim([-120.0, 20.0])
+ sp2_f.grid(True)
+
+ sp2_f.set_title(("Channel %d" % i), weight="bold")
+ sp2_f.set_xlabel("Frequency (kHz)")
+ sp2_f.set_ylabel("Power (dBW)")
+
+
+ Ts = 1.0/fs_o
+ Tmax = len(d)*Ts
+ t_o = scipy.arange(0, Tmax, Ts)
+
+ x_t = scipy.array(d)
+ sp2_t = fig3.add_subplot(Nrows, Ncols, 1+i)
+ p2_t = sp2_t.plot(t_o, x_t.real, "b")
+ p2_t = sp2_t.plot(t_o, x_t.imag, "r")
+ sp2_t.set_xlim([min(t_o), max(t_o)+1])
+ sp2_t.set_ylim([-1, 1])
+
+ sp2_t.set_xlabel("Time (s)")
+ sp2_t.set_ylabel("Amplitude")
+
+
+ pylab.show()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/gr-filter/examples/interpolate.py b/gr-filter/examples/interpolate.py
new file mode 100755
index 000000000..56d78d597
--- /dev/null
+++ b/gr-filter/examples/interpolate.py
@@ -0,0 +1,240 @@
+#!/usr/bin/env python
+#
+# Copyright 2009,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr
+from gnuradio import filter
+import sys, time
+
+try:
+ import scipy
+ from scipy import fftpack
+except ImportError:
+ print "Error: Program requires scipy (see: www.scipy.org)."
+ sys.exit(1)
+
+try:
+ import pylab
+ from pylab import mlab
+except ImportError:
+ print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)."
+ sys.exit(1)
+
+class pfb_top_block(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ self._N = 100000 # number of samples to use
+ self._fs = 2000 # initial sampling rate
+ self._interp = 5 # Interpolation rate for PFB interpolator
+ self._ainterp = 5.5 # Resampling rate for the PFB arbitrary resampler
+
+ # Frequencies of the signals we construct
+ freq1 = 100
+ freq2 = 200
+
+ # Create a set of taps for the PFB interpolator
+ # This is based on the post-interpolation sample rate
+ self._taps = filter.firdes.low_pass_2(self._interp,
+ self._interp*self._fs,
+ freq2+50, 50,
+ attenuation_dB=120,
+ window=filter.firdes.WIN_BLACKMAN_hARRIS)
+
+ # Create a set of taps for the PFB arbitrary resampler
+ # The filter size is the number of filters in the filterbank; 32 will give very low side-lobes,
+ # and larger numbers will reduce these even farther
+ # The taps in this filter are based on a sampling rate of the filter size since it acts
+ # internally as an interpolator.
+ flt_size = 32
+ self._taps2 = filter.firdes.low_pass_2(flt_size,
+ flt_size*self._fs,
+ freq2+50, 150,
+ attenuation_dB=120,
+ window=filter.firdes.WIN_BLACKMAN_hARRIS)
+
+ # Calculate the number of taps per channel for our own information
+ tpc = scipy.ceil(float(len(self._taps)) / float(self._interp))
+ print "Number of taps: ", len(self._taps)
+ print "Number of filters: ", self._interp
+ print "Taps per channel: ", tpc
+
+ # Create a couple of signals at different frequencies
+ self.signal1 = gr.sig_source_c(self._fs, gr.GR_SIN_WAVE, freq1, 0.5)
+ self.signal2 = gr.sig_source_c(self._fs, gr.GR_SIN_WAVE, freq2, 0.5)
+ self.signal = gr.add_cc()
+
+ self.head = gr.head(gr.sizeof_gr_complex, self._N)
+
+ # Construct the PFB interpolator filter
+ self.pfb = filter.pfb.interpolator_ccf(self._interp, self._taps)
+
+ # Construct the PFB arbitrary resampler filter
+ self.pfb_ar = filter.pfb.arb_resampler_ccf(self._ainterp, self._taps2, flt_size)
+ self.snk_i = gr.vector_sink_c()
+
+ #self.pfb_ar.pfb.print_taps()
+ #self.pfb.pfb.print_taps()
+
+ # Connect the blocks
+ self.connect(self.signal1, self.head, (self.signal,0))
+ self.connect(self.signal2, (self.signal,1))
+ self.connect(self.signal, self.pfb)
+ self.connect(self.signal, self.pfb_ar)
+ self.connect(self.signal, self.snk_i)
+
+ # Create the sink for the interpolated signals
+ self.snk1 = gr.vector_sink_c()
+ self.snk2 = gr.vector_sink_c()
+ self.connect(self.pfb, self.snk1)
+ self.connect(self.pfb_ar, self.snk2)
+
+
+def main():
+ tb = pfb_top_block()
+
+ tstart = time.time()
+ tb.run()
+ tend = time.time()
+ print "Run time: %f" % (tend - tstart)
+
+
+ if 1:
+ fig1 = pylab.figure(1, figsize=(12,10), facecolor="w")
+ fig2 = pylab.figure(2, figsize=(12,10), facecolor="w")
+ fig3 = pylab.figure(3, figsize=(12,10), facecolor="w")
+
+ Ns = 10000
+ Ne = 10000
+
+ fftlen = 8192
+ winfunc = scipy.blackman
+
+ # Plot input signal
+ fs = tb._fs
+
+ d = tb.snk_i.data()[Ns:Ns+Ne]
+ sp1_f = fig1.add_subplot(2, 1, 1)
+
+ X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs,
+ window = lambda d: d*winfunc(fftlen),
+ scale_by_freq=True)
+ X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X)))
+ f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size))
+ p1_f = sp1_f.plot(f_in, X_in, "b")
+ sp1_f.set_xlim([min(f_in), max(f_in)+1])
+ sp1_f.set_ylim([-200.0, 50.0])
+
+
+ sp1_f.set_title("Input Signal", weight="bold")
+ sp1_f.set_xlabel("Frequency (Hz)")
+ sp1_f.set_ylabel("Power (dBW)")
+
+ Ts = 1.0/fs
+ Tmax = len(d)*Ts
+
+ t_in = scipy.arange(0, Tmax, Ts)
+ x_in = scipy.array(d)
+ sp1_t = fig1.add_subplot(2, 1, 2)
+ p1_t = sp1_t.plot(t_in, x_in.real, "b-o")
+ #p1_t = sp1_t.plot(t_in, x_in.imag, "r-o")
+ sp1_t.set_ylim([-2.5, 2.5])
+
+ sp1_t.set_title("Input Signal", weight="bold")
+ sp1_t.set_xlabel("Time (s)")
+ sp1_t.set_ylabel("Amplitude")
+
+
+ # Plot output of PFB interpolator
+ fs_int = tb._fs*tb._interp
+
+ sp2_f = fig2.add_subplot(2, 1, 1)
+ d = tb.snk1.data()[Ns:Ns+(tb._interp*Ne)]
+ X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs,
+ window = lambda d: d*winfunc(fftlen),
+ scale_by_freq=True)
+ X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X)))
+ f_o = scipy.arange(-fs_int/2.0, fs_int/2.0, fs_int/float(X_o.size))
+ p2_f = sp2_f.plot(f_o, X_o, "b")
+ sp2_f.set_xlim([min(f_o), max(f_o)+1])
+ sp2_f.set_ylim([-200.0, 50.0])
+
+ sp2_f.set_title("Output Signal from PFB Interpolator", weight="bold")
+ sp2_f.set_xlabel("Frequency (Hz)")
+ sp2_f.set_ylabel("Power (dBW)")
+
+ Ts_int = 1.0/fs_int
+ Tmax = len(d)*Ts_int
+
+ t_o = scipy.arange(0, Tmax, Ts_int)
+ x_o1 = scipy.array(d)
+ sp2_t = fig2.add_subplot(2, 1, 2)
+ p2_t = sp2_t.plot(t_o, x_o1.real, "b-o")
+ #p2_t = sp2_t.plot(t_o, x_o.imag, "r-o")
+ sp2_t.set_ylim([-2.5, 2.5])
+
+ sp2_t.set_title("Output Signal from PFB Interpolator", weight="bold")
+ sp2_t.set_xlabel("Time (s)")
+ sp2_t.set_ylabel("Amplitude")
+
+
+ # Plot output of PFB arbitrary resampler
+ fs_aint = tb._fs * tb._ainterp
+
+ sp3_f = fig3.add_subplot(2, 1, 1)
+ d = tb.snk2.data()[Ns:Ns+(tb._interp*Ne)]
+ X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs,
+ window = lambda d: d*winfunc(fftlen),
+ scale_by_freq=True)
+ X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X)))
+ f_o = scipy.arange(-fs_aint/2.0, fs_aint/2.0, fs_aint/float(X_o.size))
+ p3_f = sp3_f.plot(f_o, X_o, "b")
+ sp3_f.set_xlim([min(f_o), max(f_o)+1])
+ sp3_f.set_ylim([-200.0, 50.0])
+
+ sp3_f.set_title("Output Signal from PFB Arbitrary Resampler", weight="bold")
+ sp3_f.set_xlabel("Frequency (Hz)")
+ sp3_f.set_ylabel("Power (dBW)")
+
+ Ts_aint = 1.0/fs_aint
+ Tmax = len(d)*Ts_aint
+
+ t_o = scipy.arange(0, Tmax, Ts_aint)
+ x_o2 = scipy.array(d)
+ sp3_f = fig3.add_subplot(2, 1, 2)
+ p3_f = sp3_f.plot(t_o, x_o2.real, "b-o")
+ p3_f = sp3_f.plot(t_o, x_o1.real, "m-o")
+ #p3_f = sp3_f.plot(t_o, x_o2.imag, "r-o")
+ sp3_f.set_ylim([-2.5, 2.5])
+
+ sp3_f.set_title("Output Signal from PFB Arbitrary Resampler", weight="bold")
+ sp3_f.set_xlabel("Time (s)")
+ sp3_f.set_ylabel("Amplitude")
+
+ pylab.show()
+
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-filter/examples/reconstruction.py b/gr-filter/examples/reconstruction.py
new file mode 100755
index 000000000..9e38f3669
--- /dev/null
+++ b/gr-filter/examples/reconstruction.py
@@ -0,0 +1,164 @@
+#!/usr/bin/env python
+#
+# Copyright 2010,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, digital
+from gnuradio import filter
+
+try:
+ import scipy
+ from scipy import fftpack
+except ImportError:
+ print "Error: Program requires scipy (see: www.scipy.org)."
+ sys.exit(1)
+
+try:
+ import pylab
+except ImportError:
+ print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)."
+ sys.exit(1)
+
+fftlen = 8192
+
+def main():
+ N = 10000
+ fs = 2000.0
+ Ts = 1.0/fs
+ t = scipy.arange(0, N*Ts, Ts)
+
+ # When playing with the number of channels, be careful about the filter
+ # specs and the channel map of the synthesizer set below.
+ nchans = 10
+
+ # Build the filter(s)
+ bw = 1000
+ tb = 400
+ proto_taps = filter.firdes.low_pass_2(1, nchans*fs,
+ bw, tb, 80,
+ filter.firdes.WIN_BLACKMAN_hARRIS)
+ print "Filter length: ", len(proto_taps)
+
+
+ # Create a modulated signal
+ npwr = 0.01
+ data = scipy.random.randint(0, 256, N)
+ rrc_taps = filter.firdes.root_raised_cosine(1, 2, 1, 0.35, 41)
+
+ src = gr.vector_source_b(data.astype(scipy.uint8).tolist(), False)
+ mod = digital.bpsk_mod(samples_per_symbol=2)
+ chan = gr.channel_model(npwr)
+ rrc = filter.fft_filter_ccc(1, rrc_taps)
+
+ # Split it up into pieces
+ channelizer = filter.pfb.channelizer_ccf(nchans, proto_taps, 2)
+
+ # Put the pieces back together again
+ syn_taps = [nchans*t for t in proto_taps]
+ synthesizer = filter.pfb_synthesizer_ccf(nchans, syn_taps, True)
+ src_snk = gr.vector_sink_c()
+ snk = gr.vector_sink_c()
+
+ # Remap the location of the channels
+ # Can be done in synth or channelizer (watch out for rotattions in
+ # the channelizer)
+ synthesizer.set_channel_map([ 0, 1, 2, 3, 4,
+ 15, 16, 17, 18, 19])
+
+ tb = gr.top_block()
+ tb.connect(src, mod, chan, rrc, channelizer)
+ tb.connect(rrc, src_snk)
+
+ vsnk = []
+ for i in xrange(nchans):
+ tb.connect((channelizer,i), (synthesizer, i))
+
+ vsnk.append(gr.vector_sink_c())
+ tb.connect((channelizer,i), vsnk[i])
+
+ tb.connect(synthesizer, snk)
+ tb.run()
+
+ sin = scipy.array(src_snk.data()[1000:])
+ sout = scipy.array(snk.data()[1000:])
+
+
+ # Plot original signal
+ fs_in = nchans*fs
+ f1 = pylab.figure(1, figsize=(16,12), facecolor='w')
+ s11 = f1.add_subplot(2,2,1)
+ s11.psd(sin, NFFT=fftlen, Fs=fs_in)
+ s11.set_title("PSD of Original Signal")
+ s11.set_ylim([-200, -20])
+
+ s12 = f1.add_subplot(2,2,2)
+ s12.plot(sin.real[1000:1500], "o-b")
+ s12.plot(sin.imag[1000:1500], "o-r")
+ s12.set_title("Original Signal in Time")
+
+ start = 1
+ skip = 4
+ s13 = f1.add_subplot(2,2,3)
+ s13.plot(sin.real[start::skip], sin.imag[start::skip], "o")
+ s13.set_title("Constellation")
+ s13.set_xlim([-2, 2])
+ s13.set_ylim([-2, 2])
+
+ # Plot channels
+ nrows = int(scipy.sqrt(nchans))
+ ncols = int(scipy.ceil(float(nchans)/float(nrows)))
+
+ f2 = pylab.figure(2, figsize=(16,12), facecolor='w')
+ for n in xrange(nchans):
+ s = f2.add_subplot(nrows, ncols, n+1)
+ s.psd(vsnk[n].data(), NFFT=fftlen, Fs=fs_in)
+ s.set_title("Channel {0}".format(n))
+ s.set_ylim([-200, -20])
+
+ # Plot reconstructed signal
+ fs_out = 2*nchans*fs
+ f3 = pylab.figure(3, figsize=(16,12), facecolor='w')
+ s31 = f3.add_subplot(2,2,1)
+ s31.psd(sout, NFFT=fftlen, Fs=fs_out)
+ s31.set_title("PSD of Reconstructed Signal")
+ s31.set_ylim([-200, -20])
+
+ s32 = f3.add_subplot(2,2,2)
+ s32.plot(sout.real[1000:1500], "o-b")
+ s32.plot(sout.imag[1000:1500], "o-r")
+ s32.set_title("Reconstructed Signal in Time")
+
+ start = 2
+ skip = 4
+ s33 = f3.add_subplot(2,2,3)
+ s33.plot(sout.real[start::skip], sout.imag[start::skip], "o")
+ s33.set_title("Constellation")
+ s33.set_xlim([-2, 2])
+ s33.set_ylim([-2, 2])
+
+ pylab.show()
+
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-filter/examples/resampler.py b/gr-filter/examples/resampler.py
new file mode 100755
index 000000000..395e095cb
--- /dev/null
+++ b/gr-filter/examples/resampler.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python
+#
+# Copyright 2009,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr
+from gnuradio import filter
+import sys
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Program requires scipy (see: www.scipy.org)."
+ sys.exit(1)
+
+try:
+ import pylab
+except ImportError:
+ print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)."
+ sys.exit(1)
+
+class mytb(gr.top_block):
+ def __init__(self, fs_in, fs_out, fc, N=10000):
+ gr.top_block.__init__(self)
+
+ rerate = float(fs_out) / float(fs_in)
+ print "Resampling from %f to %f by %f " %(fs_in, fs_out, rerate)
+
+ # Creating our own taps
+ taps = gr.firdes.low_pass_2(32, 32, 0.25, 0.1, 80)
+
+ self.src = gr.sig_source_c(fs_in, gr.GR_SIN_WAVE, fc, 1)
+ #self.src = gr.noise_source_c(gr.GR_GAUSSIAN, 1)
+ self.head = gr.head(gr.sizeof_gr_complex, N)
+
+ # A resampler with our taps
+ self.resamp_0 = filter.pfb.arb_resampler_ccf(rerate, taps,
+ flt_size=32)
+
+ # A resampler that just needs a resampling rate.
+ # Filter is created for us and designed to cover
+ # entire bandwidth of the input signal.
+ # An optional atten=XX rate can be used here to
+ # specify the out-of-band rejection (default=80).
+ self.resamp_1 = filter.pfb.arb_resampler_ccf(rerate)
+
+ self.snk_in = gr.vector_sink_c()
+ self.snk_0 = gr.vector_sink_c()
+ self.snk_1 = gr.vector_sink_c()
+
+ self.connect(self.src, self.head, self.snk_in)
+ self.connect(self.head, self.resamp_0, self.snk_0)
+ self.connect(self.head, self.resamp_1, self.snk_1)
+
+def main():
+ fs_in = 8000
+ fs_out = 20000
+ fc = 1000
+ N = 10000
+
+ tb = mytb(fs_in, fs_out, fc, N)
+ tb.run()
+
+
+ # Plot PSD of signals
+ nfftsize = 2048
+ fig1 = pylab.figure(1, figsize=(10,10), facecolor="w")
+ sp1 = fig1.add_subplot(2,1,1)
+ sp1.psd(tb.snk_in.data(), NFFT=nfftsize,
+ noverlap=nfftsize/4, Fs = fs_in)
+ sp1.set_title(("Input Signal at f_s=%.2f kHz" % (fs_in/1000.0)))
+ sp1.set_xlim([-fs_in/2, fs_in/2])
+
+ sp2 = fig1.add_subplot(2,1,2)
+ sp2.psd(tb.snk_0.data(), NFFT=nfftsize,
+ noverlap=nfftsize/4, Fs = fs_out,
+ label="With our filter")
+ sp2.psd(tb.snk_1.data(), NFFT=nfftsize,
+ noverlap=nfftsize/4, Fs = fs_out,
+ label="With auto-generated filter")
+ sp2.set_title(("Output Signals at f_s=%.2f kHz" % (fs_out/1000.0)))
+ sp2.set_xlim([-fs_out/2, fs_out/2])
+ sp2.legend()
+
+ # Plot signals in time
+ Ts_in = 1.0/fs_in
+ Ts_out = 1.0/fs_out
+ t_in = scipy.arange(0, len(tb.snk_in.data())*Ts_in, Ts_in)
+ t_out = scipy.arange(0, len(tb.snk_0.data())*Ts_out, Ts_out)
+
+ fig2 = pylab.figure(2, figsize=(10,10), facecolor="w")
+ sp21 = fig2.add_subplot(2,1,1)
+ sp21.plot(t_in, tb.snk_in.data())
+ sp21.set_title(("Input Signal at f_s=%.2f kHz" % (fs_in/1000.0)))
+ sp21.set_xlim([t_in[100], t_in[200]])
+
+ sp22 = fig2.add_subplot(2,1,2)
+ sp22.plot(t_out, tb.snk_0.data(),
+ label="With our filter")
+ sp22.plot(t_out, tb.snk_1.data(),
+ label="With auto-generated filter")
+ sp22.set_title(("Output Signals at f_s=%.2f kHz" % (fs_out/1000.0)))
+ r = float(fs_out)/float(fs_in)
+ sp22.set_xlim([t_out[r * 100], t_out[r * 200]])
+ sp22.legend()
+
+ pylab.show()
+
+if __name__ == "__main__":
+ main()
+
diff --git a/gr-filter/examples/resampler_demo.grc b/gr-filter/examples/resampler_demo.grc
new file mode 100644
index 000000000..b3991ac19
--- /dev/null
+++ b/gr-filter/examples/resampler_demo.grc
@@ -0,0 +1,630 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+ <timestamp>Tue Jun 19 21:31:30 2012</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>resampler_demo</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></value>
+ </param>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>wx_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 10)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>import</key>
+ <param>
+ <key>id</key>
+ <value>import_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>import</key>
+ <value>import math</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(11, 59)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>rs_taps</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>firdes.low_pass(nphases, nphases, frac_bw, 0.5-frac_bw)</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(273, 154)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_add_const_vxx</key>
+ <param>
+ <key>id</key>
+ <value>adder</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>const</key>
+ <value>-1.0</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(227, 303)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_throttle</key>
+ <param>
+ <key>id</key>
+ <value>throttle</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(227, 493)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>wxgui_fftsink2</key>
+ <param>
+ <key>id</key>
+ <value>orig_fft</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>Original Spectrum</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>baseband_freq</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>y_per_div</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>y_divs</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ref_level</key>
+ <value>30</value>
+ </param>
+ <param>
+ <key>ref_scale</key>
+ <value>2.0</value>
+ </param>
+ <param>
+ <key>fft_size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>fft_rate</key>
+ <value>30</value>
+ </param>
+ <param>
+ <key>peak_hold</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>average</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>avg_alpha</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>win</key>
+ <value>None</value>
+ </param>
+ <param>
+ <key>win_size</key>
+ <value></value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value>1, 0, 1, 3</value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(409, 289)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_sig_source_x</key>
+ <param>
+ <key>id</key>
+ <value>tri_source</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>waveform</key>
+ <value>gr.GR_TRI_WAVE</value>
+ </param>
+ <param>
+ <key>freq</key>
+ <value>0.05</value>
+ </param>
+ <param>
+ <key>amp</key>
+ <value>2.0</value>
+ </param>
+ <param>
+ <key>offset</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(21, 271)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>nphases</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>32</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(185, 153)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_static_text</key>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Sample Rate</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>44100</value>
+ </param>
+ <param>
+ <key>converver</key>
+ <value>float_converter</value>
+ </param>
+ <param>
+ <key>formatter</key>
+ <value>None</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value>0, 0, 1, 1</value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(179, 14)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_static_text</key>
+ <param>
+ <key>id</key>
+ <value>new_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Resampled Rate</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>48000</value>
+ </param>
+ <param>
+ <key>converver</key>
+ <value>float_converter</value>
+ </param>
+ <param>
+ <key>formatter</key>
+ <value>None</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value>0, 1, 1, 1</value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(328, 15)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_static_text</key>
+ <param>
+ <key>id</key>
+ <value>frac_bw</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Fractional Bandwidth</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>0.45</value>
+ </param>
+ <param>
+ <key>converver</key>
+ <value>float_converter</value>
+ </param>
+ <param>
+ <key>formatter</key>
+ <value>lambda x: "%0.2f"%x</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value>0,2,1,1</value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(473, 14)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_frequency_modulator_fc</key>
+ <param>
+ <key>id</key>
+ <value>fm_mod</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>sensitivity</key>
+ <value>math.pi</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(411, 493)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>wxgui_fftsink2</key>
+ <param>
+ <key>id</key>
+ <value>resamp_fft</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>Resampled Spectrum</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>new_rate</value>
+ </param>
+ <param>
+ <key>baseband_freq</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>y_per_div</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>y_divs</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ref_level</key>
+ <value>30</value>
+ </param>
+ <param>
+ <key>ref_scale</key>
+ <value>2.0</value>
+ </param>
+ <param>
+ <key>fft_size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>fft_rate</key>
+ <value>30</value>
+ </param>
+ <param>
+ <key>peak_hold</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>average</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>avg_alpha</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>win</key>
+ <value>None</value>
+ </param>
+ <param>
+ <key>win_size</key>
+ <value></value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value>2, 0, 1, 3</value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(640, 256)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>pfb_arb_resampler_xxx</key>
+ <param>
+ <key>id</key>
+ <value>pfb_arb_resampler_xxx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>ccf</value>
+ </param>
+ <param>
+ <key>rrate</key>
+ <value>float(new_rate)/samp_rate</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value>rs_taps</value>
+ </param>
+ <param>
+ <key>nfilts</key>
+ <value>nphases</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(649, 469)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>tri_source</source_block_id>
+ <sink_block_id>adder</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>adder</source_block_id>
+ <sink_block_id>throttle</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>fm_mod</source_block_id>
+ <sink_block_id>orig_fft</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>throttle</source_block_id>
+ <sink_block_id>fm_mod</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>fm_mod</source_block_id>
+ <sink_block_id>pfb_arb_resampler_xxx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>pfb_arb_resampler_xxx_0</source_block_id>
+ <sink_block_id>resamp_fft</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gr-filter/examples/synth_filter.py b/gr-filter/examples/synth_filter.py
new file mode 100755
index 000000000..a5b6fdf4c
--- /dev/null
+++ b/gr-filter/examples/synth_filter.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+#
+# Copyright 2010,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr
+from gnuradio import filter
+import sys
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Program requires scipy (see: www.scipy.org)."
+ sys.exit(1)
+
+try:
+ import pylab
+except ImportError:
+ print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)."
+ sys.exit(1)
+
+def main():
+ N = 1000000
+ fs = 8000
+
+ freqs = [100, 200, 300, 400, 500]
+ nchans = 7
+
+ sigs = list()
+ for fi in freqs:
+ s = gr.sig_source_c(fs, gr.GR_SIN_WAVE, fi, 1)
+ sigs.append(s)
+
+ taps = filter.firdes.low_pass_2(len(freqs), fs,
+ fs/float(nchans)/2, 100, 100)
+ print "Num. Taps = %d (taps per filter = %d)" % (len(taps),
+ len(taps)/nchans)
+ filtbank = filter.pfb_synthesizer_ccf(nchans, taps)
+
+ head = gr.head(gr.sizeof_gr_complex, N)
+ snk = gr.vector_sink_c()
+
+ tb = gr.top_block()
+ tb.connect(filtbank, head, snk)
+
+ for i,si in enumerate(sigs):
+ tb.connect(si, (filtbank, i))
+
+ tb.run()
+
+ if 1:
+ f1 = pylab.figure(1)
+ s1 = f1.add_subplot(1,1,1)
+ s1.plot(snk.data()[1000:])
+
+ fftlen = 2048
+ f2 = pylab.figure(2)
+ s2 = f2.add_subplot(1,1,1)
+ winfunc = scipy.blackman
+ s2.psd(snk.data()[10000:], NFFT=fftlen,
+ Fs = nchans*fs,
+ noverlap=fftlen/4,
+ window = lambda d: d*winfunc(fftlen))
+
+ pylab.show()
+
+if __name__ == "__main__":
+ main()
diff --git a/gr-filter/examples/synth_to_chan.py b/gr-filter/examples/synth_to_chan.py
new file mode 100755
index 000000000..b5f4c958e
--- /dev/null
+++ b/gr-filter/examples/synth_to_chan.py
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+#
+# Copyright 2010,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, blks2
+from gnuradio import filter
+import sys
+
+try:
+ import scipy
+except ImportError:
+ print "Error: Program requires scipy (see: www.scipy.org)."
+ sys.exit(1)
+
+try:
+ import pylab
+except ImportError:
+ print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)."
+ sys.exit(1)
+
+def main():
+ N = 1000000
+ fs = 8000
+
+ freqs = [100, 200, 300, 400, 500]
+ nchans = 7
+
+ sigs = list()
+ fmtx = list()
+ for fi in freqs:
+ s = gr.sig_source_f(fs, gr.GR_SIN_WAVE, fi, 1)
+ fm = blks2.nbfm_tx (fs, 4*fs, max_dev=10000, tau=75e-6)
+ sigs.append(s)
+ fmtx.append(fm)
+
+ syntaps = filter.firdes.low_pass_2(len(freqs), fs, fs/float(nchans)/2, 100, 100)
+ print "Synthesis Num. Taps = %d (taps per filter = %d)" % (len(syntaps),
+ len(syntaps)/nchans)
+ chtaps = filter.firdes.low_pass_2(len(freqs), fs, fs/float(nchans)/2, 100, 100)
+ print "Channelizer Num. Taps = %d (taps per filter = %d)" % (len(chtaps),
+ len(chtaps)/nchans)
+ filtbank = filter.pfb_synthesizer_ccf(nchans, syntaps)
+ channelizer = filter.pfb.channelizer_ccf(nchans, chtaps)
+
+ noise_level = 0.01
+ head = gr.head(gr.sizeof_gr_complex, N)
+ noise = gr.noise_source_c(gr.GR_GAUSSIAN, noise_level)
+ addnoise = gr.add_cc()
+ snk_synth = gr.vector_sink_c()
+
+ tb = gr.top_block()
+
+ tb.connect(noise, (addnoise,0))
+ tb.connect(filtbank, head, (addnoise, 1))
+ tb.connect(addnoise, channelizer)
+ tb.connect(addnoise, snk_synth)
+
+ snk = list()
+ for i,si in enumerate(sigs):
+ tb.connect(si, fmtx[i], (filtbank, i))
+
+ for i in xrange(nchans):
+ snk.append(gr.vector_sink_c())
+ tb.connect((channelizer, i), snk[i])
+
+ tb.run()
+
+ if 1:
+ channel = 1
+ data = snk[channel].data()[1000:]
+
+ f1 = pylab.figure(1)
+ s1 = f1.add_subplot(1,1,1)
+ s1.plot(data[10000:10200] )
+ s1.set_title(("Output Signal from Channel %d" % channel))
+
+ fftlen = 2048
+ winfunc = scipy.blackman
+ #winfunc = scipy.hamming
+
+ f2 = pylab.figure(2)
+ s2 = f2.add_subplot(1,1,1)
+ s2.psd(data, NFFT=fftlen,
+ Fs = nchans*fs,
+ noverlap=fftlen/4,
+ window = lambda d: d*winfunc(fftlen))
+ s2.set_title(("Output PSD from Channel %d" % channel))
+
+ f3 = pylab.figure(3)
+ s3 = f3.add_subplot(1,1,1)
+ s3.psd(snk_synth.data()[1000:], NFFT=fftlen,
+ Fs = nchans*fs,
+ noverlap=fftlen/4,
+ window = lambda d: d*winfunc(fftlen))
+ s3.set_title("Output of Synthesis Filter")
+
+ pylab.show()
+
+if __name__ == "__main__":
+ main()
diff --git a/gr-filter/gnuradio-filter.pc.in b/gr-filter/gnuradio-filter.pc.in
new file mode 100644
index 000000000..e4e83b350
--- /dev/null
+++ b/gr-filter/gnuradio-filter.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: gnuradio-filter
+Description: GNU Radio's filter signal processing blocks
+Requires: gnuradio-core gnuradio-fft
+Version: @LIBVER@
+Libs: -L${libdir} -lgnuradio-filter
+Cflags: -I${includedir}
diff --git a/gr-filter/grc/CMakeLists.txt b/gr-filter/grc/CMakeLists.txt
new file mode 100644
index 000000000..2e3fef4f0
--- /dev/null
+++ b/gr-filter/grc/CMakeLists.txt
@@ -0,0 +1,41 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+install(FILES
+ filter_block_tree.xml
+ dc_blocker_xx.xml
+ fft_filter_xxx.xml
+ fir_filter_xxx.xml
+ filter_delay_fc.xml
+ fractional_interpolator_xx.xml
+ freq_xlating_fir_filter_xxx.xml
+ hilbert_fc.xml
+ iir_filter_ffd.xml
+ interp_fir_filter_xxx.xml
+ pfb_arb_resampler.xml
+ pfb_channelizer.xml
+ pfb_decimator.xml
+ pfb_interpolator.xml
+ pfb_synthesizer.xml
+ rational_resampler_base_xxx.xml
+ single_pole_iir_filter_xx.xml
+ channel_model.xml
+ DESTINATION ${GRC_BLOCKS_DIR}
+ COMPONENT "filter_python"
+)
diff --git a/gr-filter/grc/channel_model.xml b/gr-filter/grc/channel_model.xml
new file mode 100644
index 000000000..6d780974a
--- /dev/null
+++ b/gr-filter/grc/channel_model.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Channel Model
+###################################################
+ -->
+<block>
+ <name>Channel Model</name>
+ <key>channel_model</key>
+ <import>from gnuradio import filter</import>
+ <import>from gnuradio.filter import firdes</import>
+ <make>filter.channel_model(
+ noise_voltage=$noise_voltage,
+ frequency_offset=$freq_offset,
+ epsilon=$epsilon,
+ taps=$taps,
+ noise_seed=$seed,
+)</make>
+ <callback>set_noise_voltage($noise_voltage)</callback>
+ <callback>set_frequency_offset($freq_offset)</callback>
+ <callback>set_taps($taps)</callback>
+ <callback>set_timing_offset($epsilon)</callback>
+ <param>
+ <name>Noise Voltage</name>
+ <key>noise_voltage</key>
+ <value>0.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Frequency Offset</name>
+ <key>freq_offset</key>
+ <value>0.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Epsilon</name>
+ <key>epsilon</key>
+ <value>1.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <value>1.0 + 1.0j</value>
+ <type>complex_vector</type>
+ </param>
+ <param>
+ <name>Seed</name>
+ <key>seed</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/gr-filter/grc/dc_blocker_xx.xml b/gr-filter/grc/dc_blocker_xx.xml
new file mode 100644
index 000000000..9bce5e980
--- /dev/null
+++ b/gr-filter/grc/dc_blocker_xx.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## DC Blocker
+###################################################
+ -->
+<block>
+ <name>DC Blocker</name>
+ <key>dc_blocker_xx</key>
+ <import>from gnuradio import filter</import>
+ <make>filter.dc_blocker_$(type)($length, $long_form)</make>
+ <!-- <callback>set_length($length)</callback> -->
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex</name>
+ <key>cc</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ </option>
+ <option>
+ <name>Float->Float</name>
+ <key>ff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ </option>
+ </param>
+ <param>
+ <name>Length</name>
+ <key>length</key>
+ <value>32</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Long Form</name>
+ <key>long_form</key>
+ <value>True</value>
+ <type>bool</type>
+ </param>
+
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+</block>
diff --git a/gr-filter/grc/fft_filter_xxx.xml b/gr-filter/grc/fft_filter_xxx.xml
new file mode 100644
index 000000000..29612dffd
--- /dev/null
+++ b/gr-filter/grc/fft_filter_xxx.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##FFT Filter
+###################################################
+ -->
+<block>
+ <name>FFT Filter</name>
+ <key>fft_filter_xxx</key>
+ <import>from gnuradio import filter</import>
+ <import>from gnuradio.gr import firdes</import>
+ <make>filter.fft_filter_$(type)($decim, $taps, $nthreads)</make>
+ <callback>set_taps($taps)</callback>
+ <callback>set_nthreads($nthreads)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Complex Taps)</name>
+ <key>ccc</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Float->Float (Real Taps)</name>
+ <key>fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ </param>
+ <param>
+ <name>Decimation</name>
+ <key>decim</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>$type.taps</type>
+ </param>
+ <param>
+ <name>Num. Threads</name>
+ <key>nthreads</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+</block>
diff --git a/gr-filter/grc/filter_block_tree.xml b/gr-filter/grc/filter_block_tree.xml
new file mode 100644
index 000000000..711ce4059
--- /dev/null
+++ b/gr-filter/grc/filter_block_tree.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+
+<!--
+ Copyright 2012 Free Software Foundation, Inc.
+
+ This file is part of GNU Radio
+
+ GNU Radio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GNU Radio is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Radio; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street,
+ Boston, MA 02110-1301, USA.
+-->
+
+<!--
+###################################################
+##Block Tree for GR Filter blocks.
+###################################################
+ -->
+<cat>
+ <name></name> <!-- Blank for Root Name -->
+ <cat>
+ <name>Filters</name>
+ <block>dc_blocker_xx</block>
+ <block>fft_filter_xxx</block>
+ <block>fir_filter_xxx</block>
+ <block>filter_delay_fc</block>
+ <block>fractional_interpolator_xx</block>
+ <block>freq_xlating_fir_filter_xxx</block>
+ <block>hilbert_fc</block>
+ <block>iir_filter_ffd</block>
+ <block>interp_fir_filter_xxx</block>
+ <block>pfb_arb_resampler_xxx</block>
+ <block>pfb_channelizer_ccf</block>
+ <block>pfb_decimator_ccf</block>
+ <block>pfb_interpolator_ccf</block>
+ <block>pfb_synthesizer_ccf</block>
+ <block>rational_resampler_base_xxx</block>
+ <block>single_pole_iir_filter_xx</block>
+ <block>channel_model</block>
+ </cat>
+</cat>
diff --git a/gr-filter/grc/filter_delay_fc.xml b/gr-filter/grc/filter_delay_fc.xml
new file mode 100644
index 000000000..7b77c2caf
--- /dev/null
+++ b/gr-filter/grc/filter_delay_fc.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Filter Delay
+###################################################
+ -->
+<block>
+ <name>Filter Delay</name>
+ <key>filter_delay_fc</key>
+ <import>from gnuradio import filter</import>
+ <import>from gnuradio.filter import firdes</import>
+ <make>filter.filter_delay_fc($taps)</make>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>real_vector</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ <optional>1</optional>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/gr-filter/grc/fir_filter_xxx.xml b/gr-filter/grc/fir_filter_xxx.xml
new file mode 100644
index 000000000..3925eb555
--- /dev/null
+++ b/gr-filter/grc/fir_filter_xxx.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Decimating FIR Filter
+###################################################
+ -->
+<block>
+ <name>Decimating FIR Filter</name>
+ <key>fir_filter_xxx</key>
+ <import>from gnuradio import filter</import>
+ <import>from gnuradio.filter import firdes</import>
+ <make>filter.fir_filter_$(type)($decim, $taps)</make>
+ <callback>set_taps($taps)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Complex Taps)</name>
+ <key>ccc</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Complex->Complex (Real Taps)</name>
+ <key>ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Complex (Complex Taps)</name>
+ <key>fcc</key>
+ <opt>input:float</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Float->Float (Real Taps)</name>
+ <key>fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Short (Real Taps)</name>
+ <key>fsf</key>
+ <opt>input:float</opt>
+ <opt>output:short</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Short->Complex (Complex Taps)</name>
+ <key>scc</key>
+ <opt>input:short</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ </param>
+ <param>
+ <name>Decimation</name>
+ <key>decim</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>$type.taps</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+</block>
diff --git a/gr-filter/grc/fractional_interpolator_xx.xml b/gr-filter/grc/fractional_interpolator_xx.xml
new file mode 100644
index 000000000..760e8bb06
--- /dev/null
+++ b/gr-filter/grc/fractional_interpolator_xx.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Fractional Interpolator
+###################################################
+ -->
+<block>
+ <name>Fractional Interpolator</name>
+ <key>fractional_interpolator_xx</key>
+ <import>from gnuradio import filter</import>
+ <make>filter.fractional_interpolator_$(type.fcn)($phase_shift, $interp_ratio)</make>
+ <callback>set_interp_ratio($interp_ratio)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:cc</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ </option>
+ </param>
+ <param>
+ <name>Phase Shift</name>
+ <key>phase_shift</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Interpolation Ratio</name>
+ <key>interp_ratio</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/gr-filter/grc/freq_xlating_fir_filter_xxx.xml b/gr-filter/grc/freq_xlating_fir_filter_xxx.xml
new file mode 100644
index 000000000..178a42f48
--- /dev/null
+++ b/gr-filter/grc/freq_xlating_fir_filter_xxx.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Frequency Xlating Filter
+###################################################
+ -->
+<block>
+ <name>Frequency Xlating FIR Filter</name>
+ <key>freq_xlating_fir_filter_xxx</key>
+ <import>from gnuradio import filter</import>
+ <import>from gnuradio.filter import firdes</import>
+ <make>filter.freq_xlating_fir_filter_$(type)($decim, $taps, $center_freq, $samp_rate)</make>
+ <callback>set_taps($taps)</callback>
+ <callback>set_center_freq($center_freq)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Complex Taps)</name>
+ <key>ccc</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Complex->Complex (Real Taps)</name>
+ <key>ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Complex (Complex Taps)</name>
+ <key>fcc</key>
+ <opt>input:float</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Float->Complex (Real Taps)</name>
+ <key>fcf</key>
+ <opt>input:float</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Short->Complex (Complex Taps)</name>
+ <key>scc</key>
+ <opt>input:short</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Short->Complex (Real Taps)</name>
+ <key>scf</key>
+ <opt>input:short</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ </param>
+ <param>
+ <name>Decimation</name>
+ <key>decim</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>$type.taps</type>
+ </param>
+ <param>
+ <name>Center Frequency</name>
+ <key>center_freq</key>
+ <value>0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Sample Rate</name>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+</block>
diff --git a/gr-filter/grc/hilbert_fc.xml b/gr-filter/grc/hilbert_fc.xml
new file mode 100644
index 000000000..dd4c94b83
--- /dev/null
+++ b/gr-filter/grc/hilbert_fc.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Hilbert
+###################################################
+ -->
+<block>
+ <name>Hilbert</name>
+ <key>hilbert_fc</key>
+ <import>from gnuradio import filter</import>
+ <make>filter.hilbert_fc($num_taps)</make>
+ <param>
+ <name>Num Taps</name>
+ <key>num_taps</key>
+ <value>64</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/gr-filter/grc/iir_filter_ffd.xml b/gr-filter/grc/iir_filter_ffd.xml
new file mode 100644
index 000000000..261aba320
--- /dev/null
+++ b/gr-filter/grc/iir_filter_ffd.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##IIR Filter
+###################################################
+ -->
+<block>
+ <name>IIR Filter</name>
+ <key>iir_filter_ffd</key>
+ <import>from gnuradio import filter</import>
+ <make>filter.iir_filter_ffd($fftaps, $fbtaps)</make>
+ <callback>set_taps($fftaps, $fbtaps)</callback>
+ <param>
+ <name>Feed-forward Taps</name>
+ <key>fftaps</key>
+ <type>real_vector</type>
+ </param>
+ <param>
+ <name>Feedback Taps</name>
+ <key>fbtaps</key>
+ <type>real_vector</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/gr-filter/grc/interp_fir_filter_xxx.xml b/gr-filter/grc/interp_fir_filter_xxx.xml
new file mode 100644
index 000000000..98a143f53
--- /dev/null
+++ b/gr-filter/grc/interp_fir_filter_xxx.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Interpolating FIR Filter
+###################################################
+ -->
+<block>
+ <name>Interpolating FIR Filter</name>
+ <key>interp_fir_filter_xxx</key>
+ <import>from gnuradio import filter</import>
+ <import>from gnuradio.filter import firdes</import>
+ <make>filter.interp_fir_filter_$(type)($interp, $taps)</make>
+ <callback>set_taps($taps)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Complex Taps)</name>
+ <key>ccc</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Complex->Complex (Real Taps)</name>
+ <key>ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Complex (Complex Taps)</name>
+ <key>fcc</key>
+ <opt>input:float</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Float->Float (Real Taps)</name>
+ <key>fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Short (Real Taps)</name>
+ <key>fsf</key>
+ <opt>input:float</opt>
+ <opt>output:short</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Short->Complex (Complex Taps)</name>
+ <key>scc</key>
+ <opt>input:short</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ </param>
+ <param>
+ <name>Interpolation</name>
+ <key>interp</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>$type.taps</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+</block>
diff --git a/gr-filter/grc/pfb_arb_resampler.xml b/gr-filter/grc/pfb_arb_resampler.xml
new file mode 100644
index 000000000..f3048000a
--- /dev/null
+++ b/gr-filter/grc/pfb_arb_resampler.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Polyphase Arbitrary Resampler
+###################################################
+ -->
+<block>
+ <name>Polyphase Arbitrary Resampler</name>
+ <key>pfb_arb_resampler_xxx</key>
+ <import>from gnuradio import filter</import>
+ <import>from gnuradio.filter import firdes</import>
+ <make>filter.pfb_arb_resampler_$(type)(
+ $rrate,
+ $taps,
+ $nfilts)
+ </make>
+ <callback>set_taps($taps)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Real Taps)</name>
+ <key>ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Float (Real Taps)</name>
+ <key>fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ </param>
+ <param>
+ <name>Resampling Rate</name>
+ <key>rrate</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>$type.taps</type>
+ </param>
+ <param>
+ <name>Number of Filters</name>
+ <key>nfilts</key>
+ <value>32</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/gr-filter/grc/pfb_channelizer.xml b/gr-filter/grc/pfb_channelizer.xml
new file mode 100644
index 000000000..114abc0f0
--- /dev/null
+++ b/gr-filter/grc/pfb_channelizer.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Polyphase Channelizer
+###################################################
+ -->
+<block>
+ <name>Polyphase Channelizer</name>
+ <key>pfb_channelizer_ccf</key>
+ <import>from gnuradio import filter</import>
+ <import>from gnuradio.filter import firdes</import>
+ <make>filter.pfb.channelizer_ccf(
+ $nchans,
+ $taps,
+ $osr,
+ $atten)
+self.$(id).set_channel_map($ch_map)
+ </make>
+ <!-- Set taps not implemented yet
+ <callback>set_taps($taps)</callback>
+ -->
+ <callback>set_channel_map($ch_map)</callback>
+
+ <param>
+ <name>Channels</name>
+ <key>nchans</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <value>None</value>
+ <type>real_vector</type>
+ </param>
+ <param>
+ <name>Over Sample Ratio</name>
+ <key>osr</key>
+ <value>1.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Attenuation</name>
+ <key>atten</key>
+ <value>100</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Channel Map</name>
+ <key>ch_map</key>
+ <value>[]</value>
+ <type>int_vector</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ <nports>$nchans</nports>
+ </source>
+</block>
diff --git a/gr-filter/grc/pfb_decimator.xml b/gr-filter/grc/pfb_decimator.xml
new file mode 100644
index 000000000..b0540d3e2
--- /dev/null
+++ b/gr-filter/grc/pfb_decimator.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Polyphase Decimator
+###################################################
+ -->
+<block>
+ <name>Polyphase Decimator</name>
+ <key>pfb_decimator_ccf</key>
+ <import>from gnuradio import filter</import>
+ <import>from gnuradio.filter import firdes</import>
+ <make>filter.pfb_decimator_ccf(
+ $decim,
+ $taps,
+ $channel)
+ </make>
+ <callback>set_taps($taps)</callback>
+ <param>
+ <name>Decimation</name>
+ <key>decim</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <value>None</value>
+ <type>real_vector</type>
+ </param>
+ <param>
+ <name>Output Channel</name>
+ <key>channel</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/gr-filter/grc/pfb_interpolator.xml b/gr-filter/grc/pfb_interpolator.xml
new file mode 100644
index 000000000..600493123
--- /dev/null
+++ b/gr-filter/grc/pfb_interpolator.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Polyphase Interpolator
+###################################################
+ -->
+<block>
+ <name>Polyphase Interpolator</name>
+ <key>pfb_interpolator_ccf</key>
+ <import>from gnuradio import filter</import>
+ <import>from gnuradio.filter import firdes</import>
+ <make>filter.pfb.interpolator_ccf(
+ $interp,
+ $taps)
+ </make>
+ <callback>set_taps($taps)</callback>
+ <param>
+ <name>Interpolation</name>
+ <key>interp</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <value>None</value>
+ <type>real_vector</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/gr-filter/grc/pfb_synthesizer.xml b/gr-filter/grc/pfb_synthesizer.xml
new file mode 100644
index 000000000..e84b25e62
--- /dev/null
+++ b/gr-filter/grc/pfb_synthesizer.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Polyphase Synthesis Filterbank
+###################################################
+ -->
+<block>
+ <name>Polyphase Synthesizer</name>
+ <key>pfb_synthesizer_ccf</key>
+ <import>from gnuradio import filter</import>
+ <import>from gnuradio.filter import firdes</import>
+ <make>filter.pfb_synthesizer_ccf(
+ $numchans, $taps, $twox)
+self.$(id).set_channel_map($ch_map)
+ </make>
+ <callback>set_taps($taps)</callback>
+ <callback>set_channel_map($ch_map)</callback>
+
+ <param>
+ <name>Channels</name>
+ <key>numchans</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Connections</name>
+ <key>connections</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>real_vector</type>
+ </param>
+ <param>
+ <name>2x Sample Rate</name>
+ <key>twox</key>
+ <value>False</value>
+ <type>bool</type>
+ </param>
+ <param>
+ <name>Channel Map</name>
+ <key>ch_map</key>
+ <value>[]</value>
+ <type>int_vector</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ <nports>$connections</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/gr-filter/grc/rational_resampler_base_xxx.xml b/gr-filter/grc/rational_resampler_base_xxx.xml
new file mode 100644
index 000000000..399bfc74c
--- /dev/null
+++ b/gr-filter/grc/rational_resampler_base_xxx.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Rational Resampler Base
+###################################################
+ -->
+<block>
+ <name>Rational Resampler Base</name>
+ <key>rational_resampler_base_xxx</key>
+ <import>from gnuradio import filter</import>
+ <import>from gnuradio.filter import firdes</import>
+ <make>filter.rational_resampler_base_$(type)($interp, $decim, $taps)</make>
+ <callback>set_taps($taps)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Complex Taps)</name>
+ <key>ccc</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Complex->Complex (Real Taps)</name>
+ <key>ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Complex (Complex Taps)</name>
+ <key>fcc</key>
+ <opt>input:float</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Float->Float (Real Taps)</name>
+ <key>fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Short (Real Taps)</name>
+ <key>fsf</key>
+ <opt>input:float</opt>
+ <opt>output:short</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Short->Complex (Complex Taps)</name>
+ <key>scc</key>
+ <opt>input:short</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ </param>
+ <param>
+ <name>Interpolation</name>
+ <key>interp</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Decimation</name>
+ <key>decim</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>$type.taps</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+</block>
diff --git a/gr-filter/grc/single_pole_iir_filter_xx.xml b/gr-filter/grc/single_pole_iir_filter_xx.xml
new file mode 100644
index 000000000..3eaf52625
--- /dev/null
+++ b/gr-filter/grc/single_pole_iir_filter_xx.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Single Pole IIR Filter
+###################################################
+ -->
+<block>
+ <name>Single Pole IIR Filter</name>
+ <key>single_pole_iir_filter_xx</key>
+ <import>from gnuradio import filter</import>
+ <make>filter.single_pole_iir_filter_$(type.fcn)($alpha, $vlen)</make>
+ <callback>set_taps($alpha)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:cc</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ </option>
+ </param>
+ <param>
+ <name>Alpha</name>
+ <key>alpha</key>
+ <value>1.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/gr-filter/include/filter/CMakeLists.txt b/gr-filter/include/filter/CMakeLists.txt
new file mode 100644
index 000000000..c6bf109cd
--- /dev/null
+++ b/gr-filter/include/filter/CMakeLists.txt
@@ -0,0 +1,116 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+# generate helper scripts to expand templated files
+########################################################################
+include(GrPython)
+
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py "
+#!${PYTHON_EXECUTABLE}
+
+import sys, os, re
+sys.path.append('${GR_CORE_PYTHONPATH}')
+os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}'
+os.chdir('${CMAKE_CURRENT_BINARY_DIR}')
+
+if __name__ == '__main__':
+ import build_utils
+ root, inp = sys.argv[1:3]
+ for sig in sys.argv[3:]:
+ name = re.sub ('X+', sig, root)
+ d = build_utils.standard_dict2(name, sig, 'filter')
+ build_utils.expand_template(d, inp)
+
+")
+
+macro(expand_h root)
+ #make a list of all the generated files
+ unset(expanded_files_h)
+ foreach(sig ${ARGN})
+ string(REGEX REPLACE "X+" ${sig} name ${root})
+ list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/${name}.h)
+ endforeach(sig)
+
+ #create a command to generate the files
+ add_custom_command(
+ OUTPUT ${expanded_files_h}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.h.t
+ COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
+ ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
+ ${root} ${root}.h.t ${ARGN}
+ )
+
+ #install rules for the generated h files
+ list(APPEND generated_includes ${expanded_files_h})
+endmacro(expand_h)
+
+########################################################################
+# Invoke macro to generate various sources
+#######################################################################
+expand_h(fir_filter_XXX ccc ccf fcc fff fsf scc)
+expand_h(freq_xlating_fir_filter_XXX ccc ccf fcc fcf scf scc)
+expand_h(interp_fir_filter_XXX ccc ccf fcc fff fsf scc)
+expand_h(rational_resampler_base_XXX ccc ccf fcc fff fsf scc)
+
+add_custom_target(filter_generated_includes DEPENDS
+ ${generated_includes}
+)
+
+########################################################################
+# Install header files
+########################################################################
+install(FILES
+ api.h
+ firdes.h
+ fir_filter.h
+ fir_filter_with_buffer.h
+ fft_filter.h
+ iir_filter.h
+ interpolator_taps.h
+ mmse_fir_interpolator_cc.h
+ mmse_fir_interpolator_ff.h
+ pm_remez.h
+ polyphase_filterbank.h
+ single_pole_iir.h
+ ${generated_includes}
+ adaptive_fir_ccc.h
+ adaptive_fir_ccf.h
+ dc_blocker_cc.h
+ dc_blocker_ff.h
+ filter_delay_fc.h
+ fft_filter_ccc.h
+ fft_filter_fff.h
+ fractional_interpolator_cc.h
+ fractional_interpolator_ff.h
+ hilbert_fc.h
+ iir_filter_ffd.h
+ pfb_arb_resampler_ccf.h
+ pfb_arb_resampler_fff.h
+ pfb_channelizer_ccf.h
+ pfb_decimator_ccf.h
+ pfb_interpolator_ccf.h
+ pfb_synthesizer_ccf.h
+ single_pole_iir_filter_cc.h
+ single_pole_iir_filter_ff.h
+ channel_model.h
+ DESTINATION ${GR_INCLUDE_DIR}/gnuradio/filter
+ COMPONENT "filter_devel"
+)
+
diff --git a/gr-filter/include/filter/adaptive_fir_ccc.h b/gr-filter/include/filter/adaptive_fir_ccc.h
new file mode 100644
index 000000000..261259957
--- /dev/null
+++ b/gr-filter/include/filter/adaptive_fir_ccc.h
@@ -0,0 +1,85 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_ADAPTIVE_FIR_CCC_H
+#define INCLUDED_FILTER_ADAPTIVE_FIR_CCC_H
+
+#include <filter/api.h>
+#include <gr_sync_decimator.h>
+#include <filter/fir_filter.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief Adaptive FIR filter with gr_complex input, gr_complex output and gr_complex taps
+ * \ingroup filter_blk
+ *
+ * This is a base class to implement an adaptive FIR
+ * filter. Generally, another block will inherit from this one to
+ * build a new type of adaptive filter such as an equalizer.
+ *
+ * This class implements two functions that are designed to be
+ * overloaded by the child class: error(gr_complex out) and
+ * update_tap(gr_complex tap, gr_complex in).
+ *
+ * The error() function calculates the error value that will be
+ * used to adjust the taps. The update_tap function then uses the
+ * error and the input signal value to update a particular
+ * tap. Typically, the error is calculated for a given output and
+ * then this is used in a loop to update all of the filter taps in
+ * a loop:
+ *
+ * \code
+ * d_error = error(sum);
+ * for(k = 0; k < l; k++) {
+ * update_tap(d_taps[ntaps-k-1], in[i+k]);
+ * }
+ * \endcode
+ *
+ * See digital::cma_equalizer_cc and digital::lms_dd_equalizer_cc
+ * for example usage.
+ */
+ class FILTER_API adaptive_fir_ccc : virtual public gr_sync_decimator
+ {
+ public:
+ // gr::filter::adaptive_fir_ccc::sptr
+ typedef boost::shared_ptr<adaptive_fir_ccc> sptr;
+
+ /*!
+ * \brief Adaptive FIR filter with gr_complex input, gr_complex output and gr_complex taps
+ *
+ * \param name Provides a name to identify this type of algorithm
+ * \param decimation (interger) decimation rate of the filter
+ * \param taps (complex) filter taps
+ */
+ static sptr make(const char *name, int decimation,
+ const std::vector<gr_complex> &taps);
+
+ virtual void set_taps(const std::vector<gr_complex> &taps) = 0;
+ virtual std::vector<gr_complex> taps() const = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_ADAPTIVE_FIR_CCC_H */
diff --git a/gr-filter/include/filter/adaptive_fir_ccf.h b/gr-filter/include/filter/adaptive_fir_ccf.h
new file mode 100644
index 000000000..0fd8d5746
--- /dev/null
+++ b/gr-filter/include/filter/adaptive_fir_ccf.h
@@ -0,0 +1,81 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_ADAPTIVE_FIR_CCF_H
+#define INCLUDED_FILTER_ADAPTIVE_FIR_CCF_H
+
+#include <filter/api.h>
+#include <gr_sync_decimator.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief Adaptive FIR filter with gr_complex input, gr_complex output and float taps
+ * \ingroup filter_blk
+ *
+ * This is a base class to implement an adaptive FIR
+ * filter. Generally, another block will inherit from this one to
+ * build a new type of adaptive filter such as an equalizer.
+ *
+ * This class implements two functions that are designed to be
+ * overloaded by the child class: error(gr_complex out) and
+ * update_tap(float tap, gr_complex in).
+ *
+ * The error() function calculates the error value that will be
+ * used to adjust the taps. The update_tap function then uses the
+ * error and the input signal value to update a particular
+ * tap. Typically, the error is calculated for a given output and
+ * then this is used in a loop to update all of the filter taps in
+ * a loop:
+ *
+ * \code
+ * d_error = error(sum);
+ * for(k = 0; k < l; k++) {
+ * update_tap(d_taps[ntaps-k-1], in[i+k]);
+ * }
+ * \endcode
+ */
+ class FILTER_API adaptive_fir_ccf : virtual public gr_sync_decimator
+ {
+ public:
+ // gr::filter::adaptive_fir_ccf::sptr
+ typedef boost::shared_ptr<adaptive_fir_ccf> sptr;
+
+ /*!
+ * \brief Adaptive FIR filter with gr_complex input, gr_complex output and float taps
+ *
+ * \param name Provides a name to identify this type of algorithm
+ * \param decimation (interger) decimation rate of the filter
+ * \param taps (real) filter taps
+ */
+ static sptr make(const char *name, int decimation,
+ const std::vector<float> &taps);
+
+ virtual void set_taps(const std::vector<float> &taps) = 0;
+ virtual std::vector<float> taps() = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_ADAPTIVE_FIR_CCF_H */
diff --git a/gr-filter/include/filter/api.h b/gr-filter/include/filter/api.h
new file mode 100644
index 000000000..025b0bd4a
--- /dev/null
+++ b/gr-filter/include/filter/api.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_API_H
+#define INCLUDED_FILTER_API_H
+
+#include <gruel/attributes.h>
+
+#ifdef gnuradio_filter_EXPORTS
+# define FILTER_API __GR_ATTR_EXPORT
+#else
+# define FILTER_API __GR_ATTR_IMPORT
+#endif
+
+#endif /* INCLUDED_FILTER_API_H */
diff --git a/gr-filter/include/filter/channel_model.h b/gr-filter/include/filter/channel_model.h
new file mode 100644
index 000000000..2e808de8e
--- /dev/null
+++ b/gr-filter/include/filter/channel_model.h
@@ -0,0 +1,87 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_CHANNEL_MODEL_H
+#define INCLUDED_FILTER_CHANNEL_MODEL_H
+
+#include <filter/api.h>
+#include <gr_hier_block2.h>
+#include <gr_types.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief channel simulator
+ * \ingroup misc_blk
+ *
+ * This block implements a basic channel model simulator that can
+ * be used to help evaluate, design, and test various signals,
+ * waveforms, and algorithms. This model allows the user to set
+ * the voltage of an AWGN noise source, a (normalized) frequency
+ * offset, a sample timing offset, and a noise seed to randomize
+ * the AWGN noise source.
+ *
+ * Multipath can be approximated in this model by using a FIR
+ * filter representation of a multipath delay profile..
+ */
+ class FILTER_API channel_model : virtual public gr_hier_block2
+ {
+ public:
+ // gr::filter::channel_model::sptr
+ typedef boost::shared_ptr<channel_model> sptr;
+
+ /*! \brief Build the channel simulator.
+ *
+ * \param noise_voltage The AWGN noise level as a voltage (to be
+ * calculated externally to meet, say, a
+ * desired SNR).
+ * \param frequency_offset The normalized frequency offset. 0 is
+ * no offset; 0.25 would be, for a digital
+ * modem, one quarter of the symbol rate.
+ * \param epsilon The sample timing offset to emulate the
+ * different rates between the sample clocks of
+ * the transmitter and receiver. 1.0 is no difference.
+ * \param taps Taps of a FIR filter to emulate a multipath delay profile.
+ * \param noise_seed A random number generator seed for the noise source.
+ */
+ static sptr make(double noise_voltage=0.0,
+ double frequency_offset=0.0,
+ double epsilon=1.0,
+ const std::vector<gr_complex> &taps=std::vector<gr_complex>(1,1),
+ double noise_seed=3021);
+
+ virtual void set_noise_voltage(double noise_voltage) = 0;
+ virtual void set_frequency_offset(double frequency_offset) = 0;
+ virtual void set_taps(const std::vector<gr_complex> &taps) = 0;
+ virtual void set_timing_offset(double epsilon) = 0;
+
+ virtual double noise_voltage() const = 0;
+ virtual double frequency_offset() const = 0;
+ virtual std::vector<gr_complex> taps() const = 0;
+ virtual double timing_offset() const = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_CHANNEL_MODEL_H */
diff --git a/gr-filter/include/filter/dc_blocker_cc.h b/gr-filter/include/filter/dc_blocker_cc.h
new file mode 100644
index 000000000..df4c815d6
--- /dev/null
+++ b/gr-filter/include/filter/dc_blocker_cc.h
@@ -0,0 +1,76 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_DC_BLOCKER_CC_H
+#define INCLUDED_FILTER_DC_BLOCKER_CC_H
+
+#include <filter/api.h>
+#include <gr_sync_block.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API dc_blocker_cc : virtual public gr_sync_block
+ {
+ public:
+
+ // gr::filter::dc_blocker_cc::sptr
+ typedef boost::shared_ptr<dc_blocker_cc> sptr;
+
+ /*!
+ * \class dc_blocker_cc
+ * \brief a computationally efficient controllable DC blocker
+ *
+ * \ingroup filter_blk
+ *
+ * This block implements a computationally efficient DC blocker that produces
+ * a tighter notch filter around DC for a smaller group delay than an
+ * equivalent FIR filter or using a single pole IIR filter (though the IIR
+ * filter is computationally cheaper).
+ *
+ * The block defaults to using a delay line of length 32 and the long form
+ * of the filter. Optionally, the delay line length can be changed to alter
+ * the width of the DC notch (longer lines will decrease the width).
+ *
+ * The long form of the filter produces a nearly flat response outside of
+ * the notch but at the cost of a group delay of 2D-2.
+ *
+ * The short form of the filter does not have as flat a response in the
+ * passband but has a group delay of only D-1 and is cheaper to compute.
+ *
+ * The theory behind this block can be found in the paper:
+ *
+ * <B><EM>R. Yates, "DC Blocker Algorithms," IEEE Signal Processing Magazine,
+ * Mar. 2008, pp 132-134.</EM></B>
+ *
+ * \param D (int) the length of the delay line
+ * \param long_form (bool) whether to use long (true, default) or short form
+ */
+ static sptr make(int D, bool long_form);
+
+ virtual int group_delay() = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_DC_BLOCKER_CC_H */
diff --git a/gr-filter/include/filter/dc_blocker_ff.h b/gr-filter/include/filter/dc_blocker_ff.h
new file mode 100644
index 000000000..6ab4d5a3d
--- /dev/null
+++ b/gr-filter/include/filter/dc_blocker_ff.h
@@ -0,0 +1,76 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_DC_BLOCKER_FF_H
+#define INCLUDED_FILTER_DC_BLOCKER_FF_H
+
+#include <filter/api.h>
+#include <gr_sync_block.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API dc_blocker_ff : virtual public gr_sync_block
+ {
+ public:
+
+ // gr::filter::dc_blocker_ff::sptr
+ typedef boost::shared_ptr<dc_blocker_ff> sptr;
+
+ /*!
+ * \class dc_blocker_ff
+ * \brief a computationally efficient controllable DC blocker
+ *
+ * \ingroup filter_blk
+ *
+ * This block implements a computationally efficient DC blocker that produces
+ * a tighter notch filter around DC for a smaller group delay than an
+ * equivalent FIR filter or using a single pole IIR filter (though the IIR
+ * filter is computationally cheaper).
+ *
+ * The block defaults to using a delay line of length 32 and the long form
+ * of the filter. Optionally, the delay line length can be changed to alter
+ * the width of the DC notch (longer lines will decrease the width).
+ *
+ * The long form of the filter produces a nearly flat response outside of
+ * the notch but at the cost of a group delay of 2D-2.
+ *
+ * The short form of the filter does not have as flat a response in the
+ * passband but has a group delay of only D-1 and is cheaper to compute.
+ *
+ * The theory behind this block can be found in the paper:
+ *
+ * <B><EM>R. Yates, "DC Blocker Algorithms," IEEE Signal Processing Magazine,
+ * Mar. 2008, pp 132-134.</EM></B>
+ *
+ * \param D (int) the length of the delay line
+ * \param long_form (bool) whether to use long (true, default) or short form
+ */
+ static sptr make(int D, bool long_form=true);
+
+ virtual int group_delay() = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_DC_BLOCKER_FF_H */
diff --git a/gr-filter/include/filter/fft_filter.h b/gr-filter/include/filter/fft_filter.h
new file mode 100644
index 000000000..8c7d6cf78
--- /dev/null
+++ b/gr-filter/include/filter/fft_filter.h
@@ -0,0 +1,171 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_FFT_FILTER_H
+#define INCLUDED_FILTER_FFT_FILTER_H
+
+#include <filter/api.h>
+#include <vector>
+#include <gr_complex.h>
+#include <fft/fft.h>
+
+namespace gr {
+ namespace filter {
+ namespace kernel {
+ /*!
+ * \brief Fast FFT filter with float input, float output and float taps
+ * \ingroup filter_blk
+ */
+ class FILTER_API fft_filter_fff
+ {
+ private:
+ int d_ntaps;
+ int d_nsamples;
+ int d_fftsize; // fftsize = ntaps + nsamples - 1
+ int d_decimation;
+ fft::fft_real_fwd *d_fwdfft; // forward "plan"
+ fft::fft_real_rev *d_invfft; // inverse "plan"
+ int d_nthreads; // number of FFTW threads to use
+ std::vector<float> d_tail; // state carried between blocks for overlap-add
+ std::vector<float> d_new_taps;
+ gr_complex *d_xformed_taps; // Fourier xformed taps
+
+ void compute_sizes(int ntaps);
+ int tailsize() const { return d_ntaps - 1; }
+
+ public:
+ /*!
+ * \brief Construct an FFT filter for float vectors with the given taps and decimation rate.
+ *
+ * This is the basic implementation for performing FFT filter for fast convolution
+ * in other blocks for complex vectors (such as fft_filter_ccc).
+ *
+ * \param decimation The decimation rate of the filter (int)
+ * \param taps The filter taps (complex)
+ * \param nthreads The number of threads for the FFT to use (int)
+ */
+ fft_filter_fff(int decimation,
+ const std::vector<float> &taps,
+ int nthreads=1);
+
+ ~fft_filter_fff();
+
+ /*!
+ * \brief Set new taps for the filter.
+ *
+ * Sets new taps and resets the class properties to handle different sizes
+ * \param taps The filter taps (complex)
+ */
+ int set_taps(const std::vector<float> &taps);
+
+ /*!
+ * \brief Set number of threads to use.
+ */
+ void set_nthreads(int n);
+
+ /*!
+ * \brief Get number of threads being used.
+ */
+ int nthreads() const;
+
+ /*!
+ * \brief Perform the filter operation
+ *
+ * \param nitems The number of items to produce
+ * \param input The input vector to be filtered
+ * \param output The result of the filter operation
+ */
+ int filter(int nitems, const float *input, float *output);
+ };
+
+
+ /*!
+ * \brief Fast FFT filter with gr_complex input, gr_complex output and gr_complex taps
+ * \ingroup filter_blk
+ */
+ class FILTER_API fft_filter_ccc
+ {
+ private:
+ int d_ntaps;
+ int d_nsamples;
+ int d_fftsize; // fftsize = ntaps + nsamples - 1
+ int d_decimation;
+ fft::fft_complex *d_fwdfft; // forward "plan"
+ fft::fft_complex *d_invfft; // inverse "plan"
+ int d_nthreads; // number of FFTW threads to use
+ std::vector<gr_complex> d_tail; // state carried between blocks for overlap-add
+ std::vector<gr_complex> d_new_taps;
+ gr_complex *d_xformed_taps; // Fourier xformed taps
+
+ void compute_sizes(int ntaps);
+ int tailsize() const { return d_ntaps - 1; }
+
+ public:
+ /*!
+ * \brief Construct an FFT filter for complex vectors with the given taps and decimation rate.
+ *
+ * This is the basic implementation for performing FFT filter for fast convolution
+ * in other blocks for complex vectors (such as fft_filter_ccc).
+ *
+ * \param decimation The decimation rate of the filter (int)
+ * \param taps The filter taps (complex)
+ * \param nthreads The number of threads for the FFT to use (int)
+ */
+ fft_filter_ccc(int decimation,
+ const std::vector<gr_complex> &taps,
+ int nthreads=1);
+
+ ~fft_filter_ccc();
+
+ /*!
+ * \brief Set new taps for the filter.
+ *
+ * Sets new taps and resets the class properties to handle different sizes
+ * \param taps The filter taps (complex)
+ */
+ int set_taps(const std::vector<gr_complex> &taps);
+
+ /*!
+ * \brief Set number of threads to use.
+ */
+ void set_nthreads(int n);
+
+ /*!
+ * \brief Get number of threads being used.
+ */
+ int nthreads() const;
+
+ /*!
+ * \brief Perform the filter operation
+ *
+ * \param nitems The number of items to produce
+ * \param input The input vector to be filtered
+ * \param output The result of the filter operation
+ */
+ int filter(int nitems, const gr_complex *input, gr_complex *output);
+ };
+
+ } /* namespace kernel */
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_FFT_FILTER_H */
diff --git a/gr-filter/include/filter/fft_filter_ccc.h b/gr-filter/include/filter/fft_filter_ccc.h
new file mode 100644
index 000000000..acec93277
--- /dev/null
+++ b/gr-filter/include/filter/fft_filter_ccc.h
@@ -0,0 +1,86 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_FFT_FILTER_CCC_H
+#define INCLUDED_FILTER_FFT_FILTER_CCC_H
+
+#include <filter/api.h>
+#include <gr_sync_decimator.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API fft_filter_ccc : virtual public gr_sync_decimator
+ {
+ public:
+ // gr::filter::fft_filter_ccc::sptr
+ typedef boost::shared_ptr<fft_filter_ccc> sptr;
+
+ /*!
+ * \brief Fast FFT filter with gr_complex input, gr_complex output and gr_complex taps
+ * \ingroup filter_blk
+ *
+ * This block implements a complex decimating filter using the
+ * fast convolution method via an FFT. The decimation factor is
+ * an interger that is greater than or equal to 1.
+ *
+ * The filter takes a set of complex (or real) taps to use in
+ * the filtering operation. These taps can be defined as
+ * anything that satisfies the user's filtering needs. For
+ * standard filters such as lowpass, highpass, bandpass, etc.,
+ * the filter.firdes and filter.optfir classes provide
+ * convenient generating methods.
+ *
+ * This filter is implemented by using the FFTW package to
+ * perform the required FFTs. An optional argument, nthreads,
+ * may be passed to the constructor (or set using the
+ * set_nthreads member function) to split the FFT among N number
+ * of threads. This can improve performance on very large FFTs
+ * (that is, if the number of taps used is very large) if you
+ * have enough threads/cores to support it.
+ *
+ * \param decimation >= 1
+ * \param taps complex filter taps
+ * \param nthreads number of threads for the FFT to use
+ */
+ static sptr make(int decimation,
+ const std::vector<gr_complex> &taps,
+ int nthreads=1);
+
+ virtual void set_taps(const std::vector<gr_complex> &taps) = 0;
+ virtual std::vector<gr_complex> taps() const = 0;
+
+ /*!
+ * \brief Set number of threads to use.
+ */
+ virtual void set_nthreads(int n) = 0;
+
+ /*!
+ * \brief Get number of threads being used.
+ */
+ virtual int nthreads() const = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_FFT_FILTER_CCC_H */
diff --git a/gr-filter/include/filter/fft_filter_fff.h b/gr-filter/include/filter/fft_filter_fff.h
new file mode 100644
index 000000000..d8140325f
--- /dev/null
+++ b/gr-filter/include/filter/fft_filter_fff.h
@@ -0,0 +1,86 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_FFT_FILTER_FFF_H
+#define INCLUDED_FILTER_FFT_FILTER_FFF_H
+
+#include <filter/api.h>
+#include <gr_sync_decimator.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API fft_filter_fff : virtual public gr_sync_decimator
+ {
+ public:
+ // gr::filter::fft_filter_fff::sptr
+ typedef boost::shared_ptr<fft_filter_fff> sptr;
+
+ /*!
+ * \brief Fast FFT filter with float input, float output and float taps
+ * \ingroup filter_blk
+ *
+ * This block implements a real-value decimating filter using
+ * the fast convolution method via an FFT. The decimation factor
+ * is an interger that is greater than or equal to 1.
+ *
+ * The filter takes a set of real-valued taps to use in
+ * the filtering operation. These taps can be defined as
+ * anything that satisfies the user's filtering needs. For
+ * standard filters such as lowpass, highpass, bandpass, etc.,
+ * the filter.firdes and filter.optfir classes provide
+ * convenient generating methods.
+ *
+ * This filter is implemented by using the FFTW package to
+ * perform the required FFTs. An optional argument, nthreads,
+ * may be passed to the constructor (or set using the
+ * set_nthreads member function) to split the FFT among N number
+ * of threads. This can improve performance on very large FFTs
+ * (that is, if the number of taps used is very large) if you
+ * have enough threads/cores to support it.
+ *
+ * \param decimation >= 1
+ * \param taps float filter taps
+ * \param nthreads number of threads for the FFT to use
+ */
+ static sptr make(int decimation,
+ const std::vector<float> &taps,
+ int nthreads=1);
+
+ virtual void set_taps(const std::vector<float> &taps) = 0;
+ virtual std::vector<float> taps() const = 0;
+
+ /*!
+ * \brief Set number of threads to use.
+ */
+ virtual void set_nthreads(int n) = 0;
+
+ /*!
+ * \brief Get number of threads being used.
+ */
+ virtual int nthreads() const = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_FFT_FILTER_FFF_H */
diff --git a/gr-filter/include/filter/filter_delay_fc.h b/gr-filter/include/filter/filter_delay_fc.h
new file mode 100644
index 000000000..8a84a6a0e
--- /dev/null
+++ b/gr-filter/include/filter/filter_delay_fc.h
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_FILTER_DELAY_FC_H
+#define INCLUDED_FILTER_FILTER_DELAY_FC_H
+
+#include <filter/api.h>
+#include <gr_sync_block.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API filter_delay_fc : virtual public gr_sync_block
+ {
+ public:
+
+ // gr::filter::filter_delay_fc::sptr
+ typedef boost::shared_ptr<filter_delay_fc> sptr;
+
+ /*!
+ * \brief Filter-Delay Combination Block.
+ * \ingroup filter_blk
+ *
+ * The block takes one or two float stream and outputs a complex
+ * stream.
+ *
+ * If only one float stream is input, the real output is a
+ * delayed version of this input and the imaginary output is the
+ * filtered output.
+ *
+ * If two floats are connected to the input, then the real
+ * output is the delayed version of the first input, and the
+ * imaginary output is the filtered output.
+ *
+ * The delay in the real path accounts for the group delay
+ * introduced by the filter in the imaginary path. The filter
+ * taps needs to be calculated before initializing this block.
+ *
+ */
+ static sptr make(const std::vector<float> &taps);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_FILTER_DELAY_FC_H */
diff --git a/gr-filter/include/filter/fir_filter.h b/gr-filter/include/filter/fir_filter.h
new file mode 100644
index 000000000..e86111268
--- /dev/null
+++ b/gr-filter/include/filter/fir_filter.h
@@ -0,0 +1,222 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_FIR_FILTER_H
+#define INCLUDED_FILTER_FIR_FILTER_H
+
+#include <filter/api.h>
+#include <vector>
+#include <gr_complex.h>
+
+namespace gr {
+ namespace filter {
+ namespace kernel {
+
+ class FILTER_API fir_filter_fff
+ {
+ public:
+ fir_filter_fff(int decimation,
+ const std::vector<float> &taps);
+ ~fir_filter_fff();
+
+ void set_taps(const std::vector<float> &taps);
+ std::vector<float> taps() const;
+ unsigned int ntaps() const;
+
+ float filter(const float input[]);
+ void filterN(float output[],
+ const float input[],
+ unsigned long n);
+ void filterNdec(float output[],
+ const float input[],
+ unsigned long n,
+ unsigned int decimate);
+
+ protected:
+ std::vector<float> d_taps;
+ unsigned int d_ntaps;
+ float **d_aligned_taps;
+ float *d_output;
+ int d_align;
+ int d_naligned;
+ };
+
+ /**************************************************************/
+
+ class FILTER_API fir_filter_ccf
+ {
+ public:
+ fir_filter_ccf(int decimation,
+ const std::vector<float> &taps);
+ ~fir_filter_ccf();
+
+ void set_taps(const std::vector<float> &taps);
+ std::vector<float> taps() const;
+ unsigned int ntaps() const;
+
+ gr_complex filter(const gr_complex input[]);
+ void filterN(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n);
+ void filterNdec(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n,
+ unsigned int decimate);
+
+ protected:
+ std::vector<float> d_taps;
+ unsigned int d_ntaps;
+ float **d_aligned_taps;
+ gr_complex *d_output;
+ int d_align;
+ int d_naligned;
+ };
+
+ /**************************************************************/
+
+ class FILTER_API fir_filter_fcc
+ {
+ public:
+ fir_filter_fcc(int decimation,
+ const std::vector<gr_complex> &taps);
+ ~fir_filter_fcc();
+
+ void set_taps(const std::vector<gr_complex> &taps);
+ std::vector<gr_complex> taps() const;
+ unsigned int ntaps() const;
+
+ gr_complex filter(const float input[]);
+ void filterN(gr_complex output[],
+ const float input[],
+ unsigned long n);
+ void filterNdec(gr_complex output[],
+ const float input[],
+ unsigned long n,
+ unsigned int decimate);
+
+ protected:
+ std::vector<gr_complex> d_taps;
+ unsigned int d_ntaps;
+ gr_complex **d_aligned_taps;
+ gr_complex *d_output;
+ int d_align;
+ int d_naligned;
+ };
+
+ /**************************************************************/
+
+ class FILTER_API fir_filter_ccc
+ {
+ public:
+ fir_filter_ccc(int decimation,
+ const std::vector<gr_complex> &taps);
+ ~fir_filter_ccc();
+
+ void set_taps(const std::vector<gr_complex> &taps);
+ std::vector<gr_complex> taps() const;
+ unsigned int ntaps() const;
+
+ gr_complex filter(const gr_complex input[]);
+ void filterN(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n);
+ void filterNdec(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n,
+ unsigned int decimate);
+
+ protected:
+ std::vector<gr_complex> d_taps;
+ unsigned int d_ntaps;
+ gr_complex **d_aligned_taps;
+ gr_complex *d_output;
+ int d_align;
+ int d_naligned;
+ };
+
+ /**************************************************************/
+
+ class FILTER_API fir_filter_scc
+ {
+ public:
+ fir_filter_scc(int decimation,
+ const std::vector<gr_complex> &taps);
+ ~fir_filter_scc();
+
+ void set_taps(const std::vector<gr_complex> &taps);
+ std::vector<gr_complex> taps() const;
+ unsigned int ntaps() const;
+
+ gr_complex filter(const short input[]);
+ void filterN(gr_complex output[],
+ const short input[],
+ unsigned long n);
+ void filterNdec(gr_complex output[],
+ const short input[],
+ unsigned long n,
+ unsigned int decimate);
+
+ protected:
+ std::vector<gr_complex> d_taps;
+ unsigned int d_ntaps;
+ gr_complex **d_aligned_taps;
+ gr_complex *d_output;
+ int d_align;
+ int d_naligned;
+ };
+
+ /**************************************************************/
+
+ class FILTER_API fir_filter_fsf
+ {
+ public:
+ fir_filter_fsf(int decimation,
+ const std::vector<float> &taps);
+ ~fir_filter_fsf();
+
+ void set_taps(const std::vector<float> &taps);
+ std::vector<float> taps() const;
+ unsigned int ntaps() const;
+
+ short filter(const float input[]);
+ void filterN(short output[],
+ const float input[],
+ unsigned long n);
+ void filterNdec(short output[],
+ const float input[],
+ unsigned long n,
+ unsigned int decimate);
+
+ protected:
+ std::vector<float> d_taps;
+ unsigned int d_ntaps;
+ float **d_aligned_taps;
+ short *d_output;
+ int d_align;
+ int d_naligned;
+ };
+
+ } /* namespace kernel */
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_FIR_FILTER_H */
diff --git a/gr-filter/include/filter/fir_filter_XXX.h.t b/gr-filter/include/filter/fir_filter_XXX.h.t
new file mode 100644
index 000000000..98e82f510
--- /dev/null
+++ b/gr-filter/include/filter/fir_filter_XXX.h.t
@@ -0,0 +1,82 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* @WARNING@ */
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
+
+#include <filter/api.h>
+#include <gr_sync_decimator.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief FIR filter with @I_TYPE@ input, @O_TYPE@ output, and @TAP_TYPE@ taps
+ * \ingroup filter_blk
+ *
+ * The fir_filter_XXX blocks create finite impulse response
+ * (FIR) filters that perform the convolution in the time
+ * domain:
+ *
+ * \code
+ * out = 0
+ * for i in ntaps:
+ * out += input[n-i] * taps[i]
+ * \endcode
+ *
+ * The taps are a C++ vector (or Python list) of values of the
+ * type specified by the third letter in the block's suffix. For
+ * this block, the value is of type @TAP_TYPE@. Taps can be
+ * created using the firdes or optfir tools.
+ *
+ * These versions of the filter can also act as down-samplers
+ * (or decimators) by specifying an integer value for \p
+ * decimation.
+ *
+ */
+ class FILTER_API @BASE_NAME@ : virtual public gr_sync_decimator
+ {
+ public:
+
+ // gr::filter::@BASE_NAME@::sptr
+ typedef boost::shared_ptr<@BASE_NAME@> sptr;
+
+ /*!
+ * \brief FIR filter with @I_TYPE@ input, @O_TYPE@ output, and @TAP_TYPE@ taps
+ * \ingroup filter_blk
+ *
+ * \param decimation set the integer decimation rate
+ * \param taps a vector/list of taps of type @TAP_TYPE@
+ */
+ static sptr make(int decimation,
+ const std::vector<@TAP_TYPE@> &taps);
+
+ virtual void set_taps(const std::vector<@TAP_TYPE@> &taps) = 0;
+ virtual std::vector<@TAP_TYPE@> taps() const = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* @GUARD_NAME@ */
diff --git a/gr-filter/include/filter/fir_filter_with_buffer.h b/gr-filter/include/filter/fir_filter_with_buffer.h
new file mode 100644
index 000000000..007eae3fa
--- /dev/null
+++ b/gr-filter/include/filter/fir_filter_with_buffer.h
@@ -0,0 +1,326 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_FIR_FILTER_WITH_BUFFER_H
+#define INCLUDED_FILTER_FIR_FILTER_WITH_BUFFER_H
+
+#include <filter/api.h>
+#include <vector>
+#include <gr_complex.h>
+
+namespace gr {
+ namespace filter {
+ namespace kernel {
+
+ /*!
+ * \brief FIR with internal buffer for float input, float output and float taps.
+ * \ingroup filter
+ */
+ class FILTER_API fir_filter_with_buffer_fff
+ {
+ private:
+ std::vector<float> d_taps;
+ unsigned int d_ntaps;
+ float *d_buffer_ptr;
+ float *d_buffer;
+ unsigned int d_idx;
+ float **d_aligned_taps;
+ float *d_output;
+ int d_align;
+ int d_naligned;
+
+ public:
+
+ // CONSTRUCTORS
+
+ /*!
+ * \brief construct new FIR with given taps.
+ *
+ * Note that taps must be in forward order, e.g., coefficient 0 is
+ * stored in new_taps[0], coefficient 1 is stored in
+ * new_taps[1], etc.
+ */
+ fir_filter_with_buffer_fff(const std::vector<float> &taps);
+
+ ~fir_filter_with_buffer_fff();
+
+ // MANIPULATORS
+
+ /*!
+ * \brief compute a single output value.
+ *
+ * \p input is a single input value of the filter type
+ *
+ * \returns the filtered input value.
+ */
+ float filter(float input);
+
+ /*!
+ * \brief compute a single output value; designed for decimating filters.
+ *
+ * \p input is a single input value of the filter type. The value of dec is the
+ * decimating value of the filter, so input[] must have dec valid values.
+ * The filter pushes dec number of items onto the circ. buffer before computing
+ * a single output.
+ *
+ * \returns the filtered input value.
+ */
+ float filter(const float input[], unsigned long dec);
+
+ /*!
+ * \brief compute an array of N output values.
+ *
+ * \p input must have (n - 1 + ntaps()) valid entries.
+ * input[0] .. input[n - 1 + ntaps() - 1] are referenced to compute the output values.
+ */
+ void filterN(float output[],
+ const float input[],
+ unsigned long n);
+
+ /*!
+ * \brief compute an array of N output values, decimating the input
+ *
+ * \p input must have (decimate * (n - 1) + ntaps()) valid entries.
+ * input[0] .. input[decimate * (n - 1) + ntaps() - 1] are referenced to
+ * compute the output values.
+ */
+ void filterNdec(float output[], const float input[],
+ unsigned long n, unsigned long decimate);
+
+ // ACCESSORS
+
+ /*!
+ * \return number of taps in filter.
+ */
+ unsigned int ntaps() const { return d_ntaps; }
+
+ /*!
+ * \brief install \p new_taps as the current taps.
+ */
+ void set_taps(const std::vector<float> &taps);
+
+ /*!
+ * \return current taps
+ */
+ std::vector<float> taps() const;
+ };
+
+
+ /**************************************************************/
+
+
+ /*!
+ * \brief FIR with internal buffer for gr_complex input, gr_complex output and gr_complex taps.
+ * \ingroup filter
+ */
+ class FILTER_API fir_filter_with_buffer_ccc
+ {
+ private:
+ std::vector<gr_complex> d_taps;
+ unsigned int d_ntaps;
+ gr_complex *d_buffer_ptr;
+ gr_complex *d_buffer;
+ unsigned int d_idx;
+ gr_complex **d_aligned_taps;
+ gr_complex *d_output;
+ int d_align;
+ int d_naligned;
+
+ public:
+
+ // CONSTRUCTORS
+
+ /*!
+ * \brief construct new FIR with given taps.
+ *
+ * Note that taps must be in forward order, e.g., coefficient 0 is
+ * stored in new_taps[0], coefficient 1 is stored in
+ * new_taps[1], etc.
+ */
+ fir_filter_with_buffer_ccc(const std::vector<gr_complex> &taps);
+
+ ~fir_filter_with_buffer_ccc();
+
+ // MANIPULATORS
+
+ /*!
+ * \brief compute a single output value.
+ *
+ * \p input is a single input value of the filter type
+ *
+ * \returns the filtered input value.
+ */
+ gr_complex filter(gr_complex input);
+
+ /*!
+ * \brief compute a single output value; designed for decimating filters.
+ *
+ * \p input is a single input value of the filter type. The value of dec is the
+ * decimating value of the filter, so input[] must have dec valid values.
+ * The filter pushes dec number of items onto the circ. buffer before computing
+ * a single output.
+ *
+ * \returns the filtered input value.
+ */
+ gr_complex filter(const gr_complex input[], unsigned long dec);
+
+ /*!
+ * \brief compute an array of N output values.
+ *
+ * \p input must have (n - 1 + ntaps()) valid entries.
+ * input[0] .. input[n - 1 + ntaps() - 1] are referenced to compute the output values.
+ */
+ void filterN(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n);
+
+ /*!
+ * \brief compute an array of N output values, decimating the input
+ *
+ * \p input must have (decimate * (n - 1) + ntaps()) valid entries.
+ * input[0] .. input[decimate * (n - 1) + ntaps() - 1] are referenced to
+ * compute the output values.
+ */
+ void filterNdec(gr_complex output[], const gr_complex input[],
+ unsigned long n, unsigned long decimate);
+
+ // ACCESSORS
+
+ /*!
+ * \return number of taps in filter.
+ */
+ unsigned int ntaps() const { return d_ntaps; }
+
+ /*!
+ * \brief install \p new_taps as the current taps.
+ */
+ void set_taps(const std::vector<gr_complex> &taps);
+
+ /*!
+ * \return current taps
+ */
+ std::vector<gr_complex> taps() const;
+ };
+
+
+ /**************************************************************/
+
+
+ /*!
+ * \brief FIR with internal buffer for gr_complex input, gr_complex output and gr_complex taps.
+ * \ingroup filter
+ */
+ class FILTER_API fir_filter_with_buffer_ccf
+ {
+ private:
+ std::vector<float> d_taps;
+ unsigned int d_ntaps;
+ gr_complex *d_buffer_ptr;
+ gr_complex *d_buffer;
+ unsigned int d_idx;
+ float **d_aligned_taps;
+ gr_complex *d_output;
+ int d_align;
+ int d_naligned;
+
+ public:
+
+ // CONSTRUCTORS
+
+ /*!
+ * \brief construct new FIR with given taps.
+ *
+ * Note that taps must be in forward order, e.g., coefficient 0 is
+ * stored in new_taps[0], coefficient 1 is stored in
+ * new_taps[1], etc.
+ */
+ fir_filter_with_buffer_ccf(const std::vector<float> &taps);
+
+ ~fir_filter_with_buffer_ccf();
+
+ // MANIPULATORS
+
+ /*!
+ * \brief compute a single output value.
+ *
+ * \p input is a single input value of the filter type
+ *
+ * \returns the filtered input value.
+ */
+ gr_complex filter(gr_complex input);
+
+ /*!
+ * \brief compute a single output value; designed for decimating filters.
+ *
+ * \p input is a single input value of the filter type. The value of dec is the
+ * decimating value of the filter, so input[] must have dec valid values.
+ * The filter pushes dec number of items onto the circ. buffer before computing
+ * a single output.
+ *
+ * \returns the filtered input value.
+ */
+ gr_complex filter(const gr_complex input[], unsigned long dec);
+
+ /*!
+ * \brief compute an array of N output values.
+ *
+ * \p input must have (n - 1 + ntaps()) valid entries.
+ * input[0] .. input[n - 1 + ntaps() - 1] are referenced to compute the output values.
+ */
+ void filterN(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n);
+
+ /*!
+ * \brief compute an array of N output values, decimating the input
+ *
+ * \p input must have (decimate * (n - 1) + ntaps()) valid entries.
+ * input[0] .. input[decimate * (n - 1) + ntaps() - 1] are referenced to
+ * compute the output values.
+ */
+ void filterNdec(gr_complex output[], const gr_complex input[],
+ unsigned long n, unsigned long decimate);
+
+ // ACCESSORS
+
+ /*!
+ * \return number of taps in filter.
+ */
+ unsigned int ntaps() const { return d_ntaps; }
+
+ /*!
+ * \brief install \p new_taps as the current taps.
+ */
+ void set_taps(const std::vector<float> &taps);
+
+ /*!
+ * \return current taps
+ */
+ std::vector<float> taps() const;
+ };
+
+
+ } /* namespace kernel */
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_FIR_FILTER_WITH_BUFFER_H */
diff --git a/gr-filter/include/filter/firdes.h b/gr-filter/include/filter/firdes.h
new file mode 100644
index 000000000..172563ea0
--- /dev/null
+++ b/gr-filter/include/filter/firdes.h
@@ -0,0 +1,378 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2008,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _FILTER_FIRDES_H_
+#define _FILTER_FIRDES_H_
+
+#include <filter/api.h>
+#include <vector>
+#include <cmath>
+#include <gr_complex.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief Finite Impulse Response (FIR) filter design functions.
+ * \ingroup filter_design
+ */
+
+ class FILTER_API firdes {
+ public:
+
+ enum win_type {
+ WIN_HAMMING = 0, // max attenuation 53 dB
+ WIN_HANN = 1, // max attenuation 44 dB
+ WIN_BLACKMAN = 2, // max attenuation 74 dB
+ WIN_RECTANGULAR = 3,
+ WIN_KAISER = 4, // max attenuation a function of beta, google it
+ WIN_BLACKMAN_hARRIS = 5,
+ WIN_BLACKMAN_HARRIS = 5, // alias for capitalization consistency
+ };
+
+
+ // ... class methods ...
+
+ /*!
+ * \brief use "window method" to design a low-pass FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * The normalized width of the transition
+ * band is what sets the number of taps
+ * required. Narrow --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+ static std::vector<float>
+ low_pass(double gain,
+ double sampling_freq,
+ double cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!
+ * \brief use "window method" to design a low-pass FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * \p attenuation_dB required stopband attenuation
+ * The normalized width of the transition
+ * band and the required stop band
+ * attenuation is what sets the number of taps
+ * required. Narrow --> more taps
+ * More attenuatin --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+
+ static std::vector<float>
+ low_pass_2(double gain,
+ double sampling_freq,
+ double cutoff_freq, // Hz beginning transition band
+ double transition_width, // Hz width of transition band
+ double attenuation_dB, // out of band attenuation dB
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!
+ * \brief use "window method" to design a high-pass FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * The normalized width of the transition
+ * band is what sets the number of taps
+ * required. Narrow --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+
+ static std::vector<float>
+ high_pass(double gain,
+ double sampling_freq,
+ double cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!
+ * \brief use "window method" to design a high-pass FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * \p attenuation_dB out of band attenuation
+ * The normalized width of the transition
+ * band and the required stop band
+ * attenuation is what sets the number of taps
+ * required. Narrow --> more taps
+ * More attenuation --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+
+ static std::vector<float>
+ high_pass_2(double gain,
+ double sampling_freq,
+ double cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ double attenuation_dB, // out of band attenuation dB
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!
+ * \brief use "window method" to design a band-pass FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p low_cutoff_freq: center of transition band (Hz)
+ * \p high_cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * The normalized width of the transition
+ * band is what sets the number of taps
+ * required. Narrow --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+ static std::vector<float>
+ band_pass(double gain,
+ double sampling_freq,
+ double low_cutoff_freq, // Hz center of transition band
+ double high_cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!
+ * \brief use "window method" to design a band-pass FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p low_cutoff_freq: center of transition band (Hz)
+ * \p high_cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * \p attenuation_dB out of band attenuation
+ * The normalized width of the transition
+ * band and the required stop band
+ * attenuation is what sets the number of taps
+ * required. Narrow --> more taps
+ * More attenuation --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+
+ static std::vector<float>
+ band_pass_2(double gain,
+ double sampling_freq,
+ double low_cutoff_freq, // Hz beginning transition band
+ double high_cutoff_freq, // Hz beginning transition band
+ double transition_width, // Hz width of transition band
+ double attenuation_dB, // out of band attenuation dB
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!
+ * \brief use "window method" to design a complex band-pass FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p low_cutoff_freq: center of transition band (Hz)
+ * \p high_cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * The normalized width of the transition
+ * band is what sets the number of taps
+ * required. Narrow --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+ static std::vector<gr_complex>
+ complex_band_pass(double gain,
+ double sampling_freq,
+ double low_cutoff_freq, // Hz center of transition band
+ double high_cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!
+ * \brief use "window method" to design a complex band-pass FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p low_cutoff_freq: center of transition band (Hz)
+ * \p high_cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * \p attenuation_dB out of band attenuation
+ * The normalized width of the transition
+ * band and the required stop band
+ * attenuation is what sets the number of taps
+ * required. Narrow --> more taps
+ * More attenuation --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+
+ static std::vector<gr_complex>
+ complex_band_pass_2(double gain,
+ double sampling_freq,
+ double low_cutoff_freq, // Hz beginning transition band
+ double high_cutoff_freq, // Hz beginning transition band
+ double transition_width, // Hz width of transition band
+ double attenuation_dB, // out of band attenuation dB
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!
+ * \brief use "window method" to design a band-reject FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p low_cutoff_freq: center of transition band (Hz)
+ * \p high_cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * The normalized width of the transition
+ * band is what sets the number of taps
+ * required. Narrow --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+
+ static std::vector<float>
+ band_reject(double gain,
+ double sampling_freq,
+ double low_cutoff_freq, // Hz center of transition band
+ double high_cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!
+ * \brief use "window method" to design a band-reject FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p low_cutoff_freq: center of transition band (Hz)
+ * \p high_cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * \p attenuation_dB out of band attenuation
+ * The normalized width of the transition
+ * band and the required stop band
+ * attenuation is what sets the number of taps
+ * required. Narrow --> more taps
+ * More attenuation --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+
+ static std::vector<float>
+ band_reject_2(double gain,
+ double sampling_freq,
+ double low_cutoff_freq, // Hz beginning transition band
+ double high_cutoff_freq, // Hz beginning transition band
+ double transition_width, // Hz width of transition band
+ double attenuation_dB, // out of band attenuation dB
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!\brief design a Hilbert Transform Filter
+ *
+ * \p ntaps: Number of taps, must be odd
+ * \p window_type: What kind of window to use
+ * \p beta: Only used for Kaiser
+ */
+ static std::vector<float>
+ hilbert(unsigned int ntaps = 19,
+ win_type windowtype = WIN_RECTANGULAR,
+ double beta = 6.76);
+
+ /*!
+ * \brief design a Root Cosine FIR Filter (do we need a window?)
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p symbol rate: symbol rate, must be a factor of sample rate
+ * \p alpha: excess bandwidth factor
+ * \p ntaps: number of taps
+ */
+ static std::vector<float>
+ root_raised_cosine(double gain,
+ double sampling_freq,
+ double symbol_rate, // Symbol rate, NOT bitrate (unless BPSK)
+ double alpha, // Excess Bandwidth Factor
+ int ntaps);
+
+ /*!
+ * \brief design a Gaussian filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p symbols per bit: symbol rate, must be a factor of sample rate
+ * \p ntaps: number of taps
+ */
+ static std::vector<float>
+ gaussian(double gain,
+ double spb,
+ double bt, // Bandwidth to bitrate ratio
+ int ntaps);
+
+ // window functions ...
+ static std::vector<float> window (win_type type, int ntaps, double beta);
+
+ private:
+ static double bessi0(double x);
+ static void sanity_check_1f(double sampling_freq, double f1,
+ double transition_width);
+ static void sanity_check_2f(double sampling_freq, double f1, double f2,
+ double transition_width);
+ static void sanity_check_2f_c(double sampling_freq, double f1, double f2,
+ double transition_width);
+
+ static int compute_ntaps(double sampling_freq,
+ double transition_width,
+ win_type window_type, double beta);
+
+ static int compute_ntaps_windes(double sampling_freq,
+ double transition_width,
+ double attenuation_dB);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* _FILTER_FIRDES_H_ */
diff --git a/gr-filter/include/filter/fractional_interpolator_cc.h b/gr-filter/include/filter/fractional_interpolator_cc.h
new file mode 100644
index 000000000..bb0e18932
--- /dev/null
+++ b/gr-filter/include/filter/fractional_interpolator_cc.h
@@ -0,0 +1,60 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FRACTIONAL_INTERPOLATOR_CC_H
+#define INCLUDED_FRACTIONAL_INTERPOLATOR_CC_H
+
+#include <filter/api.h>
+#include <gr_block.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief Interpolating MMSE filter with complex input, complex output
+ * \ingroup filter_blk
+ */
+ class FILTER_API fractional_interpolator_cc : virtual public gr_block
+ {
+ public:
+ // gr::filter::fractional_interpolator_cc::sptr
+ typedef boost::shared_ptr<fractional_interpolator_cc> sptr;
+
+ /*!
+ * \brief Build the interpolating MMSE filter (complex input, complex output)
+ *
+ * \param phase_shift The phase shift of the output signal to the input
+ * \param interp_ratio The interpolation ratio = input_rate / output_rate.
+ */
+ static sptr make(float phase_shift,
+ float interp_ratio);
+
+ virtual float mu() const = 0;
+ virtual float interp_ratio() const = 0;
+ virtual void set_mu (float mu) = 0;
+ virtual void set_interp_ratio(float interp_ratio) = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FRACTIONAL_INTERPOLATOR_FF_H */
diff --git a/gr-filter/include/filter/fractional_interpolator_ff.h b/gr-filter/include/filter/fractional_interpolator_ff.h
new file mode 100644
index 000000000..fc43c3457
--- /dev/null
+++ b/gr-filter/include/filter/fractional_interpolator_ff.h
@@ -0,0 +1,60 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FRACTIONAL_INTERPOLATOR_FF_H
+#define INCLUDED_FRACTIONAL_INTERPOLATOR_FF_H
+
+#include <filter/api.h>
+#include <gr_block.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief Interpolating MMSE filter with float input, float output
+ * \ingroup filter_blk
+ */
+ class FILTER_API fractional_interpolator_ff : virtual public gr_block
+ {
+ public:
+ // gr::filter::fractional_interpolator_ff::sptr
+ typedef boost::shared_ptr<fractional_interpolator_ff> sptr;
+
+ /*!
+ * \brief Build the interpolating MMSE filter (float input, float output)
+ *
+ * \param phase_shift The phase shift of the output signal to the input
+ * \param interp_ratio The interpolation ratio = input_rate / output_rate.
+ */
+ static sptr make(float phase_shift,
+ float interp_ratio);
+
+ virtual float mu() const = 0;
+ virtual float interp_ratio() const = 0;
+ virtual void set_mu (float mu) = 0;
+ virtual void set_interp_ratio(float interp_ratio) = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FRACTIONAL_INTERPOLATOR_FF_H */
diff --git a/gr-filter/include/filter/freq_xlating_fir_filter_XXX.h.t b/gr-filter/include/filter/freq_xlating_fir_filter_XXX.h.t
new file mode 100644
index 000000000..88e15f823
--- /dev/null
+++ b/gr-filter/include/filter/freq_xlating_fir_filter_XXX.h.t
@@ -0,0 +1,90 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2004,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * WARNING: This file is automatically generated by cmake.
+ * Any changes made to this file will be overwritten.
+ */
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
+
+#include <filter/api.h>
+#include <gr_sync_decimator.h>
+#include <gr_rotator.h>
+
+namespace gr {
+ namespace filter {
+
+
+ /*!
+ * \brief FIR filter combined with frequency translation with
+ * @I_TYPE@ input, @O_TYPE@ output and @TAP_TYPE@ taps
+ *
+ * \ingroup filter_blk
+ *
+ * This class efficiently combines a frequency translation
+ * (typically "down conversion") with a FIR filter (typically
+ * low-pass) and decimation. It is ideally suited for a "channel
+ * selection filter" and can be efficiently used to select and
+ * decimate a narrow band signal out of wide bandwidth input.
+ *
+ * Uses a single input array to produce a single output array.
+ * Additional inputs and/or outputs are ignored.
+ */
+ class FILTER_API @BASE_NAME@ : virtual public gr_sync_decimator
+ {
+ public:
+ // gr::filter::@BASE_NAME@::sptr
+ typedef boost::shared_ptr<@BASE_NAME@> sptr;
+
+ /*!
+ * \brief FIR filter with @I_TYPE@ input, @O_TYPE@ output, and
+ * @TAP_TYPE@ taps that also frequency translates a signal from
+ * \p center_freq.
+ *
+ * Construct a FIR filter with the given taps and a composite
+ * frequency translation that shifts center_freq down to zero
+ * Hz. The frequency translation logically comes before the
+ * filtering operation.
+ *
+ * \param decimation set the integer decimation rate
+ * \param taps a vector/list of taps of type @TAP_TYPE@
+ * \param center_freq Center frequency of signal to down convert from (Hz)
+ * \param sampling_freq Sampling rate of signal (in Hz)
+ */
+ static sptr make(int decimation,
+ const std::vector<@TAP_TYPE@> &taps,
+ double center_freq,
+ double sampling_freq);
+
+ virtual void set_center_freq(double center_freq) = 0;
+ virtual double center_freq() const = 0;
+
+ virtual void set_taps(const std::vector<@TAP_TYPE@> &taps) = 0;
+ virtual std::vector<@TAP_TYPE@> taps() const = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* @GUARD_NAME@ */
diff --git a/gr-filter/include/filter/hilbert_fc.h b/gr-filter/include/filter/hilbert_fc.h
new file mode 100644
index 000000000..de7cd82b6
--- /dev/null
+++ b/gr-filter/include/filter/hilbert_fc.h
@@ -0,0 +1,53 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_HILBERT_FC_H
+#define INCLUDED_FILTER_HILBERT_FC_H
+
+#include <filter/api.h>
+#include <gr_sync_block.h>
+#include <gr_types.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API hilbert_fc : virtual public gr_sync_block
+ {
+ public:
+ // gr::filter::hilbert_fc::sptr
+ typedef boost::shared_ptr<hilbert_fc> sptr;
+
+ /*!
+ * \brief Hilbert transformer.
+ * \ingroup filter_blk
+ *
+ * real output is input appropriately delayed.
+ * imaginary output is hilbert filtered (90 degree phase shift)
+ * version of input.
+ */
+ static sptr make(unsigned int ntaps);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_HILBERT_FC_H */
diff --git a/gr-filter/include/filter/iir_filter.h b/gr-filter/include/filter/iir_filter.h
new file mode 100644
index 000000000..667acec35
--- /dev/null
+++ b/gr-filter/include/filter/iir_filter.h
@@ -0,0 +1,183 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_IIR_FILTER_H
+#define INCLUDED_IIR_FILTER_H
+
+#include <filter/api.h>
+#include <vector>
+#include <stdexcept>
+
+namespace gr {
+ namespace filter {
+ namespace kernel {
+
+ /*!
+ * \brief base class template for Infinite Impulse Response filter (IIR)
+ */
+ template<class i_type, class o_type, class tap_type>
+ class iir_filter
+ {
+ public:
+ /*!
+ * \brief Construct an IIR with the given taps.
+ *
+ * This filter uses the Direct Form I implementation, where
+ * \p fftaps contains the feed-forward taps, and \p fbtaps the feedback ones.
+ *
+ * \p fftaps and \p fbtaps must have equal numbers of taps
+ *
+ * The input and output satisfy a difference equation of the form
+
+ \f[
+ y[n] - \sum_{k=1}^{M} a_k y[n-k] = \sum_{k=0}^{N} b_k x[n-k]
+ \f]
+
+ * with the corresponding rational system function
+
+ \f[
+ H(z) = \frac{\sum_{k=0}^{N} b_k z^{-k}}{1 - \sum_{k=1}^{M} a_k z^{-k}}
+ \f]
+
+ * Note that some texts define the system function with a + in
+ * the denominator. If you're using that convention, you'll
+ * need to negate the feedback taps.
+ */
+ iir_filter(const std::vector<tap_type>& fftaps,
+ const std::vector<tap_type>& fbtaps) throw (std::invalid_argument)
+ {
+ set_taps(fftaps, fbtaps);
+ }
+
+ iir_filter() : d_latest_n(0),d_latest_m(0) { }
+
+ ~iir_filter() {}
+
+ /*!
+ * \brief compute a single output value.
+ * \returns the filtered input value.
+ */
+ o_type filter(const i_type input);
+
+ /*!
+ * \brief compute an array of N output values.
+ * \p input must have N valid entries.
+ */
+ void filter_n(o_type output[], const i_type input[], long n);
+
+ /*!
+ * \return number of taps in filter.
+ */
+ unsigned ntaps_ff() const { return d_fftaps.size(); }
+ unsigned ntaps_fb() const { return d_fbtaps.size(); }
+
+ /*!
+ * \brief install new taps.
+ */
+ void set_taps(const std::vector<tap_type> &fftaps,
+ const std::vector<tap_type> &fbtaps) throw (std::invalid_argument)
+ {
+ d_latest_n = 0;
+ d_latest_m = 0;
+ d_fftaps = fftaps;
+ d_fbtaps = fbtaps;
+
+ int n = fftaps.size();
+ int m = fbtaps.size();
+ d_prev_input.resize(2 * n);
+ d_prev_output.resize(2 * m);
+
+ for(int i = 0; i < 2 * n; i++) {
+ d_prev_input[i] = 0;
+ }
+ for(int i = 0; i < 2 * m; i++) {
+ d_prev_output[i] = 0;
+ }
+ }
+
+ protected:
+ std::vector<tap_type> d_fftaps;
+ std::vector<tap_type> d_fbtaps;
+ int d_latest_n;
+ int d_latest_m;
+ std::vector<tap_type> d_prev_output;
+ std::vector<i_type> d_prev_input;
+ };
+
+ //
+ // general case. We may want to specialize this
+ //
+ template<class i_type, class o_type, class tap_type>
+ o_type
+ iir_filter<i_type, o_type, tap_type>::filter(const i_type input)
+ {
+ tap_type acc;
+ unsigned i = 0;
+ unsigned n = ntaps_ff();
+ unsigned m = ntaps_fb();
+
+ if(n == 0)
+ return (o_type)0;
+
+ int latest_n = d_latest_n;
+ int latest_m = d_latest_m;
+
+ acc = d_fftaps[0] * input;
+ for(i = 1; i < n; i ++)
+ acc += (d_fftaps[i] * d_prev_input[latest_n + i]);
+ for(i = 1; i < m; i ++)
+ acc += (d_fbtaps[i] * d_prev_output[latest_m + i]);
+
+ // store the values twice to avoid having to handle wrap-around in the loop
+ d_prev_output[latest_m] = acc;
+ d_prev_output[latest_m+m] = acc;
+ d_prev_input[latest_n] = input;
+ d_prev_input[latest_n+n] = input;
+
+ latest_n--;
+ latest_m--;
+ if(latest_n < 0)
+ latest_n += n;
+ if(latest_m < 0)
+ latest_m += m;
+
+ d_latest_m = latest_m;
+ d_latest_n = latest_n;
+ return (o_type)acc;
+ }
+
+ template<class i_type, class o_type, class tap_type>
+ void
+ iir_filter<i_type, o_type, tap_type>::filter_n(o_type output[],
+ const i_type input[],
+ long n)
+ {
+ for(int i = 0; i < n; i++)
+ output[i] = filter(input[i]);
+ }
+
+ } /* namespace kernel */
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_IIR_FILTER_H */
+
diff --git a/gr-filter/include/filter/iir_filter_ffd.h b/gr-filter/include/filter/iir_filter_ffd.h
new file mode 100644
index 000000000..04dd1e776
--- /dev/null
+++ b/gr-filter/include/filter/iir_filter_ffd.h
@@ -0,0 +1,82 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_IIR_FILTER_FFD_H
+#define INCLUDED_IIR_FILTER_FFD_H
+
+#include <filter/api.h>
+#include <gr_sync_block.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief IIR filter with float input, float output and double taps
+ * \ingroup filter_blk
+ *
+ * This filter uses the Direct Form I implementation, where
+ * \p fftaps contains the feed-forward taps, and \p fbtaps the feedback ones.
+ *
+ *
+ * The input and output satisfy a difference equation of the form
+ \htmlonly
+ \f{
+ y[n] - \sum_{k=1}^{M} a_k y[n-k] = \sum_{k=0}^{N} b_k x[n-k]
+ \f}
+ \endhtmlonly
+
+ \xmlonly
+ y[n] - \sum_{k=1}^{M} a_k y[n-k] = \sum_{k=0}^{N} b_k x[n-k]
+ \endxmlonly
+
+ * with the corresponding rational system function
+ \htmlonly
+ \f{
+ H(z) = \ frac{\sum_{k=0}^{M} b_k z^{-k}}{1 - \sum_{k=1}^{N} a_k z^{-k}}
+ \f}
+ \endhtmlonly
+
+ \xmlonly
+ H(z) = \ frac{\sum_{k=0}^{M} b_k z^{-k}}{1 - \sum_{k=1}^{N} a_k z^{-k}}
+ \endxmlonly
+
+ * Note that some texts define the system function with a + in the
+ * denominator. If you're using that convention, you'll need to
+ * negate the feedback taps.
+ */
+ class FILTER_API iir_filter_ffd : virtual public gr_sync_block
+ {
+ public:
+ // gr::filter::iir_filter_ffd::sptr
+ typedef boost::shared_ptr<iir_filter_ffd> sptr;
+
+ static sptr make(const std::vector<double> &fftaps,
+ const std::vector<double> &fbtaps);
+
+ virtual void set_taps(const std::vector<double> &fftaps,
+ const std::vector<double> &fbtaps) = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_IIR_FILTER_FFD_H */
diff --git a/gr-filter/include/filter/interp_fir_filter_XXX.h.t b/gr-filter/include/filter/interp_fir_filter_XXX.h.t
new file mode 100644
index 000000000..b66c9f643
--- /dev/null
+++ b/gr-filter/include/filter/interp_fir_filter_XXX.h.t
@@ -0,0 +1,81 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* @WARNING@ */
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
+
+#include <filter/api.h>
+#include <gr_sync_interpolator.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief Interpolating FIR filter with @I_TYPE@ input, @O_TYPE@ output and @TAP_TYPE@ taps
+ * \ingroup filter_blk
+ *
+ * The fir_filter_XXX blocks create finite impulse response
+ * (FIR) filters that perform the convolution in the time
+ * domain:
+ *
+ * \code
+ * out = 0
+ * for i in ntaps:
+ * out += input[n-i] * taps[i]
+ * \endcode
+ *
+ * The taps are a C++ vector (or Python list) of values of the
+ * type specified by the third letter in the block's suffix. For
+ * this block, the value is of type @TAP_TYPE@. Taps can be
+ * created using the firdes or optfir tools.
+ *
+ * These versions of the filter can also act as up-samplers
+ * (or interpolators) by specifying an integer value for \p
+ * interpolation.
+ *
+ */
+ class FILTER_API @BASE_NAME@ : virtual public gr_sync_interpolator
+ {
+ public:
+ // gr::filter::@BASE_NAME@::sptr
+ typedef boost::shared_ptr<@BASE_NAME@> sptr;
+
+ /*!
+ * \brief Interpolating FIR filter with @I_TYPE@ input, @O_TYPE@ output, and @TAP_TYPE@ taps
+ * \ingroup filter_blk
+ *
+ * \param interpolation set the integer interpolation rate
+ * \param taps a vector/list of taps of type @TAP_TYPE@
+ */
+ static sptr make(unsigned interpolation,
+ const std::vector<@TAP_TYPE@> &taps);
+
+ virtual void set_taps(const std::vector<@TAP_TYPE@> &taps) = 0;
+ virtual std::vector<@TAP_TYPE@> taps() const = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* @GUARD_NAME@ */
diff --git a/gr-filter/include/filter/interpolator_taps.h b/gr-filter/include/filter/interpolator_taps.h
new file mode 100644
index 000000000..a232edd38
--- /dev/null
+++ b/gr-filter/include/filter/interpolator_taps.h
@@ -0,0 +1,140 @@
+/*
+ * This file was machine generated by gen_interpolator_taps.
+ * DO NOT EDIT BY HAND.
+ */
+
+static const int NTAPS = 8;
+static const int NSTEPS = 128;
+
+static const float taps[NSTEPS+1][NTAPS] = {
+ // -4 -3 -2 -1 0 1 2 3 mu
+ { 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00 }, // 0/128
+ { -1.54700e-04, 8.53777e-04, -2.76968e-03, 7.89295e-03, 9.98534e-01, -5.41054e-03, 1.24642e-03, -1.98993e-04 }, // 1/128
+ { -3.09412e-04, 1.70888e-03, -5.55134e-03, 1.58840e-02, 9.96891e-01, -1.07209e-02, 2.47942e-03, -3.96391e-04 }, // 2/128
+ { -4.64053e-04, 2.56486e-03, -8.34364e-03, 2.39714e-02, 9.95074e-01, -1.59305e-02, 3.69852e-03, -5.92100e-04 }, // 3/128
+ { -6.18544e-04, 3.42130e-03, -1.11453e-02, 3.21531e-02, 9.93082e-01, -2.10389e-02, 4.90322e-03, -7.86031e-04 }, // 4/128
+ { -7.72802e-04, 4.27773e-03, -1.39548e-02, 4.04274e-02, 9.90917e-01, -2.60456e-02, 6.09305e-03, -9.78093e-04 }, // 5/128
+ { -9.26747e-04, 5.13372e-03, -1.67710e-02, 4.87921e-02, 9.88580e-01, -3.09503e-02, 7.26755e-03, -1.16820e-03 }, // 6/128
+ { -1.08030e-03, 5.98883e-03, -1.95925e-02, 5.72454e-02, 9.86071e-01, -3.57525e-02, 8.42626e-03, -1.35627e-03 }, // 7/128
+ { -1.23337e-03, 6.84261e-03, -2.24178e-02, 6.57852e-02, 9.83392e-01, -4.04519e-02, 9.56876e-03, -1.54221e-03 }, // 8/128
+ { -1.38589e-03, 7.69462e-03, -2.52457e-02, 7.44095e-02, 9.80543e-01, -4.50483e-02, 1.06946e-02, -1.72594e-03 }, // 9/128
+ { -1.53777e-03, 8.54441e-03, -2.80746e-02, 8.31162e-02, 9.77526e-01, -4.95412e-02, 1.18034e-02, -1.90738e-03 }, // 10/128
+ { -1.68894e-03, 9.39154e-03, -3.09033e-02, 9.19033e-02, 9.74342e-01, -5.39305e-02, 1.28947e-02, -2.08645e-03 }, // 11/128
+ { -1.83931e-03, 1.02356e-02, -3.37303e-02, 1.00769e-01, 9.70992e-01, -5.82159e-02, 1.39681e-02, -2.26307e-03 }, // 12/128
+ { -1.98880e-03, 1.10760e-02, -3.65541e-02, 1.09710e-01, 9.67477e-01, -6.23972e-02, 1.50233e-02, -2.43718e-03 }, // 13/128
+ { -2.13733e-03, 1.19125e-02, -3.93735e-02, 1.18725e-01, 9.63798e-01, -6.64743e-02, 1.60599e-02, -2.60868e-03 }, // 14/128
+ { -2.28483e-03, 1.27445e-02, -4.21869e-02, 1.27812e-01, 9.59958e-01, -7.04471e-02, 1.70776e-02, -2.77751e-03 }, // 15/128
+ { -2.43121e-03, 1.35716e-02, -4.49929e-02, 1.36968e-01, 9.55956e-01, -7.43154e-02, 1.80759e-02, -2.94361e-03 }, // 16/128
+ { -2.57640e-03, 1.43934e-02, -4.77900e-02, 1.46192e-01, 9.51795e-01, -7.80792e-02, 1.90545e-02, -3.10689e-03 }, // 17/128
+ { -2.72032e-03, 1.52095e-02, -5.05770e-02, 1.55480e-01, 9.47477e-01, -8.17385e-02, 2.00132e-02, -3.26730e-03 }, // 18/128
+ { -2.86289e-03, 1.60193e-02, -5.33522e-02, 1.64831e-01, 9.43001e-01, -8.52933e-02, 2.09516e-02, -3.42477e-03 }, // 19/128
+ { -3.00403e-03, 1.68225e-02, -5.61142e-02, 1.74242e-01, 9.38371e-01, -8.87435e-02, 2.18695e-02, -3.57923e-03 }, // 20/128
+ { -3.14367e-03, 1.76185e-02, -5.88617e-02, 1.83711e-01, 9.33586e-01, -9.20893e-02, 2.27664e-02, -3.73062e-03 }, // 21/128
+ { -3.28174e-03, 1.84071e-02, -6.15931e-02, 1.93236e-01, 9.28650e-01, -9.53307e-02, 2.36423e-02, -3.87888e-03 }, // 22/128
+ { -3.41815e-03, 1.91877e-02, -6.43069e-02, 2.02814e-01, 9.23564e-01, -9.84679e-02, 2.44967e-02, -4.02397e-03 }, // 23/128
+ { -3.55283e-03, 1.99599e-02, -6.70018e-02, 2.12443e-01, 9.18329e-01, -1.01501e-01, 2.53295e-02, -4.16581e-03 }, // 24/128
+ { -3.68570e-03, 2.07233e-02, -6.96762e-02, 2.22120e-01, 9.12947e-01, -1.04430e-01, 2.61404e-02, -4.30435e-03 }, // 25/128
+ { -3.81671e-03, 2.14774e-02, -7.23286e-02, 2.31843e-01, 9.07420e-01, -1.07256e-01, 2.69293e-02, -4.43955e-03 }, // 26/128
+ { -3.94576e-03, 2.22218e-02, -7.49577e-02, 2.41609e-01, 9.01749e-01, -1.09978e-01, 2.76957e-02, -4.57135e-03 }, // 27/128
+ { -4.07279e-03, 2.29562e-02, -7.75620e-02, 2.51417e-01, 8.95936e-01, -1.12597e-01, 2.84397e-02, -4.69970e-03 }, // 28/128
+ { -4.19774e-03, 2.36801e-02, -8.01399e-02, 2.61263e-01, 8.89984e-01, -1.15113e-01, 2.91609e-02, -4.82456e-03 }, // 29/128
+ { -4.32052e-03, 2.43930e-02, -8.26900e-02, 2.71144e-01, 8.83893e-01, -1.17526e-01, 2.98593e-02, -4.94589e-03 }, // 30/128
+ { -4.44107e-03, 2.50946e-02, -8.52109e-02, 2.81060e-01, 8.77666e-01, -1.19837e-01, 3.05345e-02, -5.06363e-03 }, // 31/128
+ { -4.55932e-03, 2.57844e-02, -8.77011e-02, 2.91006e-01, 8.71305e-01, -1.22047e-01, 3.11866e-02, -5.17776e-03 }, // 32/128
+ { -4.67520e-03, 2.64621e-02, -9.01591e-02, 3.00980e-01, 8.64812e-01, -1.24154e-01, 3.18153e-02, -5.28823e-03 }, // 33/128
+ { -4.78866e-03, 2.71272e-02, -9.25834e-02, 3.10980e-01, 8.58189e-01, -1.26161e-01, 3.24205e-02, -5.39500e-03 }, // 34/128
+ { -4.89961e-03, 2.77794e-02, -9.49727e-02, 3.21004e-01, 8.51437e-01, -1.28068e-01, 3.30021e-02, -5.49804e-03 }, // 35/128
+ { -5.00800e-03, 2.84182e-02, -9.73254e-02, 3.31048e-01, 8.44559e-01, -1.29874e-01, 3.35600e-02, -5.59731e-03 }, // 36/128
+ { -5.11376e-03, 2.90433e-02, -9.96402e-02, 3.41109e-01, 8.37557e-01, -1.31581e-01, 3.40940e-02, -5.69280e-03 }, // 37/128
+ { -5.21683e-03, 2.96543e-02, -1.01915e-01, 3.51186e-01, 8.30432e-01, -1.33189e-01, 3.46042e-02, -5.78446e-03 }, // 38/128
+ { -5.31716e-03, 3.02507e-02, -1.04150e-01, 3.61276e-01, 8.23188e-01, -1.34699e-01, 3.50903e-02, -5.87227e-03 }, // 39/128
+ { -5.41467e-03, 3.08323e-02, -1.06342e-01, 3.71376e-01, 8.15826e-01, -1.36111e-01, 3.55525e-02, -5.95620e-03 }, // 40/128
+ { -5.50931e-03, 3.13987e-02, -1.08490e-01, 3.81484e-01, 8.08348e-01, -1.37426e-01, 3.59905e-02, -6.03624e-03 }, // 41/128
+ { -5.60103e-03, 3.19495e-02, -1.10593e-01, 3.91596e-01, 8.00757e-01, -1.38644e-01, 3.64044e-02, -6.11236e-03 }, // 42/128
+ { -5.68976e-03, 3.24843e-02, -1.12650e-01, 4.01710e-01, 7.93055e-01, -1.39767e-01, 3.67941e-02, -6.18454e-03 }, // 43/128
+ { -5.77544e-03, 3.30027e-02, -1.14659e-01, 4.11823e-01, 7.85244e-01, -1.40794e-01, 3.71596e-02, -6.25277e-03 }, // 44/128
+ { -5.85804e-03, 3.35046e-02, -1.16618e-01, 4.21934e-01, 7.77327e-01, -1.41727e-01, 3.75010e-02, -6.31703e-03 }, // 45/128
+ { -5.93749e-03, 3.39894e-02, -1.18526e-01, 4.32038e-01, 7.69305e-01, -1.42566e-01, 3.78182e-02, -6.37730e-03 }, // 46/128
+ { -6.01374e-03, 3.44568e-02, -1.20382e-01, 4.42134e-01, 7.61181e-01, -1.43313e-01, 3.81111e-02, -6.43358e-03 }, // 47/128
+ { -6.08674e-03, 3.49066e-02, -1.22185e-01, 4.52218e-01, 7.52958e-01, -1.43968e-01, 3.83800e-02, -6.48585e-03 }, // 48/128
+ { -6.15644e-03, 3.53384e-02, -1.23933e-01, 4.62289e-01, 7.44637e-01, -1.44531e-01, 3.86247e-02, -6.53412e-03 }, // 49/128
+ { -6.22280e-03, 3.57519e-02, -1.25624e-01, 4.72342e-01, 7.36222e-01, -1.45004e-01, 3.88454e-02, -6.57836e-03 }, // 50/128
+ { -6.28577e-03, 3.61468e-02, -1.27258e-01, 4.82377e-01, 7.27714e-01, -1.45387e-01, 3.90420e-02, -6.61859e-03 }, // 51/128
+ { -6.34530e-03, 3.65227e-02, -1.28832e-01, 4.92389e-01, 7.19116e-01, -1.45682e-01, 3.92147e-02, -6.65479e-03 }, // 52/128
+ { -6.40135e-03, 3.68795e-02, -1.30347e-01, 5.02377e-01, 7.10431e-01, -1.45889e-01, 3.93636e-02, -6.68698e-03 }, // 53/128
+ { -6.45388e-03, 3.72167e-02, -1.31800e-01, 5.12337e-01, 7.01661e-01, -1.46009e-01, 3.94886e-02, -6.71514e-03 }, // 54/128
+ { -6.50285e-03, 3.75341e-02, -1.33190e-01, 5.22267e-01, 6.92808e-01, -1.46043e-01, 3.95900e-02, -6.73929e-03 }, // 55/128
+ { -6.54823e-03, 3.78315e-02, -1.34515e-01, 5.32164e-01, 6.83875e-01, -1.45993e-01, 3.96678e-02, -6.75943e-03 }, // 56/128
+ { -6.58996e-03, 3.81085e-02, -1.35775e-01, 5.42025e-01, 6.74865e-01, -1.45859e-01, 3.97222e-02, -6.77557e-03 }, // 57/128
+ { -6.62802e-03, 3.83650e-02, -1.36969e-01, 5.51849e-01, 6.65779e-01, -1.45641e-01, 3.97532e-02, -6.78771e-03 }, // 58/128
+ { -6.66238e-03, 3.86006e-02, -1.38094e-01, 5.61631e-01, 6.56621e-01, -1.45343e-01, 3.97610e-02, -6.79588e-03 }, // 59/128
+ { -6.69300e-03, 3.88151e-02, -1.39150e-01, 5.71370e-01, 6.47394e-01, -1.44963e-01, 3.97458e-02, -6.80007e-03 }, // 60/128
+ { -6.71985e-03, 3.90083e-02, -1.40136e-01, 5.81063e-01, 6.38099e-01, -1.44503e-01, 3.97077e-02, -6.80032e-03 }, // 61/128
+ { -6.74291e-03, 3.91800e-02, -1.41050e-01, 5.90706e-01, 6.28739e-01, -1.43965e-01, 3.96469e-02, -6.79662e-03 }, // 62/128
+ { -6.76214e-03, 3.93299e-02, -1.41891e-01, 6.00298e-01, 6.19318e-01, -1.43350e-01, 3.95635e-02, -6.78902e-03 }, // 63/128
+ { -6.77751e-03, 3.94578e-02, -1.42658e-01, 6.09836e-01, 6.09836e-01, -1.42658e-01, 3.94578e-02, -6.77751e-03 }, // 64/128
+ { -6.78902e-03, 3.95635e-02, -1.43350e-01, 6.19318e-01, 6.00298e-01, -1.41891e-01, 3.93299e-02, -6.76214e-03 }, // 65/128
+ { -6.79662e-03, 3.96469e-02, -1.43965e-01, 6.28739e-01, 5.90706e-01, -1.41050e-01, 3.91800e-02, -6.74291e-03 }, // 66/128
+ { -6.80032e-03, 3.97077e-02, -1.44503e-01, 6.38099e-01, 5.81063e-01, -1.40136e-01, 3.90083e-02, -6.71985e-03 }, // 67/128
+ { -6.80007e-03, 3.97458e-02, -1.44963e-01, 6.47394e-01, 5.71370e-01, -1.39150e-01, 3.88151e-02, -6.69300e-03 }, // 68/128
+ { -6.79588e-03, 3.97610e-02, -1.45343e-01, 6.56621e-01, 5.61631e-01, -1.38094e-01, 3.86006e-02, -6.66238e-03 }, // 69/128
+ { -6.78771e-03, 3.97532e-02, -1.45641e-01, 6.65779e-01, 5.51849e-01, -1.36969e-01, 3.83650e-02, -6.62802e-03 }, // 70/128
+ { -6.77557e-03, 3.97222e-02, -1.45859e-01, 6.74865e-01, 5.42025e-01, -1.35775e-01, 3.81085e-02, -6.58996e-03 }, // 71/128
+ { -6.75943e-03, 3.96678e-02, -1.45993e-01, 6.83875e-01, 5.32164e-01, -1.34515e-01, 3.78315e-02, -6.54823e-03 }, // 72/128
+ { -6.73929e-03, 3.95900e-02, -1.46043e-01, 6.92808e-01, 5.22267e-01, -1.33190e-01, 3.75341e-02, -6.50285e-03 }, // 73/128
+ { -6.71514e-03, 3.94886e-02, -1.46009e-01, 7.01661e-01, 5.12337e-01, -1.31800e-01, 3.72167e-02, -6.45388e-03 }, // 74/128
+ { -6.68698e-03, 3.93636e-02, -1.45889e-01, 7.10431e-01, 5.02377e-01, -1.30347e-01, 3.68795e-02, -6.40135e-03 }, // 75/128
+ { -6.65479e-03, 3.92147e-02, -1.45682e-01, 7.19116e-01, 4.92389e-01, -1.28832e-01, 3.65227e-02, -6.34530e-03 }, // 76/128
+ { -6.61859e-03, 3.90420e-02, -1.45387e-01, 7.27714e-01, 4.82377e-01, -1.27258e-01, 3.61468e-02, -6.28577e-03 }, // 77/128
+ { -6.57836e-03, 3.88454e-02, -1.45004e-01, 7.36222e-01, 4.72342e-01, -1.25624e-01, 3.57519e-02, -6.22280e-03 }, // 78/128
+ { -6.53412e-03, 3.86247e-02, -1.44531e-01, 7.44637e-01, 4.62289e-01, -1.23933e-01, 3.53384e-02, -6.15644e-03 }, // 79/128
+ { -6.48585e-03, 3.83800e-02, -1.43968e-01, 7.52958e-01, 4.52218e-01, -1.22185e-01, 3.49066e-02, -6.08674e-03 }, // 80/128
+ { -6.43358e-03, 3.81111e-02, -1.43313e-01, 7.61181e-01, 4.42134e-01, -1.20382e-01, 3.44568e-02, -6.01374e-03 }, // 81/128
+ { -6.37730e-03, 3.78182e-02, -1.42566e-01, 7.69305e-01, 4.32038e-01, -1.18526e-01, 3.39894e-02, -5.93749e-03 }, // 82/128
+ { -6.31703e-03, 3.75010e-02, -1.41727e-01, 7.77327e-01, 4.21934e-01, -1.16618e-01, 3.35046e-02, -5.85804e-03 }, // 83/128
+ { -6.25277e-03, 3.71596e-02, -1.40794e-01, 7.85244e-01, 4.11823e-01, -1.14659e-01, 3.30027e-02, -5.77544e-03 }, // 84/128
+ { -6.18454e-03, 3.67941e-02, -1.39767e-01, 7.93055e-01, 4.01710e-01, -1.12650e-01, 3.24843e-02, -5.68976e-03 }, // 85/128
+ { -6.11236e-03, 3.64044e-02, -1.38644e-01, 8.00757e-01, 3.91596e-01, -1.10593e-01, 3.19495e-02, -5.60103e-03 }, // 86/128
+ { -6.03624e-03, 3.59905e-02, -1.37426e-01, 8.08348e-01, 3.81484e-01, -1.08490e-01, 3.13987e-02, -5.50931e-03 }, // 87/128
+ { -5.95620e-03, 3.55525e-02, -1.36111e-01, 8.15826e-01, 3.71376e-01, -1.06342e-01, 3.08323e-02, -5.41467e-03 }, // 88/128
+ { -5.87227e-03, 3.50903e-02, -1.34699e-01, 8.23188e-01, 3.61276e-01, -1.04150e-01, 3.02507e-02, -5.31716e-03 }, // 89/128
+ { -5.78446e-03, 3.46042e-02, -1.33189e-01, 8.30432e-01, 3.51186e-01, -1.01915e-01, 2.96543e-02, -5.21683e-03 }, // 90/128
+ { -5.69280e-03, 3.40940e-02, -1.31581e-01, 8.37557e-01, 3.41109e-01, -9.96402e-02, 2.90433e-02, -5.11376e-03 }, // 91/128
+ { -5.59731e-03, 3.35600e-02, -1.29874e-01, 8.44559e-01, 3.31048e-01, -9.73254e-02, 2.84182e-02, -5.00800e-03 }, // 92/128
+ { -5.49804e-03, 3.30021e-02, -1.28068e-01, 8.51437e-01, 3.21004e-01, -9.49727e-02, 2.77794e-02, -4.89961e-03 }, // 93/128
+ { -5.39500e-03, 3.24205e-02, -1.26161e-01, 8.58189e-01, 3.10980e-01, -9.25834e-02, 2.71272e-02, -4.78866e-03 }, // 94/128
+ { -5.28823e-03, 3.18153e-02, -1.24154e-01, 8.64812e-01, 3.00980e-01, -9.01591e-02, 2.64621e-02, -4.67520e-03 }, // 95/128
+ { -5.17776e-03, 3.11866e-02, -1.22047e-01, 8.71305e-01, 2.91006e-01, -8.77011e-02, 2.57844e-02, -4.55932e-03 }, // 96/128
+ { -5.06363e-03, 3.05345e-02, -1.19837e-01, 8.77666e-01, 2.81060e-01, -8.52109e-02, 2.50946e-02, -4.44107e-03 }, // 97/128
+ { -4.94589e-03, 2.98593e-02, -1.17526e-01, 8.83893e-01, 2.71144e-01, -8.26900e-02, 2.43930e-02, -4.32052e-03 }, // 98/128
+ { -4.82456e-03, 2.91609e-02, -1.15113e-01, 8.89984e-01, 2.61263e-01, -8.01399e-02, 2.36801e-02, -4.19774e-03 }, // 99/128
+ { -4.69970e-03, 2.84397e-02, -1.12597e-01, 8.95936e-01, 2.51417e-01, -7.75620e-02, 2.29562e-02, -4.07279e-03 }, // 100/128
+ { -4.57135e-03, 2.76957e-02, -1.09978e-01, 9.01749e-01, 2.41609e-01, -7.49577e-02, 2.22218e-02, -3.94576e-03 }, // 101/128
+ { -4.43955e-03, 2.69293e-02, -1.07256e-01, 9.07420e-01, 2.31843e-01, -7.23286e-02, 2.14774e-02, -3.81671e-03 }, // 102/128
+ { -4.30435e-03, 2.61404e-02, -1.04430e-01, 9.12947e-01, 2.22120e-01, -6.96762e-02, 2.07233e-02, -3.68570e-03 }, // 103/128
+ { -4.16581e-03, 2.53295e-02, -1.01501e-01, 9.18329e-01, 2.12443e-01, -6.70018e-02, 1.99599e-02, -3.55283e-03 }, // 104/128
+ { -4.02397e-03, 2.44967e-02, -9.84679e-02, 9.23564e-01, 2.02814e-01, -6.43069e-02, 1.91877e-02, -3.41815e-03 }, // 105/128
+ { -3.87888e-03, 2.36423e-02, -9.53307e-02, 9.28650e-01, 1.93236e-01, -6.15931e-02, 1.84071e-02, -3.28174e-03 }, // 106/128
+ { -3.73062e-03, 2.27664e-02, -9.20893e-02, 9.33586e-01, 1.83711e-01, -5.88617e-02, 1.76185e-02, -3.14367e-03 }, // 107/128
+ { -3.57923e-03, 2.18695e-02, -8.87435e-02, 9.38371e-01, 1.74242e-01, -5.61142e-02, 1.68225e-02, -3.00403e-03 }, // 108/128
+ { -3.42477e-03, 2.09516e-02, -8.52933e-02, 9.43001e-01, 1.64831e-01, -5.33522e-02, 1.60193e-02, -2.86289e-03 }, // 109/128
+ { -3.26730e-03, 2.00132e-02, -8.17385e-02, 9.47477e-01, 1.55480e-01, -5.05770e-02, 1.52095e-02, -2.72032e-03 }, // 110/128
+ { -3.10689e-03, 1.90545e-02, -7.80792e-02, 9.51795e-01, 1.46192e-01, -4.77900e-02, 1.43934e-02, -2.57640e-03 }, // 111/128
+ { -2.94361e-03, 1.80759e-02, -7.43154e-02, 9.55956e-01, 1.36968e-01, -4.49929e-02, 1.35716e-02, -2.43121e-03 }, // 112/128
+ { -2.77751e-03, 1.70776e-02, -7.04471e-02, 9.59958e-01, 1.27812e-01, -4.21869e-02, 1.27445e-02, -2.28483e-03 }, // 113/128
+ { -2.60868e-03, 1.60599e-02, -6.64743e-02, 9.63798e-01, 1.18725e-01, -3.93735e-02, 1.19125e-02, -2.13733e-03 }, // 114/128
+ { -2.43718e-03, 1.50233e-02, -6.23972e-02, 9.67477e-01, 1.09710e-01, -3.65541e-02, 1.10760e-02, -1.98880e-03 }, // 115/128
+ { -2.26307e-03, 1.39681e-02, -5.82159e-02, 9.70992e-01, 1.00769e-01, -3.37303e-02, 1.02356e-02, -1.83931e-03 }, // 116/128
+ { -2.08645e-03, 1.28947e-02, -5.39305e-02, 9.74342e-01, 9.19033e-02, -3.09033e-02, 9.39154e-03, -1.68894e-03 }, // 117/128
+ { -1.90738e-03, 1.18034e-02, -4.95412e-02, 9.77526e-01, 8.31162e-02, -2.80746e-02, 8.54441e-03, -1.53777e-03 }, // 118/128
+ { -1.72594e-03, 1.06946e-02, -4.50483e-02, 9.80543e-01, 7.44095e-02, -2.52457e-02, 7.69462e-03, -1.38589e-03 }, // 119/128
+ { -1.54221e-03, 9.56876e-03, -4.04519e-02, 9.83392e-01, 6.57852e-02, -2.24178e-02, 6.84261e-03, -1.23337e-03 }, // 120/128
+ { -1.35627e-03, 8.42626e-03, -3.57525e-02, 9.86071e-01, 5.72454e-02, -1.95925e-02, 5.98883e-03, -1.08030e-03 }, // 121/128
+ { -1.16820e-03, 7.26755e-03, -3.09503e-02, 9.88580e-01, 4.87921e-02, -1.67710e-02, 5.13372e-03, -9.26747e-04 }, // 122/128
+ { -9.78093e-04, 6.09305e-03, -2.60456e-02, 9.90917e-01, 4.04274e-02, -1.39548e-02, 4.27773e-03, -7.72802e-04 }, // 123/128
+ { -7.86031e-04, 4.90322e-03, -2.10389e-02, 9.93082e-01, 3.21531e-02, -1.11453e-02, 3.42130e-03, -6.18544e-04 }, // 124/128
+ { -5.92100e-04, 3.69852e-03, -1.59305e-02, 9.95074e-01, 2.39714e-02, -8.34364e-03, 2.56486e-03, -4.64053e-04 }, // 125/128
+ { -3.96391e-04, 2.47942e-03, -1.07209e-02, 9.96891e-01, 1.58840e-02, -5.55134e-03, 1.70888e-03, -3.09412e-04 }, // 126/128
+ { -1.98993e-04, 1.24642e-03, -5.41054e-03, 9.98534e-01, 7.89295e-03, -2.76968e-03, 8.53777e-04, -1.54700e-04 }, // 127/128
+ { 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00 }, // 128/128
+};
diff --git a/gr-filter/include/filter/mmse_fir_interpolator_cc.h b/gr-filter/include/filter/mmse_fir_interpolator_cc.h
new file mode 100644
index 000000000..0436b4a0f
--- /dev/null
+++ b/gr-filter/include/filter/mmse_fir_interpolator_cc.h
@@ -0,0 +1,79 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2007,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef _GRI_MMSE_FIR_INTERPOLATOR_CC_H_
+#define _GRI_MMSE_FIR_INTERPOLATOR_CC_H_
+
+#include <filter/api.h>
+#include <filter/fir_filter.h>
+#include <gr_complex.h>
+#include <vector>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief Compute intermediate samples between signal samples x(k*Ts)
+ * \ingroup filter_primitive
+ *
+ * This implements a Mininum Mean Squared Error interpolator with
+ * 8 taps. It is suitable for signals where the bandwidth of
+ * interest B = 1/(4*Ts) Where Ts is the time between samples.
+ *
+ * Although mu, the fractional delay, is specified as a float, it
+ * is actually quantized. 0.0 <= mu <= 1.0. That is, mu is
+ * quantized in the interpolate method to 32nd's of a sample.
+ *
+ * For more information, in the GNU Radio source code, see:
+ * \li gnuradio-core/src/gen_interpolator_taps/README
+ * \li gnuradio-core/src/gen_interpolator_taps/praxis.txt
+ */
+
+ class FILTER_API mmse_fir_interpolator_cc
+ {
+ public:
+ mmse_fir_interpolator_cc();
+ ~mmse_fir_interpolator_cc();
+
+ unsigned ntaps() const;
+ unsigned nsteps() const;
+
+ /*!
+ * \brief compute a single interpolated output value.
+ *
+ * \p input must have ntaps() valid entries and be 8-byte aligned.
+ * input[0] .. input[ntaps() - 1] are referenced to compute the output value.
+ * \throws std::invalid_argument if input is not 8-byte aligned.
+ *
+ * \p mu must be in the range [0, 1] and specifies the fractional delay.
+ *
+ * \returns the interpolated input value.
+ */
+ gr_complex interpolate(const gr_complex input[], float mu) const;
+
+ protected:
+ std::vector<kernel::fir_filter_ccf *> filters;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* _MMSE_FIR_INTERPOLATOR_CC_H_ */
diff --git a/gr-filter/include/filter/mmse_fir_interpolator_ff.h b/gr-filter/include/filter/mmse_fir_interpolator_ff.h
new file mode 100644
index 000000000..4353aa94f
--- /dev/null
+++ b/gr-filter/include/filter/mmse_fir_interpolator_ff.h
@@ -0,0 +1,76 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _MMSE_FIR_INTERPOLATOR_FF_H_
+#define _MMSE_FIR_INTERPOLATOR_FF_H_
+
+#include <filter/api.h>
+#include <filter/fir_filter.h>
+#include <vector>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief Compute intermediate samples between signal samples x(k*Ts)
+ * \ingroup filter_primitive
+ *
+ * This implements a Mininum Mean Squared Error interpolator with
+ * 8 taps. It is suitable for signals where the bandwidth of
+ * interest B = 1/(4*Ts) Where Ts is the time between samples.
+ *
+ * Although mu, the fractional delay, is specified as a float, it
+ * is actually quantized. 0.0 <= mu <= 1.0. That is, mu is
+ * quantized in the interpolate method to 32nd's of a sample.
+ *
+ * For more information, in the GNU Radio source code, see:
+ * \li gnuradio-core/src/gen_interpolator_taps/README
+ * \li gnuradio-core/src/gen_interpolator_taps/praxis.txt
+ */
+ class FILTER_API mmse_fir_interpolator_ff
+ {
+ public:
+ mmse_fir_interpolator_ff();
+ ~mmse_fir_interpolator_ff();
+
+ unsigned ntaps() const;
+ unsigned nsteps() const;
+
+ /*!
+ * \brief compute a single interpolated output value.
+ * \p input must have ntaps() valid entries.
+ * input[0] .. input[ntaps() - 1] are referenced to compute the output value.
+ *
+ * \p mu must be in the range [0, 1] and specifies the fractional delay.
+ *
+ * \returns the interpolated input value.
+ */
+ float interpolate(const float input[], float mu) const;
+
+ protected:
+ std::vector<kernel::fir_filter_fff*> filters;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* _MMSE_FIR_INTERPOLATOR_FF_H_ */
diff --git a/gr-filter/include/filter/pfb_arb_resampler_ccf.h b/gr-filter/include/filter/pfb_arb_resampler_ccf.h
new file mode 100644
index 000000000..a154e055a
--- /dev/null
+++ b/gr-filter/include/filter/pfb_arb_resampler_ccf.h
@@ -0,0 +1,151 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_PFB_ARB_RESAMPLER_CCF_H
+#define INCLUDED_PFB_ARB_RESAMPLER_CCF_H
+
+#include <filter/api.h>
+#include <gr_block.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \class pfb_arb_resampler_ccf
+ *
+ * \brief Polyphase filterbank arbitrary resampler with
+ * gr_complex input, gr_complex output and float taps
+ *
+ * \ingroup filter_blk
+ * \ingroup pfb_blk
+ *
+ * This block takes in a signal stream and performs arbitrary
+ * resampling. The resampling rate can be any real number
+ * <EM>r</EM>. The resampling is done by constructing <EM>N</EM>
+ * filters where <EM>N</EM> is the interpolation rate. We then
+ * calculate <EM>D</EM> where <EM>D = floor(N/r)</EM>.
+ *
+ * Using <EM>N</EM> and <EM>D</EM>, we can perform rational
+ * resampling where <EM>N/D</EM> is a rational number close to the
+ * input rate <EM>r</EM> where we have <EM>N</EM> filters and we
+ * cycle through them as a polyphase filterbank with a stride of
+ * <EM>D</EM> so that <EM>i+1 = (i + D) % N</EM>.
+ *
+ * To get the arbitrary rate, we want to interpolate between two
+ * points. For each value out, we take an output from the current
+ * filter, <EM>i</EM>, and the next filter <EM>i+1</EM> and then
+ * linearly interpolate between the two based on the real
+ * resampling rate we want.
+ *
+ * The linear interpolation only provides us with an approximation
+ * to the real sampling rate specified. The error is a
+ * quantization error between the two filters we used as our
+ * interpolation points. To this end, the number of filters,
+ * <EM>N</EM>, used determines the quantization error; the larger
+ * <EM>N</EM>, the smaller the noise. You can design for a
+ * specified noise floor by setting the filter size (parameters
+ * <EM>filter_size</EM>). The size defaults to 32 filters, which
+ * is about as good as most implementations need.
+ *
+ * The trick with designing this filter is in how to specify the
+ * taps of the prototype filter. Like the PFB interpolator, the
+ * taps are specified using the interpolated filter rate. In this
+ * case, that rate is the input sample rate multiplied by the
+ * number of filters in the filterbank, which is also the
+ * interpolation rate. All other values should be relative to this
+ * rate.
+ *
+ * For example, for a 32-filter arbitrary resampler and using the
+ * GNU Radio's firdes utility to build the filter, we build a
+ * low-pass filter with a sampling rate of <EM>fs</EM>, a 3-dB
+ * bandwidth of <EM>BW</EM> and a transition bandwidth of
+ * <EM>TB</EM>. We can also specify the out-of-band attenuation to
+ * use, <EM>ATT</EM>, and the filter window function (a
+ * Blackman-harris window in this case). The first input is the
+ * gain of the filter, which we specify here as the interpolation
+ * rate (<EM>32</EM>).
+ *
+ * <B><EM>self._taps = filter.firdes.low_pass_2(32, 32*fs, BW, TB,
+ * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
+ *
+ * The theory behind this block can be found in Chapter 7.5 of
+ * the following book.
+ *
+ * <B><EM>f. harris, "Multirate Signal Processing for Communication
+ * Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
+ */
+
+ class FILTER_API pfb_arb_resampler_ccf : virtual public gr_block
+ {
+ public:
+ // gr::filter::pfb_arb_resampler_ccf::sptr
+ typedef boost::shared_ptr<pfb_arb_resampler_ccf> sptr;
+
+ /*!
+ * Build the polyphase filterbank arbitray resampler.
+ * \param rate (float) Specifies the resampling rate to use
+ * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps
+ * should be generated at the filter_size sampling rate.
+ * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly
+ * related to quantization noise introduced during the resampling.
+ * Defaults to 32 filters.
+ */
+ static sptr make(float rate,
+ const std::vector<float> &taps,
+ unsigned int filter_size=32);
+ /*!
+ * Resets the filterbank's filter taps with the new prototype filter
+ * \param taps (vector/list of floats) The prototype filter to populate the filterbank.
+ */
+ virtual void set_taps(const std::vector<float> &taps) = 0;
+
+ /*!
+ * Return a vector<vector<>> of the filterbank taps
+ */
+ virtual std::vector<std::vector<float> > taps() const = 0;
+
+ /*!
+ * Print all of the filterbank taps to screen.
+ */
+ virtual void print_taps() = 0;
+
+ /*!
+ * Sets the resampling rate of the block.
+ */
+ virtual void set_rate (float rate) = 0;
+
+ /*!
+ * Sets the current phase offset in radians (0 to 2pi).
+ */
+ virtual void set_phase(float ph) = 0;
+
+ /*!
+ * Gets the current phase of the resampler in radians (2 to 2pi).
+ */
+ virtual float phase() const = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_PFB_ARB_RESAMPLER_CCF_H */
diff --git a/gr-filter/include/filter/pfb_arb_resampler_fff.h b/gr-filter/include/filter/pfb_arb_resampler_fff.h
new file mode 100644
index 000000000..38dcc7132
--- /dev/null
+++ b/gr-filter/include/filter/pfb_arb_resampler_fff.h
@@ -0,0 +1,152 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009-2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_PFB_ARB_RESAMPLER_FFF_H
+#define INCLUDED_PFB_ARB_RESAMPLER_FFF_H
+
+#include <filter/api.h>
+#include <gr_block.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \class pfb_arb_resampler_fff
+ *
+ * \brief Polyphase filterbank arbitrary resampler with
+ * float input, float output and float taps
+ *
+ * \ingroup filter_blk
+ * \ingroup pfb_blk
+ *
+ * This block takes in a signal stream and performs arbitrary
+ * resampling. The resampling rate can be any real number
+ * <EM>r</EM>. The resampling is done by constructing <EM>N</EM>
+ * filters where <EM>N</EM> is the interpolation rate. We then
+ * calculate <EM>D</EM> where <EM>D = floor(N/r)</EM>.
+ *
+ * Using <EM>N</EM> and <EM>D</EM>, we can perform rational
+ * resampling where <EM>N/D</EM> is a rational number close to the
+ * input rate <EM>r</EM> where we have <EM>N</EM> filters and we
+ * cycle through them as a polyphase filterbank with a stride of
+ * <EM>D</EM> so that <EM>i+1 = (i + D) % N</EM>.
+ *
+ * To get the arbitrary rate, we want to interpolate between two
+ * points. For each value out, we take an output from the current
+ * filter, <EM>i</EM>, and the next filter <EM>i+1</EM> and then
+ * linearly interpolate between the two based on the real
+ * resampling rate we want.
+ *
+ * The linear interpolation only provides us with an approximation
+ * to the real sampling rate specified. The error is a
+ * quantization error between the two filters we used as our
+ * interpolation points. To this end, the number of filters,
+ * <EM>N</EM>, used determines the quantization error; the larger
+ * <EM>N</EM>, the smaller the noise. You can design for a
+ * specified noise floor by setting the filter size (parameters
+ * <EM>filter_size</EM>). The size defaults to 32 filters, which
+ * is about as good as most implementations need.
+ *
+ * The trick with designing this filter is in how to specify the
+ * taps of the prototype filter. Like the PFB interpolator, the
+ * taps are specified using the interpolated filter rate. In this
+ * case, that rate is the input sample rate multiplied by the
+ * number of filters in the filterbank, which is also the
+ * interpolation rate. All other values should be relative to this
+ * rate.
+ *
+ * For example, for a 32-filter arbitrary resampler and using the
+ * GNU Radio's firdes utility to build the filter, we build a
+ * low-pass filter with a sampling rate of <EM>fs</EM>, a 3-dB
+ * bandwidth of <EM>BW</EM> and a transition bandwidth of
+ * <EM>TB</EM>. We can also specify the out-of-band attenuation to
+ * use, <EM>ATT</EM>, and the filter window function (a
+ * Blackman-harris window in this case). The first input is the
+ * gain of the filter, which we specify here as the interpolation
+ * rate (<EM>32</EM>).
+ *
+ * <B><EM>self._taps = filter.firdes.low_pass_2(32, 32*fs, BW, TB,
+ * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
+ *
+ * The theory behind this block can be found in Chapter 7.5 of the
+ * following book.
+ *
+ * <B><EM>f. harris, "Multirate Signal Processing for Communication
+ * Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
+ */
+
+ class FILTER_API pfb_arb_resampler_fff : virtual public gr_block
+ {
+ public:
+ // gr::filter::pfb_arb_resampler_fff::sptr
+ typedef boost::shared_ptr<pfb_arb_resampler_fff> sptr;
+
+ /*!
+ * Build the polyphase filterbank arbitray resampler.
+ * \param rate (float) Specifies the resampling rate to use
+ * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps
+ * should be generated at the filter_size sampling rate.
+ * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly
+ * related to quantization noise introduced during the resampling.
+ * Defaults to 32 filters.
+ */
+ static sptr make(float rate,
+ const std::vector<float> &taps,
+ unsigned int filter_size=32);
+
+ /*!
+ * Resets the filterbank's filter taps with the new prototype filter
+ * \param taps (vector/list of floats) The prototype filter to populate the filterbank.
+ */
+ virtual void set_taps(const std::vector<float> &taps) = 0;
+
+ /*!
+ * Return a vector<vector<>> of the filterbank taps
+ */
+ virtual std::vector<std::vector<float> > taps() const = 0;
+
+ /*!
+ * Print all of the filterbank taps to screen.
+ */
+ virtual void print_taps() = 0;
+
+ /*!
+ * Sets the resampling rate of the block.
+ */
+ virtual void set_rate (float rate) = 0;
+
+ /*!
+ * Sets the current phase offset in radians (0 to 2pi).
+ */
+ virtual void set_phase(float ph) = 0;
+
+ /*!
+ * Gets the current phase of the resampler in radians (2 to 2pi).
+ */
+ virtual float phase() const = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_PFB_ARB_RESAMPLER_FFF_H */
diff --git a/gr-filter/include/filter/pfb_channelizer_ccf.h b/gr-filter/include/filter/pfb_channelizer_ccf.h
new file mode 100644
index 000000000..2ff83b5e7
--- /dev/null
+++ b/gr-filter/include/filter/pfb_channelizer_ccf.h
@@ -0,0 +1,204 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_FILTER_PFB_CHANNELIZER_CCF_H
+#define INCLUDED_FILTER_PFB_CHANNELIZER_CCF_H
+
+#include <filter/api.h>
+#include <gr_block.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \class pfb_channelizer_ccf
+ *
+ * \brief Polyphase filterbank channelizer with
+ * gr_complex input, gr_complex output and float taps
+ *
+ * \ingroup filter_blk
+ * \ingroup pfb_blk
+ *
+ * This block takes in complex inputs and channelizes it to <EM>M</EM>
+ * channels of equal bandwidth. Each of the resulting channels is
+ * decimated to the new rate that is the input sampling rate
+ * <EM>fs</EM> divided by the number of channels, <EM>M</EM>.
+ *
+ * The PFB channelizer code takes the taps generated above and builds
+ * a set of filters. The set contains <EM>M</EM> number of filters
+ * and each filter contains ceil(taps.size()/decim) number of taps.
+ * Each tap from the filter prototype is sequentially inserted into
+ * the next filter. When all of the input taps are used, the remaining
+ * filters in the filterbank are filled out with 0's to make sure each
+ * filter has the same number of taps.
+ *
+ * Each filter operates using the gr_fir filter classs of GNU Radio,
+ * which takes the input stream at <EM>i</EM> and performs the inner
+ * product calculation to <EM>i+(n-1)</EM> where <EM>n</EM> is the
+ * number of filter taps. To efficiently handle this in the GNU Radio
+ * structure, each filter input must come from its own input
+ * stream. So the channelizer must be provided with <EM>M</EM> streams
+ * where the input stream has been deinterleaved. This is most easily
+ * done using the gr_stream_to_streams block.
+ *
+ * The output is then produced as a vector, where index <EM>i</EM> in
+ * the vector is the next sample from the <EM>i</EM>th channel. This
+ * is most easily handled by sending the output to a
+ * gr_vector_to_streams block to handle the conversion and passing
+ * <EM>M</EM> streams out.
+ *
+ * The input and output formatting is done using a hier_block2 called
+ * pfb_channelizer_ccf. This can take in a single stream and outputs
+ * <EM>M</EM> streams based on the behavior described above.
+ *
+ * The filter's taps should be based on the input sampling rate.
+ *
+ * For example, using the GNU Radio's firdes utility to building
+ * filters, we build a low-pass filter with a sampling rate of
+ * <EM>fs</EM>, a 3-dB bandwidth of <EM>BW</EM> and a transition
+ * bandwidth of <EM>TB</EM>. We can also specify the out-of-band
+ * attenuation to use, <EM>ATT</EM>, and the filter window
+ * function (a Blackman-harris window in this case). The first input
+ * is the gain of the filter, which we specify here as unity.
+ *
+ * <B><EM>self._taps = filter.firdes.low_pass_2(1, fs, BW, TB,
+ * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
+ *
+ * The filter output can also be overs ampled. The over sampling rate
+ * is the ratio of the the actual output sampling rate to the normal
+ * output sampling rate. It must be rationally related to the number
+ * of channels as N/i for i in [1,N], which gives an outputsample rate
+ * of [fs/N, fs] where fs is the input sample rate and N is the number
+ * of channels.
+ *
+ * For example, for 6 channels with fs = 6000 Hz, the normal rate is
+ * 6000/6 = 1000 Hz. Allowable oversampling rates are 6/6, 6/5, 6/4,
+ * 6/3, 6/2, and 6/1 where the output sample rate of a 6/1 oversample
+ * ratio is 6000 Hz, or 6 times the normal 1000 Hz. A rate of 6/5 = 1.2,
+ * so the output rate would be 1200 Hz.
+ *
+ * The theory behind this block can be found in Chapter 6 of
+ * the following book.
+ *
+ * <B><EM>f. harris, "Multirate Signal Processing for Communication
+ * Systems," Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
+ *
+ */
+
+ class FILTER_API pfb_channelizer_ccf : virtual public gr_block
+ {
+ public:
+ // gr::filter::pfb_channelizer_ccf::sptr
+ typedef boost::shared_ptr<pfb_channelizer_ccf> sptr;
+
+ /*!
+ * Build the polyphase filterbank decimator.
+ * \param numchans (unsigned integer) Specifies the number of
+ * channels <EM>M</EM>
+ * \param taps (vector/list of floats) The prototype filter to
+ * populate the filterbank.
+ * \param oversample_rate (float) The over sampling rate is the
+ * ratio of the the actual output
+ * sampling rate to the normal
+ * output sampling rate. It must
+ * be rationally related to the
+ * number of channels as N/i for
+ * i in [1,N], which gives an
+ * outputsample rate of [fs/N,
+ * fs] where fs is the input
+ * sample rate and N is the
+ * number of channels.
+ *
+ * For example, for 6 channels
+ * with fs = 6000 Hz, the normal
+ * rateis 6000/6 = 1000
+ * Hz. Allowable oversampling
+ * rates are 6/6, 6/5, 6/4, 6/3,
+ * 6/2, and 6/1 where the output
+ * sample rate of a 6/1
+ * oversample ratio is 6000 Hz,
+ * or 6 times the normal 1000 Hz.
+ */
+ static sptr make(unsigned int numchans,
+ const std::vector<float> &taps,
+ float oversample_rate);
+
+ /*!
+ * Resets the filterbank's filter taps with the new prototype filter
+ * \param taps (vector/list of floats) The prototype filter to populate the filterbank.
+ */
+ virtual void set_taps(const std::vector<float> &taps) = 0;
+
+ /*!
+ * Print all of the filterbank taps to screen.
+ */
+ virtual void print_taps() = 0;
+
+ /*!
+ * Return a vector<vector<>> of the filterbank taps
+ */
+ virtual std::vector<std::vector<float> > taps() const = 0;
+
+ /*!
+ * Set the channel map. Channels are numbers as:
+ *
+ * N/2+1 | ... | N-1 | 0 | 1 | 2 | ... | N/2
+ * <------------------- 0 -------------------->
+ * freq
+ *
+ * So output stream 0 comes from channel 0, etc. Setting a new
+ * channel map allows the user to specify which channel in frequency
+ * he/she wants to got to which output stream.
+ *
+ * The map should have the same number of elements as the number
+ * of output connections from the block. The minimum value of
+ * the map is 0 (for the 0th channel) and the maximum number is
+ * N-1 where N is the number of channels.
+ *
+ * We specify M as the number of output connections made where M
+ * <= N, so only M out of N channels are driven to an output
+ * stream. The number of items in the channel map should be at
+ * least M long. If there are more channels specified, any value
+ * in the map over M-1 will be ignored. If the size of the map
+ * is less than M the behavior is unknown (we don't wish to
+ * check every entry into the work function).
+ *
+ * This means that if the channelizer is splitting the signal up
+ * into N channels but only M channels are specified in the map
+ * (where M <= N), then M output streams must be connected and
+ * the map and the channel numbers used must be less than
+ * N-1. Output channel number can be reused, too. By default,
+ * the map is [0...M-1] with M = N.
+ */
+ virtual void set_channel_map(const std::vector<int> &map) = 0;
+
+ /*!
+ * Gets the current channel map.
+ */
+ virtual std::vector<int> channel_map() const = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_PFB_CHANNELIZER_CCF_H */
diff --git a/gr-filter/include/filter/pfb_decimator_ccf.h b/gr-filter/include/filter/pfb_decimator_ccf.h
new file mode 100644
index 000000000..bf9d0d950
--- /dev/null
+++ b/gr-filter/include/filter/pfb_decimator_ccf.h
@@ -0,0 +1,131 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_PFB_DECIMATOR_CCF_H
+#define INCLUDED_PFB_DECIMATOR_CCF_H
+
+#include <filter/api.h>
+#include <gr_sync_block.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \class pfb_decimator_ccf
+ * \brief Polyphase filterbank bandpass decimator with gr_complex
+ * input, gr_complex output and float taps
+ *
+ * \ingroup filter_blk
+ * \ingroup pfb_blk
+ *
+ * This block takes in a signal stream and performs interger down-
+ * sampling (decimation) with a polyphase filterbank. The first
+ * input is the integer specifying how much to decimate by. The
+ * second input is a vector (Python list) of floating-point taps
+ * of the prototype filter. The third input specifies the channel
+ * to extract. By default, the zeroth channel is used, which is
+ * the baseband channel (first Nyquist zone).
+ *
+ * The <EM>channel</EM> parameter specifies which channel to use
+ * since this class is capable of bandpass decimation. Given a
+ * complex input stream at a sampling rate of <EM>fs</EM> and a
+ * decimation rate of <EM>decim</EM>, the input frequency domain
+ * is split into <EM>decim</EM> channels that represent the
+ * Nyquist zones. Using the polyphase filterbank, we can select
+ * any one of these channels to decimate.
+ *
+ * The output signal will be the basebanded and decimated signal
+ * from that channel. This concept is very similar to the PFB
+ * channelizer (see #gr_pfb_channelizer_ccf) where only a single
+ * channel is extracted at a time.
+ *
+ * The filter's taps should be based on the sampling rate before
+ * decimation.
+ *
+ * For example, using the GNU Radio's firdes utility to building
+ * filters, we build a low-pass filter with a sampling rate of
+ * <EM>fs</EM>, a 3-dB bandwidth of <EM>BW</EM> and a transition
+ * bandwidth of <EM>TB</EM>. We can also specify the out-of-band
+ * attenuation to use, <EM>ATT</EM>, and the filter window
+ * function (a Blackman-harris window in this case). The first
+ * input is the gain of the filter, which we specify here as
+ * unity.
+ *
+ * <B><EM>self._taps = filter.firdes.low_pass_2(1, fs, BW, TB,
+ * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
+ *
+ * The PFB decimator code takes the taps generated above and
+ * builds a set of filters. The set contains <EM>decim</EM> number
+ * of filters and each filter contains ceil(taps.size()/decim)
+ * number of taps. Each tap from the filter prototype is
+ * sequentially inserted into the next filter. When all of the
+ * input taps are used, the remaining filters in the filterbank
+ * are filled out with 0's to make sure each filter has the same
+ * number of taps.
+ *
+ * The theory behind this block can be found in Chapter 6 of
+ * the following book.
+ *
+ * <B><EM>f. harris, "Multirate Signal Processing for Communication
+ * Systems," Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
+ */
+
+ class FILTER_API pfb_decimator_ccf : virtual public gr_sync_block
+ {
+ public:
+ // gr::filter::pfb_decimator_ccf::sptr
+ typedef boost::shared_ptr<pfb_decimator_ccf> sptr;
+
+ /*!
+ * Build the polyphase filterbank decimator.
+ * \param decim (unsigned integer) Specifies the decimation rate to use
+ * \param taps (vector/list of floats) The prototype filter to populate the filterbank.
+ * \param channel (unsigned integer) Selects the channel to return [default=0].
+ */
+ static sptr make(unsigned int decim,
+ const std::vector<float> &taps,
+ unsigned int channel);
+
+ /*!
+ * Resets the filterbank's filter taps with the new prototype filter
+ * \param taps (vector/list of floats) The prototype filter to populate the filterbank.
+ */
+ virtual void set_taps(const std::vector<float> &taps) = 0;
+
+ /*!
+ * Return a vector<vector<>> of the filterbank taps
+ */
+ virtual std::vector<std::vector<float> > taps() const = 0;
+
+ /*!
+ * Print all of the filterbank taps to screen.
+ */
+ virtual void print_taps() = 0;
+
+ //virtual void set_channel(unsigned int channel) = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_PFB_DECIMATOR_CCF_H */
diff --git a/gr-filter/include/filter/pfb_interpolator_ccf.h b/gr-filter/include/filter/pfb_interpolator_ccf.h
new file mode 100644
index 000000000..df28ab64d
--- /dev/null
+++ b/gr-filter/include/filter/pfb_interpolator_ccf.h
@@ -0,0 +1,118 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_PFB_INTERPOLATOR_CCF_H
+#define INCLUDED_PFB_INTERPOLATOR_CCF_H
+
+#include <filter/api.h>
+#include <gr_sync_interpolator.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \class gr_pfb_interpolator_ccf
+ *
+ * \brief Polyphase filterbank interpolator with gr_complex input,
+ * gr_complex output and float taps
+ *
+ * \ingroup filter_blk
+ * \ingroup pfb_blk
+ *
+ * This block takes in a signal stream and performs interger up-
+ * sampling (interpolation) with a polyphase filterbank. The first
+ * input is the integer specifying how much to interpolate by. The
+ * second input is a vector (Python list) of floating-point taps
+ * of the prototype filter.
+ *
+ * The filter's taps should be based on the interpolation rate
+ * specified. That is, the bandwidth specified is relative to the
+ * bandwidth after interpolation.
+ *
+ * For example, using the GNU Radio's firdes utility to building
+ * filters, we build a low-pass filter with a sampling rate of
+ * <EM>fs</EM>, a 3-dB bandwidth of <EM>BW</EM> and a transition
+ * bandwidth of <EM>TB</EM>. We can also specify the out-of-band
+ * attenuation to use, ATT, and the filter window function (a
+ * Blackman-harris window in this case). The first input is the
+ * gain, which is also specified as the interpolation rate so that
+ * the output levels are the same as the input (this creates an
+ * overall increase in power).
+ *
+ * <B><EM>self._taps = filter.firdes.low_pass_2(interp, interp*fs, BW, TB,
+ * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
+ *
+ * The PFB interpolator code takes the taps generated above and
+ * builds a set of filters. The set contains <EM>interp</EM>
+ * number of filters and each filter contains
+ * ceil(taps.size()/interp) number of taps. Each tap from the
+ * filter prototype is sequentially inserted into the next
+ * filter. When all of the input taps are used, the remaining
+ * filters in the filterbank are filled out with 0's to make sure
+ * each filter has the same number of taps.
+ *
+ * The theory behind this block can be found in Chapter 7.1 of the
+ * following book.
+ *
+ * <B><EM>f. harris, "Multirate Signal Processing for Communication
+ * Systems</EM>," Upper Saddle River, NJ: Prentice Hall,
+ * Inc. 2004.</EM></B>
+ */
+
+ class FILTER_API pfb_interpolator_ccf : virtual public gr_sync_interpolator
+ {
+ public:
+ // gr::filter::pfb_interpolator_ccf::sptr
+ typedef boost::shared_ptr<pfb_interpolator_ccf> sptr;
+
+ /*!
+ * Build the polyphase filterbank interpolator.
+ * \param interp (unsigned integer) Specifies the interpolation rate to use
+ * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps
+ * should be generated at the interpolated sampling rate.
+ */
+ static sptr make(unsigned int interp,
+ const std::vector<float> &taps);
+
+ /*!
+ * Resets the filterbank's filter taps with the new prototype filter
+ * \param taps (vector/list of floats) The prototype filter to populate the filterbank.
+ * The taps should be generated at the interpolated sampling rate.
+ */
+ virtual void set_taps(const std::vector<float> &taps) = 0;
+
+ /*!
+ * Return a vector<vector<>> of the filterbank taps
+ */
+ virtual std::vector<std::vector<float> > taps() const = 0;
+
+ /*!
+ * Print all of the filterbank taps to screen.
+ */
+ virtual void print_taps() = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_PFB_INTERPOLATOR_CCF_H */
diff --git a/gr-filter/include/filter/pfb_synthesizer_ccf.h b/gr-filter/include/filter/pfb_synthesizer_ccf.h
new file mode 100644
index 000000000..faa16990c
--- /dev/null
+++ b/gr-filter/include/filter/pfb_synthesizer_ccf.h
@@ -0,0 +1,107 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_PFB_SYNTHESIZER_CCF_H
+#define INCLUDED_PFB_SYNTHESIZER_CCF_H
+
+#include <filter/api.h>
+#include <gr_sync_interpolator.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \class pfb_synthesizer_ccf
+ *
+ * \brief Polyphase synthesis filterbank with
+ * gr_complex input, gr_complex output and float taps
+ *
+ * \ingroup filter_blk
+ * \ingroup pfb_blk
+ */
+
+ class FILTER_API pfb_synthesizer_ccf : virtual public gr_sync_interpolator
+ {
+ public:
+ // gr::filter::pfb_synthesizer_ccf::sptr
+ typedef boost::shared_ptr<pfb_synthesizer_ccf> sptr;
+
+ /*!
+ * Build the polyphase synthesis filterbank.
+ * \param numchans (unsigned integer) Specifies the number of
+ * channels <EM>M</EM>
+ * \param taps (vector/list of floats) The prototype filter to
+ * populate the filterbank.
+ * \param twox (bool) use 2x oversampling or not (default is no)
+ */
+ static sptr make(unsigned int numchans,
+ const std::vector<float> &taps,
+ bool twox=false);
+
+ /*!
+ * Resets the filterbank's filter taps with the new prototype filter
+ * \param taps (vector/list of floats) The prototype filter to
+ * populate the filterbank.
+ */
+ virtual void set_taps(const std::vector<float> &taps) = 0;
+
+ /*!
+ * Print all of the filterbank taps to screen.
+ */
+ virtual void print_taps() = 0;
+
+ /*!
+ * Return a vector<vector<>> of the filterbank taps
+ */
+ virtual std::vector<std::vector<float> > taps() const = 0;
+
+ /*!
+ * Set the channel map. Channels are numbers as:
+ * N/2+1 | ... | N-1 | 0 | 1 | 2 | ... | N/2
+ * <------------------- 0 -------------------->
+ * freq
+ *
+ * So input stream 0 goes to channel 0, etc. Setting a new channel
+ * map allows the user to specify where in frequency he/she wants
+ * the input stream to go. This is especially useful to avoid
+ * putting signals into the channels on the edge of the spectrum
+ * which can either wrap around (in the case of odd number of
+ * channels) and be affected by filter rolloff in the transmitter.
+ *
+ * The map must be at least the number of streams being sent to the
+ * block. Less and the algorithm will not have enough data to
+ * properly setup the buffers. Any more channels specified will be
+ * ignored.
+ */
+ virtual void set_channel_map(const std::vector<int> &map) = 0;
+
+ /*!
+ * Gets the current channel map.
+ */
+ virtual std::vector<int> channel_map() const = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_PFB_SYNTHESIZER_CCF_H */
diff --git a/gr-filter/include/filter/pm_remez.h b/gr-filter/include/filter/pm_remez.h
new file mode 100644
index 000000000..a57e9e276
--- /dev/null
+++ b/gr-filter/include/filter/pm_remez.h
@@ -0,0 +1,72 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_PM_REMEZ_H
+#define INCLUDED_FILTER_PM_REMEZ_H
+
+#include <filter/api.h>
+#include <gr_types.h>
+#include <string>
+#include <stdexcept>
+
+namespace gr {
+ namespace filter {
+ /*!
+ * \brief Parks-McClellan FIR filter design using Remez algorithm.
+ *
+ * \ingroup filter_design
+ *
+ * Calculates the optimal (in the Chebyshev/minimax sense) FIR
+ * filter inpulse reponse given a set of band edges, the desired
+ * reponse on those bands, and the weight given to the error in
+ * those bands.
+ *
+ * \param order filter order (number of taps in the returned filter - 1)
+ * \param bands frequency at the band edges [ b1 e1 b2 e2 b3 e3 ...]
+ * \param ampl desired amplitude at the band edges [ a(b1) a(e1) a(b2) a(e2) ...]
+ * \param error_weight weighting applied to each band (usually 1)
+ * \param filter_type one of "bandpass", "hilbert" or "differentiator"
+ * \param grid_density determines how accurately the filter will be constructed. \
+ * The minimum value is 16; higher values are slower to compute.
+ *
+ * Frequency is in the range [0, 1], with 1 being the Nyquist
+ * frequency (Fs/2)
+ *
+ * \returns vector of computed taps
+ *
+ * \throws std::runtime_error if args are invalid or calculation
+ * fails to converge.
+ */
+
+ FILTER_API std::vector<double>
+ pm_remez(int order,
+ const std::vector<double> &bands,
+ const std::vector<double> &ampl,
+ const std::vector<double> &error_weight,
+ const std::string filter_type = "bandpass",
+ int grid_density = 16
+ ) throw (std::runtime_error);
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_PM_REMEZ_H */
diff --git a/gr-filter/include/filter/polyphase_filterbank.h b/gr-filter/include/filter/polyphase_filterbank.h
new file mode 100644
index 000000000..33e9522e1
--- /dev/null
+++ b/gr-filter/include/filter/polyphase_filterbank.h
@@ -0,0 +1,148 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_FILTER_POLYPHASE_FILTERBANK_H
+#define INCLUDED_FILTER_POLYPHASE_FILTERBANK_H
+
+#include <filter/api.h>
+#include <filter/fir_filter.h>
+#include <fft/fft.h>
+
+namespace gr {
+ namespace filter {
+ namespace kernel {
+
+ /*!
+ * \class polyphase_filterbank
+ *
+ * \brief Polyphase filterbank parent class
+ *
+ * \ingroup filter_blk
+ * \ingroup pfb_blk
+ *
+ * This block takes in complex inputs and channelizes it to
+ * <EM>M</EM> channels of equal bandwidth. Each of the resulting
+ * channels is decimated to the new rate that is the input
+ * sampling rate <EM>fs</EM> divided by the number of channels,
+ * <EM>M</EM>.
+ *
+ * The PFB channelizer code takes the taps generated above and
+ * builds a set of filters. The set contains <EM>M</EM> number
+ * of filters and each filter contains ceil(taps.size()/decim)
+ * number of taps. Each tap from the filter prototype is
+ * sequentially inserted into the next filter. When all of the
+ * input taps are used, the remaining filters in the filterbank
+ * are filled out with 0's to make sure each filter has the same
+ * number of taps.
+ *
+ * Each filter operates using the gr_fir filter classs of GNU
+ * Radio, which takes the input stream at <EM>i</EM> and
+ * performs the inner product calculation to <EM>i+(n-1)</EM>
+ * where <EM>n</EM> is the number of filter taps. To efficiently
+ * handle this in the GNU Radio structure, each filter input
+ * must come from its own input stream. So the channelizer must
+ * be provided with <EM>M</EM> streams where the input stream
+ * has been deinterleaved. This is most easily done using the
+ * gr_stream_to_streams block.
+ *
+ * The output is then produced as a vector, where index
+ * <EM>i</EM> in the vector is the next sample from the
+ * <EM>i</EM>th channel. This is most easily handled by sending
+ * the output to a gr_vector_to_streams block to handle the
+ * conversion and passing <EM>M</EM> streams out.
+ *
+ * The input and output formatting is done using a hier_block2
+ * called pfb_channelizer_ccf. This can take in a single stream
+ * and outputs <EM>M</EM> streams based on the behavior
+ * described above.
+ *
+ * The filter's taps should be based on the input sampling rate.
+ *
+ * For example, using the GNU Radio's firdes utility to building
+ * filters, we build a low-pass filter with a sampling rate of
+ * <EM>fs</EM>, a 3-dB bandwidth of <EM>BW</EM> and a transition
+ * bandwidth of <EM>TB</EM>. We can also specify the out-of-band
+ * attenuation to use, <EM>ATT</EM>, and the filter window
+ * function (a Blackman-harris window in this case). The first
+ * input is the gain of the filter, which we specify here as
+ * unity.
+ *
+ * <B><EM>self._taps = filter.firdes.low_pass_2(1, fs, BW, TB,
+ * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
+ *
+ * More on the theory of polyphase filterbanks can be found in
+ * the following book.
+ *
+ * <B><EM>f. harris, "Multirate Signal Processing for
+ * Communication Systems," Upper Saddle River, NJ:
+ * Prentice Hall, Inc. 2004.</EM></B>
+ *
+ */
+
+ class FILTER_API polyphase_filterbank
+ {
+ protected:
+ unsigned int d_nfilts;
+ std::vector<kernel::fir_filter_ccf*> d_filters;
+ std::vector< std::vector<float> > d_taps;
+ unsigned int d_taps_per_filter;
+ fft::fft_complex *d_fft;
+
+ public:
+ /*!
+ * Build the polyphase filterbank decimator.
+ * \param nfilts (unsigned integer) Specifies the number of
+ * channels <EM>M</EM>
+ * \param taps (vector/list of floats) The prototype filter to
+ * populate the filterbank.
+ */
+ polyphase_filterbank(unsigned int nfilts,
+ const std::vector<float> &taps);
+
+ ~polyphase_filterbank();
+
+ /*!
+ * Update the filterbank's filter taps from a prototype
+ * filter.
+ *
+ * \param taps (vector/list of floats) The prototype filter to
+ * populate the filterbank.
+ */
+ void set_taps(const std::vector<float> &taps);
+
+ /*!
+ * Print all of the filterbank taps to screen.
+ */
+ void print_taps();
+
+ /*!
+ * Return a vector<vector<>> of the filterbank taps
+ */
+ std::vector<std::vector<float> > taps() const;
+ };
+
+ } /* namespace kernel */
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_POLYPHASE_FILTERBANK_H */
diff --git a/gr-filter/include/filter/rational_resampler_base_XXX.h.t b/gr-filter/include/filter/rational_resampler_base_XXX.h.t
new file mode 100644
index 000000000..e47a16ec6
--- /dev/null
+++ b/gr-filter/include/filter/rational_resampler_base_XXX.h.t
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* @WARNING@ */
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
+
+#include <filter/api.h>
+#include <gr_block.h>
+
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief Rational Resampling Polyphase FIR filter with @I_TYPE@
+ * input, @O_TYPE@ output and @TAP_TYPE@ taps.
+ *
+ *\ingroup filter_blk
+ */
+ class FILTER_API @NAME@ : virtual public gr_block
+ {
+ public:
+ // gr::filter::@BASE_NAME@::sptr
+ typedef boost::shared_ptr<@BASE_NAME@> sptr;
+
+ static sptr make(unsigned interpolation,
+ unsigned decimation,
+ const std::vector<@TAP_TYPE@> &taps);
+
+ virtual unsigned interpolation() const = 0;
+ virtual unsigned decimation() const = 0;
+
+ virtual void set_taps(const std::vector<@TAP_TYPE@> &taps) = 0;
+ virtual std::vector<@TAP_TYPE@> taps() const = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* @GUARD_NAME@ */
diff --git a/gr-filter/include/filter/single_pole_iir.h b/gr-filter/include/filter/single_pole_iir.h
new file mode 100644
index 000000000..10d1b4791
--- /dev/null
+++ b/gr-filter/include/filter/single_pole_iir.h
@@ -0,0 +1,200 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2006,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_SINGLE_POLE_IIR_H
+#define INCLUDED_SINGLE_POLE_IIR_H
+
+#include <filter/api.h>
+#include <stdexcept>
+#include <gr_complex.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief class template for single pole IIR filter
+ */
+ template<class o_type, class i_type, class tap_type>
+ class single_pole_iir
+ {
+ public:
+ /*!
+ * \brief construct new single pole IIR with given alpha
+ *
+ * computes y(i) = (1-alpha) * y(i-1) + alpha * x(i)
+ */
+ single_pole_iir(tap_type alpha = 1.0)
+ {
+ d_prev_output = 0;
+ set_taps(alpha);
+ }
+
+ /*!
+ * \brief compute a single output value.
+ * \returns the filtered input value.
+ */
+ o_type filter(const i_type input);
+
+ /*!
+ * \brief compute an array of N output values.
+ * \p input must have n valid entries.
+ */
+ void filterN(o_type output[], const i_type input[], unsigned long n);
+
+ /*!
+ * \brief install \p alpha as the current taps.
+ */
+ void set_taps(tap_type alpha)
+ {
+ if(alpha < 0 || alpha > 1)
+ throw std::out_of_range("Alpha must be in [0, 1]\n");
+
+ d_alpha = alpha;
+ d_one_minus_alpha = 1.0 - alpha;
+ }
+
+ //! reset state to zero
+ void reset()
+ {
+ d_prev_output = 0;
+ }
+
+ o_type prev_output() const { return d_prev_output; }
+
+ protected:
+ tap_type d_alpha;
+ tap_type d_one_minus_alpha;
+ o_type d_prev_output;
+ };
+
+ //
+ // general case. We may want to specialize this
+ //
+ template<class o_type, class i_type, class tap_type>
+ o_type
+ single_pole_iir<o_type, i_type, tap_type>::filter(const i_type input)
+ {
+ o_type output;
+
+ output = d_alpha * input + d_one_minus_alpha * d_prev_output;
+ d_prev_output = output;
+
+ return (o_type) output;
+ }
+
+
+ template<class o_type, class i_type, class tap_type>
+ void
+ single_pole_iir<o_type, i_type, tap_type>::filterN(o_type output[],
+ const i_type input[],
+ unsigned long n)
+ {
+ for(unsigned i = 0; i < n; i++)
+ output[i] = filter(input[i]);
+ }
+
+
+ //
+ // Specialized case for gr_complex output and double taps
+ // We need to have a gr_complexd type for the calculations and prev_output variable (in stead of double)
+
+ template<class i_type>
+ class single_pole_iir<gr_complex, i_type, double>
+ {
+ public:
+ /*!
+ * \brief construct new single pole IIR with given alpha
+ *
+ * computes y(i) = (1-alpha) * y(i-1) + alpha * x(i)
+ */
+ single_pole_iir(double alpha = 1.0)
+ {
+ d_prev_output = 0;
+ set_taps(alpha);
+ }
+
+ /*!
+ * \brief compute a single output value.
+ * \returns the filtered input value.
+ */
+ gr_complex filter(const i_type input);
+
+ /*!
+ * \brief compute an array of N output values.
+ * \p input must have n valid entries.
+ */
+ void filterN(gr_complex output[], const i_type input[], unsigned long n);
+
+ /*!
+ * \brief install \p alpha as the current taps.
+ */
+ void set_taps(double alpha)
+ {
+ if(alpha < 0 || alpha > 1)
+ throw std::out_of_range("Alpha must be in [0, 1]\n");
+
+ d_alpha = alpha;
+ d_one_minus_alpha = 1.0 - alpha;
+ }
+
+ //! reset state to zero
+ void reset()
+ {
+ d_prev_output = 0;
+ }
+
+ gr_complexd prev_output() const { return d_prev_output; }
+
+ protected:
+ double d_alpha;
+ double d_one_minus_alpha;
+ gr_complexd d_prev_output;
+ };
+
+ template< class i_type>
+ gr_complex
+ single_pole_iir<gr_complex, i_type, double>::filter(const i_type input)
+ {
+ gr_complexd output;
+
+ output = d_alpha * (gr_complexd)input + d_one_minus_alpha * d_prev_output;
+ d_prev_output = output;
+
+ return (gr_complex) output;
+ }
+
+ //Do we need to specialize this, although it is the same as the general case?
+
+ template<class i_type>
+ void
+ single_pole_iir<gr_complex, i_type, double>::filterN(gr_complex output[],
+ const i_type input[],
+ unsigned long n)
+ {
+ for(unsigned i = 0; i < n; i++)
+ output[i] = filter(input[i]);
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_SINGLE_POLE_IIR_H */
diff --git a/gr-filter/include/filter/single_pole_iir_filter_cc.h b/gr-filter/include/filter/single_pole_iir_filter_cc.h
new file mode 100644
index 000000000..82febe8ec
--- /dev/null
+++ b/gr-filter/include/filter/single_pole_iir_filter_cc.h
@@ -0,0 +1,78 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004-2006,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_SINGLE_POLE_IIR_FILTER_CC_H
+#define INCLUDED_SINGLE_POLE_IIR_FILTER_CC_H
+
+#include <filter/api.h>
+#include <filter/single_pole_iir.h>
+#include <gr_sync_block.h>
+#include <gr_complex.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief single pole IIR filter with complex input, complex output
+ * \ingroup filter_blk
+ *
+ * The input and output satisfy a difference equation of the form
+ \htmlonly
+ \f{
+ y[n] - (1-alpha) y[n-1] = alpha x[n]
+ \f}
+ \endhtmlonly
+
+ \xmlonly
+ y[n] - (1-alpha) y[n-1] = alpha x[n]
+ \endxmlonly
+
+ * with the corresponding rational system function
+ \htmlonly
+ \f{
+ H(z) = \frac{alpha}{1 - (1-alpha) z^{-1}}
+ \f}
+ \endhtmlonly
+
+ \xmlonly
+ H(z) = \ frac{alpha}{1 - (1-alpha) z^{-1}}
+ \endxmlonly
+
+ * Note that some texts define the system function with a + in the
+ * denominator. If you're using that convention, you'll need to
+ * negate the feedback tap.
+ */
+ class FILTER_API single_pole_iir_filter_cc : virtual public gr_sync_block
+ {
+ public:
+ // gr::filter::single_pole_iir_filter_cc::sptr
+ typedef boost::shared_ptr<single_pole_iir_filter_cc> sptr;
+
+ static sptr make(double alpha, unsigned int vlen=1);
+
+ virtual void set_taps(double alpha) = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_SINGLE_POLE_IIR_FILTER_CC_H */
diff --git a/gr-filter/include/filter/single_pole_iir_filter_ff.h b/gr-filter/include/filter/single_pole_iir_filter_ff.h
new file mode 100644
index 000000000..d85688db8
--- /dev/null
+++ b/gr-filter/include/filter/single_pole_iir_filter_ff.h
@@ -0,0 +1,78 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2005 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_SINGLE_POLE_IIR_FILTER_FF_H
+#define INCLUDED_SINGLE_POLE_IIR_FILTER_FF_H
+
+#include <filter/api.h>
+#include <filter/single_pole_iir.h>
+#include <gr_sync_block.h>
+#include <gr_complex.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief single pole IIR filter with float input, float output
+ * \ingroup filter_blk
+ *
+ * The input and output satisfy a difference equation of the form
+ \htmlonly
+ \f{
+ y[n] - (1-alpha) y[n-1] = alpha x[n]
+ \f}
+ \endhtmlonly
+
+ \xmlonly
+ y[n] - (1-alpha) y[n-1] = alpha x[n]
+ \endxmlonly
+
+ * with the corresponding rational system function
+ \htmlonly
+ \f{
+ H(z) = \frac{alpha}{1 - (1-alpha) z^{-1}}
+ \f}
+ \endhtmlonly
+
+ \xmlonly
+ H(z) = \ frac{alpha}{1 - (1-alpha) z^{-1}}
+ \endxmlonly
+
+ * Note that some texts define the system function with a + in the
+ * denominator. If you're using that convention, you'll need to
+ * negate the feedback tap.
+ */
+ class FILTER_API single_pole_iir_filter_ff : virtual public gr_sync_block
+ {
+ public:
+ // gr::filter::single_pole_iir_filter_ff::sptr
+ typedef boost::shared_ptr<single_pole_iir_filter_ff> sptr;
+
+ static sptr make(double alpha, unsigned int vlen=1);
+
+ virtual void set_taps (double alpha) = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_SINGLE_POLE_IIR_FILTER_FF_H */
diff --git a/gr-filter/lib/CMakeLists.txt b/gr-filter/lib/CMakeLists.txt
new file mode 100644
index 000000000..532bd1992
--- /dev/null
+++ b/gr-filter/lib/CMakeLists.txt
@@ -0,0 +1,185 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+# generate helper scripts to expand templated files
+########################################################################
+include(GrPython)
+
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py "
+#!${PYTHON_EXECUTABLE}
+
+import sys, os, re
+sys.path.append('${GR_CORE_PYTHONPATH}')
+os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}'
+os.chdir('${CMAKE_CURRENT_BINARY_DIR}')
+
+if __name__ == '__main__':
+ import build_utils
+ root, inp = sys.argv[1:3]
+ for sig in sys.argv[3:]:
+ name = re.sub ('X+', sig, root)
+ d = build_utils.standard_impl_dict2(name, sig, 'filter')
+ build_utils.expand_template(d, inp)
+")
+
+macro(expand_cc root)
+ #make a list of all the generated files
+ unset(expanded_files_cc)
+ unset(expanded_files_h)
+ foreach(sig ${ARGN})
+ string(REGEX REPLACE "X+" ${sig} name ${root})
+ list(APPEND expanded_files_cc ${CMAKE_CURRENT_BINARY_DIR}/${name}.cc)
+ list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/${name}.h)
+ endforeach(sig)
+
+ #create a command to generate the source files
+ add_custom_command(
+ OUTPUT ${expanded_files_cc}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.cc.t
+ COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
+ ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
+ ${root} ${root}.cc.t ${ARGN}
+ )
+
+ #create a command to generate the header file
+ add_custom_command(
+ OUTPUT ${expanded_files_h}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.h.t
+ COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
+ ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
+ ${root} ${root}.h.t ${ARGN}
+ )
+
+ #make source files depends on headers to force generation
+ set_source_files_properties(${expanded_files_cc}
+ PROPERTIES OBJECT_DEPENDS "${expanded_files_h}"
+ )
+
+ #install rules for the generated cc files
+ list(APPEND generated_sources ${expanded_files_cc})
+ list(APPEND generated_headers ${expanded_files_h})
+endmacro(expand_cc)
+
+########################################################################
+# Invoke macro to generate various sources
+########################################################################
+expand_cc(fir_filter_XXX_impl ccc ccf fcc fff fsf scc)
+expand_cc(freq_xlating_fir_filter_XXX_impl ccc ccf fcc fcf scf scc)
+expand_cc(interp_fir_filter_XXX_impl ccc ccf fcc fff fsf scc)
+expand_cc(rational_resampler_base_XXX_impl ccc ccf fcc fff fsf scc)
+
+
+########################################################################
+# Setup the include and linker paths
+########################################################################
+include_directories(
+ ${GR_FILTER_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${VOLK_INCLUDE_DIRS}
+ ${GNURADIO_CORE_INCLUDE_DIRS}
+ ${GR_FFT_INCLUDE_DIRS}
+ ${Boost_INCLUDE_DIRS}
+ ${FFTW3F_INCLUDE_DIRS}
+)
+
+link_directories(${FFT_LIBRARY_DIRS})
+link_directories(${Boost_LIBRARY_DIRS})
+link_directories(${FFTW3F_LIBRARY_DIRS})
+
+########################################################################
+# Setup library
+########################################################################
+list(APPEND filter_sources
+ fir_filter.cc
+ fir_filter_with_buffer.cc
+ fft_filter.cc
+ firdes.cc
+ mmse_fir_interpolator_cc.cc
+ mmse_fir_interpolator_ff.cc
+ pm_remez.cc
+ polyphase_filterbank.cc
+ ${generated_sources}
+ adaptive_fir_ccc_impl.cc
+ adaptive_fir_ccf_impl.cc
+ dc_blocker_cc_impl.cc
+ dc_blocker_ff_impl.cc
+ filter_delay_fc_impl.cc
+ fft_filter_ccc_impl.cc
+ fft_filter_fff_impl.cc
+ fractional_interpolator_cc_impl.cc
+ fractional_interpolator_ff_impl.cc
+ hilbert_fc_impl.cc
+ iir_filter_ffd_impl.cc
+ pfb_arb_resampler_ccf_impl.cc
+ pfb_arb_resampler_fff_impl.cc
+ pfb_channelizer_ccf_impl.cc
+ pfb_decimator_ccf_impl.cc
+ pfb_interpolator_ccf_impl.cc
+ pfb_synthesizer_ccf_impl.cc
+ single_pole_iir_filter_cc_impl.cc
+ single_pole_iir_filter_ff_impl.cc
+ channel_model_impl.cc
+)
+
+list(APPEND filter_libs
+ gnuradio-core
+ gnuradio-fft
+ volk
+ ${Boost_LIBRARIES}
+ ${FFTW3F_LIBRARIES}
+)
+
+add_library(gnuradio-filter SHARED ${filter_sources})
+target_link_libraries(gnuradio-filter ${filter_libs})
+GR_LIBRARY_FOO(gnuradio-filter RUNTIME_COMPONENT "filter_runtime" DEVEL_COMPONENT "filter_devel")
+add_dependencies(gnuradio-filter gnuradio-fft filter_generated_includes filter_generated_swigs)
+
+
+########################################################################
+# QA C++ Code for gr-filter
+########################################################################
+if(ENABLE_TESTING)
+ include(GrTest)
+
+ include_directories(${CPPUNIT_INCLUDE_DIRS})
+ link_directories(${CPPUNIT_LIBRARY_DIRS})
+
+ list(APPEND test_gr_filter_sources
+ ${CMAKE_CURRENT_SOURCE_DIR}/test_gr_filter.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/qa_filter.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/qa_firdes.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/qa_fir_filter_with_buffer.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/qa_mmse_fir_interpolator_cc.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/qa_mmse_fir_interpolator_ff.cc
+ )
+
+ add_executable(test-gr-filter ${test_gr_filter_sources})
+
+ target_link_libraries(
+ test-gr-filter
+ gnuradio-core
+ gnuradio-filter
+ ${Boost_LIBRARIES}
+ ${CPPUNIT_LIBRARIES}
+ )
+
+ GR_ADD_TEST(test_gr_filter test-gr-filter)
+endif(ENABLE_TESTING)
diff --git a/gr-filter/lib/adaptive_fir_ccc_impl.cc b/gr-filter/lib/adaptive_fir_ccc_impl.cc
new file mode 100644
index 000000000..515ef90cd
--- /dev/null
+++ b/gr-filter/lib/adaptive_fir_ccc_impl.cc
@@ -0,0 +1,106 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "adaptive_fir_ccc_impl.h"
+#include <gr_io_signature.h>
+
+namespace gr {
+ namespace filter {
+
+ adaptive_fir_ccc::sptr adaptive_fir_ccc::make(const char *name, int decimation,
+ const std::vector<gr_complex> &taps)
+ {
+ return gnuradio::get_initial_sptr(new adaptive_fir_ccc_impl
+ (name, decimation, taps));
+ }
+
+ adaptive_fir_ccc_impl::adaptive_fir_ccc_impl(const char *name, int decimation,
+ const std::vector<gr_complex> &taps)
+ : gr_sync_decimator(name,
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ decimation),
+ kernel::fir_filter_ccc(decimation, taps),
+ d_updated(false)
+ {
+ set_history(d_ntaps);
+ }
+
+ void
+ adaptive_fir_ccc_impl::set_taps(const std::vector<gr_complex> &taps)
+ {
+ d_new_taps = taps;
+ d_updated = true;
+ }
+
+ std::vector<gr_complex>
+ adaptive_fir_ccc_impl::taps() const
+ {
+ return kernel::fir_filter_ccc::taps();
+ }
+
+ gr_complex
+ adaptive_fir_ccc_impl::error(const gr_complex &out)
+ {
+ return 0;
+ }
+
+ void
+ adaptive_fir_ccc_impl::update_tap(gr_complex &tap, const gr_complex &in)
+ {
+ tap = tap;
+ }
+
+ int
+ adaptive_fir_ccc_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ gr_complex *in = (gr_complex *)input_items[0];
+ gr_complex *out = (gr_complex *)output_items[0];
+
+ if (d_updated) {
+ kernel::fir_filter_ccc::set_taps(d_new_taps);
+ set_history(d_ntaps);
+ d_updated = false;
+ return 0; // history requirements may have changed.
+ }
+
+ // Call base class filtering function that uses
+ // overloaded error and update_tap functions.
+ if (decimation() == 1) {
+ filterN(out, in, noutput_items);
+ }
+ else {
+ filterNdec(out, in, noutput_items,
+ decimation());
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/adaptive_fir_ccc_impl.h b/gr-filter/lib/adaptive_fir_ccc_impl.h
new file mode 100644
index 000000000..fd6274a1d
--- /dev/null
+++ b/gr-filter/lib/adaptive_fir_ccc_impl.h
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_ADAPTIVE_FIR_CCC_IMPL_H
+#define INCLUDED_FILTER_ADAPTIVE_FIR_CCC_IMPL_H
+
+#include <filter/adaptive_fir_ccc.h>
+#include <filter/fir_filter.h>
+#include <gr_types.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API adaptive_fir_ccc_impl : public adaptive_fir_ccc, public kernel::fir_filter_ccc
+ {
+ private:
+ std::vector<gr_complex> d_new_taps;
+ bool d_updated;
+
+ protected:
+ // Override to calculate error signal per output
+ gr_complex error(const gr_complex &out);
+
+ // Override to calculate new weight from old, corresponding input
+ void update_tap(gr_complex &tap, const gr_complex &in);
+
+ public:
+ void set_taps(const std::vector<gr_complex> &taps);
+ std::vector<gr_complex> taps() const;
+
+ adaptive_fir_ccc_impl(const char *name, int decimation,
+ const std::vector<gr_complex> &taps);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_ADAPTIVE_FIR_CCC_IMPL_H */
diff --git a/gr-filter/lib/adaptive_fir_ccf_impl.cc b/gr-filter/lib/adaptive_fir_ccf_impl.cc
new file mode 100644
index 000000000..004a9286b
--- /dev/null
+++ b/gr-filter/lib/adaptive_fir_ccf_impl.cc
@@ -0,0 +1,106 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "adaptive_fir_ccf_impl.h"
+#include <gr_io_signature.h>
+
+namespace gr {
+ namespace filter {
+
+ adaptive_fir_ccf::sptr adaptive_fir_ccf::make(const char *name, int decimation,
+ const std::vector<float> &taps)
+ {
+ return gnuradio::get_initial_sptr(new adaptive_fir_ccf_impl
+ (name, decimation, taps));
+ }
+
+ adaptive_fir_ccf_impl::adaptive_fir_ccf_impl(const char *name, int decimation,
+ const std::vector<float> &taps)
+ : gr_sync_decimator(name,
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ decimation),
+ kernel::fir_filter_ccf(decimation, taps),
+ d_updated(false)
+ {
+ set_history(d_ntaps);
+ }
+
+ void
+ adaptive_fir_ccf_impl::set_taps(const std::vector<float> &taps)
+ {
+ d_new_taps = taps;
+ d_updated = true;
+ }
+
+ std::vector<float>
+ adaptive_fir_ccf_impl::taps()
+ {
+ return kernel::fir_filter_ccf::taps();
+ }
+
+ float
+ adaptive_fir_ccf_impl::error(const gr_complex &out)
+ {
+ return 0;
+ }
+
+ void
+ adaptive_fir_ccf_impl::update_tap(float &tap, const gr_complex &in)
+ {
+ tap = tap;
+ }
+
+ int
+ adaptive_fir_ccf_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ gr_complex *in = (gr_complex *)input_items[0];
+ gr_complex *out = (gr_complex *)output_items[0];
+
+ if (d_updated) {
+ kernel::fir_filter_ccf::set_taps(d_new_taps);
+ set_history(d_ntaps);
+ d_updated = false;
+ return 0; // history requirements may have changed.
+ }
+
+ // Call base class filtering function that uses
+ // overloaded error and update_tap functions.
+ if (decimation() == 1) {
+ filterN(out, in, noutput_items);
+ }
+ else {
+ filterNdec(out, in, noutput_items,
+ decimation());
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/adaptive_fir_ccf_impl.h b/gr-filter/lib/adaptive_fir_ccf_impl.h
new file mode 100644
index 000000000..a0c9581ea
--- /dev/null
+++ b/gr-filter/lib/adaptive_fir_ccf_impl.h
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_ADAPTIVE_FIR_CCF_IMPL_H
+#define INCLUDED_FILTER_ADAPTIVE_FIR_CCF_IMPL_H
+
+#include <filter/adaptive_fir_ccf.h>
+#include <filter/fir_filter.h>
+#include <gr_types.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API adaptive_fir_ccf_impl : public adaptive_fir_ccf, public kernel::fir_filter_ccf
+ {
+ private:
+ std::vector<float> d_new_taps;
+ bool d_updated;
+
+ protected:
+ // Override to calculate error signal per output
+ float error(const gr_complex &out);
+
+ // Override to calculate new weight from old, corresponding input
+ void update_tap(float &tap, const gr_complex &in);
+
+ public:
+ void set_taps(const std::vector<float> &taps);
+ std::vector<float> taps();
+
+ adaptive_fir_ccf_impl(const char *name, int decimation,
+ const std::vector<float> &taps);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_ADAPTIVE_FIR_CCF_IMPL_H */
diff --git a/gr-filter/lib/channel_model_impl.cc b/gr-filter/lib/channel_model_impl.cc
new file mode 100644
index 000000000..f9e995479
--- /dev/null
+++ b/gr-filter/lib/channel_model_impl.cc
@@ -0,0 +1,135 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "channel_model_impl.h"
+#include <gr_io_signature.h>
+#include <iostream>
+
+namespace gr {
+ namespace filter {
+
+ channel_model::sptr
+ channel_model::make(double noise_voltage,
+ double frequency_offset,
+ double epsilon,
+ const std::vector<gr_complex> &taps,
+ double noise_seed)
+ {
+ return gnuradio::get_initial_sptr
+ (new channel_model_impl(noise_voltage,
+ frequency_offset,
+ epsilon,
+ taps,
+ noise_seed));
+ }
+
+ // Hierarchical block constructor
+ channel_model_impl::channel_model_impl(double noise_voltage,
+ double frequency_offset,
+ double epsilon,
+ const std::vector<gr_complex> &taps,
+ double noise_seed)
+ : gr_hier_block2("gr_channel_model",
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ gr_make_io_signature(1, 1, sizeof(gr_complex)))
+ {
+ d_taps = taps;
+ while(d_taps.size() < 2) {
+ d_taps.push_back(0);
+ }
+
+ d_timing_offset = fractional_interpolator_cc::make(0, epsilon);
+
+ d_multipath = fir_filter_ccc::make(1, d_taps);
+
+ d_noise_adder = gr_make_add_cc();
+ d_noise = gr_make_noise_source_c(GR_GAUSSIAN, noise_voltage, noise_seed);
+ d_freq_offset = gr_make_sig_source_c(1, GR_SIN_WAVE, frequency_offset, 1.0, 0.0);
+ d_mixer_offset = gr_make_multiply_cc();
+
+ connect(self(), 0, d_timing_offset, 0);
+ connect(d_timing_offset, 0, d_multipath, 0);
+ connect(d_multipath, 0, d_mixer_offset, 0);
+ connect(d_freq_offset, 0, d_mixer_offset, 1);
+ connect(d_mixer_offset, 0, d_noise_adder, 1);
+ connect(d_noise, 0, d_noise_adder, 0);
+ connect(d_noise_adder, 0, self(), 0);
+ }
+
+ channel_model_impl::~channel_model_impl()
+ {
+ }
+
+ void
+ channel_model_impl::set_noise_voltage(double noise_voltage)
+ {
+ d_noise->set_amplitude(noise_voltage);
+ }
+
+ void
+ channel_model_impl::set_frequency_offset(double frequency_offset)
+ {
+ d_freq_offset->set_frequency(frequency_offset);
+ }
+
+ void
+ channel_model_impl::set_taps(const std::vector<gr_complex> &taps)
+ {
+ d_taps = taps;
+ while(d_taps.size() < 2) {
+ d_taps.push_back(0);
+ }
+ d_multipath->set_taps(d_taps);
+ }
+
+ void
+ channel_model_impl::set_timing_offset(double epsilon)
+ {
+ d_timing_offset->set_interp_ratio(epsilon);
+ }
+
+ double
+ channel_model_impl::noise_voltage() const
+ {
+ return d_noise->amplitude();
+ }
+
+ double
+ channel_model_impl::frequency_offset() const
+ {
+ return d_freq_offset->frequency();
+ }
+
+ std::vector<gr_complex>
+ channel_model_impl::taps() const
+ {
+ return d_multipath->taps();
+ }
+
+ double
+ channel_model_impl::timing_offset() const
+ {
+ return d_timing_offset->interp_ratio();
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/channel_model_impl.h b/gr-filter/lib/channel_model_impl.h
new file mode 100644
index 000000000..95a63d790
--- /dev/null
+++ b/gr-filter/lib/channel_model_impl.h
@@ -0,0 +1,74 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_CHANNEL_MODEL_IMPL_H
+#define INCLUDED_FILTER_CHANNEL_MODEL_IMPL_H
+
+#include <gr_top_block.h>
+#include <gr_sig_source_c.h>
+#include <gr_add_cc.h>
+#include <gr_multiply_cc.h>
+#include <gr_noise_source_c.h>
+#include <filter/channel_model.h>
+#include <filter/fractional_interpolator_cc.h>
+#include <filter/fir_filter_ccc.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API channel_model_impl : public channel_model
+ {
+ private:
+ gr_sig_source_c_sptr d_freq_offset;
+ gr_add_cc_sptr d_noise_adder;
+ gr_noise_source_c_sptr d_noise;
+ gr_multiply_cc_sptr d_mixer_offset;
+
+ fractional_interpolator_cc::sptr d_timing_offset;
+ fir_filter_ccc::sptr d_multipath;
+
+ std::vector<gr_complex> d_taps;
+
+ public:
+ channel_model_impl(double noise_voltage,
+ double frequency_offset,
+ double epsilon,
+ const std::vector<gr_complex> &taps,
+ double noise_seed);
+
+ ~channel_model_impl();
+
+ void set_noise_voltage(double noise_voltage);
+ void set_frequency_offset(double frequency_offset);
+ void set_taps(const std::vector<gr_complex> &taps);
+ void set_timing_offset(double epsilon);
+
+ double noise_voltage() const;
+ double frequency_offset() const;
+ std::vector<gr_complex> taps() const;
+ double timing_offset() const;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_CHANNEL_MODEL_IMPL_H */
diff --git a/gr-filter/lib/dc_blocker_cc_impl.cc b/gr-filter/lib/dc_blocker_cc_impl.cc
new file mode 100644
index 000000000..663ba94f1
--- /dev/null
+++ b/gr-filter/lib/dc_blocker_cc_impl.cc
@@ -0,0 +1,144 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "dc_blocker_cc_impl.h"
+#include <gr_io_signature.h>
+#include <cstdio>
+
+namespace gr {
+ namespace filter {
+
+ moving_averager_c::moving_averager_c(int D)
+ : d_length(D), d_out(0), d_out_d1(0), d_out_d2(0)
+ {
+ d_delay_line = std::deque<gr_complex>(d_length-1, gr_complex(0,0));
+ }
+
+ moving_averager_c::~moving_averager_c()
+ {
+ }
+
+ gr_complex
+ moving_averager_c::filter(gr_complex x)
+ {
+ d_out_d1 = d_out;
+ d_delay_line.push_back(x);
+ d_out = d_delay_line[0];
+ d_delay_line.pop_front();
+
+ gr_complex y = x - d_out_d1 + d_out_d2;
+ d_out_d2 = y;
+
+ return (y / (float)(d_length));
+ }
+
+
+
+ dc_blocker_cc::sptr dc_blocker_cc::make(int D, bool long_form)
+ {
+ return gnuradio::get_initial_sptr(new dc_blocker_cc_impl(D, long_form));
+ }
+
+
+ dc_blocker_cc_impl::dc_blocker_cc_impl(int D, bool long_form)
+ : gr_sync_block("dc_blocker_cc",
+ gr_make_io_signature (1, 1, sizeof(gr_complex)),
+ gr_make_io_signature (1, 1, sizeof(gr_complex))),
+ d_length(D), d_long_form(long_form)
+ {
+ if(d_long_form) {
+ d_ma_0 = new moving_averager_c(D);
+ d_ma_1 = new moving_averager_c(D);
+ d_ma_2 = new moving_averager_c(D);
+ d_ma_3 = new moving_averager_c(D);
+ d_delay_line = std::deque<gr_complex>(d_length-1, gr_complex(0,0));
+ }
+ else {
+ d_ma_0 = new moving_averager_c(D);
+ d_ma_1 = new moving_averager_c(D);
+ }
+ }
+
+ dc_blocker_cc_impl::~dc_blocker_cc_impl()
+ {
+ if(d_long_form) {
+ delete d_ma_0;
+ delete d_ma_1;
+ delete d_ma_2;
+ delete d_ma_3;
+ }
+ else {
+ delete d_ma_0;
+ delete d_ma_1;
+ }
+ }
+
+ int
+ dc_blocker_cc_impl::group_delay()
+ {
+ if(d_long_form)
+ return (2*d_length-2);
+ else
+ return d_length - 1;
+ }
+
+ int
+ dc_blocker_cc_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const gr_complex *in = (const gr_complex*)input_items[0];
+ gr_complex *out = (gr_complex*)output_items[0];
+
+ if(d_long_form) {
+ gr_complex y1, y2, y3, y4, d;
+ for(int i = 0; i < noutput_items; i++) {
+ y1 = d_ma_0->filter(in[i]);
+ y2 = d_ma_1->filter(y1);
+ y3 = d_ma_2->filter(y2);
+ y4 = d_ma_3->filter(y3);
+
+ d_delay_line.push_back(d_ma_0->delayed_sig());
+ d = d_delay_line[0];
+ d_delay_line.pop_front();
+
+ out[i] = d - y4;
+ }
+ }
+ else {
+ gr_complex y1, y2;
+ for(int i = 0; i < noutput_items; i++) {
+ y1 = d_ma_0->filter(in[i]);
+ y2 = d_ma_1->filter(y1);
+ out[i] = d_ma_0->delayed_sig() - y2;
+ }
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/dc_blocker_cc_impl.h b/gr-filter/lib/dc_blocker_cc_impl.h
new file mode 100644
index 000000000..6f8bc16c7
--- /dev/null
+++ b/gr-filter/lib/dc_blocker_cc_impl.h
@@ -0,0 +1,76 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_FILTER_DC_BLOCKER_CC_IMPL_H
+#define INCLUDED_FILTER_DC_BLOCKER_CC_IMPL_H
+
+#include <filter/dc_blocker_cc.h>
+#include <deque>
+
+namespace gr {
+ namespace filter {
+
+ class moving_averager_c
+ {
+ public:
+ moving_averager_c(int D);
+ ~moving_averager_c();
+
+ gr_complex filter(gr_complex x);
+ gr_complex delayed_sig() { return d_out; }
+
+ private:
+ int d_length;
+ gr_complex d_out, d_out_d1, d_out_d2;
+ std::deque<gr_complex> d_delay_line;
+ };
+
+ class FILTER_API dc_blocker_cc_impl : public dc_blocker_cc
+ {
+ private:
+ int d_length;
+ bool d_long_form;
+ moving_averager_c *d_ma_0;
+ moving_averager_c *d_ma_1;
+ moving_averager_c *d_ma_2;
+ moving_averager_c *d_ma_3;
+ std::deque<gr_complex> d_delay_line;
+
+ public:
+ dc_blocker_cc_impl(int D, bool long_form);
+
+ ~dc_blocker_cc_impl();
+
+ int group_delay();
+
+ //int set_length(int D);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_DC_BLOCKER_CC_IMPL_H */
diff --git a/gr-filter/lib/dc_blocker_ff_impl.cc b/gr-filter/lib/dc_blocker_ff_impl.cc
new file mode 100644
index 000000000..22822d147
--- /dev/null
+++ b/gr-filter/lib/dc_blocker_ff_impl.cc
@@ -0,0 +1,142 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "dc_blocker_ff_impl.h"
+#include <gr_io_signature.h>
+#include <cstdio>
+
+namespace gr {
+ namespace filter {
+
+ moving_averager_f::moving_averager_f(int D)
+ : d_length(D), d_out(0), d_out_d1(0), d_out_d2(0)
+ {
+ d_delay_line = std::deque<float>(d_length-1, 0);
+ }
+
+ moving_averager_f::~moving_averager_f()
+ {
+ }
+
+ float
+ moving_averager_f::filter(float x)
+ {
+ d_out_d1 = d_out;
+ d_delay_line.push_back(x);
+ d_out = d_delay_line[0];
+ d_delay_line.pop_front();
+
+ float y = x - d_out_d1 + d_out_d2;
+ d_out_d2 = y;
+
+ return (y / (float)(d_length));
+ }
+
+
+ dc_blocker_ff::sptr dc_blocker_ff::make(int D, bool long_form)
+ {
+ return gnuradio::get_initial_sptr(new dc_blocker_ff_impl(D, long_form));
+ }
+
+ dc_blocker_ff_impl::dc_blocker_ff_impl(int D, bool long_form)
+ : gr_sync_block("dc_blocker_ff",
+ gr_make_io_signature (1, 1, sizeof(float)),
+ gr_make_io_signature (1, 1, sizeof(float))),
+ d_length(D), d_long_form(long_form)
+ {
+ if(d_long_form) {
+ d_ma_0 = new moving_averager_f(D);
+ d_ma_1 = new moving_averager_f(D);
+ d_ma_2 = new moving_averager_f(D);
+ d_ma_3 = new moving_averager_f(D);
+ d_delay_line = std::deque<float>(d_length-1, 0);
+ }
+ else {
+ d_ma_0 = new moving_averager_f(D);
+ d_ma_1 = new moving_averager_f(D);
+ }
+ }
+
+ dc_blocker_ff_impl::~dc_blocker_ff_impl()
+ {
+ if(d_long_form) {
+ delete d_ma_0;
+ delete d_ma_1;
+ delete d_ma_2;
+ delete d_ma_3;
+ }
+ else {
+ delete d_ma_0;
+ delete d_ma_1;
+ }
+ }
+
+ int
+ dc_blocker_ff_impl::group_delay()
+ {
+ if(d_long_form)
+ return (2*d_length-2);
+ else
+ return d_length - 1;
+ }
+
+ int
+ dc_blocker_ff_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const float *in = (const float*)input_items[0];
+ float *out = (float*)output_items[0];
+
+ if(d_long_form) {
+ float y1, y2, y3, y4, d;
+ for(int i = 0; i < noutput_items; i++) {
+ y1 = d_ma_0->filter(in[i]);
+ y2 = d_ma_1->filter(y1);
+ y3 = d_ma_2->filter(y2);
+ y4 = d_ma_3->filter(y3);
+
+ d_delay_line.push_back(d_ma_0->delayed_sig());
+ d = d_delay_line[0];
+ d_delay_line.pop_front();
+
+ out[i] = d - y4;
+ }
+ }
+ else {
+ float y1, y2;
+ for(int i = 0; i < noutput_items; i++) {
+ y1 = d_ma_0->filter(in[i]);
+ y2 = d_ma_1->filter(y1);
+ out[i] = d_ma_0->delayed_sig() - y2;
+ }
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/dc_blocker_ff_impl.h b/gr-filter/lib/dc_blocker_ff_impl.h
new file mode 100644
index 000000000..5ae60e2e4
--- /dev/null
+++ b/gr-filter/lib/dc_blocker_ff_impl.h
@@ -0,0 +1,76 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_FILTER_DC_BLOCKER_FF_IMPL_H
+#define INCLUDED_FILTER_DC_BLOCKER_FF_IMPL_H
+
+#include <filter/dc_blocker_ff.h>
+#include <deque>
+
+namespace gr {
+ namespace filter {
+
+ class moving_averager_f
+ {
+ public:
+ moving_averager_f(int D);
+ ~moving_averager_f();
+
+ float filter(float x);
+ float delayed_sig() { return d_out; }
+
+ private:
+ int d_length;
+ float d_out, d_out_d1, d_out_d2;
+ std::deque<float> d_delay_line;
+ };
+
+ class FILTER_API dc_blocker_ff_impl : public dc_blocker_ff
+ {
+ private:
+ int d_length;
+ bool d_long_form;
+ moving_averager_f *d_ma_0;
+ moving_averager_f *d_ma_1;
+ moving_averager_f *d_ma_2;
+ moving_averager_f *d_ma_3;
+ std::deque<float> d_delay_line;
+
+ public:
+ dc_blocker_ff_impl(int D, bool long_form);
+
+ ~dc_blocker_ff_impl();
+
+ int group_delay();
+
+ //int set_length(int D);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_DC_BLOCKER_FF_IMPL_H */
diff --git a/gr-filter/lib/fft_filter.cc b/gr-filter/lib/fft_filter.cc
new file mode 100644
index 000000000..1b256a3da
--- /dev/null
+++ b/gr-filter/lib/fft_filter.cc
@@ -0,0 +1,316 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <filter/fft_filter.h>
+#include <volk/volk.h>
+#include <iostream>
+#include <cstring>
+
+namespace gr {
+ namespace filter {
+ namespace kernel {
+
+ #define VERBOSE 0
+
+ fft_filter_fff::fft_filter_fff(int decimation,
+ const std::vector<float> &taps,
+ int nthreads)
+ : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0),
+ d_invfft(0), d_nthreads(nthreads)
+ {
+ set_taps(taps);
+ }
+
+ fft_filter_fff::~fft_filter_fff()
+ {
+ delete d_fwdfft;
+ delete d_invfft;
+ fft::free(d_xformed_taps);
+ }
+
+ /*
+ * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps
+ */
+ int
+ fft_filter_fff::set_taps(const std::vector<float> &taps)
+ {
+ int i = 0;
+ compute_sizes(taps.size());
+
+ d_tail.resize(tailsize());
+ for(i = 0; i < tailsize(); i++)
+ d_tail[i] = 0;
+
+ float *in = d_fwdfft->get_inbuf();
+ gr_complex *out = d_fwdfft->get_outbuf();
+
+ float scale = 1.0 / d_fftsize;
+
+ // Compute forward xform of taps.
+ // Copy taps into first ntaps slots, then pad with zeros
+ for (i = 0; i < d_ntaps; i++)
+ in[i] = taps[i] * scale;
+
+ for (; i < d_fftsize; i++)
+ in[i] = 0;
+
+ d_fwdfft->execute(); // do the xform
+
+ // now copy output to d_xformed_taps
+ for (i = 0; i < d_fftsize/2+1; i++)
+ d_xformed_taps[i] = out[i];
+
+ return d_nsamples;
+ }
+
+ // determine and set d_ntaps, d_nsamples, d_fftsize
+ void
+ fft_filter_fff::compute_sizes(int ntaps)
+ {
+ int old_fftsize = d_fftsize;
+ d_ntaps = ntaps;
+ d_fftsize = (int) (2 * pow(2.0, ceil(log(double(ntaps)) / log(2.0))));
+ d_nsamples = d_fftsize - d_ntaps + 1;
+
+ if(VERBOSE) {
+ std::cerr << "fft_filter_fff: ntaps = " << d_ntaps
+ << " fftsize = " << d_fftsize
+ << " nsamples = " << d_nsamples << std::endl;
+ }
+
+ // compute new plans
+ if(d_fftsize != old_fftsize) {
+ delete d_fwdfft;
+ delete d_invfft;
+ d_fwdfft = new fft::fft_real_fwd(d_fftsize);
+ d_invfft = new fft::fft_real_rev(d_fftsize);
+ d_xformed_taps = fft::malloc_complex(d_fftsize/2+1);
+ }
+ }
+
+ void
+ fft_filter_fff::set_nthreads(int n)
+ {
+ d_nthreads = n;
+ if(d_fwdfft)
+ d_fwdfft->set_nthreads(n);
+ if(d_invfft)
+ d_invfft->set_nthreads(n);
+ }
+
+ int
+ fft_filter_fff::nthreads() const
+ {
+ return d_nthreads;
+ }
+
+ int
+ fft_filter_fff::filter(int nitems, const float *input, float *output)
+ {
+ int dec_ctr = 0;
+ int j = 0;
+ int ninput_items = nitems * d_decimation;
+
+ for (int i = 0; i < ninput_items; i += d_nsamples){
+
+ memcpy(d_fwdfft->get_inbuf(), &input[i], d_nsamples * sizeof(float));
+
+ for (j = d_nsamples; j < d_fftsize; j++)
+ d_fwdfft->get_inbuf()[j] = 0;
+
+ d_fwdfft->execute(); // compute fwd xform
+
+ gr_complex *a = d_fwdfft->get_outbuf();
+ gr_complex *b = d_xformed_taps;
+ gr_complex *c = d_invfft->get_inbuf();
+
+ volk_32fc_x2_multiply_32fc_a(c, a, b, d_fftsize/2+1);
+
+ d_invfft->execute(); // compute inv xform
+
+ // add in the overlapping tail
+ for (j = 0; j < tailsize(); j++)
+ d_invfft->get_outbuf()[j] += d_tail[j];
+
+ // copy nsamples to output
+ j = dec_ctr;
+ while (j < d_nsamples) {
+ *output++ = d_invfft->get_outbuf()[j];
+ j += d_decimation;
+ }
+ dec_ctr = (j - d_nsamples);
+
+ // stash the tail
+ memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples,
+ tailsize() * sizeof(float));
+ }
+
+ return nitems;
+ }
+
+
+ /**************************************************************/
+
+
+ fft_filter_ccc::fft_filter_ccc(int decimation,
+ const std::vector<gr_complex> &taps,
+ int nthreads)
+ : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0),
+ d_invfft(0), d_nthreads(nthreads)
+ {
+ set_taps(taps);
+ }
+
+ fft_filter_ccc::~fft_filter_ccc()
+ {
+ delete d_fwdfft;
+ delete d_invfft;
+ fft::free(d_xformed_taps);
+ }
+
+ /*
+ * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps
+ */
+ int
+ fft_filter_ccc::set_taps(const std::vector<gr_complex> &taps)
+ {
+ int i = 0;
+ compute_sizes(taps.size());
+
+ d_tail.resize(tailsize());
+ for(i = 0; i < tailsize(); i++)
+ d_tail[i] = 0;
+
+ gr_complex *in = d_fwdfft->get_inbuf();
+ gr_complex *out = d_fwdfft->get_outbuf();
+
+ float scale = 1.0 / d_fftsize;
+
+ // Compute forward xform of taps.
+ // Copy taps into first ntaps slots, then pad with zeros
+ for(i = 0; i < d_ntaps; i++)
+ in[i] = taps[i] * scale;
+
+ for(; i < d_fftsize; i++)
+ in[i] = 0;
+
+ d_fwdfft->execute(); // do the xform
+
+ // now copy output to d_xformed_taps
+ for(i = 0; i < d_fftsize; i++)
+ d_xformed_taps[i] = out[i];
+
+ return d_nsamples;
+ }
+
+ // determine and set d_ntaps, d_nsamples, d_fftsize
+ void
+ fft_filter_ccc::compute_sizes(int ntaps)
+ {
+ int old_fftsize = d_fftsize;
+ d_ntaps = ntaps;
+ d_fftsize = (int) (2 * pow(2.0, ceil(log(double(ntaps)) / log(2.0))));
+ d_nsamples = d_fftsize - d_ntaps + 1;
+
+ if(VERBOSE) {
+ std::cerr << "fft_filter_ccc: ntaps = " << d_ntaps
+ << " fftsize = " << d_fftsize
+ << " nsamples = " << d_nsamples << std::endl;
+ }
+
+ // compute new plans
+ if(d_fftsize != old_fftsize) {
+ delete d_fwdfft;
+ delete d_invfft;
+ d_fwdfft = new fft::fft_complex(d_fftsize, true, d_nthreads);
+ d_invfft = new fft::fft_complex(d_fftsize, false, d_nthreads);
+ d_xformed_taps = fft::malloc_complex(d_fftsize);
+ }
+ }
+
+ void
+ fft_filter_ccc::set_nthreads(int n)
+ {
+ d_nthreads = n;
+ if(d_fwdfft)
+ d_fwdfft->set_nthreads(n);
+ if(d_invfft)
+ d_invfft->set_nthreads(n);
+ }
+
+ int
+ fft_filter_ccc::nthreads() const
+ {
+ return d_nthreads;
+ }
+
+ int
+ fft_filter_ccc::filter(int nitems, const gr_complex *input, gr_complex *output)
+ {
+ int dec_ctr = 0;
+ int j = 0;
+ int ninput_items = nitems * d_decimation;
+
+ for(int i = 0; i < ninput_items; i += d_nsamples) {
+ memcpy(d_fwdfft->get_inbuf(), &input[i], d_nsamples * sizeof(gr_complex));
+
+ for(j = d_nsamples; j < d_fftsize; j++)
+ d_fwdfft->get_inbuf()[j] = 0;
+
+ d_fwdfft->execute(); // compute fwd xform
+
+ gr_complex *a = d_fwdfft->get_outbuf();
+ gr_complex *b = d_xformed_taps;
+ gr_complex *c = d_invfft->get_inbuf();
+
+ volk_32fc_x2_multiply_32fc_a(c, a, b, d_fftsize);
+
+ d_invfft->execute(); // compute inv xform
+
+ // add in the overlapping tail
+
+ for(j = 0; j < tailsize(); j++)
+ d_invfft->get_outbuf()[j] += d_tail[j];
+
+ // copy nsamples to output
+ j = dec_ctr;
+ while(j < d_nsamples) {
+ *output++ = d_invfft->get_outbuf()[j];
+ j += d_decimation;
+ }
+ dec_ctr = (j - d_nsamples);
+
+ // stash the tail
+ memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples,
+ tailsize() * sizeof(gr_complex));
+ }
+
+ return nitems;
+ }
+
+ } /* namespace kernel */
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/fft_filter_ccc_impl.cc b/gr-filter/lib/fft_filter_ccc_impl.cc
new file mode 100644
index 000000000..0a2002991
--- /dev/null
+++ b/gr-filter/lib/fft_filter_ccc_impl.cc
@@ -0,0 +1,118 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "fft_filter_ccc_impl.h"
+#include <gr_io_signature.h>
+
+#include <math.h>
+#include <assert.h>
+#include <stdexcept>
+
+namespace gr {
+ namespace filter {
+
+ fft_filter_ccc::sptr fft_filter_ccc::make(int decimation,
+ const std::vector<gr_complex> &taps,
+ int nthreads)
+ {
+ return gnuradio::get_initial_sptr(new fft_filter_ccc_impl
+ (decimation, taps, nthreads));
+ }
+
+ fft_filter_ccc_impl::fft_filter_ccc_impl(int decimation,
+ const std::vector<gr_complex> &taps,
+ int nthreads)
+ : gr_sync_decimator("fft_filter_ccc",
+ gr_make_io_signature (1, 1, sizeof(gr_complex)),
+ gr_make_io_signature (1, 1, sizeof(gr_complex)),
+ decimation),
+ d_updated(false)
+ {
+ set_history(1);
+
+ d_filter = new kernel::fft_filter_ccc(decimation, taps, nthreads);
+
+ d_new_taps = taps;
+ d_nsamples = d_filter->set_taps(taps);
+ set_output_multiple(d_nsamples);
+ }
+
+ fft_filter_ccc_impl::~fft_filter_ccc_impl()
+ {
+ delete d_filter;
+ }
+
+ void
+ fft_filter_ccc_impl::set_taps(const std::vector<gr_complex> &taps)
+ {
+ d_new_taps = taps;
+ d_updated = true;
+ }
+
+ std::vector<gr_complex>
+ fft_filter_ccc_impl::taps() const
+ {
+ return d_new_taps;
+ }
+
+ void
+ fft_filter_ccc_impl::set_nthreads(int n)
+ {
+ if(d_filter)
+ d_filter->set_nthreads(n);
+ }
+
+ int
+ fft_filter_ccc_impl::nthreads() const
+ {
+ if(d_filter)
+ return d_filter->nthreads();
+ else
+ return 0;
+ }
+
+ int
+ fft_filter_ccc_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const gr_complex *in = (const gr_complex *) input_items[0];
+ gr_complex *out = (gr_complex *) output_items[0];
+
+ if (d_updated){
+ d_nsamples = d_filter->set_taps(d_new_taps);
+ d_updated = false;
+ set_output_multiple(d_nsamples);
+ return 0; // output multiple may have changed
+ }
+
+ d_filter->filter(noutput_items, in, out);
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/fft_filter_ccc_impl.h b/gr-filter/lib/fft_filter_ccc_impl.h
new file mode 100644
index 000000000..82be00915
--- /dev/null
+++ b/gr-filter/lib/fft_filter_ccc_impl.h
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDED_FILTER_FFT_FILTER_CCC_IMPL_H
+#define INCLUDED_FILTER_FFT_FILTER_CCC_IMPL_H
+
+#include <filter/api.h>
+#include <filter/fft_filter.h>
+#include <filter/fft_filter_ccc.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API fft_filter_ccc_impl : public fft_filter_ccc
+ {
+ private:
+ int d_nsamples;
+ bool d_updated;
+ kernel::fft_filter_ccc *d_filter;
+ std::vector<gr_complex> d_new_taps;
+
+ public:
+ fft_filter_ccc_impl(int decimation,
+ const std::vector<gr_complex> &taps,
+ int nthreads=1);
+
+ ~fft_filter_ccc_impl();
+
+ void set_taps(const std::vector<gr_complex> &taps);
+ std::vector<gr_complex> taps() const;
+
+ void set_nthreads(int n);
+ int nthreads() const;
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_FFT_FILTER_CCC_IMPL_H */
diff --git a/gr-filter/lib/fft_filter_fff_impl.cc b/gr-filter/lib/fft_filter_fff_impl.cc
new file mode 100644
index 000000000..1d6eb02db
--- /dev/null
+++ b/gr-filter/lib/fft_filter_fff_impl.cc
@@ -0,0 +1,119 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "fft_filter_fff_impl.h"
+#include <gr_io_signature.h>
+
+#include <math.h>
+#include <assert.h>
+#include <stdexcept>
+
+namespace gr {
+ namespace filter {
+
+ fft_filter_fff::sptr fft_filter_fff::make(int decimation,
+ const std::vector<float> &taps,
+ int nthreads)
+ {
+ return gnuradio::get_initial_sptr(new fft_filter_fff_impl
+ (decimation, taps, nthreads));
+ }
+
+
+ fft_filter_fff_impl::fft_filter_fff_impl(int decimation,
+ const std::vector<float> &taps,
+ int nthreads)
+ : gr_sync_decimator("fft_filter_fff",
+ gr_make_io_signature (1, 1, sizeof(float)),
+ gr_make_io_signature (1, 1, sizeof(float)),
+ decimation),
+ d_updated(false)
+ {
+ set_history(1);
+
+ d_filter = new kernel::fft_filter_fff(decimation, taps, nthreads);
+
+ d_new_taps = taps;
+ d_nsamples = d_filter->set_taps(taps);
+ set_output_multiple(d_nsamples);
+ }
+
+ fft_filter_fff_impl::~fft_filter_fff_impl()
+ {
+ delete d_filter;
+ }
+
+ void
+ fft_filter_fff_impl::set_taps(const std::vector<float> &taps)
+ {
+ d_new_taps = taps;
+ d_updated = true;
+ }
+
+ std::vector<float>
+ fft_filter_fff_impl::taps() const
+ {
+ return d_new_taps;
+ }
+
+ void
+ fft_filter_fff_impl::set_nthreads(int n)
+ {
+ if(d_filter)
+ d_filter->set_nthreads(n);
+ }
+
+ int
+ fft_filter_fff_impl::nthreads() const
+ {
+ if(d_filter)
+ return d_filter->nthreads();
+ else
+ return 0;
+ }
+
+ int
+ fft_filter_fff_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const float *in = (const float *)input_items[0];
+ float *out = (float *)output_items[0];
+
+ if (d_updated){
+ d_nsamples = d_filter->set_taps(d_new_taps);
+ d_updated = false;
+ set_output_multiple(d_nsamples);
+ return 0; // output multiple may have changed
+ }
+
+ d_filter->filter(noutput_items, in, out);
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/fft_filter_fff_impl.h b/gr-filter/lib/fft_filter_fff_impl.h
new file mode 100644
index 000000000..df35d3df7
--- /dev/null
+++ b/gr-filter/lib/fft_filter_fff_impl.h
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDED_FILTER_FFT_FILTER_FFF_IMPL_H
+#define INCLUDED_FILTER_FFT_FILTER_FFF_IMPL_H
+
+#include <filter/api.h>
+#include <filter/fft_filter.h>
+#include <filter/fft_filter_fff.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API fft_filter_fff_impl : public fft_filter_fff
+ {
+ private:
+ int d_nsamples;
+ bool d_updated;
+ kernel::fft_filter_fff *d_filter;
+ std::vector<float> d_new_taps;
+
+ public:
+ fft_filter_fff_impl(int decimation,
+ const std::vector<float> &taps,
+ int nthreads=1);
+
+ ~fft_filter_fff_impl();
+
+ void set_taps(const std::vector<float> &taps);
+ std::vector<float> taps() const;
+
+ void set_nthreads(int n);
+ int nthreads() const;
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_FFT_FILTER_FFF_IMPL_H */
diff --git a/gr-filter/lib/filter_delay_fc_impl.cc b/gr-filter/lib/filter_delay_fc_impl.cc
new file mode 100644
index 000000000..3bb550864
--- /dev/null
+++ b/gr-filter/lib/filter_delay_fc_impl.cc
@@ -0,0 +1,112 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "filter_delay_fc_impl.h"
+#include <volk/volk.h>
+
+namespace gr {
+ namespace filter {
+
+ filter_delay_fc::sptr filter_delay_fc::make(const std::vector<float> &taps)
+ {
+ return gnuradio::get_initial_sptr(new filter_delay_fc_impl(taps));
+ }
+
+ filter_delay_fc_impl::filter_delay_fc_impl(const std::vector<float> &taps)
+ : gr_sync_block("filter_delay_fc",
+ gr_make_io_signature(1, 2, sizeof(float)),
+ gr_make_io_signature(1, 1, sizeof(gr_complex))),
+ d_update(false)
+ {
+ d_taps = taps;
+ d_fir = new kernel::fir_filter_fff(1, taps);
+ d_delay = d_fir->ntaps() / 2;
+ set_history(d_fir->ntaps());
+
+ const int alignment_multiple =
+ volk_get_alignment() / sizeof(float);
+ set_alignment(std::max(1, alignment_multiple));
+ }
+
+ filter_delay_fc_impl::~filter_delay_fc_impl()
+ {
+ delete d_fir;
+ }
+
+ std::vector<float>
+ filter_delay_fc_impl::taps()
+ {
+ return d_fir->taps();
+ }
+
+ void
+ filter_delay_fc_impl::set_taps(const std::vector<float> &taps)
+ {
+ // don't reset taps in case history changes
+ d_taps = taps;
+ d_update = true;
+ }
+
+ int
+ filter_delay_fc_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ float *in0 = (float *)input_items[0];
+ float *in1 = (float *)input_items[1];
+ gr_complex *out = (gr_complex *)output_items[0];
+
+ if(d_update) {
+ d_fir->set_taps(d_taps);
+ d_delay = d_fir->ntaps() / 2;
+ set_history(d_fir->ntaps());
+ return 0;
+ }
+
+ switch(input_items.size ()) {
+ case 1:
+ for(int i = 0; i < noutput_items; i++) {
+ out[i] = gr_complex(in0[i + d_delay],
+ d_fir->filter(&in0[i]));
+ }
+ break;
+
+ case 2:
+ for(int j = 0; j < noutput_items; j++) {
+ out[j] = gr_complex(in0[j + d_delay],
+ d_fir->filter(&in1[j]));
+ }
+ break;
+
+ default:
+ assert(0);
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/filter_delay_fc_impl.h b/gr-filter/lib/filter_delay_fc_impl.h
new file mode 100644
index 000000000..5157d6e02
--- /dev/null
+++ b/gr-filter/lib/filter_delay_fc_impl.h
@@ -0,0 +1,56 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_FILTER_DELAY_FC_IMPL_H
+#define INCLUDED_FILTER_FILTER_DELAY_FC_IMPL_H
+
+#include <filter/filter_delay_fc.h>
+#include <filter/fir_filter.h>
+#include <gr_io_signature.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API filter_delay_fc_impl : public filter_delay_fc
+ {
+ private:
+ unsigned int d_delay;
+ kernel::fir_filter_fff *d_fir;
+ std::vector<float> d_taps;
+ bool d_update;
+
+ public:
+ filter_delay_fc_impl(const std::vector<float> &taps);
+ ~filter_delay_fc_impl();
+
+ std::vector<float> taps();
+ void set_taps(const std::vector<float> &taps);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_FILTER_DELAY_FC_IMPL_H */
diff --git a/gr-filter/lib/fir_filter.cc b/gr-filter/lib/fir_filter.cc
new file mode 100644
index 000000000..233405824
--- /dev/null
+++ b/gr-filter/lib/fir_filter.cc
@@ -0,0 +1,667 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <filter/fir_filter.h>
+#include <fft/fft.h>
+#include <volk/volk.h>
+#include <cstdio>
+#include <cstring>
+
+namespace gr {
+ namespace filter {
+ namespace kernel {
+
+ fir_filter_fff::fir_filter_fff(int decimation,
+ const std::vector<float> &taps)
+ {
+ d_align = volk_get_alignment();
+ d_naligned = d_align / sizeof(float);
+
+ d_aligned_taps = NULL;
+ set_taps(taps);
+
+ // Make sure the output sample is always aligned, too.
+ d_output = fft::malloc_float(1);
+ }
+
+ fir_filter_fff::~fir_filter_fff()
+ {
+ // Free all aligned taps
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ // Free output sample
+ fft::free(d_output);
+ }
+
+ void
+ fir_filter_fff::set_taps(const std::vector<float> &taps)
+ {
+ // Free the taps if already allocated
+ if(d_aligned_taps!= NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ d_ntaps = (int)taps.size();
+ d_taps = taps;
+ std::reverse(d_taps.begin(), d_taps.end());
+
+ // Make a set of taps at all possible arch alignments
+ d_aligned_taps = (float**)malloc(d_naligned*sizeof(float**));
+ for(int i = 0; i < d_naligned; i++) {
+ d_aligned_taps[i] = fft::malloc_float(d_ntaps+d_naligned-1);
+ memset(d_aligned_taps[i], 0, sizeof(float)*(d_ntaps+d_naligned-1));
+ for(unsigned int j = 0; j < d_ntaps; j++)
+ d_aligned_taps[i][i+j] = d_taps[j];
+ }
+ }
+
+ std::vector<float>
+ fir_filter_fff::taps() const
+ {
+ std::vector<float> t = d_taps;
+ std::reverse(t.begin(), t.end());
+ return t;
+ }
+
+ unsigned int
+ fir_filter_fff::ntaps() const
+ {
+ return d_ntaps;
+ }
+
+ float
+ fir_filter_fff::filter(const float input[])
+ {
+ const float *ar = (float *)((unsigned long) input & ~(d_align-1));
+ unsigned al = input - ar;
+
+ volk_32f_x2_dot_prod_32f_a(d_output, ar,
+ d_aligned_taps[al],
+ d_ntaps+al);
+ return *d_output;
+ }
+
+ void
+ fir_filter_fff::filterN(float output[],
+ const float input[],
+ unsigned long n)
+ {
+ for(unsigned long i = 0; i < n; i++) {
+ output[i] = filter(&input[i]);
+ }
+ }
+
+ void
+ fir_filter_fff::filterNdec(float output[],
+ const float input[],
+ unsigned long n,
+ unsigned int decimate)
+ {
+ unsigned long j = 0;
+ for(unsigned long i = 0; i < n; i++) {
+ output[i] = filter(&input[j]);
+ j += decimate;
+ }
+ }
+
+ /**************************************************************/
+
+ fir_filter_ccf::fir_filter_ccf(int decimation,
+ const std::vector<float> &taps)
+ {
+ d_align = volk_get_alignment();
+ d_naligned = d_align / sizeof(gr_complex);
+
+ d_aligned_taps = NULL;
+ set_taps(taps);
+
+ // Make sure the output sample is always aligned, too.
+ d_output = fft::malloc_complex(1);
+ }
+
+ fir_filter_ccf::~fir_filter_ccf()
+ {
+ // Free all aligned taps
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ // Free output sample
+ fft::free(d_output);
+ }
+
+ void
+ fir_filter_ccf::set_taps(const std::vector<float> &taps)
+ {
+ // Free the taps if already allocated
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ d_ntaps = (int)taps.size();
+ d_taps = taps;
+ std::reverse(d_taps.begin(), d_taps.end());
+
+ // Make a set of taps at all possible arch alignments
+ d_aligned_taps = (float**)malloc(d_naligned*sizeof(float**));
+ for(int i = 0; i < d_naligned; i++) {
+ d_aligned_taps[i] = fft::malloc_float(d_ntaps+d_naligned-1);
+ memset(d_aligned_taps[i], 0, sizeof(float)*(d_ntaps+d_naligned-1));
+ for(unsigned int j = 0; j < d_ntaps; j++)
+ d_aligned_taps[i][i+j] = d_taps[j];
+ }
+ }
+
+ std::vector<float>
+ fir_filter_ccf::taps() const
+ {
+ std::vector<float> t = d_taps;
+ std::reverse(t.begin(), t.end());
+ return t;
+ }
+
+ unsigned int
+ fir_filter_ccf::ntaps() const
+ {
+ return d_ntaps;
+ }
+
+ gr_complex
+ fir_filter_ccf::filter(const gr_complex input[])
+ {
+ const gr_complex *ar = (gr_complex *)((unsigned long) input & ~(d_align-1));
+ unsigned al = input - ar;
+
+ volk_32fc_32f_dot_prod_32fc_a(d_output, ar,
+ d_aligned_taps[al],
+ (d_ntaps+al));
+ return *d_output;
+ }
+
+ void
+ fir_filter_ccf::filterN(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n)
+ {
+ for(unsigned long i = 0; i < n; i++)
+ output[i] = filter(&input[i]);
+ }
+
+
+ void
+ fir_filter_ccf::filterNdec(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n,
+ unsigned int decimate)
+ {
+ unsigned long j = 0;
+ for(unsigned long i = 0; i < n; i++){
+ output[i] = filter(&input[j]);
+ j += decimate;
+ }
+ }
+
+
+ /**************************************************************/
+
+
+ fir_filter_fcc::fir_filter_fcc(int decimation,
+ const std::vector<gr_complex> &taps)
+ {
+ d_align = volk_get_alignment();
+ d_naligned = d_align / sizeof(float);
+
+ d_aligned_taps = NULL;
+ set_taps(taps);
+
+ // Make sure the output sample is always aligned, too.
+ d_output = fft::malloc_complex(1);
+ }
+
+ fir_filter_fcc::~fir_filter_fcc()
+ {
+ // Free all aligned taps
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ // Free output sample
+ fft::free(d_output);
+ }
+
+ void
+ fir_filter_fcc::set_taps(const std::vector<gr_complex> &taps)
+ {
+ // Free the taps if already allocated
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ d_ntaps = (int)taps.size();
+ d_taps = taps;
+ std::reverse(d_taps.begin(), d_taps.end());
+
+ // Make a set of taps at all possible arch alignments
+ d_aligned_taps = (gr_complex**)malloc(d_naligned*sizeof(gr_complex**));
+ for(int i = 0; i < d_naligned; i++) {
+ d_aligned_taps[i] = fft::malloc_complex(d_ntaps+d_naligned-1);
+ memset(d_aligned_taps[i], 0, sizeof(gr_complex)*(d_ntaps+d_naligned-1));
+ for(unsigned int j = 0; j < d_ntaps; j++)
+ d_aligned_taps[i][i+j] = d_taps[j];
+ }
+ }
+
+ std::vector<gr_complex>
+ fir_filter_fcc::taps() const
+ {
+ std::vector<gr_complex> t = d_taps;
+ std::reverse(t.begin(), t.end());
+ return t;
+ }
+
+ unsigned int
+ fir_filter_fcc::ntaps() const
+ {
+ return d_ntaps;
+ }
+
+ gr_complex
+ fir_filter_fcc::filter(const float input[])
+ {
+ const float *ar = (float *)((unsigned long) input & ~(d_align-1));
+ unsigned al = input - ar;
+
+ volk_32fc_32f_dot_prod_32fc_a(d_output,
+ d_aligned_taps[al],
+ ar,
+ (d_ntaps+al));
+ return *d_output;
+ }
+
+ void
+ fir_filter_fcc::filterN(gr_complex output[],
+ const float input[],
+ unsigned long n)
+ {
+ for(unsigned long i = 0; i < n; i++)
+ output[i] = filter(&input[i]);
+ }
+
+
+ void
+ fir_filter_fcc::filterNdec(gr_complex output[],
+ const float input[],
+ unsigned long n,
+ unsigned int decimate)
+ {
+ unsigned long j = 0;
+ for(unsigned long i = 0; i < n; i++){
+ output[i] = filter(&input[j]);
+ j += decimate;
+ }
+ }
+
+ /**************************************************************/
+
+ fir_filter_ccc::fir_filter_ccc(int decimation,
+ const std::vector<gr_complex> &taps)
+ {
+ d_align = volk_get_alignment();
+ d_naligned = d_align / sizeof(gr_complex);
+
+ d_aligned_taps = NULL;
+ set_taps(taps);
+
+ // Make sure the output sample is always aligned, too.
+ d_output = fft::malloc_complex(1);
+ }
+
+ fir_filter_ccc::~fir_filter_ccc()
+ {
+ // Free all aligned taps
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ // Free output sample
+ fft::free(d_output);
+ }
+
+ void
+ fir_filter_ccc::set_taps(const std::vector<gr_complex> &taps)
+ {
+ // Free the taps if already allocated
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ d_ntaps = (int)taps.size();
+ d_taps = taps;
+ std::reverse(d_taps.begin(), d_taps.end());
+
+ // Make a set of taps at all possible arch alignments
+ d_aligned_taps = (gr_complex**)malloc(d_naligned*sizeof(gr_complex**));
+ for(int i = 0; i < d_naligned; i++) {
+ d_aligned_taps[i] = fft::malloc_complex(d_ntaps+d_naligned-1);
+ memset(d_aligned_taps[i], 0, sizeof(gr_complex)*(d_ntaps+d_naligned-1));
+ for(unsigned int j = 0; j < d_ntaps; j++)
+ d_aligned_taps[i][i+j] = d_taps[j];
+ }
+ }
+
+ std::vector<gr_complex>
+ fir_filter_ccc::taps() const
+ {
+ std::vector<gr_complex> t = d_taps;
+ std::reverse(t.begin(), t.end());
+ return t;
+ }
+
+ unsigned int
+ fir_filter_ccc::ntaps() const
+ {
+ return d_ntaps;
+ }
+
+ gr_complex
+ fir_filter_ccc::filter(const gr_complex input[])
+ {
+ const gr_complex *ar = (gr_complex *)((unsigned long) input & ~(d_align-1));
+ unsigned al = input - ar;
+
+ volk_32fc_x2_dot_prod_32fc_a(d_output, ar,
+ d_aligned_taps[al],
+ (d_ntaps+al)*sizeof(gr_complex));
+ return *d_output;
+ }
+
+ void
+ fir_filter_ccc::filterN(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n)
+ {
+ for(unsigned long i = 0; i < n; i++)
+ output[i] = filter(&input[i]);
+ }
+
+
+ void
+ fir_filter_ccc::filterNdec(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n,
+ unsigned int decimate)
+ {
+ unsigned long j = 0;
+ for(unsigned long i = 0; i < n; i++){
+ output[i] = filter(&input[j]);
+ j += decimate;
+ }
+ }
+
+ /**************************************************************/
+
+ fir_filter_scc::fir_filter_scc(int decimation,
+ const std::vector<gr_complex> &taps)
+ {
+ d_align = volk_get_alignment();
+ d_naligned = d_align / sizeof(short);
+
+ d_aligned_taps = NULL;
+ set_taps(taps);
+
+ // Make sure the output sample is always aligned, too.
+ d_output = fft::malloc_complex(1);
+ }
+
+ fir_filter_scc::~fir_filter_scc()
+ {
+ // Free all aligned taps
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ // Free output sample
+ fft::free(d_output);
+ }
+
+ void
+ fir_filter_scc::set_taps(const std::vector<gr_complex> &taps)
+ {
+ // Free the taps if already allocated
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ d_ntaps = (int)taps.size();
+ d_taps = taps;
+ std::reverse(d_taps.begin(), d_taps.end());
+
+ // Make a set of taps at all possible arch alignments
+ d_aligned_taps = (gr_complex**)malloc(d_naligned*sizeof(gr_complex**));
+ for(int i = 0; i < d_naligned; i++) {
+ d_aligned_taps[i] = fft::malloc_complex(d_ntaps+d_naligned-1);
+ memset(d_aligned_taps[i], 0, sizeof(gr_complex)*(d_ntaps+d_naligned-1));
+ for(unsigned int j = 0; j < d_ntaps; j++)
+ d_aligned_taps[i][i+j] = d_taps[j];
+ }
+ }
+
+ std::vector<gr_complex>
+ fir_filter_scc::taps() const
+ {
+ std::vector<gr_complex> t = d_taps;
+ std::reverse(t.begin(), t.end());
+ return t;
+ }
+
+ unsigned int
+ fir_filter_scc::ntaps() const
+ {
+ return d_ntaps;
+ }
+
+ gr_complex
+ fir_filter_scc::filter(const short input[])
+ {
+ const short *ar = (short *)((unsigned long) input & ~(d_align-1));
+ unsigned al = input - ar;
+
+ volk_16i_32fc_dot_prod_32fc_a(d_output, ar,
+ d_aligned_taps[al],
+ (d_ntaps+al));
+
+ return *d_output;
+ }
+
+ void
+ fir_filter_scc::filterN(gr_complex output[],
+ const short input[],
+ unsigned long n)
+ {
+ for(unsigned long i = 0; i < n; i++)
+ output[i] = filter(&input[i]);
+ }
+
+
+ void
+ fir_filter_scc::filterNdec(gr_complex output[],
+ const short input[],
+ unsigned long n,
+ unsigned int decimate)
+ {
+ unsigned long j = 0;
+ for(unsigned long i = 0; i < n; i++){
+ output[i] = filter(&input[j]);
+ j += decimate;
+ }
+ }
+
+ /**************************************************************/
+
+ fir_filter_fsf::fir_filter_fsf(int decimation,
+ const std::vector<float> &taps)
+ {
+ d_align = volk_get_alignment();
+ d_naligned = d_align / sizeof(float);
+
+ d_aligned_taps = NULL;
+ set_taps(taps);
+
+ // Make sure the output sample is always aligned, too.
+ d_output = (short*)fft::malloc_float(1);
+ }
+
+ fir_filter_fsf::~fir_filter_fsf()
+ {
+ // Free all aligned taps
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ // Free output sample
+ fft::free(d_output);
+ }
+
+ void
+ fir_filter_fsf::set_taps(const std::vector<float> &taps)
+ {
+ // Free the taps if already allocated
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ d_ntaps = (int)taps.size();
+ d_taps = taps;
+ std::reverse(d_taps.begin(), d_taps.end());
+
+ // Make a set of taps at all possible arch alignments
+ d_aligned_taps = (float**)malloc(d_naligned*sizeof(float**));
+ for(int i = 0; i < d_naligned; i++) {
+ d_aligned_taps[i] = fft::malloc_float(d_ntaps+d_naligned-1);
+ memset(d_aligned_taps[i], 0, sizeof(float)*(d_ntaps+d_naligned-1));
+ for(unsigned int j = 0; j < d_ntaps; j++)
+ d_aligned_taps[i][i+j] = d_taps[j];
+ }
+ }
+
+ std::vector<float>
+ fir_filter_fsf::taps() const
+ {
+ std::vector<float> t = d_taps;
+ std::reverse(t.begin(), t.end());
+ return t;
+ }
+
+ unsigned int
+ fir_filter_fsf::ntaps() const
+ {
+ return d_ntaps;
+ }
+
+ short
+ fir_filter_fsf::filter(const float input[])
+ {
+ const float *ar = (float *)((unsigned long) input & ~(d_align-1));
+ unsigned al = input - ar;
+
+ volk_32f_x2_dot_prod_16i_a(d_output, ar,
+ d_aligned_taps[al],
+ (d_ntaps+al));
+
+ return *d_output;
+ }
+
+ void
+ fir_filter_fsf::filterN(short output[],
+ const float input[],
+ unsigned long n)
+ {
+ for(unsigned long i = 0; i < n; i++)
+ output[i] = filter(&input[i]);
+ }
+
+ void
+ fir_filter_fsf::filterNdec(short output[],
+ const float input[],
+ unsigned long n,
+ unsigned int decimate)
+ {
+ unsigned long j = 0;
+ for(unsigned long i = 0; i < n; i++){
+ output[i] = filter(&input[j]);
+ j += decimate;
+ }
+ }
+
+ } /* namespace kernel */
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/fir_filter_XXX_impl.cc.t b/gr-filter/lib/fir_filter_XXX_impl.cc.t
new file mode 100644
index 000000000..529c51e2b
--- /dev/null
+++ b/gr-filter/lib/fir_filter_XXX_impl.cc.t
@@ -0,0 +1,104 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* @WARNING@ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "@IMPL_NAME@.h"
+#include <gr_io_signature.h>
+#include <volk/volk.h>
+
+namespace gr {
+ namespace filter {
+
+ @BASE_NAME@::sptr
+ @BASE_NAME@::make(int decimation, const std::vector<@TAP_TYPE@> &taps)
+ {
+ return gnuradio::get_initial_sptr(new @IMPL_NAME@
+ (decimation, taps));
+ }
+
+
+ @IMPL_NAME@::@IMPL_NAME@(int decimation, const std::vector<@TAP_TYPE@> &taps)
+ : gr_sync_decimator("@BASE_NAME@",
+ gr_make_io_signature(1, 1, sizeof(@I_TYPE@)),
+ gr_make_io_signature(1, 1, sizeof(@O_TYPE@)),
+ decimation)
+ {
+ d_fir = new kernel::@BASE_NAME@(decimation, taps);
+ d_updated = false;
+ set_history(d_fir->ntaps());
+
+ const int alignment_multiple =
+ volk_get_alignment() / sizeof(float);
+ set_alignment(std::max(1, alignment_multiple));
+ }
+
+ @IMPL_NAME@::~@IMPL_NAME@()
+ {
+ delete d_fir;
+ }
+
+ void
+ @IMPL_NAME@::set_taps(const std::vector<@TAP_TYPE@> &taps)
+ {
+ d_fir->set_taps(taps);
+ d_updated = true;
+ }
+
+ std::vector<@TAP_TYPE@>
+ @IMPL_NAME@::taps() const
+ {
+ return d_fir->taps();
+ }
+
+ int
+ @IMPL_NAME@::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const @I_TYPE@ *in = (const @I_TYPE@*)input_items[0];
+ @O_TYPE@ *out = (@O_TYPE@*)output_items[0];
+
+ if (d_updated) {
+ set_history(d_fir->ntaps());
+ d_updated = false;
+ return 0; // history requirements may have changed.
+ }
+
+ if (decimation() == 1) {
+ d_fir->filterN(out, in, noutput_items);
+ }
+ else {
+ d_fir->filterNdec(out, in, noutput_items,
+ decimation());
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
+
diff --git a/gr-filter/lib/fir_filter_XXX_impl.h.t b/gr-filter/lib/fir_filter_XXX_impl.h.t
new file mode 100644
index 000000000..ef0a7adfe
--- /dev/null
+++ b/gr-filter/lib/fir_filter_XXX_impl.h.t
@@ -0,0 +1,56 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* @WARNING@ */
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
+
+#include <filter/fir_filter.h>
+#include <filter/@BASE_NAME@.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API @IMPL_NAME@ : public @BASE_NAME@
+ {
+ private:
+ kernel::@BASE_NAME@ *d_fir;
+ bool d_updated;
+
+ public:
+ @IMPL_NAME@(int decimation, const std::vector<@TAP_TYPE@> &taps);
+
+ ~@IMPL_NAME@();
+
+ void set_taps(const std::vector<@TAP_TYPE@> &taps);
+ std::vector<@TAP_TYPE@> taps() const;
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* @GUARD_NAME@ */
diff --git a/gr-filter/lib/fir_filter_with_buffer.cc b/gr-filter/lib/fir_filter_with_buffer.cc
new file mode 100644
index 000000000..7a35a9225
--- /dev/null
+++ b/gr-filter/lib/fir_filter_with_buffer.cc
@@ -0,0 +1,496 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <filter/fir_filter_with_buffer.h>
+#include <fft/fft.h>
+#include <volk/volk.h>
+#include <algorithm>
+#include <cstdio>
+#include <cstring>
+
+namespace gr {
+ namespace filter {
+ namespace kernel {
+
+ fir_filter_with_buffer_fff::fir_filter_with_buffer_fff(const std::vector<float> &taps)
+ {
+ d_align = volk_get_alignment();
+ d_naligned = d_align / sizeof(float);
+
+ d_buffer_ptr = NULL;
+ d_aligned_taps = NULL;
+ set_taps(taps);
+
+ // Make sure the output sample is always aligned, too.
+ d_output = fft::malloc_float(1);
+ }
+
+ fir_filter_with_buffer_fff::~fir_filter_with_buffer_fff()
+ {
+ if(d_buffer_ptr != NULL) {
+ fft::free(d_buffer_ptr);
+ d_buffer_ptr = NULL;
+ }
+
+ // Free aligned taps
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ // Free output sample
+ fft::free(d_output);
+ }
+
+ void
+ fir_filter_with_buffer_fff::set_taps(const std::vector<float> &taps)
+ {
+ if(d_buffer_ptr != NULL) {
+ fft::free(d_buffer_ptr);
+ d_buffer_ptr = NULL;
+ }
+
+ // Free the taps if already allocated
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ d_ntaps = (int)taps.size();
+ d_taps = taps;
+ std::reverse(d_taps.begin(), d_taps.end());
+
+ // We allocate enough to be able to look back and forth
+ // d_naligned beyond the buffer boundaries and make sure these
+ // are zeroed out (or they may be nan, which will cause
+ // problems). We then set d_buffer to the position in the
+ // d_buffer_ptr such that we only touch the internally
+ // allocated space.
+ d_buffer_ptr = fft::malloc_float(2*(d_ntaps + d_naligned));
+ memset(d_buffer_ptr, 0, 2*(d_ntaps + d_naligned)*sizeof(float));
+ d_buffer = d_buffer_ptr + d_naligned;
+
+ // Allocate aligned taps
+ d_aligned_taps = (float**)malloc(d_naligned*sizeof(float**));
+ for(int i = 0; i < d_naligned; i++) {
+ d_aligned_taps[i] = fft::malloc_float(d_ntaps+d_naligned-1);
+ memset(d_aligned_taps[i], 0, sizeof(float)*(d_ntaps+d_naligned-1));
+ for(unsigned int j = 0; j < d_ntaps; j++)
+ d_aligned_taps[i][i+j] = d_taps[j];
+ }
+
+ d_idx = 0;
+ }
+
+ std::vector<float>
+ fir_filter_with_buffer_fff::taps() const
+ {
+ std::vector<float> t = d_taps;
+ std::reverse(t.begin(), t.end());
+ return t;
+ }
+
+ float
+ fir_filter_with_buffer_fff::filter(float input)
+ {
+ d_buffer[d_idx] = input;
+ d_buffer[d_idx+ntaps()] = input;
+
+ d_idx++;
+ if(d_idx >= ntaps())
+ d_idx = 0;
+
+ const float *ar = (float*)((unsigned long)(&d_buffer[d_idx]) & ~(d_align-1));
+ unsigned al = (&d_buffer[d_idx]) - ar;
+
+ volk_32f_x2_dot_prod_32f_a(d_output, ar,
+ d_aligned_taps[al],
+ ntaps()+al);
+ return *d_output;
+ }
+
+ float
+ fir_filter_with_buffer_fff::filter(const float input[],
+ unsigned long dec)
+ {
+ unsigned int i;
+
+ for(i = 0; i < dec; i++) {
+ d_buffer[d_idx] = input[i];
+ d_buffer[d_idx+ntaps()] = input[i];
+ d_idx++;
+ if(d_idx >= ntaps())
+ d_idx = 0;
+ }
+
+ const float *ar = (float*)((unsigned long)(&d_buffer[d_idx]) & ~(d_align-1));
+ unsigned al = (&d_buffer[d_idx]) - ar;
+
+ volk_32f_x2_dot_prod_32f_a(d_output, ar,
+ d_aligned_taps[al],
+ ntaps()+al);
+ return *d_output;
+ }
+
+ void
+ fir_filter_with_buffer_fff::filterN(float output[],
+ const float input[],
+ unsigned long n)
+ {
+ for(unsigned long i = 0; i < n; i++) {
+ output[i] = filter(input[i]);
+ }
+ }
+
+ void
+ fir_filter_with_buffer_fff::filterNdec(float output[],
+ const float input[],
+ unsigned long n,
+ unsigned long decimate)
+ {
+ unsigned long j = 0;
+ for(unsigned long i = 0; i < n; i++) {
+ output[i] = filter(&input[j], decimate);
+ j += decimate;
+ }
+ }
+
+
+ /**************************************************************/
+
+
+ fir_filter_with_buffer_ccc::fir_filter_with_buffer_ccc(const std::vector<gr_complex> &taps)
+ {
+ d_align = volk_get_alignment();
+ d_naligned = d_align / sizeof(gr_complex);
+
+ d_buffer_ptr = NULL;
+ d_aligned_taps = NULL;
+ set_taps(taps);
+
+ // Make sure the output sample is always aligned, too.
+ d_output = fft::malloc_complex(1);
+ }
+
+ fir_filter_with_buffer_ccc::~fir_filter_with_buffer_ccc()
+ {
+ if(d_buffer_ptr != NULL) {
+ fft::free(d_buffer_ptr);
+ d_buffer_ptr = NULL;
+ }
+
+ // Free aligned taps
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ // Free output sample
+ fft::free(d_output);
+ }
+
+ void
+ fir_filter_with_buffer_ccc::set_taps(const std::vector<gr_complex> &taps)
+ {
+ if(d_buffer_ptr != NULL) {
+ fft::free(d_buffer_ptr);
+ d_buffer_ptr = NULL;
+ }
+
+ // Free the taps if already allocated
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ d_ntaps = (int)taps.size();
+ d_taps = taps;
+ std::reverse(d_taps.begin(), d_taps.end());
+
+ // We allocate enough to be able to look back and forth
+ // d_naligned beyond the buffer boundaries and make sure these
+ // are zeroed out (or they may be nan, which will cause
+ // problems). We then set d_buffer to the position in the
+ // d_buffer_ptr such that we only touch the internally
+ // allocated space.
+ d_buffer_ptr = fft::malloc_complex(2*(d_ntaps + d_naligned));
+ memset(d_buffer_ptr, 0, 2*(d_ntaps + d_naligned)*sizeof(gr_complex));
+ d_buffer = d_buffer_ptr + d_naligned;
+
+ // Allocate aligned taps
+ d_aligned_taps = (gr_complex**)malloc(d_naligned*sizeof(gr_complex**));
+ for(int i = 0; i < d_naligned; i++) {
+ d_aligned_taps[i] = fft::malloc_complex(d_ntaps+d_naligned-1);
+ memset(d_aligned_taps[i], 0, sizeof(gr_complex)*(d_ntaps+d_naligned-1));
+ for(unsigned int j = 0; j < d_ntaps; j++)
+ d_aligned_taps[i][i+j] = d_taps[j];
+ }
+
+ d_idx = 0;
+ }
+
+ std::vector<gr_complex>
+ fir_filter_with_buffer_ccc::taps() const
+ {
+ std::vector<gr_complex> t = d_taps;
+ std::reverse(t.begin(), t.end());
+ return t;
+ }
+
+ gr_complex
+ fir_filter_with_buffer_ccc::filter(gr_complex input)
+ {
+ d_buffer[d_idx] = input;
+ d_buffer[d_idx+ntaps()] = input;
+
+ d_idx++;
+ if(d_idx >= ntaps())
+ d_idx = 0;
+
+ const gr_complex *ar = (gr_complex *)((unsigned long)(&d_buffer[d_idx]) & ~(d_align-1));
+ unsigned al = (&d_buffer[d_idx]) - ar;
+
+ volk_32fc_x2_dot_prod_32fc_a(d_output, ar,
+ d_aligned_taps[al],
+ (ntaps()+al)*sizeof(gr_complex));
+ return *d_output;
+ }
+
+ gr_complex
+ fir_filter_with_buffer_ccc::filter(const gr_complex input[],
+ unsigned long dec)
+ {
+ unsigned int i;
+
+ for(i = 0; i < dec; i++) {
+ d_buffer[d_idx] = input[i];
+ d_buffer[d_idx+ntaps()] = input[i];
+ d_idx++;
+ if(d_idx >= ntaps())
+ d_idx = 0;
+ }
+
+ const gr_complex *ar = (gr_complex *)((unsigned long)(&d_buffer[d_idx]) & ~(d_align-1));
+ unsigned al = (&d_buffer[d_idx]) - ar;
+
+ volk_32fc_x2_dot_prod_32fc_a(d_output, ar,
+ d_aligned_taps[al],
+ (ntaps()+al)*sizeof(gr_complex));
+ return *d_output;
+ }
+
+ void
+ fir_filter_with_buffer_ccc::filterN(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n)
+ {
+ for(unsigned long i = 0; i < n; i++) {
+ output[i] = filter(input[i]);
+ }
+ }
+
+ void
+ fir_filter_with_buffer_ccc::filterNdec(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n,
+ unsigned long decimate)
+ {
+ unsigned long j = 0;
+ for(unsigned long i = 0; i < n; i++) {
+ output[i] = filter(&input[j], decimate);
+ j += decimate;
+ }
+ }
+
+
+ /**************************************************************/
+
+
+ fir_filter_with_buffer_ccf::fir_filter_with_buffer_ccf(const std::vector<float> &taps)
+ {
+ d_align = volk_get_alignment();
+ d_naligned = d_align / sizeof(gr_complex);
+
+ d_buffer_ptr = NULL;
+ d_aligned_taps = NULL;
+ set_taps(taps);
+
+ // Make sure the output sample is always aligned, too.
+ d_output = fft::malloc_complex(1);
+ }
+
+ fir_filter_with_buffer_ccf::~fir_filter_with_buffer_ccf()
+ {
+ if(d_buffer_ptr != NULL) {
+ fft::free(d_buffer_ptr);
+ d_buffer_ptr = NULL;
+ }
+
+ // Free aligned taps
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ // Free output sample
+ fft::free(d_output);
+ }
+
+ void
+ fir_filter_with_buffer_ccf::set_taps(const std::vector<float> &taps)
+ {
+ if(d_buffer_ptr != NULL) {
+ fft::free(d_buffer_ptr);
+ d_buffer_ptr = NULL;
+ }
+
+ // Free the taps if already allocated
+ if(d_aligned_taps != NULL) {
+ for(int i = 0; i < d_naligned; i++) {
+ fft::free(d_aligned_taps[i]);
+ }
+ fft::free(d_aligned_taps);
+ d_aligned_taps = NULL;
+ }
+
+ d_ntaps = (int)taps.size();
+ d_taps = taps;
+ std::reverse(d_taps.begin(), d_taps.end());
+
+ // We allocate enough to be able to look back and forth
+ // d_naligned beyond the buffer boundaries and make sure these
+ // are zeroed out (or they may be nan, which will cause
+ // problems). We then set d_buffer to the position in the
+ // d_buffer_ptr such that we only touch the internally
+ // allocated space.
+ d_buffer_ptr = fft::malloc_complex(2*(d_ntaps + d_naligned));
+ memset(d_buffer_ptr, 0, 2*(d_ntaps + d_naligned)*sizeof(gr_complex));
+ d_buffer = d_buffer_ptr + d_naligned;
+
+ // Allocate aligned taps
+ d_aligned_taps = (float**)malloc(d_naligned*sizeof(float**));
+ for(int i = 0; i < d_naligned; i++) {
+ d_aligned_taps[i] = fft::malloc_float(d_ntaps+d_naligned-1);
+ memset(d_aligned_taps[i], 0, sizeof(float)*(d_ntaps+d_naligned-1));
+ for(unsigned int j = 0; j < d_ntaps; j++)
+ d_aligned_taps[i][i+j] = d_taps[j];
+ }
+
+ d_idx = 0;
+ }
+
+ std::vector<float>
+ fir_filter_with_buffer_ccf::taps() const
+ {
+ std::vector<float> t = d_taps;
+ std::reverse(t.begin(), t.end());
+ return t;
+ }
+
+ gr_complex
+ fir_filter_with_buffer_ccf::filter(gr_complex input)
+ {
+ d_buffer[d_idx] = input;
+ d_buffer[d_idx+ntaps()] = input;
+
+ d_idx++;
+ if(d_idx >= ntaps())
+ d_idx = 0;
+
+ const gr_complex *ar = (gr_complex *)((unsigned long)(&d_buffer[d_idx]) & ~(d_align-1));
+ unsigned al = (&d_buffer[d_idx]) - ar;
+
+ volk_32fc_32f_dot_prod_32fc_a(d_output, ar,
+ d_aligned_taps[al],
+ ntaps()+al);
+ return *d_output;
+ }
+
+ gr_complex
+ fir_filter_with_buffer_ccf::filter(const gr_complex input[],
+ unsigned long dec)
+ {
+ unsigned int i;
+
+ for(i = 0; i < dec; i++) {
+ d_buffer[d_idx] = input[i];
+ d_buffer[d_idx+ntaps()] = input[i];
+ d_idx++;
+ if(d_idx >= ntaps())
+ d_idx = 0;
+ }
+
+ const gr_complex *ar = (gr_complex *)((unsigned long)(&d_buffer[d_idx]) & ~(d_align-1));
+ unsigned al = (&d_buffer[d_idx]) - ar;
+
+ volk_32fc_32f_dot_prod_32fc_a(d_output, ar,
+ d_aligned_taps[al],
+ ntaps()+al);
+ return *d_output;
+ }
+
+ void
+ fir_filter_with_buffer_ccf::filterN(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n)
+ {
+ for(unsigned long i = 0; i < n; i++) {
+ output[i] = filter(input[i]);
+ }
+ }
+
+ void
+ fir_filter_with_buffer_ccf::filterNdec(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n,
+ unsigned long decimate)
+ {
+ unsigned long j = 0;
+ for(unsigned long i = 0; i < n; i++) {
+ output[i] = filter(&input[j], decimate);
+ j += decimate;
+ }
+ }
+
+
+ } /* namespace kernel */
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/firdes.cc b/gr-filter/lib/firdes.cc
new file mode 100644
index 000000000..5c3320d71
--- /dev/null
+++ b/gr-filter/lib/firdes.cc
@@ -0,0 +1,855 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2007,2008,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <filter/firdes.h>
+#include <stdexcept>
+
+using std::vector;
+
+namespace gr {
+ namespace filter {
+
+#define IzeroEPSILON 1E-21 /* Max error acceptable in Izero */
+
+ static double Izero(double x)
+ {
+ double sum, u, halfx, temp;
+ int n;
+
+ sum = u = n = 1;
+ halfx = x/2.0;
+ do {
+ temp = halfx/(double)n;
+ n += 1;
+ temp *= temp;
+ u *= temp;
+ sum += u;
+ } while (u >= IzeroEPSILON*sum);
+ return(sum);
+ }
+
+
+ //
+ // === Low Pass ===
+ //
+
+ vector<float>
+ firdes::low_pass_2(double gain,
+ double sampling_freq, // Hz
+ double cutoff_freq, // Hz BEGINNING of transition band
+ double transition_width, // Hz width of transition band
+ double attenuation_dB, // attenuation dB
+ win_type window_type,
+ double beta) // used only with Kaiser
+ {
+ sanity_check_1f(sampling_freq, cutoff_freq, transition_width);
+
+ int ntaps = compute_ntaps_windes(sampling_freq,
+ transition_width,
+ attenuation_dB);
+
+ // construct the truncated ideal impulse response
+ // [sin(x)/x for the low pass case]
+
+ vector<float> taps(ntaps);
+ vector<float> w = window(window_type, ntaps, beta);
+
+ int M = (ntaps - 1) / 2;
+ double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq;
+ for(int n = -M; n <= M; n++) {
+ if (n == 0)
+ taps[n + M] = fwT0 / M_PI * w[n + M];
+ else {
+ // a little algebra gets this into the more familiar sin(x)/x form
+ taps[n + M] = sin(n * fwT0) / (n * M_PI) * w[n + M];
+ }
+ }
+
+ // find the factor to normalize the gain, fmax.
+ // For low-pass, gain @ zero freq = 1.0
+
+ double fmax = taps[0 + M];
+ for(int n = 1; n <= M; n++)
+ fmax += 2 * taps[n + M];
+
+ gain /= fmax; // normalize
+
+ for(int i = 0; i < ntaps; i++)
+ taps[i] *= gain;
+
+ return taps;
+ }
+
+ vector<float>
+ firdes::low_pass(double gain,
+ double sampling_freq,
+ double cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ win_type window_type,
+ double beta) // used only with Kaiser
+ {
+ sanity_check_1f(sampling_freq, cutoff_freq, transition_width);
+
+ int ntaps = compute_ntaps(sampling_freq,
+ transition_width,
+ window_type, beta);
+
+ // construct the truncated ideal impulse response
+ // [sin(x)/x for the low pass case]
+
+ vector<float> taps(ntaps);
+ vector<float> w = window(window_type, ntaps, beta);
+
+ int M = (ntaps - 1) / 2;
+ double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq;
+
+ for(int n = -M; n <= M; n++) {
+ if(n == 0)
+ taps[n + M] = fwT0 / M_PI * w[n + M];
+ else {
+ // a little algebra gets this into the more familiar sin(x)/x form
+ taps[n + M] = sin(n * fwT0) / (n * M_PI) * w[n + M];
+ }
+ }
+
+ // find the factor to normalize the gain, fmax.
+ // For low-pass, gain @ zero freq = 1.0
+
+ double fmax = taps[0 + M];
+ for(int n = 1; n <= M; n++)
+ fmax += 2 * taps[n + M];
+
+ gain /= fmax; // normalize
+
+ for(int i = 0; i < ntaps; i++)
+ taps[i] *= gain;
+
+ return taps;
+ }
+
+
+ //
+ // === High Pass ===
+ //
+
+ vector<float>
+ firdes::high_pass_2(double gain,
+ double sampling_freq,
+ double cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ double attenuation_dB, // attenuation dB
+ win_type window_type,
+ double beta) // used only with Kaiser
+ {
+ sanity_check_1f(sampling_freq, cutoff_freq, transition_width);
+
+ int ntaps = compute_ntaps_windes(sampling_freq,
+ transition_width,
+ attenuation_dB);
+
+ // construct the truncated ideal impulse response times the window function
+
+ vector<float> taps(ntaps);
+ vector<float> w = window(window_type, ntaps, beta);
+
+ int M = (ntaps - 1) / 2;
+ double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq;
+
+ for(int n = -M; n <= M; n++) {
+ if(n == 0)
+ taps[n + M] = (1 - (fwT0 / M_PI)) * w[n + M];
+ else {
+ // a little algebra gets this into the more familiar sin(x)/x form
+ taps[n + M] = -sin(n * fwT0) / (n * M_PI) * w[n + M];
+ }
+ }
+
+ // find the factor to normalize the gain, fmax.
+ // For high-pass, gain @ fs/2 freq = 1.0
+
+ double fmax = taps[0 + M];
+ for(int n = 1; n <= M; n++)
+ fmax += 2 * taps[n + M] * cos(n * M_PI);
+
+ gain /= fmax; // normalize
+
+ for(int i = 0; i < ntaps; i++)
+ taps[i] *= gain;
+
+ return taps;
+ }
+
+
+ vector<float>
+ firdes::high_pass(double gain,
+ double sampling_freq,
+ double cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ win_type window_type,
+ double beta) // used only with Kaiser
+ {
+ sanity_check_1f(sampling_freq, cutoff_freq, transition_width);
+
+ int ntaps = compute_ntaps(sampling_freq,
+ transition_width,
+ window_type, beta);
+
+ // construct the truncated ideal impulse response times the window function
+
+ vector<float> taps(ntaps);
+ vector<float> w = window(window_type, ntaps, beta);
+
+ int M = (ntaps - 1) / 2;
+ double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq;
+
+ for(int n = -M; n <= M; n++) {
+ if(n == 0)
+ taps[n + M] = (1 - (fwT0 / M_PI)) * w[n + M];
+ else {
+ // a little algebra gets this into the more familiar sin(x)/x form
+ taps[n + M] = -sin(n * fwT0) / (n * M_PI) * w[n + M];
+ }
+ }
+
+ // find the factor to normalize the gain, fmax.
+ // For high-pass, gain @ fs/2 freq = 1.0
+
+ double fmax = taps[0 + M];
+ for(int n = 1; n <= M; n++)
+ fmax += 2 * taps[n + M] * cos(n * M_PI);
+
+ gain /= fmax; // normalize
+
+ for(int i = 0; i < ntaps; i++)
+ taps[i] *= gain;
+
+ return taps;
+ }
+
+ //
+ // === Band Pass ===
+ //
+
+ vector<float>
+ firdes::band_pass_2(double gain,
+ double sampling_freq,
+ double low_cutoff_freq, // Hz center of transition band
+ double high_cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ double attenuation_dB, // attenuation dB
+ win_type window_type,
+ double beta) // used only with Kaiser
+ {
+ sanity_check_2f(sampling_freq,
+ low_cutoff_freq,
+ high_cutoff_freq, transition_width);
+
+ int ntaps = compute_ntaps_windes(sampling_freq,
+ transition_width,
+ attenuation_dB);
+
+ vector<float> taps(ntaps);
+ vector<float> w = window(window_type, ntaps, beta);
+
+ int M = (ntaps - 1) / 2;
+ double fwT0 = 2 * M_PI * low_cutoff_freq / sampling_freq;
+ double fwT1 = 2 * M_PI * high_cutoff_freq / sampling_freq;
+
+ for(int n = -M; n <= M; n++) {
+ if (n == 0)
+ taps[n + M] = (fwT1 - fwT0) / M_PI * w[n + M];
+ else {
+ taps[n + M] = (sin(n * fwT1) - sin(n * fwT0)) / (n * M_PI) * w[n + M];
+ }
+ }
+
+ // find the factor to normalize the gain, fmax.
+ // For band-pass, gain @ center freq = 1.0
+
+ double fmax = taps[0 + M];
+ for(int n = 1; n <= M; n++)
+ fmax += 2 * taps[n + M] * cos(n * (fwT0 + fwT1) * 0.5);
+
+ gain /= fmax; // normalize
+
+ for(int i = 0; i < ntaps; i++)
+ taps[i] *= gain;
+
+ return taps;
+ }
+
+
+ vector<float>
+ firdes::band_pass(double gain,
+ double sampling_freq,
+ double low_cutoff_freq, // Hz center of transition band
+ double high_cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ win_type window_type,
+ double beta) // used only with Kaiser
+ {
+ sanity_check_2f(sampling_freq,
+ low_cutoff_freq,
+ high_cutoff_freq,
+ transition_width);
+
+ int ntaps = compute_ntaps(sampling_freq,
+ transition_width,
+ window_type, beta);
+
+ // construct the truncated ideal impulse response times the window function
+
+ vector<float> taps(ntaps);
+ vector<float> w = window(window_type, ntaps, beta);
+
+ int M = (ntaps - 1) / 2;
+ double fwT0 = 2 * M_PI * low_cutoff_freq / sampling_freq;
+ double fwT1 = 2 * M_PI * high_cutoff_freq / sampling_freq;
+
+ for(int n = -M; n <= M; n++) {
+ if (n == 0)
+ taps[n + M] = (fwT1 - fwT0) / M_PI * w[n + M];
+ else {
+ taps[n + M] = (sin(n * fwT1) - sin(n * fwT0)) / (n * M_PI) * w[n + M];
+ }
+ }
+
+ // find the factor to normalize the gain, fmax.
+ // For band-pass, gain @ center freq = 1.0
+
+ double fmax = taps[0 + M];
+ for(int n = 1; n <= M; n++)
+ fmax += 2 * taps[n + M] * cos(n * (fwT0 + fwT1) * 0.5);
+
+ gain /= fmax; // normalize
+
+ for(int i = 0; i < ntaps; i++)
+ taps[i] *= gain;
+
+ return taps;
+ }
+
+ //
+ // === Complex Band Pass ===
+ //
+
+ vector<gr_complex>
+ firdes::complex_band_pass_2(double gain,
+ double sampling_freq,
+ double low_cutoff_freq, // Hz center of transition band
+ double high_cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ double attenuation_dB, // attenuation dB
+ win_type window_type,
+ double beta) // used only with Kaiser
+ {
+ sanity_check_2f_c(sampling_freq,
+ low_cutoff_freq,
+ high_cutoff_freq,
+ transition_width);
+
+ int ntaps = compute_ntaps_windes(sampling_freq,
+ transition_width,
+ attenuation_dB);
+
+ vector<gr_complex> taps(ntaps);
+ vector<float> lptaps(ntaps);
+ vector<float> w = window(window_type, ntaps, beta);
+
+ lptaps = low_pass_2(gain, sampling_freq,
+ (high_cutoff_freq - low_cutoff_freq)/2,
+ transition_width, attenuation_dB,
+ window_type, beta);
+
+ gr_complex *optr = &taps[0];
+ float *iptr = &lptaps[0];
+ float freq = M_PI * (high_cutoff_freq + low_cutoff_freq)/sampling_freq;
+ float phase = 0;
+ if (lptaps.size() & 01) {
+ phase = - freq * ( lptaps.size() >> 1 );
+ }
+ else
+ phase = - freq/2.0 * ((1 + 2*lptaps.size()) >> 1);
+
+ for(unsigned int i = 0; i < lptaps.size(); i++) {
+ *optr++ = gr_complex(*iptr * cos(phase), *iptr * sin(phase));
+ iptr++, phase += freq;
+ }
+
+ return taps;
+ }
+
+
+ vector<gr_complex>
+ firdes::complex_band_pass(double gain,
+ double sampling_freq,
+ double low_cutoff_freq, // Hz center of transition band
+ double high_cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ win_type window_type,
+ double beta) // used only with Kaiser
+ {
+ sanity_check_2f_c (sampling_freq,
+ low_cutoff_freq,
+ high_cutoff_freq,
+ transition_width);
+
+ int ntaps = compute_ntaps(sampling_freq,
+ transition_width,
+ window_type, beta);
+
+ // construct the truncated ideal impulse response times the window function
+
+ vector<gr_complex> taps(ntaps);
+ vector<float> lptaps(ntaps);
+ vector<float> w = window(window_type, ntaps, beta);
+
+ lptaps = low_pass(gain, sampling_freq,
+ (high_cutoff_freq - low_cutoff_freq)/2,
+ transition_width, window_type, beta);
+
+ gr_complex *optr = &taps[0];
+ float *iptr = &lptaps[0];
+ float freq = M_PI * (high_cutoff_freq + low_cutoff_freq)/sampling_freq;
+ float phase = 0;
+ if(lptaps.size() & 01) {
+ phase = - freq * ( lptaps.size() >> 1 );
+ }
+ else
+ phase = - freq/2.0 * ((1 + 2*lptaps.size()) >> 1);
+
+ for(unsigned int i=0;i<lptaps.size();i++) {
+ *optr++ = gr_complex(*iptr * cos(phase), *iptr * sin(phase));
+ iptr++, phase += freq;
+ }
+
+ return taps;
+ }
+
+ //
+ // === Band Reject ===
+ //
+
+ vector<float>
+ firdes::band_reject_2(double gain,
+ double sampling_freq,
+ double low_cutoff_freq, // Hz center of transition band
+ double high_cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ double attenuation_dB, // attenuation dB
+ win_type window_type,
+ double beta) // used only with Kaiser
+ {
+ sanity_check_2f(sampling_freq,
+ low_cutoff_freq,
+ high_cutoff_freq,
+ transition_width);
+
+ int ntaps = compute_ntaps_windes(sampling_freq,
+ transition_width,
+ attenuation_dB);
+
+ // construct the truncated ideal impulse response times the window function
+
+ vector<float> taps(ntaps);
+ vector<float> w = window(window_type, ntaps, beta);
+
+ int M = (ntaps - 1) / 2;
+ double fwT0 = 2 * M_PI * low_cutoff_freq / sampling_freq;
+ double fwT1 = 2 * M_PI * high_cutoff_freq / sampling_freq;
+
+ for(int n = -M; n <= M; n++) {
+ if (n == 0)
+ taps[n + M] = 1.0 + ((fwT0 - fwT1) / M_PI * w[n + M]);
+ else {
+ taps[n + M] = (sin(n * fwT0) - sin(n * fwT1)) / (n * M_PI) * w[n + M];
+ }
+ }
+
+ // find the factor to normalize the gain, fmax.
+ // For band-reject, gain @ zero freq = 1.0
+
+ double fmax = taps[0 + M];
+ for(int n = 1; n <= M; n++)
+ fmax += 2 * taps[n + M];
+
+ gain /= fmax; // normalize
+
+ for(int i = 0; i < ntaps; i++)
+ taps[i] *= gain;
+
+ return taps;
+ }
+
+ vector<float>
+ firdes::band_reject(double gain,
+ double sampling_freq,
+ double low_cutoff_freq, // Hz center of transition band
+ double high_cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ win_type window_type,
+ double beta) // used only with Kaiser
+ {
+ sanity_check_2f(sampling_freq,
+ low_cutoff_freq,
+ high_cutoff_freq,
+ transition_width);
+
+ int ntaps = compute_ntaps(sampling_freq,
+ transition_width,
+ window_type, beta);
+
+ // construct the truncated ideal impulse response times the window function
+
+ vector<float> taps(ntaps);
+ vector<float> w = window(window_type, ntaps, beta);
+
+ int M = (ntaps - 1) / 2;
+ double fwT0 = 2 * M_PI * low_cutoff_freq / sampling_freq;
+ double fwT1 = 2 * M_PI * high_cutoff_freq / sampling_freq;
+
+ for(int n = -M; n <= M; n++) {
+ if (n == 0)
+ taps[n + M] = 1.0 + ((fwT0 - fwT1) / M_PI * w[n + M]);
+ else {
+ taps[n + M] = (sin(n * fwT0) - sin(n * fwT1)) / (n * M_PI) * w[n + M];
+ }
+ }
+
+ // find the factor to normalize the gain, fmax.
+ // For band-reject, gain @ zero freq = 1.0
+
+ double fmax = taps[0 + M];
+ for(int n = 1; n <= M; n++)
+ fmax += 2 * taps[n + M];
+
+ gain /= fmax; // normalize
+
+ for(int i = 0; i < ntaps; i++)
+ taps[i] *= gain;
+
+ return taps;
+ }
+
+ //
+ // Hilbert Transform
+ //
+
+ vector<float>
+ firdes::hilbert(unsigned int ntaps,
+ win_type windowtype,
+ double beta)
+ {
+ if(!(ntaps & 1))
+ throw std::out_of_range("Hilbert: Must have odd number of taps");
+
+ vector<float> taps(ntaps);
+ vector<float> w = window (windowtype, ntaps, beta);
+ unsigned int h = (ntaps-1)/2;
+ float gain=0;
+ for(unsigned int i = 1; i <= h; i++) {
+ if(i & 1) {
+ float x = 1/(float)i;
+ taps[h+i] = x * w[h+i];
+ taps[h-i] = -x * w[h-i];
+ gain = taps[h+i] - gain;
+ }
+ else
+ taps[h+i] = taps[h-i] = 0;
+ }
+
+ gain = 2 * fabs(gain);
+ for(unsigned int i = 0; i < ntaps; i++)
+ taps[i] /= gain;
+ return taps;
+ }
+
+ //
+ // Gaussian
+ //
+
+ vector<float>
+ firdes::gaussian(double gain,
+ double spb,
+ double bt,
+ int ntaps)
+ {
+ vector<float> taps(ntaps);
+ double scale = 0;
+ double dt = 1.0/spb;
+ double s = 1.0/(sqrt(log(2.0)) / (2*M_PI*bt));
+ double t0 = -0.5 * ntaps;
+ double ts;
+ for(int i=0;i<ntaps;i++) {
+ t0++;
+ ts = s*dt*t0;
+ taps[i] = exp(-0.5*ts*ts);
+ scale += taps[i];
+ }
+ for(int i=0;i<ntaps;i++)
+ taps[i] = taps[i] / scale * gain;
+
+ return taps;
+ }
+
+
+ //
+ // Root Raised Cosine
+ //
+
+ vector<float>
+ firdes::root_raised_cosine(double gain,
+ double sampling_freq,
+ double symbol_rate,
+ double alpha,
+ int ntaps)
+ {
+ ntaps |= 1; // ensure that ntaps is odd
+
+ double spb = sampling_freq/symbol_rate; // samples per bit/symbol
+ vector<float> taps(ntaps);
+ double scale = 0;
+ for(int i = 0; i < ntaps; i++) {
+ double x1,x2,x3,num,den;
+ double xindx = i - ntaps/2;
+ x1 = M_PI * xindx/spb;
+ x2 = 4 * alpha * xindx / spb;
+ x3 = x2*x2 - 1;
+
+ if(fabs(x3) >= 0.000001) { // Avoid Rounding errors...
+ if(i != ntaps/2)
+ num = cos((1+alpha)*x1) + sin((1-alpha)*x1)/(4*alpha*xindx/spb);
+ else
+ num = cos((1+alpha)*x1) + (1-alpha) * M_PI / (4*alpha);
+ den = x3 * M_PI;
+ }
+ else {
+ if(alpha==1) {
+ taps[i] = -1;
+ continue;
+ }
+ x3 = (1-alpha)*x1;
+ x2 = (1+alpha)*x1;
+ num = (sin(x2)*(1+alpha)*M_PI
+ - cos(x3)*((1-alpha)*M_PI*spb)/(4*alpha*xindx)
+ + sin(x3)*spb*spb/(4*alpha*xindx*xindx));
+ den = -32 * M_PI * alpha * alpha * xindx/spb;
+ }
+ taps[i] = 4 * alpha * num / den;
+ scale += taps[i];
+ }
+
+ for(int i = 0; i < ntaps; i++)
+ taps[i] = taps[i] * gain / scale;
+
+ return taps;
+ }
+
+ //
+ // === Utilities ===
+ //
+
+ // delta_f / width_factor gives number of taps required.
+ static const float width_factor[5] = { // indexed by win_type
+ 3.3, // WIN_HAMMING
+ 3.1, // WIN_HANN
+ 5.5, // WIN_BLACKMAN
+ 2.0, // WIN_RECTANGULAR
+ //5.0 // WIN_KAISER (guesstimate compromise)
+ //2.0 // WIN_KAISER (guesstimate compromise)
+ 10.0 // WIN_KAISER
+ };
+
+ int
+ firdes::compute_ntaps_windes(double sampling_freq,
+ double transition_width, // this is frequency, not relative frequency
+ double attenuation_dB)
+ {
+ // Based on formula from Multirate Signal Processing for
+ // Communications Systems, fredric j harris
+ int ntaps = (int)(attenuation_dB*sampling_freq/(22.0*transition_width));
+ if ((ntaps & 1) == 0) // if even...
+ ntaps++; // ...make odd
+ return ntaps;
+ }
+
+ int
+ firdes::compute_ntaps(double sampling_freq,
+ double transition_width,
+ win_type window_type,
+ double beta)
+ {
+ // normalized transition width
+ double delta_f = transition_width / sampling_freq;
+
+ // compute number of taps required for given transition width
+ int ntaps = (int)(width_factor[window_type] / delta_f + 0.5);
+ if((ntaps & 1) == 0) // if even...
+ ntaps++; // ...make odd
+
+ return ntaps;
+ }
+
+ double
+ firdes::bessi0(double x)
+ {
+ double ax,ans;
+ double y;
+
+ ax=fabs(x);
+ if (ax < 3.75) {
+ y=x/3.75;
+ y*=y;
+ ans=1.0+y*(3.5156229+y*(3.0899424+y*(1.2067492
+ +y*(0.2659732+y*(0.360768e-1+y*0.45813e-2)))));
+ }
+ else {
+ y=3.75/ax;
+ ans=(exp(ax)/sqrt(ax))*(0.39894228+y*(0.1328592e-1
+ +y*(0.225319e-2+y*(-0.157565e-2+y*(0.916281e-2
+ +y*(-0.2057706e-1+y*(0.2635537e-1+y*(-0.1647633e-1
+ +y*0.392377e-2))))))));
+ }
+ return ans;
+ }
+
+ vector<float>
+ firdes::window (win_type type, int ntaps, double beta)
+ {
+ vector<float> taps(ntaps);
+ int M = ntaps - 1; // filter order
+
+ switch (type) {
+ case WIN_RECTANGULAR:
+ for(int n = 0; n < ntaps; n++)
+ taps[n] = 1;
+
+ case WIN_HAMMING:
+ for(int n = 0; n < ntaps; n++)
+ taps[n] = 0.54 - 0.46 * cos((2 * M_PI * n) / M);
+ break;
+
+ case WIN_HANN:
+ for(int n = 0; n < ntaps; n++)
+ taps[n] = 0.5 - 0.5 * cos((2 * M_PI * n) / M);
+ break;
+
+ case WIN_BLACKMAN:
+ for(int n = 0; n < ntaps; n++)
+ taps[n] = 0.42 - 0.50 * cos((2*M_PI * n) / (M-1))
+ - 0.08 * cos((4*M_PI * n) / (M-1));
+ break;
+
+ case WIN_BLACKMAN_hARRIS:
+ for(int n = -ntaps/2; n < ntaps/2; n++)
+ taps[n+ntaps/2] = 0.35875 + 0.48829*cos((2*M_PI * n) / (float)M) +
+ 0.14128*cos((4*M_PI * n) / (float)M) + 0.01168*cos((6*M_PI * n) / (float)M);
+ break;
+
+ case WIN_KAISER:
+ {
+ double IBeta = 1.0/Izero(beta);
+ double inm1 = 1.0/((double)(ntaps));
+ double temp;
+ //fprintf(stderr, "IBeta = %g; inm1 = %g\n", IBeta, inm1);
+
+ for(int i=0; i<ntaps; i++) {
+ temp = i * inm1;
+ //fprintf(stderr, "temp = %g\n", temp);
+ taps[i] = Izero(beta*sqrt(1.0-temp*temp)) * IBeta;
+ //fprintf(stderr, "taps[%d] = %g\n", i, taps[i]);
+ }
+ }
+ break;
+
+ default:
+ throw std::out_of_range("firdes:window: type out of range");
+ }
+
+ return taps;
+ }
+
+ void
+ firdes::sanity_check_1f(double sampling_freq,
+ double fa, // cutoff freq
+ double transition_width)
+ {
+ if(sampling_freq <= 0.0)
+ throw std::out_of_range("firdes check failed: sampling_freq > 0");
+
+ if(fa <= 0.0 || fa > sampling_freq / 2)
+ throw std::out_of_range("firdes check failed: 0 < fa <= sampling_freq / 2");
+
+ if(transition_width <= 0)
+ throw std::out_of_range("gr_dirdes check failed: transition_width > 0");
+ }
+
+ void
+ firdes::sanity_check_2f(double sampling_freq,
+ double fa, // first cutoff freq
+ double fb, // second cutoff freq
+ double transition_width)
+ {
+ if (sampling_freq <= 0.0)
+ throw std::out_of_range("firdes check failed: sampling_freq > 0");
+
+ if (fa <= 0.0 || fa > sampling_freq / 2)
+ throw std::out_of_range("firdes check failed: 0 < fa <= sampling_freq / 2");
+
+ if (fb <= 0.0 || fb > sampling_freq / 2)
+ throw std::out_of_range("firdes check failed: 0 < fb <= sampling_freq / 2");
+
+ if (fa > fb)
+ throw std::out_of_range("firdes check failed: fa <= fb");
+
+ if (transition_width <= 0)
+ throw std::out_of_range("firdes check failed: transition_width > 0");
+ }
+
+ void
+ firdes::sanity_check_2f_c(double sampling_freq,
+ double fa, // first cutoff freq
+ double fb, // second cutoff freq
+ double transition_width)
+ {
+ if(sampling_freq <= 0.0)
+ throw std::out_of_range("firdes check failed: sampling_freq > 0");
+
+ if(fa < -sampling_freq / 2 || fa > sampling_freq / 2)
+ throw std::out_of_range("firdes check failed: 0 < fa <= sampling_freq / 2");
+
+ if(fb < -sampling_freq / 2 || fb > sampling_freq / 2)
+ throw std::out_of_range("firdes check failed: 0 < fb <= sampling_freq / 2");
+
+ if(fa > fb)
+ throw std::out_of_range("firdes check failed: fa <= fb");
+
+ if(transition_width <= 0)
+ throw std::out_of_range("firdes check failed: transition_width > 0");
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/fractional_interpolator_cc_impl.cc b/gr-filter/lib/fractional_interpolator_cc_impl.cc
new file mode 100644
index 000000000..8fd89f437
--- /dev/null
+++ b/gr-filter/lib/fractional_interpolator_cc_impl.cc
@@ -0,0 +1,125 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include "fractional_interpolator_cc_impl.h"
+#include <stdexcept>
+
+namespace gr {
+ namespace filter {
+
+ fractional_interpolator_cc::sptr
+ fractional_interpolator_cc::make(float phase_shift, float interp_ratio)
+ {
+ return gnuradio::get_initial_sptr(
+ new fractional_interpolator_cc_impl(phase_shift, interp_ratio));
+ }
+
+ fractional_interpolator_cc_impl::fractional_interpolator_cc_impl
+ (float phase_shift, float interp_ratio)
+ : gr_block("fractional_interpolator_cc",
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ gr_make_io_signature(1, 1, sizeof(gr_complex))),
+ d_mu (phase_shift), d_mu_inc (interp_ratio),
+ d_interp(new mmse_fir_interpolator_cc())
+ {
+ if(interp_ratio <= 0)
+ throw std::out_of_range("interpolation ratio must be > 0");
+ if(phase_shift < 0 || phase_shift > 1)
+ throw std::out_of_range("phase shift ratio must be > 0 and < 1");
+
+ set_relative_rate(1.0 / interp_ratio);
+ }
+
+ fractional_interpolator_cc_impl::~fractional_interpolator_cc_impl()
+ {
+ delete d_interp;
+ }
+
+ void
+ fractional_interpolator_cc_impl::forecast(int noutput_items,
+ gr_vector_int &ninput_items_required)
+ {
+ unsigned ninputs = ninput_items_required.size();
+ for(unsigned i=0; i < ninputs; i++) {
+ ninput_items_required[i] =
+ (int)ceil((noutput_items * d_mu_inc) + d_interp->ntaps());
+ }
+ }
+
+ int
+ fractional_interpolator_cc_impl::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const gr_complex *in = (const gr_complex*)input_items[0];
+ gr_complex *out = (gr_complex*)output_items[0];
+
+ int ii = 0; // input index
+ int oo = 0; // output index
+
+ while(oo < noutput_items) {
+ out[oo++] = d_interp->interpolate(&in[ii], d_mu);
+
+ double s = d_mu + d_mu_inc;
+ double f = floor(s);
+ int incr = (int)f;
+ d_mu = s - f;
+ ii += incr;
+ }
+
+ consume_each(ii);
+
+ return noutput_items;
+ }
+
+ float
+ fractional_interpolator_cc_impl::mu() const
+ {
+ return d_mu;
+ }
+
+ float
+ fractional_interpolator_cc_impl::interp_ratio() const
+ {
+ return d_mu_inc;
+ }
+
+ void
+ fractional_interpolator_cc_impl::set_mu(float mu)
+ {
+ d_mu = mu;
+ }
+
+ void
+ fractional_interpolator_cc_impl::set_interp_ratio(float interp_ratio)
+ {
+ d_mu_inc = interp_ratio;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/fractional_interpolator_cc_impl.h b/gr-filter/lib/fractional_interpolator_cc_impl.h
new file mode 100644
index 000000000..cb4218603
--- /dev/null
+++ b/gr-filter/lib/fractional_interpolator_cc_impl.h
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FRACTIONAL_INTERPOLATOR_CC_IMPL_H
+#define INCLUDED_FRACTIONAL_INTERPOLATOR_CC_IMPL_H
+
+#include <filter/fractional_interpolator_cc.h>
+#include <filter/mmse_fir_interpolator_cc.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API fractional_interpolator_cc_impl
+ : public fractional_interpolator_cc
+ {
+ private:
+ float d_mu;
+ float d_mu_inc;
+ mmse_fir_interpolator_cc *d_interp;
+
+ public:
+ fractional_interpolator_cc_impl(float phase_shift,
+ float interp_ratio);
+ ~fractional_interpolator_cc_impl();
+
+ void forecast(int noutput_items,
+ gr_vector_int &ninput_items_required);
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ float mu() const;
+ float interp_ratio() const;
+ void set_mu(float mu);
+ void set_interp_ratio(float interp_ratio);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FRACTIONAL_INTERPOLATOR_CC_IMPL_H */
diff --git a/gr-filter/lib/fractional_interpolator_ff_impl.cc b/gr-filter/lib/fractional_interpolator_ff_impl.cc
new file mode 100644
index 000000000..6b35dc106
--- /dev/null
+++ b/gr-filter/lib/fractional_interpolator_ff_impl.cc
@@ -0,0 +1,125 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007,2010 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include "fractional_interpolator_ff_impl.h"
+#include <stdexcept>
+
+namespace gr {
+ namespace filter {
+
+ fractional_interpolator_ff::sptr
+ fractional_interpolator_ff::make(float phase_shift, float interp_ratio)
+ {
+ return gnuradio::get_initial_sptr(
+ new fractional_interpolator_ff_impl(phase_shift, interp_ratio));
+ }
+
+ fractional_interpolator_ff_impl::fractional_interpolator_ff_impl
+ (float phase_shift, float interp_ratio)
+ : gr_block("fractional_interpolator_ff",
+ gr_make_io_signature(1, 1, sizeof(float)),
+ gr_make_io_signature(1, 1, sizeof(float))),
+ d_mu (phase_shift), d_mu_inc (interp_ratio),
+ d_interp(new mmse_fir_interpolator_ff())
+ {
+ if(interp_ratio <= 0)
+ throw std::out_of_range("interpolation ratio must be > 0");
+ if(phase_shift < 0 || phase_shift > 1)
+ throw std::out_of_range("phase shift ratio must be > 0 and < 1");
+
+ set_relative_rate(1.0 / interp_ratio);
+ }
+
+ fractional_interpolator_ff_impl::~fractional_interpolator_ff_impl()
+ {
+ delete d_interp;
+ }
+
+ void
+ fractional_interpolator_ff_impl::forecast(int noutput_items,
+ gr_vector_int &ninput_items_required)
+ {
+ unsigned ninputs = ninput_items_required.size();
+ for(unsigned i=0; i < ninputs; i++) {
+ ninput_items_required[i] =
+ (int)ceil((noutput_items * d_mu_inc) + d_interp->ntaps());
+ }
+ }
+
+ int
+ fractional_interpolator_ff_impl::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const float *in = (const float*)input_items[0];
+ float *out = (float*)output_items[0];
+
+ int ii = 0; // input index
+ int oo = 0; // output index
+
+ while(oo < noutput_items) {
+ out[oo++] = d_interp->interpolate(&in[ii], d_mu);
+
+ double s = d_mu + d_mu_inc;
+ double f = floor(s);
+ int incr = (int)f;
+ d_mu = s - f;
+ ii += incr;
+ }
+
+ consume_each(ii);
+
+ return noutput_items;
+ }
+
+ float
+ fractional_interpolator_ff_impl::mu() const
+ {
+ return d_mu;
+ }
+
+ float
+ fractional_interpolator_ff_impl::interp_ratio() const
+ {
+ return d_mu_inc;
+ }
+
+ void
+ fractional_interpolator_ff_impl::set_mu(float mu)
+ {
+ d_mu = mu;
+ }
+
+ void
+ fractional_interpolator_ff_impl::set_interp_ratio(float interp_ratio)
+ {
+ d_mu_inc = interp_ratio;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/fractional_interpolator_ff_impl.h b/gr-filter/lib/fractional_interpolator_ff_impl.h
new file mode 100644
index 000000000..d31385cc4
--- /dev/null
+++ b/gr-filter/lib/fractional_interpolator_ff_impl.h
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FRACTIONAL_INTERPOLATOR_FF_IMPL_H
+#define INCLUDED_FRACTIONAL_INTERPOLATOR_FF_IMPL_H
+
+#include <filter/fractional_interpolator_ff.h>
+#include <filter/mmse_fir_interpolator_ff.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API fractional_interpolator_ff_impl
+ : public fractional_interpolator_ff
+ {
+ private:
+ float d_mu;
+ float d_mu_inc;
+ mmse_fir_interpolator_ff *d_interp;
+
+ public:
+ fractional_interpolator_ff_impl(float phase_shift,
+ float interp_ratio);
+ ~fractional_interpolator_ff_impl();
+
+ void forecast(int noutput_items,
+ gr_vector_int &ninput_items_required);
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ float mu() const;
+ float interp_ratio() const;
+ void set_mu(float mu);
+ void set_interp_ratio(float interp_ratio);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FRACTIONAL_INTERPOLATOR_FF_IMPL_H */
diff --git a/gr-filter/lib/freq_xlating_fir_filter_XXX_impl.cc.t b/gr-filter/lib/freq_xlating_fir_filter_XXX_impl.cc.t
new file mode 100644
index 000000000..a59fa12b3
--- /dev/null
+++ b/gr-filter/lib/freq_xlating_fir_filter_XXX_impl.cc.t
@@ -0,0 +1,143 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * WARNING: This file is automatically generated by cmake.
+ * Any changes made to this file will be overwritten.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "@IMPL_NAME@.h"
+#include <gr_io_signature.h>
+#include <volk/volk.h>
+
+namespace gr {
+ namespace filter {
+
+ @BASE_NAME@::sptr
+ @BASE_NAME@::make(int decimation,
+ const std::vector<@TAP_TYPE@> &taps,
+ double center_freq,
+ double sampling_freq)
+ {
+ return gnuradio::get_initial_sptr(new @IMPL_NAME@
+ (decimation, taps,
+ center_freq,
+ sampling_freq));
+ }
+
+ @IMPL_NAME@::@IMPL_NAME@(int decimation,
+ const std::vector<@TAP_TYPE@> &taps,
+ double center_freq,
+ double sampling_freq)
+ : gr_sync_decimator("@BASE_NAME@",
+ gr_make_io_signature(1, 1, sizeof(@I_TYPE@)),
+ gr_make_io_signature(1, 1, sizeof(@O_TYPE@)),
+ decimation),
+ d_proto_taps(taps), d_center_freq(center_freq),
+ d_sampling_freq(sampling_freq),
+ d_updated(false)
+ {
+ std::vector<gr_complex> dummy_taps;
+ d_composite_fir = new kernel::@CFIR_TYPE@(decimation, dummy_taps);
+
+ set_history(d_proto_taps.size());
+ build_composite_fir();
+ }
+
+ @IMPL_NAME@::~@IMPL_NAME@()
+ {
+ delete d_composite_fir;
+ }
+
+ void
+ @IMPL_NAME@::build_composite_fir()
+ {
+ std::vector<gr_complex> ctaps(d_proto_taps.size());
+
+ float fwT0 = -2 * M_PI * d_center_freq / d_sampling_freq;
+ for(unsigned int i = 0; i < d_proto_taps.size(); i++) {
+ ctaps[i] = d_proto_taps[i] * exp(gr_complex(0, i * fwT0));
+ }
+
+ std::reverse(ctaps.begin(), ctaps.end());
+ d_composite_fir->set_taps(ctaps);
+ d_r.set_phase_incr(exp(gr_complex(0, fwT0 * decimation())));
+ }
+
+ void
+ @IMPL_NAME@::set_center_freq(double center_freq)
+ {
+ d_center_freq = center_freq;
+ d_updated = true;
+ }
+
+ double
+ @IMPL_NAME@::center_freq() const
+ {
+ return d_center_freq;
+ }
+
+ void
+ @IMPL_NAME@::set_taps(const std::vector<@TAP_TYPE@> &taps)
+ {
+ d_proto_taps = taps;
+ d_updated = true;
+ }
+
+ std::vector<@TAP_TYPE@>
+ @IMPL_NAME@::taps() const
+ {
+ return d_proto_taps;
+ }
+
+ int
+ @IMPL_NAME@::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ @I_TYPE@ *in = (@I_TYPE@ *)input_items[0];
+ @O_TYPE@ *out = (@O_TYPE@ *)output_items[0];
+
+ // rebuild composite FIR if the center freq has changed
+ if(d_updated) {
+ set_history(d_proto_taps.size());
+ build_composite_fir();
+ d_updated = false;
+ return 0; // history requirements may have changed.
+ }
+
+ unsigned j = 0;
+ for (int i = 0; i < noutput_items; i++){
+ out[i] = d_r.rotate(d_composite_fir->filter(&in[j]));
+ j += decimation();
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
+
diff --git a/gr-filter/lib/freq_xlating_fir_filter_XXX_impl.h.t b/gr-filter/lib/freq_xlating_fir_filter_XXX_impl.h.t
new file mode 100644
index 000000000..0cf976d58
--- /dev/null
+++ b/gr-filter/lib/freq_xlating_fir_filter_XXX_impl.h.t
@@ -0,0 +1,71 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2004,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * WARNING: This file is automatically generated by cmake.
+ * Any changes made to this file will be overwritten.
+ */
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
+
+#include <filter/api.h>
+#include <filter/fir_filter.h>
+#include <filter/@BASE_NAME@.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API @IMPL_NAME@ : public @BASE_NAME@
+ {
+ protected:
+ std::vector<@TAP_TYPE@> d_proto_taps;
+ kernel::@CFIR_TYPE@ *d_composite_fir;
+ gr_rotator d_r;
+ double d_center_freq;
+ double d_sampling_freq;
+ bool d_updated;
+
+ virtual void build_composite_fir();
+ public:
+
+ @IMPL_NAME@(int decimation,
+ const std::vector<@TAP_TYPE@> &taps,
+ double center_freq,
+ double sampling_freq);
+ virtual ~@IMPL_NAME@();
+
+ void set_center_freq(double center_freq);
+ double center_freq() const;
+
+ void set_taps(const std::vector<@TAP_TYPE@> &taps);
+ std::vector<@TAP_TYPE@> taps() const;
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* @GUARD_NAME@ */
diff --git a/gr-filter/lib/hilbert_fc_impl.cc b/gr-filter/lib/hilbert_fc_impl.cc
new file mode 100644
index 000000000..52b2dabae
--- /dev/null
+++ b/gr-filter/lib/hilbert_fc_impl.cc
@@ -0,0 +1,76 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2010 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "hilbert_fc_impl.h"
+#include <filter/firdes.h>
+#include <gr_io_signature.h>
+#include <volk/volk.h>
+
+namespace gr {
+ namespace filter {
+
+ hilbert_fc::sptr hilbert_fc::make(unsigned int ntaps)
+ {
+ return gnuradio::get_initial_sptr(new hilbert_fc_impl(ntaps));
+ }
+
+ hilbert_fc_impl::hilbert_fc_impl(unsigned int ntaps)
+ : gr_sync_block ("hilbert_fc",
+ gr_make_io_signature (1, 1, sizeof(float)),
+ gr_make_io_signature (1, 1, sizeof(gr_complex))),
+ d_ntaps(ntaps | 0x1) // ensure ntaps is odd
+ {
+ d_hilb = new kernel::fir_filter_fff(1, firdes::hilbert(d_ntaps));
+ set_history (d_ntaps);
+
+ const int alignment_multiple =
+ volk_get_alignment() / sizeof(float);
+ set_alignment(std::max(1, alignment_multiple));
+ }
+
+ hilbert_fc_impl::~hilbert_fc_impl()
+ {
+ delete d_hilb;
+ }
+
+ int
+ hilbert_fc_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ float *in = (float *)input_items[0];
+ gr_complex *out = (gr_complex *)output_items[0];
+
+ for(int i = 0; i < noutput_items; i++) {
+ out[i] = gr_complex(in[i + d_ntaps/2],
+ d_hilb->filter(&in[i]));
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/hilbert_fc_impl.h b/gr-filter/lib/hilbert_fc_impl.h
new file mode 100644
index 000000000..d2b41b573
--- /dev/null
+++ b/gr-filter/lib/hilbert_fc_impl.h
@@ -0,0 +1,52 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_HILBERT_FC_IMPL_H
+#define INCLUDED_FILTER_HILBERT_FC_IMPL_H
+
+#include <filter/hilbert_fc.h>
+#include <filter/fir_filter.h>
+#include <gr_types.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API hilbert_fc_impl : public hilbert_fc
+ {
+ private:
+ unsigned int d_ntaps;
+ kernel::fir_filter_fff *d_hilb;
+
+ public:
+ hilbert_fc_impl(unsigned int ntaps);
+
+ ~hilbert_fc_impl();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_HILBERT_FC_IMPL_H */
diff --git a/gr-filter/lib/iir_filter_ffd_impl.cc b/gr-filter/lib/iir_filter_ffd_impl.cc
new file mode 100644
index 000000000..24bfad190
--- /dev/null
+++ b/gr-filter/lib/iir_filter_ffd_impl.cc
@@ -0,0 +1,85 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "iir_filter_ffd_impl.h"
+#include <gr_io_signature.h>
+
+namespace gr {
+ namespace filter {
+
+ iir_filter_ffd::sptr
+ iir_filter_ffd::make(const std::vector<double> &fftaps,
+ const std::vector<double> &fbtaps)
+ {
+ return gnuradio::get_initial_sptr(new iir_filter_ffd_impl(fftaps, fbtaps));
+ }
+
+ iir_filter_ffd_impl::iir_filter_ffd_impl(const std::vector<double> &fftaps,
+ const std::vector<double> &fbtaps)
+
+ : gr_sync_block("iir_filter_ffd",
+ gr_make_io_signature(1, 1, sizeof (float)),
+ gr_make_io_signature(1, 1, sizeof (float))),
+ d_updated(false)
+ {
+ d_iir = new kernel::iir_filter<float,float,double>(fftaps, fbtaps);
+ //d_iir = new gri_iir<float,float,double>(fftaps, fbtaps);
+ }
+
+ iir_filter_ffd_impl::~iir_filter_ffd_impl()
+ {
+ delete d_iir;
+ }
+
+ void
+ iir_filter_ffd_impl::set_taps(const std::vector<double> &fftaps,
+ const std::vector<double> &fbtaps)
+ {
+ d_new_fftaps = fftaps;
+ d_new_fbtaps = fbtaps;
+ d_updated = true;
+ }
+
+ int
+ iir_filter_ffd_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const float *in = (const float*)input_items[0];
+ float *out = (float*)output_items[0];
+
+ if(d_updated) {
+ d_iir->set_taps(d_new_fftaps, d_new_fbtaps);
+ d_updated = false;
+ }
+
+ d_iir->filter_n(out, in, noutput_items);
+ return noutput_items;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
diff --git a/gr-filter/lib/iir_filter_ffd_impl.h b/gr-filter/lib/iir_filter_ffd_impl.h
new file mode 100644
index 000000000..45aab6c22
--- /dev/null
+++ b/gr-filter/lib/iir_filter_ffd_impl.h
@@ -0,0 +1,56 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_IIR_FILTER_FFD_IMPL_H
+#define INCLUDED_IIR_FILTER_FFD_IMPL_H
+
+#include <filter/iir_filter.h>
+#include <filter/iir_filter_ffd.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API iir_filter_ffd_impl : public iir_filter_ffd
+ {
+ private:
+ bool d_updated;
+ kernel::iir_filter<float,float,double> *d_iir;
+ std::vector<double> d_new_fftaps;
+ std::vector<double> d_new_fbtaps;
+
+ public:
+ iir_filter_ffd_impl(const std::vector<double> &fftaps,
+ const std::vector<double> &fbtaps);
+ ~iir_filter_ffd_impl();
+
+ void set_taps(const std::vector<double> &fftaps,
+ const std::vector<double> &fbtaps);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_IIR_FILTER_FFD_IMPL_H */
diff --git a/gr-filter/lib/interp_fir_filter_XXX_impl.cc.t b/gr-filter/lib/interp_fir_filter_XXX_impl.cc.t
new file mode 100644
index 000000000..c9127d737
--- /dev/null
+++ b/gr-filter/lib/interp_fir_filter_XXX_impl.cc.t
@@ -0,0 +1,151 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* @WARNING@ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "@IMPL_NAME@.h"
+#include <gr_io_signature.h>
+#include <volk/volk.h>
+#include <stdexcept>
+
+namespace gr {
+ namespace filter {
+
+ @BASE_NAME@::sptr
+ @BASE_NAME@::make(unsigned interpolation,
+ const std::vector<@TAP_TYPE@> &taps)
+ {
+ return gnuradio::get_initial_sptr(new @IMPL_NAME@
+ (interpolation, taps));
+ }
+
+ @IMPL_NAME@::@IMPL_NAME@(unsigned interpolation,
+ const std::vector<@TAP_TYPE@> &taps)
+ : gr_sync_interpolator("@BASE_NAME@",
+ gr_make_io_signature(1, 1, sizeof(@I_TYPE@)),
+ gr_make_io_signature(1, 1, sizeof(@O_TYPE@)),
+ interpolation),
+ d_updated(false), d_firs(interpolation)
+ {
+ if(interpolation == 0) {
+ throw std::out_of_range("@IMPL_NAME@: interpolation must be > 0\n");
+ }
+
+ std::vector<@TAP_TYPE@> dummy_taps;
+
+ for(unsigned i = 0; i < interpolation; i++) {
+ d_firs[i] = new kernel::@FIR_TYPE@(1, dummy_taps);
+ }
+
+ set_taps(taps);
+ install_taps(d_new_taps);
+ }
+
+ @IMPL_NAME@::~@IMPL_NAME@()
+ {
+ for(unsigned i = 0; i < interpolation(); i++) {
+ delete d_firs[i];
+ }
+ }
+
+ void
+ @IMPL_NAME@::set_taps(const std::vector<@TAP_TYPE@> &taps)
+ {
+ d_new_taps = taps;
+ d_updated = true;
+
+ // round up length to a multiple of the interpolation factor
+ int n = taps.size() % interpolation();
+ if(n > 0) {
+ n = interpolation() - n;
+ while(n-- > 0) {
+ d_new_taps.insert(d_new_taps.begin(), 0);
+ }
+ }
+
+ if(d_new_taps.size() % interpolation() != 0) {
+ throw std::runtime_error("@IMPL_NAME@: error setting interpolator taps.\n");
+ }
+ }
+
+ void
+ @IMPL_NAME@::install_taps(const std::vector<@TAP_TYPE@> &taps)
+ {
+ unsigned nfilters = interpolation();
+ int nt = taps.size() / nfilters;
+
+ std::vector< std::vector <@TAP_TYPE@> > xtaps(nfilters);
+
+ for(unsigned n = 0; n < nfilters; n++) {
+ xtaps[n].resize (nt);
+ }
+
+ for(size_t i = 0; i < taps.size(); i++) {
+ xtaps[i % nfilters][i / nfilters] = taps[i];
+ }
+
+ for(unsigned n = 0; n < nfilters; n++) {
+ d_firs[n]->set_taps (xtaps[n]);
+ }
+
+ set_history(nt);
+ d_updated = false;
+ }
+
+ std::vector<@TAP_TYPE@>
+ @IMPL_NAME@::taps() const
+ {
+ return d_new_taps;
+ }
+
+ int
+ @NAME@::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const @I_TYPE@ *in = (const @I_TYPE@ *)input_items[0];
+ @O_TYPE@ *out = (@O_TYPE@ *)output_items[0];
+
+ if(d_updated) {
+ install_taps(d_new_taps);
+ return 0; // history requirements may have changed.
+ }
+
+ int nfilters = interpolation();
+ int ni = noutput_items / interpolation();
+
+ for(int i = 0; i < ni; i++) {
+ for(int nf = 0; nf < nfilters; nf++) {
+ out[nf] = d_firs[nf]->filter(&in[i]);
+ }
+ out += nfilters;
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/interp_fir_filter_XXX_impl.h.t b/gr-filter/lib/interp_fir_filter_XXX_impl.h.t
new file mode 100644
index 000000000..e505fca69
--- /dev/null
+++ b/gr-filter/lib/interp_fir_filter_XXX_impl.h.t
@@ -0,0 +1,62 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* @WARNING@ */
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
+
+#include <filter/api.h>
+#include <filter/fir_filter.h>
+#include <filter/@BASE_NAME@.h>
+#include <vector>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API @IMPL_NAME@ : public @BASE_NAME@
+ {
+ private:
+ bool d_updated;
+ std::vector<kernel::@FIR_TYPE@ *> d_firs;
+ std::vector<@TAP_TYPE@> d_new_taps;
+
+ void install_taps(const std::vector<@TAP_TYPE@> &taps);
+
+ public:
+ @IMPL_NAME@(unsigned interpolation,
+ const std::vector<@TAP_TYPE@> &taps);
+
+ ~@IMPL_NAME@();
+
+ void set_taps(const std::vector<@TAP_TYPE@> &taps);
+ std::vector<@TAP_TYPE@> taps() const;
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* @GUARD_NAME@ */
diff --git a/gr-filter/lib/mmse_fir_interpolator_cc.cc b/gr-filter/lib/mmse_fir_interpolator_cc.cc
new file mode 100644
index 000000000..8af1fb39a
--- /dev/null
+++ b/gr-filter/lib/mmse_fir_interpolator_cc.cc
@@ -0,0 +1,77 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <filter/mmse_fir_interpolator_cc.h>
+#include <filter/interpolator_taps.h>
+#include <stdexcept>
+
+namespace gr {
+ namespace filter {
+
+ mmse_fir_interpolator_cc::mmse_fir_interpolator_cc()
+ {
+ filters.resize (NSTEPS + 1);
+
+ for(int i = 0; i < NSTEPS + 1; i++) {
+ std::vector<float> t (&taps[i][0], &taps[i][NTAPS]);
+ filters[i] = new kernel::fir_filter_ccf(1, t);
+ }
+ }
+
+ mmse_fir_interpolator_cc::~mmse_fir_interpolator_cc()
+ {
+ for(int i = 0; i < NSTEPS + 1; i++)
+ delete filters[i];
+ }
+
+ unsigned
+ mmse_fir_interpolator_cc::ntaps() const
+ {
+ return NTAPS;
+ }
+
+ unsigned
+ mmse_fir_interpolator_cc::nsteps() const
+ {
+ return NSTEPS;
+ }
+
+ gr_complex
+ mmse_fir_interpolator_cc::interpolate(const gr_complex input[],
+ float mu) const
+ {
+ int imu = (int)rint(mu * NSTEPS);
+
+ if((imu < 0) || (imu > NSTEPS)) {
+ throw std::runtime_error("mmse_fir_interpolator_cc: imu out of bounds.\n");
+ }
+
+ gr_complex r = filters[imu]->filter(input);
+ return r;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/mmse_fir_interpolator_ff.cc b/gr-filter/lib/mmse_fir_interpolator_ff.cc
new file mode 100644
index 000000000..ff2c4dd87
--- /dev/null
+++ b/gr-filter/lib/mmse_fir_interpolator_ff.cc
@@ -0,0 +1,77 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <filter/mmse_fir_interpolator_ff.h>
+#include <filter/interpolator_taps.h>
+#include <stdexcept>
+
+namespace gr {
+ namespace filter {
+
+ mmse_fir_interpolator_ff::mmse_fir_interpolator_ff()
+ {
+ filters.resize(NSTEPS + 1);
+
+ for(int i = 0; i < NSTEPS + 1; i++) {
+ std::vector<float> t(&taps[i][0], &taps[i][NTAPS]);
+ filters[i] = new kernel::fir_filter_fff(1, t);
+ }
+ }
+
+ mmse_fir_interpolator_ff::~mmse_fir_interpolator_ff()
+ {
+ for(int i = 0; i < NSTEPS + 1; i++)
+ delete filters[i];
+ }
+
+ unsigned
+ mmse_fir_interpolator_ff::ntaps() const
+ {
+ return NTAPS;
+ }
+
+ unsigned
+ mmse_fir_interpolator_ff::nsteps() const
+ {
+ return NSTEPS;
+ }
+
+ float
+ mmse_fir_interpolator_ff::interpolate(const float input[],
+ float mu) const
+ {
+ int imu = (int)rint(mu * NSTEPS);
+
+ if((imu < 0) || (imu > NSTEPS)) {
+ throw std::runtime_error("mmse_fir_interpolator_ff: imu out of bounds.\n");
+ }
+
+ float r = filters[imu]->filter(input);
+ return r;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/pfb_arb_resampler_ccf_impl.cc b/gr-filter/lib/pfb_arb_resampler_ccf_impl.cc
new file mode 100644
index 000000000..5480366de
--- /dev/null
+++ b/gr-filter/lib/pfb_arb_resampler_ccf_impl.cc
@@ -0,0 +1,258 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pfb_arb_resampler_ccf_impl.h"
+#include <gr_io_signature.h>
+#include <cstdio>
+
+namespace gr {
+ namespace filter {
+
+ pfb_arb_resampler_ccf::sptr
+ pfb_arb_resampler_ccf::make(float rate,
+ const std::vector<float> &taps,
+ unsigned int filter_size)
+ {
+ return gnuradio::get_initial_sptr
+ (new pfb_arb_resampler_ccf_impl(rate, taps, filter_size));
+ }
+
+
+ pfb_arb_resampler_ccf_impl::pfb_arb_resampler_ccf_impl(float rate,
+ const std::vector<float> &taps,
+ unsigned int filter_size)
+ : gr_block("pfb_arb_resampler_ccf",
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ gr_make_io_signature(1, 1, sizeof(gr_complex))),
+ d_updated (false)
+ {
+ d_acc = 0; // start accumulator at 0
+
+ /* The number of filters is specified by the user as the filter
+ size; this is also the interpolation rate of the filter. We
+ use it and the rate provided to determine the decimation
+ rate. This acts as a rational resampler. The flt_rate is
+ calculated as the residual between the integer decimation
+ rate and the real decimation rate and will be used to
+ determine to interpolation point of the resampling process.
+ */
+ d_int_rate = filter_size;
+ set_rate(rate);
+
+ // Store the last filter between calls to work
+ d_last_filter = 0;
+
+ d_start_index = 0;
+
+ d_filters = std::vector<kernel::fir_filter_ccf*>(d_int_rate);
+ d_diff_filters = std::vector<kernel::fir_filter_ccf*>(d_int_rate);
+
+ // Create an FIR filter for each channel and zero out the taps
+ std::vector<float> vtaps(0, d_int_rate);
+ for(unsigned int i = 0; i < d_int_rate; i++) {
+ d_filters[i] = new kernel::fir_filter_ccf(1, vtaps);
+ d_diff_filters[i] = new kernel::fir_filter_ccf(1, vtaps);
+ }
+
+ // Now, actually set the filters' taps
+ set_taps(taps);
+ d_updated = false;
+ }
+
+ pfb_arb_resampler_ccf_impl::~pfb_arb_resampler_ccf_impl()
+ {
+ for(unsigned int i = 0; i < d_int_rate; i++) {
+ delete d_filters[i];
+ delete d_diff_filters[i];
+ }
+ }
+
+ void
+ pfb_arb_resampler_ccf_impl::create_taps(const std::vector<float> &newtaps,
+ std::vector< std::vector<float> > &ourtaps,
+ std::vector<kernel::fir_filter_ccf*> &ourfilter)
+ {
+ unsigned int ntaps = newtaps.size();
+ d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_int_rate);
+
+ // Create d_numchan vectors to store each channel's taps
+ ourtaps.resize(d_int_rate);
+
+ // Make a vector of the taps plus fill it out with 0's to fill
+ // each polyphase filter with exactly d_taps_per_filter
+ std::vector<float> tmp_taps;
+ tmp_taps = newtaps;
+ while((float)(tmp_taps.size()) < d_int_rate*d_taps_per_filter) {
+ tmp_taps.push_back(0.0);
+ }
+
+ // Partition the filter
+ for(unsigned int i = 0; i < d_int_rate; i++) {
+ // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out
+ ourtaps[d_int_rate-1-i] = std::vector<float>(d_taps_per_filter, 0);
+ for(unsigned int j = 0; j < d_taps_per_filter; j++) {
+ ourtaps[d_int_rate - 1 - i][j] = tmp_taps[i + j*d_int_rate];
+ }
+
+ // Build a filter for each channel and add it's taps to it
+ ourfilter[i]->set_taps(ourtaps[d_int_rate-1-i]);
+ }
+ }
+
+ void
+ pfb_arb_resampler_ccf_impl::create_diff_taps(const std::vector<float> &newtaps,
+ std::vector<float> &difftaps)
+ {
+ // Calculate the differential taps (derivative filter) by taking the difference
+ // between two taps. Duplicate the last one to make both filters the same length.
+ float tap;
+ difftaps.clear();
+ for(unsigned int i = 0; i < newtaps.size()-1; i++) {
+ tap = newtaps[i+1] - newtaps[i];
+ difftaps.push_back(tap);
+ }
+ difftaps.push_back(tap);
+ }
+
+ void
+ pfb_arb_resampler_ccf_impl::set_taps(const std::vector<float> &taps)
+ {
+ gruel::scoped_lock guard(d_mutex);
+
+ std::vector<float> dtaps;
+ create_diff_taps(taps, dtaps);
+ create_taps(taps, d_taps, d_filters);
+ create_taps(dtaps, d_dtaps, d_diff_filters);
+ set_history(d_taps_per_filter + 1);
+ d_updated = true;
+ }
+
+ std::vector<std::vector<float> >
+ pfb_arb_resampler_ccf_impl::taps() const
+ {
+ return d_taps;
+ }
+
+ void
+ pfb_arb_resampler_ccf_impl::print_taps()
+ {
+ unsigned int i, j;
+ for(i = 0; i < d_int_rate; i++) {
+ printf("filter[%d]: [", i);
+ for(j = 0; j < d_taps_per_filter; j++) {
+ printf(" %.4e", d_taps[i][j]);
+ }
+ printf("]\n");
+ }
+ }
+
+ void
+ pfb_arb_resampler_ccf_impl::set_rate(float rate)
+ {
+ gruel::scoped_lock guard(d_mutex);
+
+ d_dec_rate = (unsigned int)floor(d_int_rate/rate);
+ d_flt_rate = (d_int_rate/rate) - d_dec_rate;
+ set_relative_rate(rate);
+ }
+
+ void
+ pfb_arb_resampler_ccf_impl::set_phase(float ph)
+ {
+ gruel::scoped_lock guard(d_mutex);
+ if((ph < 0) || (ph >= 2.0*M_PI)) {
+ throw std::runtime_error("pfb_arb_resampler_ccf: set_phase value out of bounds [0, 2pi).\n");
+ }
+
+ float ph_diff = 2.0*M_PI / (float)d_filters.size();
+ d_last_filter = static_cast<int>(ph / ph_diff);
+ }
+
+ float
+ pfb_arb_resampler_ccf_impl::phase() const
+ {
+ float ph_diff = 2.0*M_PI / static_cast<float>(d_filters.size());
+ return d_last_filter * ph_diff;
+ }
+
+ int
+ pfb_arb_resampler_ccf_impl::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ gruel::scoped_lock guard(d_mutex);
+
+ gr_complex *in = (gr_complex*)input_items[0];
+ gr_complex *out = (gr_complex*)output_items[0];
+
+ if(d_updated) {
+ d_updated = false;
+ return 0; // history requirements may have changed.
+ }
+
+ int i = 0, count = d_start_index;
+ unsigned int j;
+ gr_complex o0, o1;
+
+ // Restore the last filter position
+ j = d_last_filter;
+
+ // produce output as long as we can and there are enough input samples
+ int max_input = ninput_items[0] - (int)d_taps_per_filter;
+ while((i < noutput_items) && (count < max_input)) {
+ // start j by wrapping around mod the number of channels
+ while((j < d_int_rate) && (i < noutput_items)) {
+ // Take the current filter and derivative filter output
+ o0 = d_filters[j]->filter(&in[count]);
+ o1 = d_diff_filters[j]->filter(&in[count]);
+
+ out[i] = o0 + o1*d_acc; // linearly interpolate between samples
+ i++;
+
+ // Adjust accumulator and index into filterbank
+ d_acc += d_flt_rate;
+ j += d_dec_rate + (int)floor(d_acc);
+ d_acc = fmodf(d_acc, 1.0);
+ }
+ if(i < noutput_items) { // keep state for next entry
+ float ss = (int)(j / d_int_rate); // number of items to skip ahead by
+ count += ss; // we have fully consumed another input
+ j = j % d_int_rate; // roll filter around
+ }
+ }
+
+ // Store the current filter position and start of next sample
+ d_last_filter = j;
+ d_start_index = std::max(0, count - ninput_items[0]);
+
+ // consume all we've processed but no more than we can
+ consume_each(std::min(count, ninput_items[0]));
+ return i;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/pfb_arb_resampler_ccf_impl.h b/gr-filter/lib/pfb_arb_resampler_ccf_impl.h
new file mode 100644
index 000000000..891e601e0
--- /dev/null
+++ b/gr-filter/lib/pfb_arb_resampler_ccf_impl.h
@@ -0,0 +1,89 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_PFB_ARB_RESAMPLER_CCF_IMPL_H
+#define INCLUDED_PFB_ARB_RESAMPLER_CCF_IMPL_H
+
+#include <filter/pfb_arb_resampler_ccf.h>
+#include <filter/fir_filter.h>
+#include <gruel/thread.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API pfb_arb_resampler_ccf_impl : public pfb_arb_resampler_ccf
+ {
+ private:
+ std::vector<kernel::fir_filter_ccf*> d_filters;
+ std::vector<kernel::fir_filter_ccf*> d_diff_filters;
+ std::vector< std::vector<float> > d_taps;
+ std::vector< std::vector<float> > d_dtaps;
+ unsigned int d_int_rate; // the number of filters (interpolation rate)
+ unsigned int d_dec_rate; // the stride through the filters (decimation rate)
+ float d_flt_rate; // residual rate for the linear interpolation
+ float d_acc;
+ unsigned int d_last_filter;
+ int d_start_index;
+ unsigned int d_taps_per_filter;
+ bool d_updated;
+ gruel::mutex d_mutex; // mutex to protect set/work access
+
+ void create_diff_taps(const std::vector<float> &newtaps,
+ std::vector<float> &difftaps);
+
+ /*!
+ * Resets the filterbank's filter taps with the new prototype filter
+ * \param newtaps (vector of floats) The prototype filter to populate the filterbank.
+ * The taps should be generated at the interpolated sampling rate.
+ * \param ourtaps (vector of floats) Reference to our internal member of holding the taps.
+ * \param ourfilter (vector of filters) Reference to our internal filter to set the taps for.
+ */
+ void create_taps(const std::vector<float> &newtaps,
+ std::vector< std::vector<float> > &ourtaps,
+ std::vector<kernel::fir_filter_ccf*> &ourfilter);
+
+ public:
+ pfb_arb_resampler_ccf_impl(float rate,
+ const std::vector<float> &taps,
+ unsigned int filter_size);
+
+ ~pfb_arb_resampler_ccf_impl();
+
+ void set_taps(const std::vector<float> &taps);
+ std::vector<std::vector<float> > taps() const;
+ void print_taps();
+ void set_rate(float rate);
+
+ void set_phase(float ph);
+ float phase() const;
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_PFB_ARB_RESAMPLER_CCF_IMPL_H */
diff --git a/gr-filter/lib/pfb_arb_resampler_fff_impl.cc b/gr-filter/lib/pfb_arb_resampler_fff_impl.cc
new file mode 100644
index 000000000..6aff374fd
--- /dev/null
+++ b/gr-filter/lib/pfb_arb_resampler_fff_impl.cc
@@ -0,0 +1,258 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009-2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pfb_arb_resampler_fff_impl.h"
+#include <gr_io_signature.h>
+#include <cstdio>
+
+namespace gr {
+ namespace filter {
+
+ pfb_arb_resampler_fff::sptr
+ pfb_arb_resampler_fff::make(float rate,
+ const std::vector<float> &taps,
+ unsigned int filter_size)
+ {
+ return gnuradio::get_initial_sptr
+ (new pfb_arb_resampler_fff_impl(rate, taps, filter_size));
+ }
+
+
+ pfb_arb_resampler_fff_impl::pfb_arb_resampler_fff_impl(float rate,
+ const std::vector<float> &taps,
+ unsigned int filter_size)
+ : gr_block("pfb_arb_resampler_fff",
+ gr_make_io_signature(1, 1, sizeof(float)),
+ gr_make_io_signature(1, 1, sizeof(float))),
+ d_updated(false)
+ {
+ d_acc = 0; // start accumulator at 0
+
+ /* The number of filters is specified by the user as the filter
+ size; this is also the interpolation rate of the filter. We
+ use it and the rate provided to determine the decimation
+ rate. This acts as a rational resampler. The flt_rate is
+ calculated as the residual between the integer decimation
+ rate and the real decimation rate and will be used to
+ determine to interpolation point of the resampling process.
+ */
+ d_int_rate = filter_size;
+ set_rate(rate);
+
+ // Store the last filter between calls to work
+ d_last_filter = 0;
+
+ d_start_index = 0;
+
+ d_filters = std::vector<kernel::fir_filter_fff*>(d_int_rate);
+ d_diff_filters = std::vector<kernel::fir_filter_fff*>(d_int_rate);
+
+ // Create an FIR filter for each channel and zero out the taps
+ std::vector<float> vtaps(0, d_int_rate);
+ for(unsigned int i = 0; i < d_int_rate; i++) {
+ d_filters[i] = new kernel::fir_filter_fff(1, vtaps);
+ d_diff_filters[i] = new kernel::fir_filter_fff(1, vtaps);
+ }
+
+ // Now, actually set the filters' taps
+ std::vector<float> dtaps;
+ create_diff_taps(taps, dtaps);
+ create_taps(taps, d_taps, d_filters);
+ create_taps(dtaps, d_dtaps, d_diff_filters);
+ }
+
+ pfb_arb_resampler_fff_impl::~pfb_arb_resampler_fff_impl()
+ {
+ for(unsigned int i = 0; i < d_int_rate; i++) {
+ delete d_filters[i];
+ delete d_diff_filters[i];
+ }
+ }
+
+ void
+ pfb_arb_resampler_fff_impl::create_taps(const std::vector<float> &newtaps,
+ std::vector< std::vector<float> > &ourtaps,
+ std::vector<kernel::fir_filter_fff*> &ourfilter)
+ {
+ unsigned int ntaps = newtaps.size();
+ d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_int_rate);
+
+ // Create d_numchan vectors to store each channel's taps
+ ourtaps.resize(d_int_rate);
+
+ // Make a vector of the taps plus fill it out with 0's to fill
+ // each polyphase filter with exactly d_taps_per_filter
+ std::vector<float> tmp_taps;
+ tmp_taps = newtaps;
+ while((float)(tmp_taps.size()) < d_int_rate*d_taps_per_filter) {
+ tmp_taps.push_back(0.0);
+ }
+
+ // Partition the filter
+ for(unsigned int i = 0; i < d_int_rate; i++) {
+ // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out
+ ourtaps[d_int_rate-1-i] = std::vector<float>(d_taps_per_filter, 0);
+ for(unsigned int j = 0; j < d_taps_per_filter; j++) {
+ ourtaps[d_int_rate - 1 - i][j] = tmp_taps[i + j*d_int_rate];
+ }
+
+ // Build a filter for each channel and add it's taps to it
+ ourfilter[i]->set_taps(ourtaps[d_int_rate-1-i]);
+ }
+
+ // Set the history to ensure enough input items for each filter
+ set_history(d_taps_per_filter + 1);
+
+ d_updated = true;
+ }
+
+ void
+ pfb_arb_resampler_fff_impl::create_diff_taps(const std::vector<float> &newtaps,
+ std::vector<float> &difftaps)
+ {
+ // Calculate the differential taps (derivative filter) by taking the difference
+ // between two taps. Duplicate the last one to make both filters the same length.
+ float tap;
+ difftaps.clear();
+ for(unsigned int i = 0; i < newtaps.size()-1; i++) {
+ tap = newtaps[i+1] - newtaps[i];
+ difftaps.push_back(tap);
+ }
+ difftaps.push_back(tap);
+ }
+
+ void
+ pfb_arb_resampler_fff_impl::set_taps(const std::vector<float> &taps)
+ {
+ gruel::scoped_lock guard(d_mutex);
+ }
+
+ std::vector<std::vector<float> >
+ pfb_arb_resampler_fff_impl::taps() const
+ {
+ return d_taps;
+ }
+
+ void
+ pfb_arb_resampler_fff_impl::print_taps()
+ {
+ unsigned int i, j;
+ for(i = 0; i < d_int_rate; i++) {
+ printf("filter[%d]: [", i);
+ for(j = 0; j < d_taps_per_filter; j++) {
+ printf(" %.4e", d_taps[i][j]);
+ }
+ printf("]\n");
+ }
+ }
+
+ void
+ pfb_arb_resampler_fff_impl::set_rate(float rate)
+ {
+ gruel::scoped_lock guard(d_mutex);
+
+ d_dec_rate = (unsigned int)floor(d_int_rate/rate);
+ d_flt_rate = (d_int_rate/rate) - d_dec_rate;
+ set_relative_rate(rate);
+ }
+
+ void
+ pfb_arb_resampler_fff_impl::set_phase(float ph)
+ {
+ gruel::scoped_lock guard(d_mutex);
+ if((ph < 0) || (ph >= 2.0*M_PI)) {
+ throw std::runtime_error("pfb_arb_resampler_ccf: set_phase value out of bounds [0, 2pi).\n");
+ }
+
+ float ph_diff = 2.0*M_PI / (float)d_filters.size();
+ d_last_filter = static_cast<int>(ph / ph_diff);
+ }
+
+ float
+ pfb_arb_resampler_fff_impl::phase() const
+ {
+ float ph_diff = 2.0*M_PI / static_cast<float>(d_filters.size());
+ return d_last_filter * ph_diff;
+ }
+
+ int
+ pfb_arb_resampler_fff_impl::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ gruel::scoped_lock guard(d_mutex);
+
+ float *in = (float*)input_items[0];
+ float *out = (float*)output_items[0];
+
+ if(d_updated) {
+ d_updated = false;
+ return 0; // history requirements may have changed.
+ }
+
+ int i = 0, count = d_start_index;
+ unsigned int j;
+ float o0, o1;
+
+ // Restore the last filter position
+ j = d_last_filter;
+
+ // produce output as long as we can and there are enough input samples
+ int max_input = ninput_items[0] - (int)d_taps_per_filter;
+ while((i < noutput_items) && (count < max_input)) {
+ // start j by wrapping around mod the number of channels
+ while((j < d_int_rate) && (i < noutput_items)) {
+ // Take the current filter and derivative filter output
+ o0 = d_filters[j]->filter(&in[count]);
+ o1 = d_diff_filters[j]->filter(&in[count]);
+
+ out[i] = o0 + o1*d_acc; // linearly interpolate between samples
+ i++;
+
+ // Adjust accumulator and index into filterbank
+ d_acc += d_flt_rate;
+ j += d_dec_rate + (int)floor(d_acc);
+ d_acc = fmodf(d_acc, 1.0);
+ }
+ if(i < noutput_items) { // keep state for next entry
+ float ss = (int)(j / d_int_rate); // number of items to skip ahead by
+ count += ss; // we have fully consumed another input
+ j = j % d_int_rate; // roll filter around
+ }
+ }
+
+ // Store the current filter position and start of next sample
+ d_last_filter = j;
+ d_start_index = std::max(0, count - ninput_items[0]);
+
+ // consume all we've processed but no more than we can
+ consume_each(std::min(count, ninput_items[0]));
+ return i;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/pfb_arb_resampler_fff_impl.h b/gr-filter/lib/pfb_arb_resampler_fff_impl.h
new file mode 100644
index 000000000..588962711
--- /dev/null
+++ b/gr-filter/lib/pfb_arb_resampler_fff_impl.h
@@ -0,0 +1,88 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009-2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_PFB_ARB_RESAMPLER_FFF_IMPL_H
+#define INCLUDED_PFB_ARB_RESAMPLER_FFF_IMPL_H
+
+#include <filter/pfb_arb_resampler_fff.h>
+#include <filter/fir_filter.h>
+#include <gruel/thread.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API pfb_arb_resampler_fff_impl : public pfb_arb_resampler_fff
+ {
+ private:
+ std::vector<kernel::fir_filter_fff*> d_filters;
+ std::vector<kernel::fir_filter_fff*> d_diff_filters;
+ std::vector< std::vector<float> > d_taps;
+ std::vector< std::vector<float> > d_dtaps;
+ unsigned int d_int_rate; // the number of filters (interpolation rate)
+ unsigned int d_dec_rate; // the stride through the filters (decimation rate)
+ float d_flt_rate; // residual rate for the linear interpolation
+ float d_acc;
+ unsigned int d_last_filter;
+ int d_start_index;
+ unsigned int d_taps_per_filter;
+ bool d_updated;
+ gruel::mutex d_mutex; // mutex to protect set/work access
+
+ void create_diff_taps(const std::vector<float> &newtaps,
+ std::vector<float> &difftaps);
+
+ /*!
+ * Resets the filterbank's filter taps with the new prototype filter
+ * \param newtaps (vector of floats) The prototype filter to populate the filterbank.
+ * The taps should be generated at the interpolated sampling rate.
+ * \param ourtaps (vector of floats) Reference to our internal member of holding the taps.
+ * \param ourfilter (vector of filters) Reference to our internal filter to set the taps for.
+ */
+ void create_taps(const std::vector<float> &newtaps,
+ std::vector< std::vector<float> > &ourtaps,
+ std::vector<kernel::fir_filter_fff*> &ourfilter);
+ public:
+ pfb_arb_resampler_fff_impl(float rate,
+ const std::vector<float> &taps,
+ unsigned int filter_size);
+
+ ~pfb_arb_resampler_fff_impl();
+
+ void set_taps(const std::vector<float> &taps);
+ std::vector<std::vector<float> > taps() const;
+ void print_taps();
+ void set_rate(float rate);
+
+ void set_phase(float ph);
+ float phase() const;
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_PFB_ARB_RESAMPLER_FFF_IMPL_H */
diff --git a/gr-filter/lib/pfb_channelizer_ccf_impl.cc b/gr-filter/lib/pfb_channelizer_ccf_impl.cc
new file mode 100644
index 000000000..28fc1dcc1
--- /dev/null
+++ b/gr-filter/lib/pfb_channelizer_ccf_impl.cc
@@ -0,0 +1,191 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pfb_channelizer_ccf_impl.h"
+#include <gr_io_signature.h>
+
+namespace gr {
+ namespace filter {
+
+ pfb_channelizer_ccf::sptr pfb_channelizer_ccf::make(unsigned int nfilts,
+ const std::vector<float> &taps,
+ float oversample_rate)
+ {
+ return gnuradio::get_initial_sptr(new pfb_channelizer_ccf_impl(nfilts, taps,
+ oversample_rate));
+ }
+
+ pfb_channelizer_ccf_impl::pfb_channelizer_ccf_impl(unsigned int nfilts,
+ const std::vector<float> &taps,
+ float oversample_rate)
+ : gr_block("pfb_channelizer_ccf",
+ gr_make_io_signature(nfilts, nfilts, sizeof(gr_complex)),
+ gr_make_io_signature(1, nfilts, sizeof(gr_complex))),
+ polyphase_filterbank(nfilts, taps),
+ d_updated(false), d_oversample_rate(oversample_rate)
+ {
+ // The over sampling rate must be rationally related to the number of channels
+ // in that it must be N/i for i in [1,N], which gives an outputsample rate
+ // of [fs/N, fs] where fs is the input sample rate.
+ // This tests the specified input sample rate to see if it conforms to this
+ // requirement within a few significant figures.
+ double intp = 0;
+ double fltp = modf(nfilts / oversample_rate, &intp);
+ if(fltp != 0.0)
+ throw std::invalid_argument("pfb_channelizer: oversample rate must be N/i for i in [1, N]");
+
+ set_relative_rate(1.0/intp);
+
+ // Default channel map
+ d_channel_map.resize(d_nfilts);
+ for(unsigned int i = 0; i < d_nfilts; i++) {
+ d_channel_map[i] = i;
+ }
+
+ // Although the filters change, we use this look up table
+ // to set the index of the FFT input buffer, which equivalently
+ // performs the FFT shift operation on every other turn.
+ d_rate_ratio = (int)rintf(d_nfilts / d_oversample_rate);
+ d_idxlut = new int[d_nfilts];
+ for(unsigned int i = 0; i < d_nfilts; i++) {
+ d_idxlut[i] = d_nfilts - ((i + d_rate_ratio) % d_nfilts) - 1;
+ }
+
+ // Calculate the number of filtering rounds to do to evenly
+ // align the input vectors with the output channels
+ d_output_multiple = 1;
+ while((d_output_multiple * d_rate_ratio) % d_nfilts != 0)
+ d_output_multiple++;
+ set_output_multiple(d_output_multiple);
+
+ set_history(d_taps_per_filter+1);
+ }
+
+ pfb_channelizer_ccf_impl::~pfb_channelizer_ccf_impl()
+ {
+ delete [] d_idxlut;
+ }
+
+ void
+ pfb_channelizer_ccf_impl::set_taps(const std::vector<float> &taps)
+ {
+ gruel::scoped_lock guard(d_mutex);
+
+ polyphase_filterbank::set_taps(taps);
+ set_history(d_taps_per_filter+1);
+ d_updated = true;
+ }
+
+ void
+ pfb_channelizer_ccf_impl::print_taps()
+ {
+ polyphase_filterbank::print_taps();
+ }
+
+ std::vector<std::vector<float> >
+ pfb_channelizer_ccf_impl::taps() const
+ {
+ return polyphase_filterbank::taps();
+ }
+
+ void
+ pfb_channelizer_ccf_impl::set_channel_map(const std::vector<int> &map)
+ {
+ gruel::scoped_lock guard(d_mutex);
+
+ if(map.size() > 0) {
+ unsigned int max = (unsigned int)*std::max_element(map.begin(), map.end());
+ if(max >= d_nfilts) {
+ throw std::invalid_argument("pfb_channelizer_ccf_impl::set_channel_map: map range out of bounds.\n");
+ }
+ d_channel_map = map;
+ }
+ }
+
+ std::vector<int>
+ pfb_channelizer_ccf_impl::channel_map() const
+ {
+ return d_channel_map;
+ }
+
+ int
+ pfb_channelizer_ccf_impl::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ gruel::scoped_lock guard(d_mutex);
+
+ gr_complex *in = (gr_complex *) input_items[0];
+ gr_complex *out = (gr_complex *) output_items[0];
+
+ if(d_updated) {
+ d_updated = false;
+ return 0; // history requirements may have changed.
+ }
+
+ size_t noutputs = output_items.size();
+
+ int n=1, i=-1, j=0, oo=0, last;
+ int toconsume = (int)rintf(noutput_items/d_oversample_rate);
+ while(n <= toconsume) {
+ j = 0;
+ i = (i + d_rate_ratio) % d_nfilts;
+ last = i;
+ while(i >= 0) {
+ in = (gr_complex*)input_items[j];
+ d_fft->get_inbuf()[d_idxlut[j]] = d_filters[i]->filter(&in[n]);
+ j++;
+ i--;
+ }
+
+ i = d_nfilts-1;
+ while(i > last) {
+ in = (gr_complex*)input_items[j];
+ d_fft->get_inbuf()[d_idxlut[j]] = d_filters[i]->filter(&in[n-1]);
+ j++;
+ i--;
+ }
+
+ n += (i+d_rate_ratio) >= (int)d_nfilts;
+
+ // despin through FFT
+ d_fft->execute();
+
+ // Send to output channels
+ for(unsigned int nn = 0; nn < noutputs; nn++) {
+ out = (gr_complex*)output_items[nn];
+ out[oo] = d_fft->get_outbuf()[d_channel_map[nn]];
+ }
+ oo++;
+ }
+
+ consume_each(toconsume);
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/pfb_channelizer_ccf_impl.h b/gr-filter/lib/pfb_channelizer_ccf_impl.h
new file mode 100644
index 000000000..16b112b9a
--- /dev/null
+++ b/gr-filter/lib/pfb_channelizer_ccf_impl.h
@@ -0,0 +1,69 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FILTER_PFB_CHANNELIZER_CCF_IMPL_H
+#define INCLUDED_FILTER_PFB_CHANNELIZER_CCF_IMPL_H
+
+#include <filter/pfb_channelizer_ccf.h>
+#include <filter/polyphase_filterbank.h>
+#include <filter/fir_filter.h>
+#include <fft/fft.h>
+#include <gruel/thread.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API pfb_channelizer_ccf_impl : public pfb_channelizer_ccf, kernel::polyphase_filterbank
+ {
+ private:
+ bool d_updated;
+ float d_oversample_rate;
+ int *d_idxlut;
+ int d_rate_ratio;
+ int d_output_multiple;
+ std::vector<int> d_channel_map;
+ gruel::mutex d_mutex; // mutex to protect set/work access
+
+ public:
+ pfb_channelizer_ccf_impl(unsigned int nfilts,
+ const std::vector<float> &taps,
+ float oversample_rate);
+
+ ~pfb_channelizer_ccf_impl();
+
+ void set_taps(const std::vector<float> &taps);
+ void print_taps();
+ std::vector<std::vector<float> > taps() const;
+
+ void set_channel_map(const std::vector<int> &map);
+ std::vector<int> channel_map() const;
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif
diff --git a/gr-filter/lib/pfb_decimator_ccf_impl.cc b/gr-filter/lib/pfb_decimator_ccf_impl.cc
new file mode 100644
index 000000000..f9a60cb28
--- /dev/null
+++ b/gr-filter/lib/pfb_decimator_ccf_impl.cc
@@ -0,0 +1,137 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pfb_decimator_ccf_impl.h"
+#include <gr_io_signature.h>
+
+namespace gr {
+ namespace filter {
+
+ pfb_decimator_ccf::sptr
+ pfb_decimator_ccf::make(unsigned int decim,
+ const std::vector<float> &taps,
+ unsigned int channel)
+ {
+ return gnuradio::get_initial_sptr
+ (new pfb_decimator_ccf_impl(decim, taps, channel));
+ }
+
+
+ pfb_decimator_ccf_impl::pfb_decimator_ccf_impl(unsigned int decim,
+ const std::vector<float> &taps,
+ unsigned int channel)
+ : gr_sync_block("pfb_decimator_ccf",
+ gr_make_io_signature(decim, decim, sizeof(gr_complex)),
+ gr_make_io_signature(1, 1, sizeof(gr_complex))),
+ polyphase_filterbank(decim, taps),
+ d_updated(false), d_chan(channel)
+ {
+ d_rate = decim;
+ d_rotator = new gr_complex[d_rate];
+
+ set_relative_rate(1.0/(float)decim);
+ set_history(d_taps_per_filter+1);
+ }
+
+ pfb_decimator_ccf_impl::~pfb_decimator_ccf_impl()
+ {
+ }
+
+ void
+ pfb_decimator_ccf_impl::set_taps(const std::vector<float> &taps)
+ {
+ gruel::scoped_lock guard(d_mutex);
+
+ polyphase_filterbank::set_taps(taps);
+ set_history(d_taps_per_filter+1);
+ d_updated = true;
+ }
+
+ void
+ pfb_decimator_ccf_impl::print_taps()
+ {
+ polyphase_filterbank::print_taps();
+ }
+
+ std::vector<std::vector<float> >
+ pfb_decimator_ccf_impl::taps() const
+ {
+ return polyphase_filterbank::taps();
+ }
+
+#define ROTATEFFT
+
+ int
+ pfb_decimator_ccf_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ gruel::scoped_lock guard(d_mutex);
+
+ gr_complex *in;
+ gr_complex *out = (gr_complex *)output_items[0];
+
+ if(d_updated) {
+ d_updated = false;
+ return 0; // history requirements may have changed.
+ }
+
+ int i;
+ for(i = 0; i < noutput_items; i++) {
+ // Move through filters from bottom to top
+ out[i] = 0;
+ for(int j = d_rate-1; j >= 0; j--) {
+ // Take in the items from the first input stream to d_rate
+ in = (gr_complex*)input_items[d_rate - 1 - j];
+
+ // Filter current input stream from bottom filter to top
+ // The rotate them by expj(j*k*2pi/M) where M is the number of filters
+ // (the decimation rate) and k is the channel number to extract
+
+ // This is the real math that goes on; we abuse the FFT to do this quickly
+ // for decimation rates > N where N is a small number (~5):
+ // out[i] += d_filters[j]->filter(&in[i])*gr_expj(j*d_chan*2*M_PI/d_rate);
+#ifdef ROTATEFFT
+ d_fft->get_inbuf()[j] = d_filters[j]->filter(&in[i]);
+#else
+ out[i] += d_filters[j]->filter(&in[i])*d_rotator[i];
+#endif
+ }
+
+#ifdef ROTATEFFT
+ // Perform the FFT to do the complex multiply despinning for all channels
+ d_fft->execute();
+
+ // Select only the desired channel out
+ out[i] = d_fft->get_outbuf()[d_chan];
+#endif
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/pfb_decimator_ccf_impl.h b/gr-filter/lib/pfb_decimator_ccf_impl.h
new file mode 100644
index 000000000..c4338a5ec
--- /dev/null
+++ b/gr-filter/lib/pfb_decimator_ccf_impl.h
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_PFB_DECIMATOR_CCF_IMPL_H
+#define INCLUDED_PFB_DECIMATOR_CCF_IMPL_H
+
+#include <filter/pfb_decimator_ccf.h>
+#include <filter/polyphase_filterbank.h>
+#include <filter/fir_filter.h>
+#include <fft/fft.h>
+#include <gruel/thread.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API pfb_decimator_ccf_impl : public pfb_decimator_ccf, kernel::polyphase_filterbank
+ {
+ private:
+ bool d_updated;
+ unsigned int d_rate;
+ unsigned int d_chan;
+ gr_complex *d_rotator;
+ gruel::mutex d_mutex; // mutex to protect set/work access
+
+ public:
+ pfb_decimator_ccf_impl(unsigned int decim,
+ const std::vector<float> &taps,
+ unsigned int channel);
+
+ ~pfb_decimator_ccf_impl();
+
+ void set_taps(const std::vector<float> &taps);
+ void print_taps();
+ std::vector<std::vector<float> > taps() const;
+ //void set_channel(unsigned int channel);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_PFB_DECIMATOR_CCF_IMPL_H */
diff --git a/gr-filter/lib/pfb_interpolator_ccf_impl.cc b/gr-filter/lib/pfb_interpolator_ccf_impl.cc
new file mode 100644
index 000000000..572db728b
--- /dev/null
+++ b/gr-filter/lib/pfb_interpolator_ccf_impl.cc
@@ -0,0 +1,107 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pfb_interpolator_ccf_impl.h"
+#include <gr_io_signature.h>
+
+namespace gr {
+ namespace filter {
+
+ pfb_interpolator_ccf::sptr
+ pfb_interpolator_ccf::make(unsigned int interp,
+ const std::vector<float> &taps)
+ {
+ return gnuradio::get_initial_sptr
+ (new pfb_interpolator_ccf_impl(interp, taps));
+ }
+
+
+ pfb_interpolator_ccf_impl::pfb_interpolator_ccf_impl(unsigned int interp,
+ const std::vector<float> &taps)
+ : gr_sync_interpolator("pfb_interpolator_ccf",
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ interp),
+ polyphase_filterbank(interp, taps),
+ d_updated (false), d_rate(interp)
+ {
+ set_history(d_taps_per_filter+1);
+ }
+
+ pfb_interpolator_ccf_impl::~pfb_interpolator_ccf_impl()
+ {
+ }
+
+ void
+ pfb_interpolator_ccf_impl::set_taps(const std::vector<float> &taps)
+ {
+ gruel::scoped_lock guard(d_mutex);
+
+ polyphase_filterbank::set_taps(taps);
+ set_history(d_taps_per_filter+1);
+ d_updated = true;
+ }
+
+ void
+ pfb_interpolator_ccf_impl::print_taps()
+ {
+ polyphase_filterbank::print_taps();
+ }
+
+ std::vector<std::vector<float> >
+ pfb_interpolator_ccf_impl::taps() const
+ {
+ return polyphase_filterbank::taps();
+ }
+
+ int
+ pfb_interpolator_ccf_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ gr_complex *in = (gr_complex*)input_items[0];
+ gr_complex *out = (gr_complex*)output_items[0];
+
+ if(d_updated) {
+ d_updated = false;
+ return 0; // history requirements may have changed.
+ }
+
+ int i = 0, count = 0;
+
+ while(i < noutput_items) {
+ for(unsigned int j = 0; j < d_rate; j++) {
+ out[i] = d_filters[j]->filter(&in[count]);
+ i++;
+ }
+ count++;
+ }
+
+ return i;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/pfb_interpolator_ccf_impl.h b/gr-filter/lib/pfb_interpolator_ccf_impl.h
new file mode 100644
index 000000000..7e1fe2ca1
--- /dev/null
+++ b/gr-filter/lib/pfb_interpolator_ccf_impl.h
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_PFB_INTERPOLATOR_CCF_IMPL_H
+#define INCLUDED_PFB_INTERPOLATOR_CCF_IMPL_H
+
+#include <filter/pfb_interpolator_ccf.h>
+#include <filter/polyphase_filterbank.h>
+#include <filter/fir_filter.h>
+#include <fft/fft.h>
+#include <gruel/thread.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API pfb_interpolator_ccf_impl : public pfb_interpolator_ccf, kernel::polyphase_filterbank
+ {
+ private:
+ bool d_updated;
+ unsigned int d_rate;
+ gruel::mutex d_mutex; // mutex to protect set/work access
+
+ public:
+ pfb_interpolator_ccf_impl(unsigned int interp,
+ const std::vector<float> &taps);
+
+ ~pfb_interpolator_ccf_impl();
+
+ void set_taps(const std::vector<float> &taps);
+ void print_taps();
+ std::vector<std::vector<float> > taps() const;
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_PFB_INTERPOLATOR_CCF_IMPL_H */
diff --git a/gr-filter/lib/pfb_synthesizer_ccf_impl.cc b/gr-filter/lib/pfb_synthesizer_ccf_impl.cc
new file mode 100644
index 000000000..9dd519d57
--- /dev/null
+++ b/gr-filter/lib/pfb_synthesizer_ccf_impl.cc
@@ -0,0 +1,287 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pfb_synthesizer_ccf_impl.h"
+#include <gr_io_signature.h>
+#include <cstdio>
+
+namespace gr {
+ namespace filter {
+
+ pfb_synthesizer_ccf::sptr
+ pfb_synthesizer_ccf::make(unsigned int numchans,
+ const std::vector<float> &taps,
+ bool twox)
+ {
+ return gnuradio::get_initial_sptr
+ (new pfb_synthesizer_ccf_impl(numchans, taps, twox));
+ }
+
+
+ pfb_synthesizer_ccf_impl::pfb_synthesizer_ccf_impl(unsigned int numchans,
+ const std::vector<float> &taps,
+ bool twox)
+ : gr_sync_interpolator("pfb_synthesizer_ccf",
+ gr_make_io_signature(1, numchans, sizeof(gr_complex)),
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ numchans),
+ d_updated (false), d_numchans(numchans), d_state(0)
+ {
+ // set up 2x multiplier; if twox==True, set to 2, otherwise to 1
+ d_twox = (twox ? 2 : 1);
+ if(d_numchans % d_twox != 0) {
+ throw std::invalid_argument("pfb_synthesizer_ccf: number of channels must be even for 2x oversampling.\n");
+ }
+
+ d_filters = std::vector<kernel::fir_filter_with_buffer_ccf*>(d_twox*d_numchans);
+ d_channel_map.resize(d_twox*d_numchans);
+
+ // Create a FIR filter for each channel and zero out the taps
+ std::vector<float> vtaps(0, d_twox*d_numchans);
+ for(unsigned int i = 0; i < d_twox*d_numchans; i++) {
+ d_filters[i] = new kernel::fir_filter_with_buffer_ccf(vtaps);
+ d_channel_map[i] = i;
+ }
+
+ // Now, actually set the filters' taps
+ set_taps(taps);
+
+ // Create the IFFT to handle the input channel rotations
+ d_fft = new fft::fft_complex(d_twox*d_numchans, false);
+ memset(d_fft->get_inbuf(), 0, d_twox*d_numchans*sizeof(gr_complex));
+
+ set_output_multiple(d_numchans);
+ }
+
+ pfb_synthesizer_ccf_impl::~pfb_synthesizer_ccf_impl()
+ {
+ for(unsigned int i = 0; i < d_twox*d_numchans; i++) {
+ delete d_filters[i];
+ }
+ }
+
+ void
+ pfb_synthesizer_ccf_impl::set_taps(const std::vector<float> &taps)
+ {
+ gruel::scoped_lock guard(d_mutex);
+
+ if(d_twox == 1)
+ set_taps1(taps);
+ else
+ set_taps2(taps);
+
+ // Set the history to ensure enough input items for each filter
+ set_history(d_taps_per_filter+1);
+
+ d_updated = true;
+ }
+
+ void
+ pfb_synthesizer_ccf_impl::set_taps1(const std::vector<float> &taps)
+ {
+ unsigned int i,j;
+
+ unsigned int ntaps = taps.size();
+ d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_numchans);
+
+ // Create d_numchan vectors to store each channel's taps
+ d_taps.resize(d_numchans);
+
+ // Make a vector of the taps plus fill it out with 0's to fill
+ // each polyphase filter with exactly d_taps_per_filter
+ std::vector<float> tmp_taps;
+ tmp_taps = taps;
+ while((float)(tmp_taps.size()) < d_numchans*d_taps_per_filter) {
+ tmp_taps.push_back(0.0);
+ }
+
+ // Partition the filter
+ for(i = 0; i < d_numchans; i++) {
+ // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out
+ d_taps[i] = std::vector<float>(d_taps_per_filter, 0);
+ for(j = 0; j < d_taps_per_filter; j++) {
+ d_taps[i][j] = tmp_taps[i + j*d_numchans]; // add taps to channels in reverse order
+ }
+
+ // Build a filter for each channel and add it's taps to it
+ d_filters[i]->set_taps(d_taps[i]);
+ }
+ }
+
+ void
+ pfb_synthesizer_ccf_impl::set_taps2 (const std::vector<float> &taps)
+ {
+ unsigned int i,j;
+ int state = 0;
+
+ unsigned int ntaps = taps.size();
+ d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_numchans);
+
+ // Create d_numchan vectors to store each channel's taps
+ d_taps.resize(d_twox*d_numchans);
+
+ // Make a vector of the taps plus fill it out with 0's to fill
+ // each polyphase filter with exactly d_taps_per_filter
+ std::vector<float> tmp_taps;
+ tmp_taps = taps;
+ while((float)(tmp_taps.size()) < d_numchans*d_taps_per_filter) {
+ tmp_taps.push_back(0.0);
+ }
+
+ // Partition the filter
+ for(i = 0; i < d_numchans; i++) {
+ // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out
+ d_taps[i] = std::vector<float>(d_taps_per_filter, 0);
+ d_taps[d_numchans+i] = std::vector<float>(d_taps_per_filter, 0);
+ state = 0;
+ for(j = 0; j < d_taps_per_filter; j++) {
+ // add taps to channels in reverse order
+ // Zero out every other tap
+ if(state == 0) {
+ d_taps[i][j] = tmp_taps[i + j*d_numchans];
+ d_taps[d_numchans + i][j] = 0;
+ state = 1;
+ }
+ else {
+ d_taps[i][j] = 0;
+ d_taps[d_numchans + i][j] = tmp_taps[i + j*d_numchans];
+ state = 0;
+ }
+ }
+
+ // Build a filter for each channel and add it's taps to it
+ d_filters[i]->set_taps(d_taps[i]);
+ d_filters[d_numchans + i]->set_taps(d_taps[d_numchans + i]);
+ }
+ }
+
+ void
+ pfb_synthesizer_ccf_impl::print_taps()
+ {
+ unsigned int i, j;
+ for(i = 0; i < d_twox*d_numchans; i++) {
+ printf("filter[%d]: [", i);
+ for(j = 0; j < d_taps_per_filter; j++) {
+ printf(" %.4e", d_taps[i][j]);
+ }
+ printf("]\n\n");
+ }
+ }
+
+ std::vector< std::vector<float> >
+ pfb_synthesizer_ccf_impl::taps() const
+ {
+ return d_taps;
+ }
+
+ void
+ pfb_synthesizer_ccf_impl::set_channel_map(const std::vector<int> &map)
+ {
+ gruel::scoped_lock guard(d_mutex);
+
+ if(map.size() > 0) {
+ unsigned int max = (unsigned int)*std::max_element(map.begin(), map.end());
+ if(max >= d_twox*d_numchans) {
+ throw std::invalid_argument("gr_pfb_synthesizer_ccf::set_channel_map: map range out of bounds.\n");
+ }
+ d_channel_map = map;
+
+ // Zero out fft buffer so that unused channels are always 0
+ memset(d_fft->get_inbuf(), 0,d_twox*d_numchans*sizeof(gr_complex));
+ }
+ }
+
+ std::vector<int>
+ pfb_synthesizer_ccf_impl::channel_map() const
+ {
+ return d_channel_map;
+ }
+
+ int
+ pfb_synthesizer_ccf_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ gruel::scoped_lock guard(d_mutex);
+
+ gr_complex *in = (gr_complex*)input_items[0];
+ gr_complex *out = (gr_complex*)output_items[0];
+
+ if(d_updated) {
+ d_updated = false;
+ return 0; // history requirements may have changed.
+ }
+
+ unsigned int n, i;
+ size_t ninputs = input_items.size();
+
+ // Algoritm for critically sampled channels
+ if(d_twox == 1) {
+ for(n = 0; n < noutput_items/d_numchans; n++) {
+ for(i = 0; i < ninputs; i++) {
+ in = (gr_complex*)input_items[i];
+ d_fft->get_inbuf()[d_channel_map[i]] = in[n];
+ }
+
+ // spin through IFFT
+ d_fft->execute();
+
+ for(i = 0; i < d_numchans; i++) {
+ out[i] = d_filters[i]->filter(d_fft->get_outbuf()[i]);
+ }
+ out += d_numchans;
+ }
+ }
+
+ // Algorithm for oversampling by 2x
+ else {
+ for(n = 0; n < noutput_items/d_numchans; n++) {
+ for(i = 0; i < ninputs; i++) {
+ in = (gr_complex*)input_items[i];
+ d_fft->get_inbuf()[d_channel_map[i]] = in[n];
+ }
+
+ // spin through IFFT
+ d_fft->execute();
+
+ // Output is sum of two filters, but the input buffer to the filters must be circularly
+ // shifted by numchans every time through, done by using d_state to determine which IFFT
+ // buffer position to pull from.
+ for(i = 0; i < d_numchans; i++) {
+ out[i] = d_filters[i]->filter(d_fft->get_outbuf()[d_state*d_numchans+i]);
+ out[i] += d_filters[d_numchans+i]->filter(d_fft->get_outbuf()[(d_state^1)*d_numchans+i]);
+ }
+ d_state ^= 1;
+
+ out += d_numchans;
+ }
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/pfb_synthesizer_ccf_impl.h b/gr-filter/lib/pfb_synthesizer_ccf_impl.h
new file mode 100644
index 000000000..adffc143f
--- /dev/null
+++ b/gr-filter/lib/pfb_synthesizer_ccf_impl.h
@@ -0,0 +1,85 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_PFB_SYNTHESIZER_CCF_IMPL_H
+#define INCLUDED_PFB_SYNTHESIZER_CCF_IMPL_H
+
+#include <filter/pfb_synthesizer_ccf.h>
+#include <filter/fir_filter_with_buffer.h>
+#include <fft/fft.h>
+#include <gruel/thread.h>
+
+namespace gr {
+ namespace filter {
+
+ // While this is a polyphase_filterbank, we don't use the normal
+ // parent class because we have to use the fir_filter_with_buffer
+ // objects instead of normal filters.
+
+ class FILTER_API pfb_synthesizer_ccf_impl : public pfb_synthesizer_ccf
+ {
+ private:
+ bool d_updated;
+ unsigned int d_numchans;
+ unsigned int d_taps_per_filter;
+ fft::fft_complex *d_fft;
+ std::vector< kernel::fir_filter_with_buffer_ccf*> d_filters;
+ std::vector< std::vector<float> > d_taps;
+ int d_state;
+ std::vector<int> d_channel_map;
+ unsigned int d_twox;
+ gruel::mutex d_mutex; // mutex to protect set/work access
+
+ /*!
+ * \brief Tap setting algorithm for critically sampled channels
+ */
+ void set_taps1(const std::vector<float> &taps);
+
+ /*!
+ * \brief Tap setting algorithm for 2x over-sampled channels
+ */
+ void set_taps2(const std::vector<float> &taps);
+
+
+ public:
+ pfb_synthesizer_ccf_impl(unsigned int numchans,
+ const std::vector<float> &taps,
+ bool twox);
+ ~pfb_synthesizer_ccf_impl();
+
+ void set_taps(const std::vector<float> &taps);
+ std::vector<std::vector<float> > taps() const;
+ void print_taps();
+
+ void set_channel_map(const std::vector<int> &map);
+ std::vector<int> channel_map() const;
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_PFB_SYNTHESIZER_CCF_IMPL_H */
diff --git a/gr-filter/lib/pm_remez.cc b/gr-filter/lib/pm_remez.cc
new file mode 100644
index 000000000..e7136bd83
--- /dev/null
+++ b/gr-filter/lib/pm_remez.cc
@@ -0,0 +1,834 @@
+/**************************************************************************
+ * Parks-McClellan algorithm for FIR filter design (C version)
+ *-------------------------------------------------
+ * Copyright (c) 1995,1998 Jake Janovetz (janovetz@uiuc.edu)
+ * Copyright (c) 2004 Free Software Foundation, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301 USA
+ *
+ *
+ * Sep 1999 - Paul Kienzle (pkienzle@cs.indiana.edu)
+ * Modified for use in octave as a replacement for the matlab function
+ * remez.mex. In particular, magnitude responses are required for all
+ * band edges rather than one per band, griddensity is a parameter,
+ * and errors are returned rather than printed directly.
+ * Mar 2000 - Kai Habel (kahacjde@linux.zrz.tu-berlin.de)
+ * Change: ColumnVector x=arg(i).vector_value();
+ * to: ColumnVector x(arg(i).vector_value());
+ * There appear to be some problems with the routine search. See comments
+ * therein [search for PAK:]. I haven't looked closely at the rest
+ * of the code---it may also have some problems.
+ *************************************************************************/
+
+/*
+ * This code was extracted from octave.sf.net, and wrapped with
+ * GNU Radio glue.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <filter/pm_remez.h>
+#include <cmath>
+#include <assert.h>
+#include <iostream>
+
+#ifndef LOCAL_BUFFER
+#include <vector>
+#define LOCAL_BUFFER(T, buf, size) \
+ std::vector<T> buf ## _vector (size); \
+ T *buf = &(buf ## _vector[0])
+#endif
+
+namespace gr {
+ namespace filter {
+
+#define CONST const
+#define BANDPASS 1
+#define DIFFERENTIATOR 2
+#define HILBERT 3
+
+#define NEGATIVE 0
+#define POSITIVE 1
+
+#define Pi 3.14159265358979323846
+#define Pi2 (2*Pi)
+
+#define GRIDDENSITY 16
+#define MAXITERATIONS 40
+
+ /*******************
+ * create_dense_grid
+ *=================
+ *
+ * Creates the dense grid of frequencies from the specified bands.
+ * Also creates the Desired Frequency Response function (D[]) and
+ * the Weight function (W[]) on that dense grid
+ *
+ *
+ * INPUT:
+ * ------
+ * int r - 1/2 the number of filter coefficients
+ * int numtaps - Number of taps in the resulting filter
+ * int numband - Number of bands in user specification
+ * double bands[] - User-specified band edges [2*numband]
+ * double des[] - Desired response per band [2*numband]
+ * double weight[] - Weight per band [numband]
+ * int symmetry - Symmetry of filter - used for grid check
+ * int griddensity
+ *
+ * OUTPUT:
+ * -------
+ * int gridsize - Number of elements in the dense frequency grid
+ * double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize]
+ * double D[] - Desired response on the dense grid [gridsize]
+ * double W[] - Weight function on the dense grid [gridsize]
+ *******************/
+
+ static void
+ create_dense_grid(int r, int numtaps, int numband, const double bands[],
+ const double des[], const double weight[], int gridsize,
+ double Grid[], double D[], double W[],
+ int symmetry, int griddensity)
+ {
+ int i, j, k, band;
+ double delf, lowf, highf, grid0;
+
+ delf = 0.5/(griddensity*r);
+
+ /*
+ * For differentiator, hilbert,
+ * symmetry is odd and Grid[0] = max(delf, bands[0])
+ */
+ grid0 = (symmetry == NEGATIVE) && (delf > bands[0]) ? delf : bands[0];
+
+ j=0;
+ for(band=0; band < numband; band++) {
+ lowf = (band==0 ? grid0 : bands[2*band]);
+ highf = bands[2*band + 1];
+ k = (int)((highf - lowf)/delf + 0.5); /* .5 for rounding */
+ for(i=0; i<k; i++) {
+ D[j] = des[2*band] + i*(des[2*band+1]-des[2*band])/(k-1);
+ W[j] = weight[band];
+ Grid[j] = lowf;
+ lowf += delf;
+ j++;
+ }
+ Grid[j-1] = highf;
+ }
+
+ /*
+ * Similar to above, if odd symmetry, last grid point can't be .5
+ * - but, if there are even taps, leave the last grid point at .5
+ */
+ if((symmetry == NEGATIVE) &&
+ (Grid[gridsize-1] > (0.5 - delf)) &&
+ (numtaps % 2))
+ {
+ Grid[gridsize-1] = 0.5-delf;
+ }
+ }
+
+
+ /********************
+ * initial_guess
+ *==============
+ * Places Extremal Frequencies evenly throughout the dense grid.
+ *
+ *
+ * INPUT:
+ * ------
+ * int r - 1/2 the number of filter coefficients
+ * int gridsize - Number of elements in the dense frequency grid
+ *
+ * OUTPUT:
+ * -------
+ * int ext[] - Extremal indexes to dense frequency grid [r+1]
+ ********************/
+
+ static void
+ initial_guess(int r, int Ext[], int gridsize)
+ {
+ int i;
+
+ for(i=0; i<=r; i++)
+ Ext[i] = i * (gridsize-1) / r;
+ }
+
+
+ /***********************
+ * calc_parms
+ *===========
+ *
+ *
+ * INPUT:
+ * ------
+ * int r - 1/2 the number of filter coefficients
+ * int Ext[] - Extremal indexes to dense frequency grid [r+1]
+ * double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize]
+ * double D[] - Desired response on the dense grid [gridsize]
+ * double W[] - Weight function on the dense grid [gridsize]
+ *
+ * OUTPUT:
+ * -------
+ * double ad[] - 'b' in Oppenheim & Schafer [r+1]
+ * double x[] - [r+1]
+ * double y[] - 'C' in Oppenheim & Schafer [r+1]
+ ***********************/
+
+ static void
+ calc_parms(int r, int Ext[], double Grid[], double D[], double W[],
+ double ad[], double x[], double y[])
+ {
+ int i, j, k, ld;
+ double sign, xi, delta, denom, numer;
+
+ /*
+ * Find x[]
+ */
+ for(i = 0; i <= r; i++)
+ x[i] = cos(Pi2 * Grid[Ext[i]]);
+
+ /*
+ * Calculate ad[] - Oppenheim & Schafer eq 7.132
+ */
+ ld = (r-1)/15 + 1; /* Skips around to avoid round errors */
+ for(i = 0; i <= r; i++) {
+ denom = 1.0;
+ xi = x[i];
+ for(j = 0; j < ld; j++) {
+ for(k = j; k <= r; k += ld)
+ if(k != i)
+ denom *= 2.0*(xi - x[k]);
+ }
+ if(fabs(denom) < 0.00001)
+ denom = 0.00001;
+ ad[i] = 1.0/denom;
+ }
+
+ /*
+ * Calculate delta - Oppenheim & Schafer eq 7.131
+ */
+ numer = denom = 0;
+ sign = 1;
+ for(i = 0; i <= r; i++) {
+ numer += ad[i] * D[Ext[i]];
+ denom += sign * ad[i]/W[Ext[i]];
+ sign = -sign;
+ }
+ delta = numer/denom;
+ sign = 1;
+
+ /*
+ * Calculate y[] - Oppenheim & Schafer eq 7.133b
+ */
+ for(i = 0; i <= r; i++) {
+ y[i] = D[Ext[i]] - sign * delta/W[Ext[i]];
+ sign = -sign;
+ }
+ }
+
+
+ /*********************
+ * compute_A
+ *==========
+ * Using values calculated in calc_parms, compute_A calculates the
+ * actual filter response at a given frequency (freq). Uses
+ * eq 7.133a from Oppenheim & Schafer.
+ *
+ *
+ * INPUT:
+ * ------
+ * double freq - Frequency (0 to 0.5) at which to calculate A
+ * int r - 1/2 the number of filter coefficients
+ * double ad[] - 'b' in Oppenheim & Schafer [r+1]
+ * double x[] - [r+1]
+ * double y[] - 'C' in Oppenheim & Schafer [r+1]
+ *
+ * OUTPUT:
+ * -------
+ * Returns double value of A[freq]
+ *********************/
+
+ static double
+ compute_A(double freq, int r, double ad[], double x[], double y[])
+ {
+ int i;
+ double xc, c, denom, numer;
+
+ denom = numer = 0;
+ xc = cos(Pi2 * freq);
+ for(i = 0; i <= r; i++) {
+ c = xc - x[i];
+ if(fabs(c) < 1.0e-7) {
+ numer = y[i];
+ denom = 1;
+ break;
+ }
+ c = ad[i]/c;
+ denom += c;
+ numer += c*y[i];
+ }
+ return numer/denom;
+ }
+
+
+ /************************
+ * calc_error
+ *===========
+ * Calculates the Error function from the desired frequency response
+ * on the dense grid (D[]), the weight function on the dense grid (W[]),
+ * and the present response calculation (A[])
+ *
+ *
+ * INPUT:
+ * ------
+ * int r - 1/2 the number of filter coefficients
+ * double ad[] - [r+1]
+ * double x[] - [r+1]
+ * double y[] - [r+1]
+ * int gridsize - Number of elements in the dense frequency grid
+ * double Grid[] - Frequencies on the dense grid [gridsize]
+ * double D[] - Desired response on the dense grid [gridsize]
+ * double W[] - Weight function on the desnse grid [gridsize]
+ *
+ * OUTPUT:
+ * -------
+ * double E[] - Error function on dense grid [gridsize]
+ ************************/
+
+ static void
+ calc_error(int r, double ad[], double x[], double y[],
+ int gridsize, double Grid[],
+ double D[], double W[], double E[])
+ {
+ int i;
+ double A;
+
+ for(i = 0; i < gridsize; i++) {
+ A = compute_A(Grid[i], r, ad, x, y);
+ E[i] = W[i] * (D[i] - A);
+ }
+ }
+
+ /************************
+ * search
+ *========
+ * Searches for the maxima/minima of the error curve. If more than
+ * r+1 extrema are found, it uses the following heuristic (thanks
+ * Chris Hanson):
+ * 1) Adjacent non-alternating extrema deleted first.
+ * 2) If there are more than one excess extrema, delete the
+ * one with the smallest error. This will create a non-alternation
+ * condition that is fixed by 1).
+ * 3) If there is exactly one excess extremum, delete the smaller
+ * of the first/last extremum
+ *
+ *
+ * INPUT:
+ * ------
+ * int r - 1/2 the number of filter coefficients
+ * int Ext[] - Indexes to Grid[] of extremal frequencies [r+1]
+ * int gridsize - Number of elements in the dense frequency grid
+ * double E[] - Array of error values. [gridsize]
+ * OUTPUT:
+ * -------
+ * int Ext[] - New indexes to extremal frequencies [r+1]
+ ************************/
+ static int
+ search(int r, int Ext[],
+ int gridsize, double E[])
+ {
+ int i, j, k, l, extra; /* Counters */
+ int up, alt;
+ int *foundExt; /* Array of found extremals */
+
+ /*
+ * Allocate enough space for found extremals.
+ */
+ foundExt = (int *)malloc((2*r) * sizeof(int));
+ k = 0;
+
+ /*
+ * Check for extremum at 0.
+ */
+ if(((E[0] > 0.0) && (E[0] > E[1])) ||
+ ((E[0] < 0.0) && (E[0] < E[1])))
+ foundExt[k++] = 0;
+
+ /*
+ * Check for extrema inside dense grid
+ */
+ for(i = 1; i < gridsize-1; i++) {
+ if(((E[i] >= E[i-1]) && (E[i] > E[i+1]) && (E[i] > 0.0)) ||
+ ((E[i] <= E[i-1]) && (E[i] < E[i+1]) && (E[i] < 0.0))) {
+ // PAK: we sometimes get too many extremal frequencies
+ if(k >= 2*r)
+ return -3;
+ foundExt[k++] = i;
+ }
+ }
+
+ /*
+ * Check for extremum at 0.5
+ */
+ j = gridsize-1;
+ if(((E[j] > 0.0) && (E[j] > E[j-1])) ||
+ ((E[j] < 0.0) && (E[j] < E[j-1]))) {
+ if(k >= 2*r)
+ return -3;
+ foundExt[k++] = j;
+ }
+
+ // PAK: we sometimes get not enough extremal frequencies
+ if(k < r+1)
+ return -2;
+
+ /*
+ * Remove extra extremals
+ */
+ extra = k - (r+1);
+ assert(extra >= 0);
+
+ while(extra > 0) {
+ if(E[foundExt[0]] > 0.0)
+ up = 1; /* first one is a maxima */
+ else
+ up = 0; /* first one is a minima */
+
+ l=0;
+ alt = 1;
+ for(j = 1; j < k; j++) {
+ if(fabs(E[foundExt[j]]) < fabs(E[foundExt[l]]))
+ l = j; /* new smallest error. */
+ if((up) && (E[foundExt[j]] < 0.0))
+ up = 0; /* switch to a minima */
+ else if((!up) && (E[foundExt[j]] > 0.0))
+ up = 1; /* switch to a maxima */
+ else {
+ alt = 0;
+ // PAK: break now and you will delete the smallest overall
+ // extremal. If you want to delete the smallest of the
+ // pair of non-alternating extremals, then you must do:
+ //
+ // if(fabs(E[foundExt[j]]) < fabs(E[foundExt[j-1]])) l=j;
+ // else l=j-1;
+ break; /* Ooops, found two non-alternating */
+ } /* extrema. Delete smallest of them */
+ } /* if the loop finishes, all extrema are alternating */
+
+ /*
+ * If there's only one extremal and all are alternating,
+ * delete the smallest of the first/last extremals.
+ */
+ if((alt) && (extra == 1)) {
+ if(fabs(E[foundExt[k-1]]) < fabs(E[foundExt[0]]))
+ /* Delete last extremal */
+ l = k-1;
+ // PAK: changed from l = foundExt[k-1];
+ else
+ /* Delete first extremal */
+ l = 0;
+ // PAK: changed from l = foundExt[0];
+ }
+
+ for(j = l; j < k-1; j++) { /* Loop that does the deletion */
+ foundExt[j] = foundExt[j+1];
+ assert(foundExt[j]<gridsize);
+ }
+ k--;
+ extra--;
+ }
+
+ for(i = 0; i <= r; i++) {
+ assert(foundExt[i]<gridsize);
+ Ext[i] = foundExt[i]; /* Copy found extremals to Ext[] */
+ }
+
+ free(foundExt);
+ return 0;
+ }
+
+
+ /*********************
+ * freq_sample
+ *============
+ * Simple frequency sampling algorithm to determine the impulse
+ * response h[] from A's found in compute_A
+ *
+ *
+ * INPUT:
+ * ------
+ * int N - Number of filter coefficients
+ * double A[] - Sample points of desired response [N/2]
+ * int symmetry - Symmetry of desired filter
+ *
+ * OUTPUT:
+ * -------
+ * double h[] - Impulse Response of final filter [N]
+ *********************/
+ static void
+ freq_sample(int N, double A[], double h[], int symm)
+ {
+ int n, k;
+ double x, val, M;
+
+ M = (N-1.0)/2.0;
+ if(symm == POSITIVE) {
+ if(N % 2) {
+ for(n = 0; n < N; n++) {
+ val = A[0];
+ x = Pi2 * (n - M)/N;
+ for(k=1; k<=M; k++)
+ val += 2.0 * A[k] * cos(x*k);
+ h[n] = val/N;
+ }
+ }
+ else {
+ for(n = 0; n < N; n++) {
+ val = A[0];
+ x = Pi2 * (n - M)/N;
+ for(k = 1; k <= (N/2-1); k++)
+ val += 2.0 * A[k] * cos(x*k);
+ h[n] = val/N;
+ }
+ }
+ }
+ else {
+ if(N % 2) {
+ for(n = 0; n < N; n++) {
+ val = 0;
+ x = Pi2 * (n - M)/N;
+ for(k = 1; k <= M; k++)
+ val += 2.0 * A[k] * sin(x*k);
+ h[n] = val/N;
+ }
+ }
+ else {
+ for(n = 0; n < N; n++) {
+ val = A[N/2] * sin(Pi * (n - M));
+ x = Pi2 * (n - M)/N;
+ for(k = 1; k <= (N/2-1); k++)
+ val += 2.0 * A[k] * sin(x*k);
+ h[n] = val/N;
+ }
+ }
+ }
+ }
+
+ /*******************
+ * is_done
+ *========
+ * Checks to see if the error function is small enough to consider
+ * the result to have converged.
+ *
+ * INPUT:
+ * ------
+ * int r - 1/2 the number of filter coeffiecients
+ * int Ext[] - Indexes to extremal frequencies [r+1]
+ * double E[] - Error function on the dense grid [gridsize]
+ *
+ * OUTPUT:
+ * -------
+ * Returns 1 if the result converged
+ * Returns 0 if the result has not converged
+ ********************/
+
+ static bool
+ is_done(int r, int Ext[], double E[])
+ {
+ int i;
+ double min, max, current;
+
+ min = max = fabs(E[Ext[0]]);
+ for(i = 1; i <= r; i++) {
+ current = fabs(E[Ext[i]]);
+ if(current < min)
+ min = current;
+ if(current > max)
+ max = current;
+ }
+ return(((max-min)/max) < 0.0001);
+ }
+
+ /********************
+ * remez
+ *=======
+ * Calculates the optimal (in the Chebyshev/minimax sense)
+ * FIR filter impulse response given a set of band edges,
+ * the desired reponse on those bands, and the weight given to
+ * the error in those bands.
+ *
+ * INPUT:
+ * ------
+ * int numtaps - Number of filter coefficients
+ * int numband - Number of bands in filter specification
+ * double bands[] - User-specified band edges [2 * numband]
+ * double des[] - User-specified band responses [2 * numband]
+ * double weight[] - User-specified error weights [numband]
+ * int type - Type of filter
+ *
+ * OUTPUT:
+ * -------
+ * double h[] - Impulse response of final filter [numtaps]
+ * returns - true on success, false on failure to converge
+ ********************/
+
+ static int
+ remez(double h[], int numtaps,
+ int numband, const double bands[],
+ const double des[], const double weight[],
+ int type, int griddensity)
+ {
+ double *Grid, *W, *D, *E;
+ int i, iter, gridsize, r, *Ext;
+ double *taps, c;
+ double *x, *y, *ad;
+ int symmetry;
+
+ if(type == BANDPASS)
+ symmetry = POSITIVE;
+ else
+ symmetry = NEGATIVE;
+
+ r = numtaps/2; /* number of extrema */
+ if((numtaps % 2) && (symmetry == POSITIVE))
+ r++;
+
+ /*
+ * Predict dense grid size in advance for memory allocation
+ * .5 is so we round up, not truncate
+ */
+ gridsize = 0;
+ for(i = 0; i < numband; i++) {
+ gridsize +=(int)(2*r*griddensity*(bands[2*i+1] - bands[2*i]) + .5);
+ }
+ if(symmetry == NEGATIVE) {
+ gridsize--;
+ }
+
+ /*
+ * Dynamically allocate memory for arrays with proper sizes
+ */
+ Grid = (double *)malloc(gridsize * sizeof(double));
+ D = (double *)malloc(gridsize * sizeof(double));
+ W = (double *)malloc(gridsize * sizeof(double));
+ E = (double *)malloc(gridsize * sizeof(double));
+ Ext = (int *)malloc((r+1) * sizeof(int));
+ taps = (double *)malloc((r+1) * sizeof(double));
+ x = (double *)malloc((r+1) * sizeof(double));
+ y = (double *)malloc((r+1) * sizeof(double));
+ ad = (double *)malloc((r+1) * sizeof(double));
+
+ /*
+ * Create dense frequency grid
+ */
+ create_dense_grid(r, numtaps, numband, bands, des, weight,
+ gridsize, Grid, D, W, symmetry, griddensity);
+ initial_guess(r, Ext, gridsize);
+
+ /*
+ * For Differentiator: (fix grid)
+ */
+ if(type == DIFFERENTIATOR) {
+ for(i = 0; i < gridsize; i++) {
+ /* D[i] = D[i]*Grid[i]; */
+ if(D[i] > 0.0001)
+ W[i] = W[i]/Grid[i];
+ }
+ }
+
+ /*
+ * For odd or Negative symmetry filters, alter the
+ * D[] and W[] according to Parks McClellan
+ */
+ if(symmetry == POSITIVE) {
+ if(numtaps % 2 == 0) {
+ for(i = 0; i < gridsize; i++) {
+ c = cos(Pi * Grid[i]);
+ D[i] /= c;
+ W[i] *= c;
+ }
+ }
+ }
+ else {
+ if(numtaps % 2) {
+ for(i = 0; i < gridsize; i++) {
+ c = sin(Pi2 * Grid[i]);
+ D[i] /= c;
+ W[i] *= c;
+ }
+ }
+ else {
+ for(i = 0; i < gridsize; i++) {
+ c = sin(Pi * Grid[i]);
+ D[i] /= c;
+ W[i] *= c;
+ }
+ }
+ }
+
+ /*
+ * Perform the Remez Exchange algorithm
+ */
+ for(iter = 0; iter < MAXITERATIONS; iter++) {
+ calc_parms(r, Ext, Grid, D, W, ad, x, y);
+ calc_error(r, ad, x, y, gridsize, Grid, D, W, E);
+ int err = search(r, Ext, gridsize, E);
+ if(err)
+ return err;
+ for(int i = 0; i <= r; i++)
+ assert(Ext[i] < gridsize);
+ if(is_done(r, Ext, E))
+ break;
+ }
+
+ calc_parms(r, Ext, Grid, D, W, ad, x, y);
+
+ /*
+ * Find the 'taps' of the filter for use with Frequency
+ * Sampling. If odd or Negative symmetry, fix the taps
+ * according to Parks McClellan
+ */
+ for(i = 0; i <= numtaps/2; i++) {
+ if(symmetry == POSITIVE) {
+ if(numtaps % 2)
+ c = 1;
+ else
+ c = cos(Pi * (double)i/numtaps);
+ }
+ else {
+ if(numtaps % 2)
+ c = sin(Pi2 * (double)i/numtaps);
+ else
+ c = sin(Pi * (double)i/numtaps);
+ }
+ taps[i] = compute_A((double)i/numtaps, r, ad, x, y)*c;
+ }
+
+ /*
+ * Frequency sampling design with calculated taps
+ */
+ freq_sample(numtaps, taps, h, symmetry);
+
+ /*
+ * Delete allocated memory
+ */
+ free(Grid);
+ free(W);
+ free(D);
+ free(E);
+ free(Ext);
+ free(x);
+ free(y);
+ free(ad);
+
+ return iter<MAXITERATIONS?0:-1;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // GNU Radio interface
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ static void
+ punt(const std::string msg)
+ {
+ std::cerr << msg << '\n';
+ throw std::runtime_error(msg);
+ }
+
+ std::vector<double>
+ pm_remez(int order,
+ const std::vector<double> &arg_bands,
+ const std::vector<double> &arg_response,
+ const std::vector<double> &arg_weight,
+ const std::string filter_type,
+ int grid_density
+ ) throw (std::runtime_error)
+ {
+ int numtaps = order + 1;
+ if(numtaps < 4)
+ punt("gr_remez: number of taps must be >= 3");
+
+ int numbands = arg_bands.size() / 2;
+ LOCAL_BUFFER(double, bands, numbands * 2);
+ if(numbands < 1 || arg_bands.size() % 2 == 1)
+ punt("gr_remez: must have an even number of band edges");
+
+ for(unsigned int i = 1; i < arg_bands.size(); i++){
+ if(arg_bands[i] < arg_bands[i-1])
+ punt("gr_remez: band edges must be nondecreasing");
+ }
+
+ if(arg_bands[0] < 0 || arg_bands[arg_bands.size() - 1] > 1)
+ punt("gr_remez: band edges must be in the range [0,1]");
+
+ // Divide by 2 to fit with the implementation that uses a
+ // sample rate of [0, 0.5] instead of [0, 1.0]
+ for(int i = 0; i < 2 * numbands; i++)
+ bands[i] = arg_bands[i] / 2;
+
+ LOCAL_BUFFER(double, response, numbands * 2);
+ if(arg_response.size() != arg_bands.size())
+ punt("gr_remez: must have one response magnitude for each band edge");
+
+ for(int i = 0; i < 2 * numbands; i++)
+ response[i] = arg_response[i];
+
+ LOCAL_BUFFER(double, weight, numbands);
+ for(int i = 0; i < numbands; i++)
+ weight[i] = 1.0;
+
+ if(arg_weight.size() != 0) {
+ if((int) arg_weight.size() != numbands)
+ punt("gr_remez: need one weight for each band [=length(band)/2]");
+ for(int i = 0; i < numbands; i++)
+ weight[i] = arg_weight [i];
+ }
+
+ int itype = 0;
+ if(filter_type == "bandpass")
+ itype = BANDPASS;
+ else if(filter_type == "differentiator")
+ itype = DIFFERENTIATOR;
+ else if(filter_type == "hilbert")
+ itype = HILBERT;
+ else
+ punt("gr_remez: unknown ftype '" + filter_type + "'");
+
+ if(grid_density < 16)
+ punt("gr_remez: grid_density is too low; must be >= 16");
+
+ LOCAL_BUFFER(double, coeff, numtaps + 5); // FIXME why + 5?
+ int err = remez(coeff, numtaps, numbands,
+ bands, response, weight, itype, grid_density);
+
+ if(err == -1)
+ punt("gr_remez: failed to converge");
+
+ if(err == -2)
+ punt("gr_remez: insufficient extremals -- cannot continue");
+
+ if(err == -3)
+ punt("gr_remez: too many extremals -- cannot continue");
+
+ return std::vector<double>(&coeff[0], &coeff[numtaps]);
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/polyphase_filterbank.cc b/gr-filter/lib/polyphase_filterbank.cc
new file mode 100644
index 000000000..046c23fc0
--- /dev/null
+++ b/gr-filter/lib/polyphase_filterbank.cc
@@ -0,0 +1,114 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <filter/polyphase_filterbank.h>
+#include <cstdio>
+
+namespace gr {
+ namespace filter {
+ namespace kernel {
+
+ polyphase_filterbank::polyphase_filterbank(unsigned int nfilts,
+ const std::vector<float> &taps)
+ : d_nfilts(nfilts)
+ {
+ d_filters = std::vector<kernel::fir_filter_ccf*>(d_nfilts);
+
+ // Create an FIR filter for each channel and zero out the taps
+ std::vector<float> vtaps(0, d_nfilts);
+ for(unsigned int i = 0; i < d_nfilts; i++) {
+ d_filters[i] = new kernel::fir_filter_ccf(1, vtaps);
+ }
+
+ // Now, actually set the filters' taps
+ set_taps(taps);
+
+ // Create the FFT to handle the output de-spinning of the channels
+ d_fft = new fft::fft_complex(d_nfilts, false);
+ }
+
+ polyphase_filterbank::~polyphase_filterbank()
+ {
+ delete d_fft;
+ for(unsigned int i = 0; i < d_nfilts; i++) {
+ delete d_filters[i];
+ }
+ }
+
+ void
+ polyphase_filterbank::set_taps(const std::vector<float> &taps)
+ {
+ unsigned int i,j;
+
+ unsigned int ntaps = taps.size();
+ d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_nfilts);
+
+ // Create d_numchan vectors to store each channel's taps
+ d_taps.resize(d_nfilts);
+
+ // Make a vector of the taps plus fill it out with 0's to fill
+ // each polyphase filter with exactly d_taps_per_filter
+ std::vector<float> tmp_taps;
+ tmp_taps = taps;
+ while((float)(tmp_taps.size()) < d_nfilts*d_taps_per_filter) {
+ tmp_taps.push_back(0.0);
+ }
+
+ // Partition the filter
+ for(i = 0; i < d_nfilts; i++) {
+ // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out
+ d_taps[i] = std::vector<float>(d_taps_per_filter, 0);
+ for(j = 0; j < d_taps_per_filter; j++) {
+ d_taps[i][j] = tmp_taps[i + j*d_nfilts]; // add taps to channels in reverse order
+ }
+
+ // Build a filter for each channel and add it's taps to it
+ d_filters[i]->set_taps(d_taps[i]);
+ }
+ }
+
+ void
+ polyphase_filterbank::print_taps()
+ {
+ unsigned int i, j;
+ for(i = 0; i < d_nfilts; i++) {
+ printf("filter[%d]: [", i);
+ for(j = 0; j < d_taps_per_filter; j++) {
+ printf(" %.4e", d_taps[i][j]);
+ }
+ printf("]\n\n");
+ }
+ }
+
+ std::vector< std::vector<float> >
+ polyphase_filterbank::taps() const
+ {
+ return d_taps;
+ }
+
+ } /* namespace kernel */
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/qa_filter.cc b/gr-filter/lib/qa_filter.cc
new file mode 100644
index 000000000..b7760b19e
--- /dev/null
+++ b/gr-filter/lib/qa_filter.cc
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * This class gathers together all the test cases for the gr-filter
+ * directory into a single test suite. As you create new test cases,
+ * add them here.
+ */
+
+#include <qa_filter.h>
+#include <qa_firdes.h>
+#include <qa_fir_filter_with_buffer.h>
+#include <qa_mmse_fir_interpolator_cc.h>
+#include <qa_mmse_fir_interpolator_ff.h>
+
+CppUnit::TestSuite *
+qa_gr_filter::suite ()
+{
+ CppUnit::TestSuite *s = new CppUnit::TestSuite ("gr-filter");
+
+ s->addTest(gr::filter::qa_firdes::suite());
+ s->addTest(gr::filter::fff::qa_fir_filter_with_buffer_fff::suite());
+ s->addTest(gr::filter::ccc::qa_fir_filter_with_buffer_ccc::suite());
+ s->addTest(gr::filter::ccf::qa_fir_filter_with_buffer_ccf::suite());
+ s->addTest(gr::filter::qa_mmse_fir_interpolator_cc::suite());
+ s->addTest(gr::filter::qa_mmse_fir_interpolator_ff::suite());
+
+ return s;
+}
diff --git a/gr-filter/lib/qa_filter.h b/gr-filter/lib/qa_filter.h
new file mode 100644
index 000000000..427e7f9f6
--- /dev/null
+++ b/gr-filter/lib/qa_filter.h
@@ -0,0 +1,38 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _QA_GR_FILTER_H_
+#define _QA_GR_FILTER_H_
+
+#include <gruel/attributes.h>
+#include <cppunit/TestSuite.h>
+
+//! collect all the tests for the gr-filter directory
+
+class __GR_ATTR_EXPORT qa_gr_filter {
+ public:
+ //! return suite of tests for all of gr-filter directory
+ static CppUnit::TestSuite *suite ();
+};
+
+
+#endif /* _QA_GR_FILTER_H_ */
diff --git a/gr-filter/lib/qa_fir_filter_with_buffer.cc b/gr-filter/lib/qa_fir_filter_with_buffer.cc
new file mode 100644
index 000000000..ab2958ed1
--- /dev/null
+++ b/gr-filter/lib/qa_fir_filter_with_buffer.cc
@@ -0,0 +1,406 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gr_types.h>
+#include <qa_fir_filter_with_buffer.h>
+#include <filter/fir_filter_with_buffer.h>
+#include <fft/fft.h>
+#include <cppunit/TestAssert.h>
+#include <cmath>
+#include <random.h>
+#include <cstring>
+
+namespace gr {
+ namespace filter {
+
+#define MAX_DATA (16383)
+#define ERR_DELTA (1e-5)
+
+ static float
+ uniform()
+ {
+ return 2.0 * ((float) random() / RANDOM_MAX - 0.5); // uniformly (-1, 1)
+ }
+
+ static void
+ random_floats(float *buf, unsigned n)
+ {
+ for(unsigned i = 0; i < n; i++)
+ buf[i] = (float)rint(uniform() * 32767);
+ }
+
+ static void
+ random_complex(gr_complex *buf, unsigned n)
+ {
+ for(unsigned i = 0; i < n; i++) {
+ float re = rint(uniform() * MAX_DATA);
+ float im = rint(uniform() * MAX_DATA);
+ buf[i] = gr_complex(re, im);
+ }
+ }
+
+ namespace fff {
+
+ typedef float i_type;
+ typedef float o_type;
+ typedef float tap_type;
+ typedef float acc_type;
+
+ using std::vector;
+
+ static o_type
+ ref_dotprod(const i_type input[], const tap_type taps[], int ntaps)
+ {
+ acc_type sum = 0;
+ for (int i = 0; i < ntaps; i++) {
+ sum += input[i] * taps[i];
+ }
+ return sum;
+ }
+
+ void
+ qa_fir_filter_with_buffer_fff::t1()
+ {
+ test_decimate(1);
+ }
+
+ void
+ qa_fir_filter_with_buffer_fff::t2()
+ {
+ test_decimate(2);
+ }
+
+ void
+ qa_fir_filter_with_buffer_fff::t3()
+ {
+ test_decimate(5);
+ }
+
+ //
+ // Test for ntaps in [0,9], and input lengths in [0,17].
+ // This ensures that we are building the shifted taps correctly,
+ // and exercises all corner cases on input alignment and length.
+ //
+ void
+ qa_fir_filter_with_buffer_fff::test_decimate(unsigned int decimate)
+ {
+ const int MAX_TAPS = 29;
+ const int OUTPUT_LEN = 37;
+ const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN;
+
+ // Mem aligned buffer not really necessary, but why not?
+ i_type *input = fft::malloc_float(INPUT_LEN);
+ i_type *dline = fft::malloc_float(INPUT_LEN);
+ o_type *expected_output = fft::malloc_float(OUTPUT_LEN);
+ o_type *actual_output = fft::malloc_float(OUTPUT_LEN);
+ tap_type *taps = fft::malloc_float(MAX_TAPS);
+
+ srandom(0); // we want reproducibility
+ memset(dline, 0, INPUT_LEN*sizeof(i_type));
+
+ for(int n = 0; n <= MAX_TAPS; n++) {
+ for(int ol = 0; ol <= OUTPUT_LEN; ol++) {
+
+ // build random test case
+ random_floats(input, INPUT_LEN);
+ random_floats(taps, MAX_TAPS);
+
+ // compute expected output values
+ memset(dline, 0, INPUT_LEN*sizeof(i_type));
+ for(int o = 0; o < (int)(ol/decimate); o++) {
+ // use an actual delay line for this test
+ for(int dd = 0; dd < (int)decimate; dd++) {
+ for(int oo = INPUT_LEN-1; oo > 0; oo--)
+ dline[oo] = dline[oo-1];
+ dline[0] = input[decimate*o+dd];
+ }
+ expected_output[o] = ref_dotprod(dline, taps, n);
+ }
+
+ // build filter
+ vector<tap_type> f1_taps(&taps[0], &taps[n]);
+ kernel::fir_filter_with_buffer_fff *f1 = \
+ new kernel::fir_filter_with_buffer_fff(f1_taps);
+
+ // zero the output, then do the filtering
+ memset(actual_output, 0, OUTPUT_LEN*sizeof(o_type));
+ f1->filterNdec(actual_output, input, ol/decimate, decimate);
+
+ // check results
+ //
+ // we use a sloppy error margin because on the x86 architecture,
+ // our reference implementation is using 80 bit floating point
+ // arithmetic, while the SSE version is using 32 bit float point
+ // arithmetic.
+
+ for(int o = 0; o < (int)(ol/decimate); o++) {
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(expected_output[o], actual_output[o],
+ sqrt((float)n)*0.25*MAX_DATA*MAX_DATA * ERR_DELTA);
+ }
+ delete f1;
+ }
+ }
+ fft::free(input);
+ fft::free(dline);
+ fft::free(expected_output);
+ fft::free(actual_output);
+ fft::free(taps);
+ }
+
+ } /* namespace fff */
+
+
+ /**************************************************************/
+
+
+ namespace ccc {
+
+ typedef gr_complex i_type;
+ typedef gr_complex o_type;
+ typedef gr_complex tap_type;
+ typedef gr_complex acc_type;
+
+ using std::vector;
+
+ static o_type
+ ref_dotprod(const i_type input[], const tap_type taps[], int ntaps)
+ {
+ acc_type sum = 0;
+ for(int i = 0; i < ntaps; i++) {
+ sum += input[i] * taps[i];
+ }
+
+ return sum;
+ }
+
+ void
+ qa_fir_filter_with_buffer_ccc::t1()
+ {
+ test_decimate(1);
+ }
+
+ void
+ qa_fir_filter_with_buffer_ccc::t2()
+ {
+ test_decimate(2);
+ }
+
+ void
+ qa_fir_filter_with_buffer_ccc::t3()
+ {
+ test_decimate(5);
+ }
+
+ //
+ // Test for ntaps in [0,9], and input lengths in [0,17].
+ // This ensures that we are building the shifted taps correctly,
+ // and exercises all corner cases on input alignment and length.
+ //
+ void
+ qa_fir_filter_with_buffer_ccc::test_decimate(unsigned int decimate)
+ {
+ const int MAX_TAPS = 29;
+ const int OUTPUT_LEN = 37;
+ const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN;
+
+ // Mem aligned buffer not really necessary, but why not?
+ i_type *input = fft::malloc_complex(INPUT_LEN);
+ i_type *dline = fft::malloc_complex(INPUT_LEN);
+ o_type *expected_output = fft::malloc_complex(OUTPUT_LEN);
+ o_type *actual_output = fft::malloc_complex(OUTPUT_LEN);
+ tap_type *taps = fft::malloc_complex(MAX_TAPS);
+
+ srandom(0); // we want reproducibility
+ memset(dline, 0, INPUT_LEN*sizeof(i_type));
+
+ for(int n = 0; n <= MAX_TAPS; n++) {
+ for(int ol = 0; ol <= OUTPUT_LEN; ol++) {
+
+ // build random test case
+ random_complex(input, INPUT_LEN);
+ random_complex(taps, MAX_TAPS);
+
+ // compute expected output values
+ memset(dline, 0, INPUT_LEN*sizeof(i_type));
+ for(int o = 0; o < (int)(ol/decimate); o++) {
+ // use an actual delay line for this test
+ for(int dd = 0; dd < (int)decimate; dd++) {
+ for(int oo = INPUT_LEN-1; oo > 0; oo--)
+ dline[oo] = dline[oo-1];
+ dline[0] = input[decimate*o+dd];
+ }
+ expected_output[o] = ref_dotprod(dline, taps, n);
+ }
+
+ // build filter
+ vector<tap_type> f1_taps(&taps[0], &taps[n]);
+ kernel::fir_filter_with_buffer_ccc *f1 = \
+ new kernel::fir_filter_with_buffer_ccc(f1_taps);
+
+ // zero the output, then do the filtering
+ memset(actual_output, 0, OUTPUT_LEN*sizeof(o_type));
+ f1->filterNdec(actual_output, input, ol/decimate, decimate);
+
+ // check results
+ //
+ // we use a sloppy error margin because on the x86 architecture,
+ // our reference implementation is using 80 bit floating point
+ // arithmetic, while the SSE version is using 32 bit float point
+ // arithmetic.
+
+ for(int o = 0; o < (int)(ol/decimate); o++) {
+ CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o],
+ sqrt((float)n)*0.25*MAX_DATA*MAX_DATA * ERR_DELTA);
+ }
+ delete f1;
+ }
+ }
+ fft::free(input);
+ fft::free(dline);
+ fft::free(expected_output);
+ fft::free(actual_output);
+ fft::free(taps);
+ }
+
+ } /* namespace ccc */
+
+
+ /**************************************************************/
+
+ namespace ccf {
+
+ typedef gr_complex i_type;
+ typedef gr_complex o_type;
+ typedef float tap_type;
+ typedef gr_complex acc_type;
+
+ using std::vector;
+
+ static o_type
+ ref_dotprod(const i_type input[], const tap_type taps[], int ntaps)
+ {
+ acc_type sum = 0;
+ for(int i = 0; i < ntaps; i++) {
+ sum += input[i] * taps[i];
+ }
+
+ //return gr_complex(121,9)*sum;
+ return sum;
+ }
+
+ void
+ qa_fir_filter_with_buffer_ccf::t1()
+ {
+ test_decimate(1);
+ }
+
+ void
+ qa_fir_filter_with_buffer_ccf::t2()
+ {
+ test_decimate(2);
+ }
+
+ void
+ qa_fir_filter_with_buffer_ccf::t3()
+ {
+ test_decimate(5);
+ }
+
+ //
+ // Test for ntaps in [0,9], and input lengths in [0,17].
+ // This ensures that we are building the shifted taps correctly,
+ // and exercises all corner cases on input alignment and length.
+ //
+ void
+ qa_fir_filter_with_buffer_ccf::test_decimate(unsigned int decimate)
+ {
+ const int MAX_TAPS = 29;
+ const int OUTPUT_LEN = 37;
+ const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN;
+
+ // Mem aligned buffer not really necessary, but why not?
+ i_type *input = fft::malloc_complex(INPUT_LEN);
+ i_type *dline = fft::malloc_complex(INPUT_LEN);
+ o_type *expected_output = fft::malloc_complex(OUTPUT_LEN);
+ o_type *actual_output = fft::malloc_complex(OUTPUT_LEN);
+ tap_type *taps = fft::malloc_float(MAX_TAPS);
+
+ srandom(0); // we want reproducibility
+ memset(dline, 0, INPUT_LEN*sizeof(i_type));
+
+ for(int n = 0; n <= MAX_TAPS; n++) {
+ for(int ol = 0; ol <= OUTPUT_LEN; ol++) {
+
+ // build random test case
+ random_complex(input, INPUT_LEN);
+ random_floats(taps, MAX_TAPS);
+
+ // compute expected output values
+ memset(dline, 0, INPUT_LEN*sizeof(i_type));
+ for(int o = 0; o < (int)(ol/decimate); o++) {
+ // use an actual delay line for this test
+ for(int dd = 0; dd < (int)decimate; dd++) {
+ for(int oo = INPUT_LEN-1; oo > 0; oo--)
+ dline[oo] = dline[oo-1];
+ dline[0] = input[decimate*o+dd];
+ }
+ expected_output[o] = ref_dotprod(dline, taps, n);
+ }
+
+ // build filter
+ vector<tap_type> f1_taps(&taps[0], &taps[n]);
+ kernel::fir_filter_with_buffer_ccf *f1 = \
+ new kernel::fir_filter_with_buffer_ccf(f1_taps);
+
+ // zero the output, then do the filtering
+ memset(actual_output, 0, sizeof(OUTPUT_LEN*sizeof(gr_complex)));
+ f1->filterNdec(actual_output, input, ol/decimate, decimate);
+
+ // check results
+ //
+ // we use a sloppy error margin because on the x86 architecture,
+ // our reference implementation is using 80 bit floating point
+ // arithmetic, while the SSE version is using 32 bit float point
+ // arithmetic.
+
+ for(int o = 0; o < (int)(ol/decimate); o++) {
+ CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o],
+ sqrt((float)n)*0.25*MAX_DATA*MAX_DATA * ERR_DELTA);
+ }
+ delete f1;
+ }
+ }
+ fft::free(input);
+ fft::free(dline);
+ fft::free(expected_output);
+ fft::free(actual_output);
+ fft::free(taps);
+ }
+
+ } /* namespace ccf */
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/qa_fir_filter_with_buffer.h b/gr-filter/lib/qa_fir_filter_with_buffer.h
new file mode 100644
index 000000000..8850ada20
--- /dev/null
+++ b/gr-filter/lib/qa_fir_filter_with_buffer.h
@@ -0,0 +1,94 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef _QA_FIR_FILTER_WITH_BUFFER_H_
+#define _QA_FIR_FILTER_WITH_BUFFER_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+namespace gr {
+ namespace filter {
+
+ namespace fff {
+
+ class qa_fir_filter_with_buffer_fff : public CppUnit::TestCase
+ {
+ CPPUNIT_TEST_SUITE(qa_fir_filter_with_buffer_fff);
+ CPPUNIT_TEST(t1);
+ CPPUNIT_TEST(t2);
+ CPPUNIT_TEST(t3);
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ void test_decimate(unsigned int decimate);
+
+ void t1();
+ void t2();
+ void t3();
+ };
+
+ } /* namespace fff */
+
+ namespace ccc {
+
+ class qa_fir_filter_with_buffer_ccc : public CppUnit::TestCase
+ {
+ CPPUNIT_TEST_SUITE(qa_fir_filter_with_buffer_ccc);
+ CPPUNIT_TEST(t1);
+ CPPUNIT_TEST(t2);
+ CPPUNIT_TEST(t3);
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ void test_decimate(unsigned int decimate);
+
+ void t1();
+ void t2();
+ void t3();
+ };
+
+ } /* namespace ccc */
+
+ namespace ccf {
+
+ class qa_fir_filter_with_buffer_ccf : public CppUnit::TestCase
+ {
+ CPPUNIT_TEST_SUITE(qa_fir_filter_with_buffer_ccf);
+ CPPUNIT_TEST(t1);
+ CPPUNIT_TEST(t2);
+ CPPUNIT_TEST(t3);
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ void test_decimate(unsigned int decimate);
+
+ void t1();
+ void t2();
+ void t3();
+ };
+
+ } /* namespace ccf */
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* _QA_FIR_FILTER_WITH_BUFFER_H_ */
diff --git a/gr-filter/lib/qa_firdes.cc b/gr-filter/lib/qa_firdes.cc
new file mode 100644
index 000000000..c2fe399d5
--- /dev/null
+++ b/gr-filter/lib/qa_firdes.cc
@@ -0,0 +1,621 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <qa_firdes.h>
+#include <filter/firdes.h>
+#include <cppunit/TestAssert.h>
+#include <gr_complex.h>
+#include <string.h>
+#include <iostream>
+#include <iomanip>
+#include <stdio.h>
+
+namespace gr {
+ namespace filter {
+
+#define NELEM(x) (sizeof(x) / sizeof(x[0]))
+
+ using std::vector;
+
+#if 0
+ static void
+ print_taps(std::ostream &s, vector<float> &v)
+ {
+
+ for(unsigned int i = 0; i < v.size(); i++) {
+ printf("tap[%2d] = %16.7e\n", i, v[i]);
+ }
+ }
+#endif
+
+ static void
+ check_symmetry(vector<float> &v)
+ {
+ int n = v.size();
+ int m = n / 2;
+
+ for(int i = 0; i < m; i++)
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(v[i], v[n - i - 1], 1e-9);
+ }
+
+ const static float t1_exp[53] = {
+ -9.0525491e-04,
+ 2.0713841e-04,
+ 1.2388536e-03,
+ 2.9683491e-04,
+ -1.7744775e-03,
+ -1.3599906e-03,
+ 2.2031884e-03,
+ 3.2744040e-03,
+ -1.8868084e-03,
+ -5.9935520e-03,
+ 6.4301129e-18,
+ 8.9516686e-03,
+ 4.2178580e-03,
+ -1.0998557e-02,
+ -1.1173409e-02,
+ 1.0455756e-02,
+ 2.0686293e-02,
+ -5.2032238e-03,
+ -3.1896964e-02,
+ -7.4998410e-03,
+ 4.3362070e-02,
+ 3.2502845e-02,
+ -5.3328082e-02,
+ -8.5621715e-02,
+ 6.0117975e-02,
+ 3.1128189e-01,
+ 4.3769023e-01,
+ 3.1128189e-01,
+ 6.0117975e-02,
+ -8.5621715e-02,
+ -5.3328082e-02,
+ 3.2502845e-02,
+ 4.3362070e-02,
+ -7.4998410e-03,
+ -3.1896964e-02,
+ -5.2032238e-03,
+ 2.0686293e-02,
+ 1.0455756e-02,
+ -1.1173409e-02,
+ -1.0998557e-02,
+ 4.2178580e-03,
+ 8.9516686e-03,
+ 6.4301129e-18,
+ -5.9935520e-03,
+ -1.8868084e-03,
+ 3.2744040e-03,
+ 2.2031884e-03,
+ -1.3599906e-03,
+ -1.7744775e-03,
+ 2.9683491e-04,
+ 1.2388536e-03,
+ 2.0713841e-04,
+ -9.0525491e-04
+ };
+
+ const static float t2_exp[53] = {
+ 9.0380036e-04,
+ -2.0680559e-04,
+ -1.2368630e-03,
+ -2.9635796e-04,
+ 1.7716263e-03,
+ 1.3578053e-03,
+ -2.1996482e-03,
+ -3.2691427e-03,
+ 1.8837767e-03,
+ 5.9839217e-03,
+ -6.4197810e-18,
+ -8.9372853e-03,
+ -4.2110807e-03,
+ 1.0980885e-02,
+ 1.1155456e-02,
+ -1.0438956e-02,
+ -2.0653054e-02,
+ 5.1948633e-03,
+ 3.1845711e-02,
+ 7.4877902e-03,
+ -4.3292396e-02,
+ -3.2450620e-02,
+ 5.3242393e-02,
+ 8.5484132e-02,
+ -6.0021374e-02,
+ -3.1078172e-01,
+ 5.6184036e-01,
+ -3.1078172e-01,
+ -6.0021374e-02,
+ 8.5484132e-02,
+ 5.3242393e-02,
+ -3.2450620e-02,
+ -4.3292396e-02,
+ 7.4877902e-03,
+ 3.1845711e-02,
+ 5.1948633e-03,
+ -2.0653054e-02,
+ -1.0438956e-02,
+ 1.1155456e-02,
+ 1.0980885e-02,
+ -4.2110807e-03,
+ -8.9372853e-03,
+ -6.4197810e-18,
+ 5.9839217e-03,
+ 1.8837767e-03,
+ -3.2691427e-03,
+ -2.1996482e-03,
+ 1.3578053e-03,
+ 1.7716263e-03,
+ -2.9635796e-04,
+ -1.2368630e-03,
+ -2.0680559e-04,
+ 9.0380036e-04
+ };
+
+ const static float t3_exp[107] = {
+ -1.8970841e-06,
+ -7.1057165e-04,
+ 5.4005696e-04,
+ 4.6233178e-04,
+ 2.0572044e-04,
+ 3.5209916e-04,
+ -1.4098573e-03,
+ 1.1279077e-04,
+ -6.2994129e-04,
+ 1.1450432e-03,
+ 1.3637283e-03,
+ -6.4360141e-04,
+ 3.6509900e-04,
+ -3.2864159e-03,
+ 7.0192874e-04,
+ 3.7524730e-04,
+ 2.0256115e-03,
+ 3.0641893e-03,
+ -3.6618244e-03,
+ 7.5592739e-05,
+ -5.5586505e-03,
+ 2.3849572e-03,
+ 4.0114378e-03,
+ 1.6636450e-03,
+ 4.7835698e-03,
+ -1.0191196e-02,
+ -3.8158931e-04,
+ -5.5551580e-03,
+ 5.3901658e-03,
+ 1.1366769e-02,
+ -3.0000482e-03,
+ 4.9341680e-03,
+ -2.0093076e-02,
+ 5.5752542e-17,
+ 1.2093617e-03,
+ 8.6089745e-03,
+ 2.2382140e-02,
+ -1.6854567e-02,
+ 1.6913920e-03,
+ -3.1222520e-02,
+ 3.2711059e-03,
+ 2.2604836e-02,
+ 8.1451107e-03,
+ 3.7583180e-02,
+ -5.2293688e-02,
+ -8.0551542e-03,
+ -4.0092729e-02,
+ 1.5582236e-02,
+ 9.7452506e-02,
+ -1.6183170e-02,
+ 8.3281815e-02,
+ -2.8196752e-01,
+ -1.0965768e-01,
+ 5.2867508e-01,
+ -1.0965768e-01,
+ -2.8196752e-01,
+ 8.3281815e-02,
+ -1.6183170e-02,
+ 9.7452506e-02,
+ 1.5582236e-02,
+ -4.0092729e-02,
+ -8.0551542e-03,
+ -5.2293688e-02,
+ 3.7583180e-02,
+ 8.1451107e-03,
+ 2.2604836e-02,
+ 3.2711059e-03,
+ -3.1222520e-02,
+ 1.6913920e-03,
+ -1.6854567e-02,
+ 2.2382140e-02,
+ 8.6089745e-03,
+ 1.2093617e-03,
+ 5.5752542e-17,
+ -2.0093076e-02,
+ 4.9341680e-03,
+ -3.0000482e-03,
+ 1.1366769e-02,
+ 5.3901658e-03,
+ -5.5551580e-03,
+ -3.8158931e-04,
+ -1.0191196e-02,
+ 4.7835698e-03,
+ 1.6636450e-03,
+ 4.0114378e-03,
+ 2.3849572e-03,
+ -5.5586505e-03,
+ 7.5592739e-05,
+ -3.6618244e-03,
+ 3.0641893e-03,
+ 2.0256115e-03,
+ 3.7524730e-04,
+ 7.0192874e-04,
+ -3.2864159e-03,
+ 3.6509900e-04,
+ -6.4360141e-04,
+ 1.3637283e-03,
+ 1.1450432e-03,
+ -6.2994129e-04,
+ 1.1279077e-04,
+ -1.4098573e-03,
+ 3.5209916e-04,
+ 2.0572044e-04,
+ 4.6233178e-04,
+ 5.4005696e-04,
+ -7.1057165e-04,
+ -1.8970841e-06
+ };
+
+ const static float t4_exp[] = { // low pass
+ 0.001059958362,
+ 0.0002263929928,
+ -0.001277606934,
+ -0.0009675776237,
+ 0.001592264394,
+ 0.00243603508,
+ -0.001451682881,
+ -0.004769335967,
+ 5.281541594e-18,
+ 0.007567512803,
+ 0.003658855334,
+ -0.009761494584,
+ -0.01011830103,
+ 0.009636915289,
+ 0.0193619132,
+ -0.004935568199,
+ -0.03060629964,
+ -0.007267376408,
+ 0.04236677289,
+ 0.03197422624,
+ -0.05274848267,
+ -0.0850463286,
+ 0.05989059806,
+ 0.31065014,
+ 0.4370569289,
+ 0.31065014,
+ 0.05989059806,
+ -0.0850463286,
+ -0.05274848267,
+ 0.03197422624,
+ 0.04236677289,
+ -0.007267376408,
+ -0.03060629964,
+ -0.004935568199,
+ 0.0193619132,
+ 0.009636915289,
+ -0.01011830103,
+ -0.009761494584,
+ 0.003658855334,
+ 0.007567512803,
+ 5.281541594e-18,
+ -0.004769335967,
+ -0.001451682881,
+ 0.00243603508,
+ 0.001592264394,
+ -0.0009675776237,
+ -0.001277606934,
+ 0.0002263929928,
+ 0.001059958362,
+ };
+
+ const static float t5_exp[] = { //high pass
+ -0.001062123571,
+ -0.0002268554381,
+ 0.001280216733,
+ 0.000969554123,
+ -0.001595516922,
+ -0.002441011136,
+ 0.001454648213,
+ 0.004779078532,
+ -5.292330097e-18,
+ -0.007582970895,
+ -0.00366632943,
+ 0.009781434201,
+ 0.01013896987,
+ -0.009656600654,
+ -0.01940146461,
+ 0.004945650231,
+ 0.03066881932,
+ 0.00728222169,
+ -0.04245331511,
+ -0.03203954175,
+ 0.05285623297,
+ 0.08522006124,
+ -0.06001294032,
+ -0.3112847209,
+ 0.5630782247,
+ -0.3112847209,
+ -0.06001294032,
+ 0.08522006124,
+ 0.05285623297,
+ -0.03203954175,
+ -0.04245331511,
+ 0.00728222169,
+ 0.03066881932,
+ 0.004945650231,
+ -0.01940146461,
+ -0.009656600654,
+ 0.01013896987,
+ 0.009781434201,
+ -0.00366632943,
+ -0.007582970895,
+ -5.292330097e-18,
+ 0.004779078532,
+ 0.001454648213,
+ -0.002441011136,
+ -0.001595516922,
+ 0.000969554123,
+ 0.001280216733,
+ -0.0002268554381,
+ -0.001062123571,
+ };
+
+ const static float t6_exp[] = { // bandpass
+ 0.0002809273137,
+ -0.001047327649,
+ 7.936541806e-05,
+ -0.0004270860809,
+ 0.0007595835486,
+ 0.0008966081077,
+ -0.0004236323002,
+ 0.0002423936094,
+ -0.002212299034,
+ 0.0004807534278,
+ 0.0002620361629,
+ 0.001443728455,
+ 0.002229931997,
+ -0.002720607212,
+ 5.731141573e-05,
+ -0.004297634587,
+ 0.001878833398,
+ 0.003217151389,
+ 0.001357055153,
+ 0.003965090029,
+ -0.008576190099,
+ -0.0003257228818,
+ -0.004805727862,
+ 0.004721920472,
+ 0.01007549558,
+ -0.002688719891,
+ 0.004467967432,
+ -0.01837076992,
+ 5.119658377e-17,
+ 0.001125075156,
+ 0.008071650751,
+ 0.02113764361,
+ -0.01602453552,
+ 0.001618095324,
+ -0.03004053794,
+ 0.003163811285,
+ 0.0219683405,
+ 0.007950295694,
+ 0.03682873398,
+ -0.05142467469,
+ -0.00794606097,
+ -0.03965795785,
+ 0.01544955093,
+ 0.09681399167,
+ -0.01610304788,
+ 0.08297294378,
+ -0.2811714709,
+ -0.1094062924,
+ 0.5275565982,
+ -0.1094062924,
+ -0.2811714709,
+ 0.08297294378,
+ -0.01610304788,
+ 0.09681399167,
+ 0.01544955093,
+ -0.03965795785,
+ -0.00794606097,
+ -0.05142467469,
+ 0.03682873398,
+ 0.007950295694,
+ 0.0219683405,
+ 0.003163811285,
+ -0.03004053794,
+ 0.001618095324,
+ -0.01602453552,
+ 0.02113764361,
+ 0.008071650751,
+ 0.001125075156,
+ 5.119658377e-17,
+ -0.01837076992,
+ 0.004467967432,
+ -0.002688719891,
+ 0.01007549558,
+ 0.004721920472,
+ -0.004805727862,
+ -0.0003257228818,
+ -0.008576190099,
+ 0.003965090029,
+ 0.001357055153,
+ 0.003217151389,
+ 0.001878833398,
+ -0.004297634587,
+ 5.731141573e-05,
+ -0.002720607212,
+ 0.002229931997,
+ 0.001443728455,
+ 0.0002620361629,
+ 0.0004807534278,
+ -0.002212299034,
+ 0.0002423936094,
+ -0.0004236323002,
+ 0.0008966081077,
+ 0.0007595835486,
+ -0.0004270860809,
+ 7.936541806e-05,
+ -0.001047327649,
+ 0.0002809273137,
+ };
+
+ void
+ qa_firdes::t1()
+ {
+ vector<float> taps =
+ firdes::low_pass(1.0,
+ 8000,
+ 1750,
+ 500,
+ firdes::WIN_HAMMING);
+
+ // cout << "ntaps: " << taps.size() << endl;
+ // print_taps(cout, taps);
+
+ CPPUNIT_ASSERT_EQUAL(NELEM(t1_exp), taps.size());
+ for(unsigned int i = 0; i < taps.size(); i++)
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(t1_exp[i], taps[i], 1e-9);
+
+ check_symmetry(taps);
+}
+
+ void
+ qa_firdes::t2()
+ {
+ vector<float> taps =
+ firdes::high_pass(1.0,
+ 8000,
+ 1750,
+ 500,
+ firdes::WIN_HAMMING);
+
+ // cout << "ntaps: " << taps.size() << endl;
+ // print_taps(cout, taps);
+
+ CPPUNIT_ASSERT_EQUAL(NELEM(t2_exp), taps.size());
+
+ for(unsigned int i = 0; i < taps.size(); i++)
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(t2_exp[i], taps[i], 1e-9);
+
+ check_symmetry(taps);
+ }
+
+ void
+ qa_firdes::t3()
+ {
+ vector<float> taps =
+ firdes::band_pass(1.0,
+ 20e6,
+ 5.75e6 - (5.28e6/2),
+ 5.75e6 + (5.28e6/2),
+ 0.62e6,
+ firdes::WIN_HAMMING);
+
+ // cout << "ntaps: " << taps.size() << endl;
+ // print_taps(cout, taps);
+
+ CPPUNIT_ASSERT_EQUAL(NELEM(t3_exp), taps.size());
+
+ for(unsigned int i = 0; i < taps.size(); i++)
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(t3_exp[i], taps[i], 1e-7);
+
+ check_symmetry(taps);
+ }
+
+ void
+ qa_firdes::t4()
+ {
+ vector<float> taps =
+ firdes::low_pass_2(1.0,
+ 8000,
+ 1750,
+ 500,
+ 66,
+ firdes::WIN_HAMMING);
+
+ // std::cout << "ntaps: " << taps.size() << std::endl;
+ // print_taps(std::cout, taps);
+
+ CPPUNIT_ASSERT_EQUAL(NELEM(t4_exp), taps.size());
+ for(unsigned int i = 0; i < taps.size(); i++)
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(t4_exp[i], taps[i], 1e-9);
+
+ check_symmetry(taps);
+ }
+
+ void
+ qa_firdes::t5()
+ {
+ vector<float> taps =
+ firdes::high_pass_2(1.0,
+ 8000,
+ 1750,
+ 500,
+ 66,
+ firdes::WIN_HAMMING);
+
+ // std::cout << "ntaps: " << taps.size() << std::endl;
+ // print_taps(std::cout, taps);
+
+ CPPUNIT_ASSERT_EQUAL(NELEM(t5_exp), taps.size());
+
+ for(unsigned int i = 0; i < taps.size(); i++)
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(t5_exp[i], taps[i], 1e-9);
+
+ check_symmetry(taps);
+}
+
+ void
+ qa_firdes::t6()
+ {
+ vector<float> taps =
+ firdes::band_pass_2(1.0,
+ 20e6,
+ 5.75e6 - (5.28e6/2),
+ 5.75e6 + (5.28e6/2),
+ 0.62e6,
+ 66,
+ firdes::WIN_HAMMING);
+
+ // std::cout << "ntaps: " << taps.size() << std::endl;
+ // print_taps(std::cout, taps);
+
+ CPPUNIT_ASSERT_EQUAL(NELEM(t6_exp), taps.size());
+
+ for(unsigned int i = 0; i < taps.size(); i++)
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(t6_exp[i], taps[i], 1e-7);
+
+ check_symmetry(taps);
+ }
+
+ void
+ qa_firdes::t7()
+ {
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/qa_firdes.h b/gr-filter/lib/qa_firdes.h
new file mode 100644
index 000000000..b27cf78b9
--- /dev/null
+++ b/gr-filter/lib/qa_firdes.h
@@ -0,0 +1,56 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef _QA_FILTER_FIRDES_H_
+#define _QA_FILTER_FIRDES_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+namespace gr {
+ namespace filter {
+
+ class qa_firdes : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE(qa_firdes);
+ CPPUNIT_TEST(t1);
+ CPPUNIT_TEST(t2);
+ CPPUNIT_TEST(t3);
+ CPPUNIT_TEST(t4);
+ CPPUNIT_TEST(t5);
+ CPPUNIT_TEST(t6);
+ CPPUNIT_TEST(t7);
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ void t1();
+ void t2();
+ void t3();
+ void t4();
+ void t5();
+ void t6();
+ void t7();
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* _QA_FILTER_FIRDES_H_ */
diff --git a/gr-filter/lib/qa_mmse_fir_interpolator_cc.cc b/gr-filter/lib/qa_mmse_fir_interpolator_cc.cc
new file mode 100644
index 000000000..268b8801c
--- /dev/null
+++ b/gr-filter/lib/qa_mmse_fir_interpolator_cc.cc
@@ -0,0 +1,126 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2007,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cppunit/TestAssert.h>
+#include <qa_mmse_fir_interpolator_cc.h>
+#include <filter/mmse_fir_interpolator_cc.h>
+#include <fft/fft.h>
+#include <cstdio>
+#include <cmath>
+#include <stdexcept>
+#include <stdint.h>
+
+namespace gr {
+ namespace filter {
+
+ static float
+ test_fcn_sin(double index)
+ {
+ return (2 * sin (index * 0.25 * 2 * M_PI + 0.125 * M_PI)
+ + 3 * sin (index * 0.077 * 2 * M_PI + 0.3 * M_PI));
+ }
+
+ static float
+ test_fcn_cos(double index)
+ {
+ return (2 * cos (index * 0.25 * 2 * M_PI + 0.125 * M_PI)
+ + 3 * cos (index * 0.077 * 2 * M_PI + 0.3 * M_PI));
+ }
+
+ static gr_complex
+ test_fcn(double index)
+ {
+ return gr_complex(test_fcn_cos(index), test_fcn_sin(index));
+ }
+
+
+ void
+ qa_mmse_fir_interpolator_cc::t1()
+ {
+ static const unsigned N = 100;
+ gr_complex *input = fft::malloc_complex(N + 10);
+
+ for(unsigned i = 0; i < N+10; i++)
+ input[i] = test_fcn((double) i);
+
+ mmse_fir_interpolator_cc intr;
+ float inv_nsteps = 1.0 / intr.nsteps();
+
+ for(unsigned i = 0; i < N; i++) {
+ for(unsigned imu = 0; imu <= intr.nsteps (); imu += 1) {
+ gr_complex expected = test_fcn((i + 3) + imu * inv_nsteps);
+ gr_complex actual = intr.interpolate(&input[i], imu * inv_nsteps);
+
+ CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected, actual, 0.004);
+ // printf ("%9.6f %9.6f %9.6f\n", expected, actual, expected - actual);
+ }
+ }
+ fft::free(input);
+ }
+
+ /*
+ * Force bad alignment and confirm that it raises an exception
+ */
+ void
+ qa_mmse_fir_interpolator_cc::t2_body()
+ {
+ static const unsigned N = 100;
+ float float_input[2*(N+10) + 1];
+ gr_complex *input;
+
+ // We require that gr_complex be aligned on an 8-byte boundary.
+ // Ensure that we ARE NOT ;)
+
+ if(((intptr_t) float_input & 0x7) == 0)
+ input = reinterpret_cast<gr_complex *>(&float_input[1]);
+ else
+ input = reinterpret_cast<gr_complex *>(&float_input[0]);
+
+ for(unsigned i = 0; i < (N+10); i++)
+ input[i] = test_fcn((double) i);
+
+ mmse_fir_interpolator_cc intr;
+ float inv_nsteps = 1.0 / intr.nsteps();
+
+ for(unsigned i = 0; i < N; i++) {
+ for(unsigned imu = 0; imu <= intr.nsteps (); imu += 1) {
+ gr_complex expected = test_fcn((i + 3) + imu * inv_nsteps);
+ gr_complex actual = intr.interpolate(&input[i], imu * inv_nsteps);
+
+ CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected, actual, 0.004);
+ // printf ("%9.6f %9.6f %9.6f\n", expected, actual, expected - actual);
+ }
+ }
+ }
+
+ void
+ qa_mmse_fir_interpolator_cc::t2()
+ {
+ CPPUNIT_ASSERT_THROW(t2_body(), std::invalid_argument);
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/qa_mmse_fir_interpolator_cc.h b/gr-filter/lib/qa_mmse_fir_interpolator_cc.h
new file mode 100644
index 000000000..a45965ca2
--- /dev/null
+++ b/gr-filter/lib/qa_mmse_fir_interpolator_cc.h
@@ -0,0 +1,48 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2007,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _QA_MMSE_FIR_INTERPOLATOR_CC_H_
+#define _QA_MMSE_FIR_INTERPOLATOR_CC_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+namespace gr {
+ namespace filter {
+
+ class qa_mmse_fir_interpolator_cc : public CppUnit::TestCase
+ {
+ CPPUNIT_TEST_SUITE(qa_mmse_fir_interpolator_cc);
+ CPPUNIT_TEST(t1);
+ // CPPUNIT_TEST(t2);
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ void t1();
+ void t2();
+ void t2_body();
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* _QA_MMSE_FIR_INTERPOLATOR_CC_H_ */
diff --git a/gr-filter/lib/qa_mmse_fir_interpolator_ff.cc b/gr-filter/lib/qa_mmse_fir_interpolator_ff.cc
new file mode 100644
index 000000000..54387fd9b
--- /dev/null
+++ b/gr-filter/lib/qa_mmse_fir_interpolator_ff.cc
@@ -0,0 +1,71 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cppunit/TestAssert.h>
+#include <qa_mmse_fir_interpolator_ff.h>
+#include <filter/mmse_fir_interpolator_ff.h>
+#include <fft/fft.h>
+#include <cstdio>
+#include <cmath>
+
+namespace gr {
+ namespace filter {
+
+ static float
+ test_fcn(double index)
+ {
+ return (2 * sin(index * 0.25 * 2 * M_PI + 0.125 * M_PI)
+ + 3 * sin(index * 0.077 * 2 * M_PI + 0.3 * M_PI));
+ }
+
+ void
+ qa_mmse_fir_interpolator_ff::t1()
+ {
+ // use aligned malloc and make sure that everything in this
+ // buffer is properly initialized.
+ static const unsigned N = 100;
+ float *input = fft::malloc_float(N + 10);
+
+ for(unsigned i = 0; i < N+10; i++)
+ input[i] = test_fcn((double) i);
+
+ mmse_fir_interpolator_ff intr;
+ float inv_nsteps = 1.0 / intr.nsteps();
+
+ for(unsigned i = 0; i < N; i++) {
+ for(unsigned imu = 0; imu <= intr.nsteps (); imu += 1) {
+ float expected = test_fcn((i + 3) + imu * inv_nsteps);
+ float actual = intr.interpolate(&input[i], imu * inv_nsteps);
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(expected, actual, 0.004);
+ // printf ("%9.6f %9.6f %9.6f\n", expected, actual, expected - actual);
+ }
+ }
+ fft::free(input);
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/qa_mmse_fir_interpolator_ff.h b/gr-filter/lib/qa_mmse_fir_interpolator_ff.h
new file mode 100644
index 000000000..833ec173a
--- /dev/null
+++ b/gr-filter/lib/qa_mmse_fir_interpolator_ff.h
@@ -0,0 +1,45 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _QA_MMSE_FIR_INTERPOLATOR_FF_H_
+#define _QA_MMSE_FIR_INTERPOLATOR_FF_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+namespace gr {
+ namespace filter {
+
+ class qa_mmse_fir_interpolator_ff : public CppUnit::TestCase
+ {
+ CPPUNIT_TEST_SUITE(qa_mmse_fir_interpolator_ff);
+ CPPUNIT_TEST(t1);
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ void t1();
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* _QA_MMSE_FIR_INTERPOLATOR_FF_H_ */
diff --git a/gr-filter/lib/rational_resampler_base_XXX_impl.cc.t b/gr-filter/lib/rational_resampler_base_XXX_impl.cc.t
new file mode 100644
index 000000000..2e9161eeb
--- /dev/null
+++ b/gr-filter/lib/rational_resampler_base_XXX_impl.cc.t
@@ -0,0 +1,174 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* @WARNING@ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "@IMPL_NAME@.h"
+#include <gr_io_signature.h>
+#include <volk/volk.h>
+#include <stdexcept>
+
+namespace gr {
+ namespace filter {
+
+ @BASE_NAME@::sptr
+ @BASE_NAME@::make(unsigned interpolation,
+ unsigned decimation,
+ const std::vector<@TAP_TYPE@> &taps)
+ {
+ return gnuradio::get_initial_sptr
+ (new @IMPL_NAME@(interpolation, decimation, taps));
+ }
+
+ @IMPL_NAME@::@IMPL_NAME@(unsigned interpolation,
+ unsigned decimation,
+ const std::vector<@TAP_TYPE@> &taps)
+ : gr_block("@BASE_NAME@",
+ gr_make_io_signature(1, 1, sizeof(@I_TYPE@)),
+ gr_make_io_signature(1, 1, sizeof(@O_TYPE@))),
+ d_history(1),
+ d_interpolation(interpolation),
+ d_decimation(decimation),
+ d_ctr(0),
+ d_firs(interpolation),
+ d_updated(false)
+ {
+ if(interpolation == 0)
+ throw std::out_of_range("@IMPL_NAME@: interpolation must be > 0");
+ if(decimation == 0)
+ throw std::out_of_range("@IMPL_NAME@: decimation must be > 0");
+
+ set_relative_rate(1.0 * interpolation / decimation);
+ set_output_multiple(1);
+
+ std::vector<@TAP_TYPE@> dummy_taps;
+
+ for(unsigned i = 0; i < interpolation; i++) {
+ d_firs[i] = new kernel::@FIR_TYPE@(1, dummy_taps);
+ }
+
+ set_taps(taps);
+ install_taps(d_new_taps);
+ }
+
+ @IMPL_NAME@::~@IMPL_NAME@()
+ {
+ int interp = interpolation();
+ for(int i = 0; i < interp; i++) {
+ delete d_firs[i];
+ }
+ }
+
+ void
+ @IMPL_NAME@::set_taps(const std::vector<@TAP_TYPE@> &taps)
+ {
+ d_new_taps = taps;
+ d_updated = true;
+
+ // round up length to a multiple of the interpolation factor
+ int n = taps.size() % interpolation();
+ if(n > 0) {
+ n = interpolation() - n;
+ while(n-- > 0) {
+ d_new_taps.insert(d_new_taps.begin(), 0);
+ }
+ }
+
+ assert(d_new_taps.size() % interpolation() == 0);
+ }
+
+ void
+ @IMPL_NAME@::install_taps(const std::vector<@TAP_TYPE@> &taps)
+ {
+ int nfilters = interpolation();
+ int nt = taps.size() / nfilters;
+
+ assert(nt * nfilters == (int) taps.size());
+
+ std::vector< std::vector <@TAP_TYPE@> > xtaps(nfilters);
+
+ for(int n = 0; n < nfilters; n++)
+ xtaps[n].resize (nt);
+
+ for(int i = 0; i < (int)taps.size(); i++)
+ xtaps[i % nfilters][i / nfilters] = taps[i];
+
+ for(int n = 0; n < nfilters; n++)
+ d_firs[n]->set_taps(xtaps[n]);
+
+ set_history(nt);
+ d_updated = false;
+ }
+
+ std::vector<@TAP_TYPE@>
+ @IMPL_NAME@::taps() const
+ {
+ return d_new_taps;
+ }
+
+ void
+ @IMPL_NAME@::forecast(int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ int nreqd = std::max((unsigned)1, (int)((double) (noutput_items+1) * \
+ decimation() / interpolation()) + history() - 1);
+ unsigned ninputs = ninput_items_required.size();
+ for(unsigned i = 0; i < ninputs; i++)
+ ninput_items_required[i] = nreqd;
+ }
+
+ int
+ @IMPL_NAME@::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const @I_TYPE@ *in = (const @I_TYPE@ *)input_items[0];
+ @O_TYPE@ *out = (@O_TYPE@ *)output_items[0];
+
+ if(d_updated) {
+ install_taps(d_new_taps);
+ return 0; // history requirement may have increased.
+ }
+
+ unsigned int ctr = d_ctr;
+
+ int i = 0;
+ while(i < noutput_items) {
+ out[i++] = d_firs[ctr]->filter(in);
+ ctr += decimation();
+ while(ctr >= interpolation()) {
+ ctr -= interpolation();
+ in++;
+ }
+ }
+
+ d_ctr = ctr;
+ consume_each(in - (@I_TYPE@*)input_items[0]);
+ return i;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/rational_resampler_base_XXX_impl.h.t b/gr-filter/lib/rational_resampler_base_XXX_impl.h.t
new file mode 100644
index 000000000..4396656da
--- /dev/null
+++ b/gr-filter/lib/rational_resampler_base_XXX_impl.h.t
@@ -0,0 +1,72 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* @WARNING@ */
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
+
+#include <filter/fir_filter.h>
+#include <filter/@BASE_NAME@.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API @IMPL_NAME@ : public @BASE_NAME@
+ {
+ private:
+ unsigned d_history;
+ unsigned d_interpolation;
+ unsigned d_decimation;
+ unsigned d_ctr;
+ std::vector<@TAP_TYPE@> d_new_taps;
+ std::vector<kernel::@FIR_TYPE@ *> d_firs;
+ bool d_updated;
+
+ void install_taps(const std::vector<@TAP_TYPE@> &taps);
+
+ public:
+ @IMPL_NAME@(unsigned interpolation, unsigned decimation,
+ const std::vector<@TAP_TYPE@> &taps);
+
+ ~@IMPL_NAME@();
+
+ unsigned history() const { return d_history; }
+ void set_history(unsigned history) { d_history = history; }
+
+ unsigned interpolation() const { return d_interpolation; }
+ unsigned decimation() const { return d_decimation; }
+
+ void set_taps(const std::vector<@TAP_TYPE@> &taps);
+ std::vector<@TAP_TYPE@> taps() const;
+
+ void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* @GUARD_NAME@ */
diff --git a/gr-filter/lib/single_pole_iir_filter_cc_impl.cc b/gr-filter/lib/single_pole_iir_filter_cc_impl.cc
new file mode 100644
index 000000000..9406f2c98
--- /dev/null
+++ b/gr-filter/lib/single_pole_iir_filter_cc_impl.cc
@@ -0,0 +1,89 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2006,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "single_pole_iir_filter_cc_impl.h"
+#include <gr_io_signature.h>
+
+
+namespace gr {
+ namespace filter {
+
+ single_pole_iir_filter_cc::sptr
+ single_pole_iir_filter_cc::make(double alpha, unsigned int vlen)
+ {
+ return gnuradio::get_initial_sptr
+ (new single_pole_iir_filter_cc_impl(alpha, vlen));
+ }
+
+ single_pole_iir_filter_cc_impl::single_pole_iir_filter_cc_impl
+ (double alpha, unsigned int vlen)
+ : gr_sync_block("single_pole_iir_filter_cc",
+ gr_make_io_signature(1, 1, sizeof (gr_complex) * vlen),
+ gr_make_io_signature(1, 1, sizeof (gr_complex) * vlen)),
+ d_vlen(vlen), d_iir(vlen)
+ {
+ set_taps(alpha);
+ }
+
+ single_pole_iir_filter_cc_impl::~single_pole_iir_filter_cc_impl()
+ {
+ }
+
+ void
+ single_pole_iir_filter_cc_impl::set_taps(double alpha)
+ {
+ for(unsigned int i = 0; i < d_vlen; i++) {
+ d_iir[i].set_taps(alpha);
+ }
+ }
+
+ int
+ single_pole_iir_filter_cc_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const gr_complex *in = (const gr_complex*)input_items[0];
+ gr_complex *out = (gr_complex*)output_items[0];
+ unsigned int vlen = d_vlen;
+
+ if(d_vlen == 1) {
+ for(int i = 0; i < noutput_items; i++) {
+ out[i] = d_iir[0].filter(in[i]);
+ }
+ }
+ else {
+ for(int i = 0; i < noutput_items; i++) {
+ for(unsigned int j = 0; j < vlen; j++) {
+ *out++ = d_iir[j].filter(*in++);
+ }
+ }
+ }
+
+ return noutput_items;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/single_pole_iir_filter_cc_impl.h b/gr-filter/lib/single_pole_iir_filter_cc_impl.h
new file mode 100644
index 000000000..fa627881e
--- /dev/null
+++ b/gr-filter/lib/single_pole_iir_filter_cc_impl.h
@@ -0,0 +1,55 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004-2006,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_SINGLE_POLE_IIR_FILTER_CC_IMPL_H
+#define INCLUDED_SINGLE_POLE_IIR_FILTER_CC_IMPL_H
+
+#include <filter/single_pole_iir.h>
+#include <filter/single_pole_iir_filter_cc.h>
+#include <gr_sync_block.h>
+#include <gr_complex.h>
+#include <stdexcept>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API single_pole_iir_filter_cc_impl : public single_pole_iir_filter_cc
+ {
+ private:
+ unsigned int d_vlen;
+ std::vector<single_pole_iir<gr_complex,gr_complex,double> > d_iir;
+
+ public:
+ single_pole_iir_filter_cc_impl(double alpha, unsigned int vlen);
+ ~single_pole_iir_filter_cc_impl();
+
+ void set_taps(double alpha);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_SINGLE_POLE_IIR_FILTER_CC_IMPL_H */
diff --git a/gr-filter/lib/single_pole_iir_filter_ff_impl.cc b/gr-filter/lib/single_pole_iir_filter_ff_impl.cc
new file mode 100644
index 000000000..7e2bae5db
--- /dev/null
+++ b/gr-filter/lib/single_pole_iir_filter_ff_impl.cc
@@ -0,0 +1,87 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "single_pole_iir_filter_ff_impl.h"
+#include <gr_io_signature.h>
+
+namespace gr {
+ namespace filter {
+
+ single_pole_iir_filter_ff::sptr
+ single_pole_iir_filter_ff::make(double alpha, unsigned int vlen)
+ {
+ return gnuradio::get_initial_sptr
+ (new single_pole_iir_filter_ff_impl(alpha, vlen));
+ }
+
+ single_pole_iir_filter_ff_impl::single_pole_iir_filter_ff_impl
+ (double alpha, unsigned int vlen)
+ : gr_sync_block("single_pole_iir_filter_ff",
+ gr_make_io_signature(1, 1, sizeof(float)*vlen),
+ gr_make_io_signature(1, 1, sizeof(float)*vlen)),
+ d_vlen(vlen), d_iir(vlen)
+ {
+ set_taps(alpha);
+ }
+
+ single_pole_iir_filter_ff_impl::~single_pole_iir_filter_ff_impl()
+ {
+ }
+
+ void
+ single_pole_iir_filter_ff_impl::set_taps(double alpha)
+ {
+ for(unsigned int i = 0; i < d_vlen; i++) {
+ d_iir[i].set_taps(alpha);
+ }
+ }
+
+ int
+ single_pole_iir_filter_ff_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const float *in = (const float*)input_items[0];
+ float *out = (float*)output_items[0];
+ unsigned int vlen = d_vlen;
+
+ if(d_vlen == 1) {
+ for(int i = 0; i < noutput_items; i++) {
+ out[i] = d_iir[0].filter (in[i]);
+ }
+ }
+ else {
+ for(int i = 0; i < noutput_items; i++) {
+ for(unsigned int j = 0; j < vlen; j++) {
+ *out++ = d_iir[j].filter(*in++);
+ }
+ }
+ }
+ return noutput_items;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/single_pole_iir_filter_ff_impl.h b/gr-filter/lib/single_pole_iir_filter_ff_impl.h
new file mode 100644
index 000000000..cba9c188c
--- /dev/null
+++ b/gr-filter/lib/single_pole_iir_filter_ff_impl.h
@@ -0,0 +1,54 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004-2006,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_SINGLE_POLE_IIR_FILTER_FF_IMPL_H
+#define INCLUDED_SINGLE_POLE_IIR_FILTER_FF_IMPL_H
+
+#include <filter/single_pole_iir.h>
+#include <filter/single_pole_iir_filter_ff.h>
+#include <gr_sync_block.h>
+#include <stdexcept>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API single_pole_iir_filter_ff_impl : public single_pole_iir_filter_ff
+ {
+ private:
+ unsigned int d_vlen;
+ std::vector<single_pole_iir<float,float,double> > d_iir;
+
+ public:
+ single_pole_iir_filter_ff_impl(double alpha, unsigned int vlen);
+ ~single_pole_iir_filter_ff_impl();
+
+ void set_taps(double alpha);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_SINGLE_POLE_IIR_FILTER_FF_IMPL_H */
diff --git a/gr-filter/lib/test_gr_filter.cc b/gr-filter/lib/test_gr_filter.cc
new file mode 100644
index 000000000..915b6286b
--- /dev/null
+++ b/gr-filter/lib/test_gr_filter.cc
@@ -0,0 +1,43 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <cppunit/TextTestRunner.h>
+#include <cppunit/XmlOutputter.h>
+
+#include <gr_unittests.h>
+#include <qa_filter.h>
+#include <iostream>
+
+int
+main (int argc, char **argv)
+{
+ CppUnit::TextTestRunner runner;
+ std::ofstream xmlfile(get_unittest_path("gr_filter.xml").c_str());
+ CppUnit::XmlOutputter *xmlout = new CppUnit::XmlOutputter(&runner.result(), xmlfile);
+
+ runner.addTest(qa_gr_filter::suite());
+ runner.setOutputter(xmlout);
+
+ bool was_successful = runner.run("", false);
+
+ return was_successful ? 0 : 1;
+}
diff --git a/gr-filter/python/CMakeLists.txt b/gr-filter/python/CMakeLists.txt
new file mode 100644
index 000000000..07f03fac4
--- /dev/null
+++ b/gr-filter/python/CMakeLists.txt
@@ -0,0 +1,50 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+include(GrPython)
+
+GR_PYTHON_INSTALL(
+ FILES
+ __init__.py
+ optfir.py
+ pfb.py
+ rational_resampler.py
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/filter
+ COMPONENT "filter_python"
+)
+
+########################################################################
+# Handle the unit tests
+########################################################################
+if(ENABLE_TESTING)
+include(GrTest)
+file(GLOB py_qa_test_files "qa_*.py")
+foreach(py_qa_test_file ${py_qa_test_files})
+ get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
+ set(GR_TEST_PYTHON_DIRS
+ ${CMAKE_BINARY_DIR}/gnuradio-core/src/python
+ ${CMAKE_BINARY_DIR}/gnuradio-core/src/lib/swig
+ ${CMAKE_BINARY_DIR}/gr-filter/python
+ ${CMAKE_BINARY_DIR}/gr-filter/swig
+ )
+ set(GR_TEST_TARGET_DEPS gruel gnuradio-core gnuradio-filter)
+ GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${py_qa_test_file})
+endforeach(py_qa_test_file)
+endif(ENABLE_TESTING)
diff --git a/gr-filter/python/__init__.py b/gr-filter/python/__init__.py
new file mode 100644
index 000000000..65a62d828
--- /dev/null
+++ b/gr-filter/python/__init__.py
@@ -0,0 +1,30 @@
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+'''
+This is the gr-filter package. This package provides GNU Radio
+processing blocks for FILTER and related functions.
+'''
+
+from filter_swig import *
+from rational_resampler import *
+import pfb
+import optfir
diff --git a/gr-filter/python/optfir.py b/gr-filter/python/optfir.py
new file mode 100644
index 000000000..bccb8c68d
--- /dev/null
+++ b/gr-filter/python/optfir.py
@@ -0,0 +1,339 @@
+#
+# Copyright 2004,2005,2009 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+'''
+Routines for designing optimal FIR filters.
+
+For a great intro to how all this stuff works, see section 6.6 of
+"Digital Signal Processing: A Practical Approach", Emmanuael C. Ifeachor
+and Barrie W. Jervis, Adison-Wesley, 1993. ISBN 0-201-54413-X.
+'''
+
+import math, cmath
+import filter_swig as filter
+
+# ----------------------------------------------------------------
+
+## Builds a low pass filter.
+# @param gain Filter gain in the passband (linear)
+# @param Fs Sampling rate (sps)
+# @param freq1 End of pass band (in Hz)
+# @param freq2 Start of stop band (in Hz)
+# @param passband_ripple_db Pass band ripple in dB (should be small, < 1)
+# @param stopband_atten_db Stop band attenuation in dB (should be large, >= 60)
+# @param nextra_taps Extra taps to use in the filter (default=2)
+def low_pass (gain, Fs, freq1, freq2, passband_ripple_db, stopband_atten_db,
+ nextra_taps=2):
+ passband_dev = passband_ripple_to_dev (passband_ripple_db)
+ stopband_dev = stopband_atten_to_dev (stopband_atten_db)
+ desired_ampls = (gain, 0)
+ (n, fo, ao, w) = remezord ([freq1, freq2], desired_ampls,
+ [passband_dev, stopband_dev], Fs)
+ # The remezord typically under-estimates the filter order, so add 2 taps by default
+ taps = filter.pm_remez (n + nextra_taps, fo, ao, w, "bandpass")
+ return taps
+
+## Builds a band pass filter.
+# @param gain Filter gain in the passband (linear)
+# @param Fs Sampling rate (sps)
+# @param freq_sb1 End of stop band (in Hz)
+# @param freq_pb1 Start of pass band (in Hz)
+# @param freq_pb2 End of pass band (in Hz)
+# @param freq_sb2 Start of stop band (in Hz)
+# @param passband_ripple_db Pass band ripple in dB (should be small, < 1)
+# @param stopband_atten_db Stop band attenuation in dB (should be large, >= 60)
+# @param nextra_taps Extra taps to use in the filter (default=2)
+def band_pass (gain, Fs, freq_sb1, freq_pb1, freq_pb2, freq_sb2,
+ passband_ripple_db, stopband_atten_db,
+ nextra_taps=2):
+ passband_dev = passband_ripple_to_dev (passband_ripple_db)
+ stopband_dev = stopband_atten_to_dev (stopband_atten_db)
+ desired_ampls = (0, gain, 0)
+ desired_freqs = [freq_sb1, freq_pb1, freq_pb2, freq_sb2]
+ desired_ripple = [stopband_dev, passband_dev, stopband_dev]
+ (n, fo, ao, w) = remezord (desired_freqs, desired_ampls,
+ desired_ripple, Fs)
+ # The remezord typically under-estimates the filter order, so add 2 taps by default
+ taps = filter.pm_remez (n + nextra_taps, fo, ao, w, "bandpass")
+ return taps
+
+
+## Builds a band pass filter with complex taps by making an LPF and
+# spinning it up to the right center frequency
+# @param gain Filter gain in the passband (linear)
+# @param Fs Sampling rate (sps)
+# @param freq_sb1 End of stop band (in Hz)
+# @param freq_pb1 Start of pass band (in Hz)
+# @param freq_pb2 End of pass band (in Hz)
+# @param freq_sb2 Start of stop band (in Hz)
+# @param passband_ripple_db Pass band ripple in dB (should be small, < 1)
+# @param stopband_atten_db Stop band attenuation in dB (should be large, >= 60)
+# @param nextra_taps Extra taps to use in the filter (default=2)
+def complex_band_pass (gain, Fs, freq_sb1, freq_pb1, freq_pb2, freq_sb2,
+ passband_ripple_db, stopband_atten_db,
+ nextra_taps=2):
+ center_freq = (freq_pb2 + freq_pb1) / 2.0
+ lp_pb = (freq_pb2 - center_freq)/1.0
+ lp_sb = freq_sb2 - center_freq
+ lptaps = low_pass(gain, Fs, lp_pb, lp_sb, passband_ripple_db,
+ stopband_atten_db, nextra_taps)
+ spinner = [cmath.exp(2j*cmath.pi*center_freq/Fs*i) for i in xrange(len(lptaps))]
+ taps = [s*t for s,t in zip(spinner, lptaps)]
+ return taps
+
+
+## Builds a band reject filter
+# spinning it up to the right center frequency
+# @param gain Filter gain in the passband (linear)
+# @param Fs Sampling rate (sps)
+# @param freq_pb1 End of pass band (in Hz)
+# @param freq_sb1 Start of stop band (in Hz)
+# @param freq_sb2 End of stop band (in Hz)
+# @param freq_pb2 Start of pass band (in Hz)
+# @param passband_ripple_db Pass band ripple in dB (should be small, < 1)
+# @param stopband_atten_db Stop band attenuation in dB (should be large, >= 60)
+# @param nextra_taps Extra taps to use in the filter (default=2)
+def band_reject (gain, Fs, freq_pb1, freq_sb1, freq_sb2, freq_pb2,
+ passband_ripple_db, stopband_atten_db,
+ nextra_taps=2):
+ passband_dev = passband_ripple_to_dev (passband_ripple_db)
+ stopband_dev = stopband_atten_to_dev (stopband_atten_db)
+ desired_ampls = (gain, 0, gain)
+ desired_freqs = [freq_pb1, freq_sb1, freq_sb2, freq_pb2]
+ desired_ripple = [passband_dev, stopband_dev, passband_dev]
+ (n, fo, ao, w) = remezord (desired_freqs, desired_ampls,
+ desired_ripple, Fs)
+ # Make sure we use an odd number of taps
+ if((n+nextra_taps)%2 == 1):
+ n += 1
+ # The remezord typically under-estimates the filter order, so add 2 taps by default
+ taps = filter.pm_remez (n + nextra_taps, fo, ao, w, "bandpass")
+ return taps
+
+
+## Builds a high pass filter.
+# @param gain Filter gain in the passband (linear)
+# @param Fs Sampling rate (sps)
+# @param freq1 End of stop band (in Hz)
+# @param freq2 Start of pass band (in Hz)
+# @param passband_ripple_db Pass band ripple in dB (should be small, < 1)
+# @param stopband_atten_db Stop band attenuation in dB (should be large, >= 60)
+# @param nextra_taps Extra taps to use in the filter (default=2)
+def high_pass (gain, Fs, freq1, freq2, passband_ripple_db, stopband_atten_db,
+ nextra_taps=2):
+ passband_dev = passband_ripple_to_dev (passband_ripple_db)
+ stopband_dev = stopband_atten_to_dev (stopband_atten_db)
+ desired_ampls = (0, 1)
+ (n, fo, ao, w) = remezord ([freq1, freq2], desired_ampls,
+ [stopband_dev, passband_dev], Fs)
+ # For a HPF, we need to use an odd number of taps
+ # In filter.remez, ntaps = n+1, so n must be even
+ if((n+nextra_taps)%2 == 1):
+ n += 1
+
+ # The remezord typically under-estimates the filter order, so add 2 taps by default
+ taps = filter.pm_remez (n + nextra_taps, fo, ao, w, "bandpass")
+ return taps
+
+# ----------------------------------------------------------------
+
+def stopband_atten_to_dev (atten_db):
+ """Convert a stopband attenuation in dB to an absolute value"""
+ return 10**(-atten_db/20)
+
+def passband_ripple_to_dev (ripple_db):
+ """Convert passband ripple spec expressed in dB to an absolute value"""
+ return (10**(ripple_db/20)-1)/(10**(ripple_db/20)+1)
+
+# ----------------------------------------------------------------
+
+def remezord (fcuts, mags, devs, fsamp = 2):
+ '''
+ FIR order estimator (lowpass, highpass, bandpass, mulitiband).
+
+ (n, fo, ao, w) = remezord (f, a, dev)
+ (n, fo, ao, w) = remezord (f, a, dev, fs)
+
+ (n, fo, ao, w) = remezord (f, a, dev) finds the approximate order,
+ normalized frequency band edges, frequency band amplitudes, and
+ weights that meet input specifications f, a, and dev, to use with
+ the remez command.
+
+ * f is a sequence of frequency band edges (between 0 and Fs/2, where
+ Fs is the sampling frequency), and a is a sequence specifying the
+ desired amplitude on the bands defined by f. The length of f is
+ twice the length of a, minus 2. The desired function is
+ piecewise constant.
+
+ * dev is a sequence the same size as a that specifies the maximum
+ allowable deviation or ripples between the frequency response
+ and the desired amplitude of the output filter, for each band.
+
+ Use remez with the resulting order n, frequency sequence fo,
+ amplitude response sequence ao, and weights w to design the filter b
+ which approximately meets the specifications given by remezord
+ input parameters f, a, and dev:
+
+ b = remez (n, fo, ao, w)
+
+ (n, fo, ao, w) = remezord (f, a, dev, Fs) specifies a sampling frequency Fs.
+
+ Fs defaults to 2 Hz, implying a Nyquist frequency of 1 Hz. You can
+ therefore specify band edges scaled to a particular applications
+ sampling frequency.
+
+ In some cases remezord underestimates the order n. If the filter
+ does not meet the specifications, try a higher order such as n+1
+ or n+2.
+ '''
+ # get local copies
+ fcuts = fcuts[:]
+ mags = mags[:]
+ devs = devs[:]
+
+ for i in range (len (fcuts)):
+ fcuts[i] = float (fcuts[i]) / fsamp
+
+ nf = len (fcuts)
+ nm = len (mags)
+ nd = len (devs)
+ nbands = nm
+
+ if nm != nd:
+ raise ValueError, "Length of mags and devs must be equal"
+
+ if nf != 2 * (nbands - 1):
+ raise ValueError, "Length of f must be 2 * len (mags) - 2"
+
+ for i in range (len (mags)):
+ if mags[i] != 0: # if not stopband, get relative deviation
+ devs[i] = devs[i] / mags[i]
+
+ # separate the passband and stopband edges
+ f1 = fcuts[0::2]
+ f2 = fcuts[1::2]
+
+ n = 0
+ min_delta = 2
+ for i in range (len (f1)):
+ if f2[i] - f1[i] < min_delta:
+ n = i
+ min_delta = f2[i] - f1[i]
+
+ if nbands == 2:
+ # lowpass or highpass case (use formula)
+ l = lporder (f1[n], f2[n], devs[0], devs[1])
+ else:
+ # bandpass or multipass case
+ # try different lowpasses and take the worst one that
+ # goes through the BP specs
+ l = 0
+ for i in range (1, nbands-1):
+ l1 = lporder (f1[i-1], f2[i-1], devs[i], devs[i-1])
+ l2 = lporder (f1[i], f2[i], devs[i], devs[i+1])
+ l = max (l, l1, l2)
+
+ n = int (math.ceil (l)) - 1 # need order, not length for remez
+
+ # cook up remez compatible result
+ ff = [0] + fcuts + [1]
+ for i in range (1, len (ff) - 1):
+ ff[i] *= 2
+
+ aa = []
+ for a in mags:
+ aa = aa + [a, a]
+
+ max_dev = max (devs)
+ wts = [1] * len(devs)
+ for i in range (len (wts)):
+ wts[i] = max_dev / devs[i]
+
+ return (n, ff, aa, wts)
+
+# ----------------------------------------------------------------
+
+def lporder (freq1, freq2, delta_p, delta_s):
+ '''
+ FIR lowpass filter length estimator. freq1 and freq2 are
+ normalized to the sampling frequency. delta_p is the passband
+ deviation (ripple), delta_s is the stopband deviation (ripple).
+
+ Note, this works for high pass filters too (freq1 > freq2), but
+ doesnt work well if the transition is near f == 0 or f == fs/2
+
+ From Herrmann et al (1973), Practical design rules for optimum
+ finite impulse response filters. Bell System Technical J., 52, 769-99
+ '''
+ df = abs (freq2 - freq1)
+ ddp = math.log10 (delta_p)
+ dds = math.log10 (delta_s)
+
+ a1 = 5.309e-3
+ a2 = 7.114e-2
+ a3 = -4.761e-1
+ a4 = -2.66e-3
+ a5 = -5.941e-1
+ a6 = -4.278e-1
+
+ b1 = 11.01217
+ b2 = 0.5124401
+
+ t1 = a1 * ddp * ddp
+ t2 = a2 * ddp
+ t3 = a4 * ddp * ddp
+ t4 = a5 * ddp
+
+ dinf=((t1 + t2 + a3) * dds) + (t3 + t4 + a6)
+ ff = b1 + b2 * (ddp - dds)
+ n = dinf / df - ff * df + 1
+ return n
+
+
+def bporder (freq1, freq2, delta_p, delta_s):
+ '''
+ FIR bandpass filter length estimator. freq1 and freq2 are
+ normalized to the sampling frequency. delta_p is the passband
+ deviation (ripple), delta_s is the stopband deviation (ripple).
+
+ From Mintzer and Liu (1979)
+ '''
+ df = abs (freq2 - freq1)
+ ddp = math.log10 (delta_p)
+ dds = math.log10 (delta_s)
+
+ a1 = 0.01201
+ a2 = 0.09664
+ a3 = -0.51325
+ a4 = 0.00203
+ a5 = -0.57054
+ a6 = -0.44314
+
+ t1 = a1 * ddp * ddp
+ t2 = a2 * ddp
+ t3 = a4 * ddp * ddp
+ t4 = a5 * ddp
+
+ cinf = dds * (t1 + t2 + a3) + t3 + t4 + a6
+ ginf = -14.6 * math.log10 (delta_p / delta_s) - 16.9
+ n = cinf / df + ginf * df + 1
+ return n
+
diff --git a/gr-filter/python/pfb.py b/gr-filter/python/pfb.py
new file mode 100644
index 000000000..ddf289982
--- /dev/null
+++ b/gr-filter/python/pfb.py
@@ -0,0 +1,271 @@
+#!/usr/bin/env python
+#
+# Copyright 2009,2010,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr
+import filter_swig as filter
+import optfir
+
+class channelizer_ccf(gr.hier_block2):
+ '''
+ Make a Polyphase Filter channelizer (complex in, complex out, floating-point taps)
+
+ This simplifies the interface by allowing a single input stream to connect to this block.
+ It will then output a stream for each channel.
+ '''
+ def __init__(self, numchans, taps=None, oversample_rate=1, atten=100):
+ gr.hier_block2.__init__(self, "pfb_channelizer_ccf",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex),
+ gr.io_signature(numchans, numchans, gr.sizeof_gr_complex))
+
+ self._nchans = numchans
+ self._oversample_rate = oversample_rate
+
+ if taps is not None:
+ self._taps = taps
+ else:
+ # Create a filter that covers the full bandwidth of the input signal
+ bw = 0.4
+ tb = 0.2
+ ripple = 0.1
+ made = False
+ while not made:
+ try:
+ self._taps = optfir.low_pass(1, self._nchans, bw, bw+tb, ripple, atten)
+ made = True
+ except RuntimeError:
+ ripple += 0.01
+ made = False
+ print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple))
+
+ # Build in an exit strategy; if we've come this far, it ain't working.
+ if(ripple >= 1.0):
+ raise RuntimeError("optfir could not generate an appropriate filter.")
+
+ self.s2ss = gr.stream_to_streams(gr.sizeof_gr_complex, self._nchans)
+ self.pfb = filter.pfb_channelizer_ccf(self._nchans, self._taps,
+ self._oversample_rate)
+ self.connect(self, self.s2ss)
+
+ for i in xrange(self._nchans):
+ self.connect((self.s2ss,i), (self.pfb,i))
+ self.connect((self.pfb,i), (self,i))
+
+ def set_channel_map(self, newmap):
+ self.pfb.set_channel_map(newmap)
+
+
+
+class interpolator_ccf(gr.hier_block2):
+ '''
+ Make a Polyphase Filter interpolator (complex in, complex out, floating-point taps)
+
+ The block takes a single complex stream in and outputs a single complex
+ stream out. As such, it requires no extra glue to handle the input/output
+ streams. This block is provided to be consistent with the interface to the
+ other PFB block.
+ '''
+ def __init__(self, interp, taps=None, atten=100):
+ gr.hier_block2.__init__(self, "pfb_interpolator_ccf",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex),
+ gr.io_signature(1, 1, gr.sizeof_gr_complex))
+
+ self._interp = interp
+ self._taps = taps
+
+ if taps is not None:
+ self._taps = taps
+ else:
+ # Create a filter that covers the full bandwidth of the input signal
+ bw = 0.4
+ tb = 0.2
+ ripple = 0.99
+ made = False
+ while not made:
+ try:
+ self._taps = optfir.low_pass(self._interp, self._interp, bw, bw+tb, ripple, atten)
+ made = True
+ except RuntimeError:
+ ripple += 0.01
+ made = False
+ print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple))
+
+ # Build in an exit strategy; if we've come this far, it ain't working.
+ if(ripple >= 1.0):
+ raise RuntimeError("optfir could not generate an appropriate filter.")
+
+ self.pfb = filter.pfb_interpolator_ccf(self._interp, self._taps)
+
+ self.connect(self, self.pfb)
+ self.connect(self.pfb, self)
+
+
+class decimator_ccf(gr.hier_block2):
+ '''
+ Make a Polyphase Filter decimator (complex in, complex out, floating-point taps)
+
+ This simplifies the interface by allowing a single input stream to connect to this block.
+ It will then output a stream that is the decimated output stream.
+ '''
+ def __init__(self, decim, taps=None, channel=0, atten=100):
+ gr.hier_block2.__init__(self, "pfb_decimator_ccf",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex),
+ gr.io_signature(1, 1, gr.sizeof_gr_complex))
+
+ self._decim = decim
+ self._channel = channel
+
+ if taps is not None:
+ self._taps = taps
+ else:
+ # Create a filter that covers the full bandwidth of the input signal
+ bw = 0.4
+ tb = 0.2
+ ripple = 0.1
+ made = False
+ while not made:
+ try:
+ self._taps = optfir.low_pass(1, self._decim, bw, bw+tb, ripple, atten)
+ made = True
+ except RuntimeError:
+ ripple += 0.01
+ made = False
+ print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple))
+
+ # Build in an exit strategy; if we've come this far, it ain't working.
+ if(ripple >= 1.0):
+ raise RuntimeError("optfir could not generate an appropriate filter.")
+
+ self.s2ss = gr.stream_to_streams(gr.sizeof_gr_complex, self._decim)
+ self.pfb = filter.pfb_decimator_ccf(self._decim, self._taps, self._channel)
+
+ self.connect(self, self.s2ss)
+
+ for i in xrange(self._decim):
+ self.connect((self.s2ss,i), (self.pfb,i))
+
+ self.connect(self.pfb, self)
+
+
+class arb_resampler_ccf(gr.hier_block2):
+ '''
+ Convenience wrapper for the polyphase filterbank arbitrary resampler.
+
+ The block takes a single complex stream in and outputs a single complex
+ stream out. As such, it requires no extra glue to handle the input/output
+ streams. This block is provided to be consistent with the interface to the
+ other PFB block.
+ '''
+ def __init__(self, rate, taps=None, flt_size=32, atten=100):
+ gr.hier_block2.__init__(self, "pfb_arb_resampler_ccf",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
+
+ self._rate = rate
+ self._size = flt_size
+
+ if taps is not None:
+ self._taps = taps
+ else:
+ # Create a filter that covers the full bandwidth of the input signal
+ bw = 0.4
+ tb = 0.2
+ ripple = 0.1
+ #self._taps = filter.firdes.low_pass_2(self._size, self._size, bw, tb, atten)
+ made = False
+ while not made:
+ try:
+ self._taps = optfir.low_pass(self._size, self._size, bw, bw+tb, ripple, atten)
+ made = True
+ except RuntimeError:
+ ripple += 0.01
+ made = False
+ print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple))
+
+ # Build in an exit strategy; if we've come this far, it ain't working.
+ if(ripple >= 1.0):
+ raise RuntimeError("optfir could not generate an appropriate filter.")
+
+ self.pfb = filter.pfb_arb_resampler_ccf(self._rate, self._taps, self._size)
+ #print "PFB has %d taps\n" % (len(self._taps),)
+
+ self.connect(self, self.pfb)
+ self.connect(self.pfb, self)
+
+ # Note -- set_taps not implemented in base class yet
+ def set_taps(self, taps):
+ self.pfb.set_taps(taps)
+
+ def set_rate(self, rate):
+ self.pfb.set_rate(rate)
+
+
+class arb_resampler_fff(gr.hier_block2):
+ '''
+ Convenience wrapper for the polyphase filterbank arbitrary resampler.
+
+ The block takes a single float stream in and outputs a single float
+ stream out. As such, it requires no extra glue to handle the input/output
+ streams. This block is provided to be consistent with the interface to the
+ other PFB block.
+ '''
+ def __init__(self, rate, taps=None, flt_size=32, atten=100):
+ gr.hier_block2.__init__(self, "pfb_arb_resampler_fff",
+ gr.io_signature(1, 1, gr.sizeof_float), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_float)) # Output signature
+
+ self._rate = rate
+ self._size = flt_size
+
+ if taps is not None:
+ self._taps = taps
+ else:
+ # Create a filter that covers the full bandwidth of the input signal
+ bw = 0.4
+ tb = 0.2
+ ripple = 0.1
+ #self._taps = filter.firdes.low_pass_2(self._size, self._size, bw, tb, atten)
+ made = False
+ while not made:
+ try:
+ self._taps = optfir.low_pass(self._size, self._size, bw, bw+tb, ripple, atten)
+ made = True
+ except RuntimeError:
+ ripple += 0.01
+ made = False
+ print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple))
+
+ # Build in an exit strategy; if we've come this far, it ain't working.
+ if(ripple >= 1.0):
+ raise RuntimeError("optfir could not generate an appropriate filter.")
+
+ self.pfb = filter.pfb_arb_resampler_fff(self._rate, self._taps, self._size)
+ #print "PFB has %d taps\n" % (len(self._taps),)
+
+ self.connect(self, self.pfb)
+ self.connect(self.pfb, self)
+
+ # Note -- set_taps not implemented in base class yet
+ def set_taps(self, taps):
+ self.pfb.set_taps(taps)
+
+ def set_rate(self, rate):
+ self.pfb.set_rate(rate)
diff --git a/gr-filter/python/qa_adaptive_fir_filter.py b/gr-filter/python/qa_adaptive_fir_filter.py
new file mode 100755
index 000000000..cadce5204
--- /dev/null
+++ b/gr-filter/python/qa_adaptive_fir_filter.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python
+#
+# Copyright 2008,2010,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+
+class test_adaptive_filter(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block ()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_adaptive_fir_filter_ccf_001(self):
+ src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j]
+ expected_data = ((0.5+0.5j), (1.5+1.5j), (3+3j), (5+5j), (5.5+5.5j),
+ (6.5+6.5j), (8+8j), (10+10j), (10.5+10.5j), (11.5+11.5j),
+ (13+13j), (15+15j), (15.5+15.5j), (16.5+16.5j), (18+18j),
+ (20+20j), (20.5+20.5j), (21.5+21.5j), (23+23j), (25+25j),
+ (25.5+25.5j), (26.5+26.5j), (28+28j), (30+30j), (30.5+30.5j),
+ (31.5+31.5j), (33+33j), (35+35j), (35.5+35.5j), (36.5+36.5j),
+ (38+38j), (40+40j), (40.5+40.5j), (41.5+41.5j), (43+43j),
+ (45+45j), (45.5+45.5j), (46.5+46.5j), (48+48j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j))
+
+ src = gr.vector_source_c(src_data)
+ op = filter.adaptive_fir_ccf("test", 1, 20*[0.5, 0.5])
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
+ def test_adaptive_fir_filter_ccf_002(self):
+ src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j]
+ expected_data = ((0.5+0.5j), (5.5+5.5j), (10.5+10.5j), (15.5+15.5j),
+ (20.5+20.5j), (25.5+25.5j), (30.5+30.5j), (35.5+35.5j),
+ (40.5+40.5j), (45.5+45.5j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j))
+
+ src = gr.vector_source_c(src_data)
+ op = filter.adaptive_fir_ccf("test", 4, 20*[0.5, 0.5])
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
+ def test_adaptive_fir_filter_ccc_001(self):
+ src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j]
+ expected_data = ((-0.5+1.5j), (-1.5+4.5j), (-3+9j), (-5+15j),
+ (-5.5+16.5j), (-6.5+19.5j), (-8+24j), (-10+30j),
+ (-10.5+31.5j), (-11.5+34.5j), (-13+39j), (-15+45j),
+ (-15.5+46.5j), (-16.5+49.5j), (-18+54j), (-20+60j),
+ (-20.5+61.5j), (-21.5+64.5j), (-23+69j), (-25+75j),
+ (-25.5+76.5j), (-26.5+79.5j), (-28+84j), (-30+90j),
+ (-30.5+91.5j), (-31.5+94.5j), (-33+99j), (-35+105j),
+ (-35.5+106.5j), (-36.5+109.5j), (-38+114j), (-40+120j),
+ (-40.5+121.5j), (-41.5+124.5j), (-43+129j), (-45+135j),
+ (-45.5+136.5j), (-46.5+139.5j), (-48+144j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j))
+ src = gr.vector_source_c(src_data)
+ op = filter.adaptive_fir_ccc("test", 1, 20*[0.5+1j, 0.5+1j])
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
+
+ def test_adaptive_fir_filter_ccc_002(self):
+ src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j]
+ expected_data = ((-0.5+1.5j), (-5.5+16.5j), (-10.5+31.5j),
+ (-15.5+46.5j), (-20.5+61.5j), (-25.5+76.5j),
+ (-30.5+91.5j), (-35.5+106.5j), (-40.5+121.5j),
+ (-45.5+136.5j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j))
+ src = gr.vector_source_c(src_data)
+ op = filter.adaptive_fir_ccc("test", 4, 20*[0.5+1j, 0.5+1j])
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_adaptive_filter, "test_adaptive_filter.xml")
+
diff --git a/gr-filter/python/qa_channel_model.py b/gr-filter/python/qa_channel_model.py
new file mode 100755
index 000000000..7f1c61b4e
--- /dev/null
+++ b/gr-filter/python/qa_channel_model.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+import math
+
+class test_channel_model(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_000(self):
+ N = 1000 # number of samples to use
+ fs = 1000 # baseband sampling rate
+ freq = 100
+
+ signal = gr.sig_source_c(fs, gr.GR_SIN_WAVE, freq, 1)
+ head = gr.head(gr.sizeof_gr_complex, N)
+ op = filter.channel_model(0.0, 0.0, 1.0, [1,], 0)
+ snk = gr.vector_sink_c()
+ snk1 = gr.vector_sink_c()
+
+ op.set_noise_voltage(0.0)
+ op.set_frequency_offset(0.0)
+ op.set_taps([1,])
+ op.set_timing_offset(1.0)
+
+ self.tb.connect(signal, head, op, snk)
+ self.tb.connect(op, snk1)
+ self.tb.run()
+
+ dst_data = snk.data()
+ exp_data = snk1.data()
+ self.assertComplexTuplesAlmostEqual(exp_data, dst_data, 5)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_channel_model, "test_channel_model.xml")
diff --git a/gr-filter/python/qa_dc_blocker.py b/gr-filter/python/qa_dc_blocker.py
new file mode 100755
index 000000000..b9df06b45
--- /dev/null
+++ b/gr-filter/python/qa_dc_blocker.py
@@ -0,0 +1,109 @@
+#!/usr/bin/env python
+#
+# Copyright 2011,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+
+class test_dc_blocker(gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001(self):
+ ''' Test impulse response - long form, cc '''
+ src_data = [1,] + 100*[0,]
+ expected_result = ((-0.02072429656982422+0j), (-0.02081298828125+0j),
+ (0.979156494140625+0j), (-0.02081298828125+0j),
+ (-0.02072429656982422+0j))
+
+ src = gr.vector_source_c(src_data)
+ op = filter.dc_blocker_cc(32, True)
+ dst = gr.vector_sink_c()
+
+ self.tb.connect (src, op, dst)
+ self.tb.run()
+
+ # only test samples around 2D-2
+ result_data = dst.data()[60:65]
+ self.assertComplexTuplesAlmostEqual (expected_result, result_data)
+
+ def test_002(self):
+ ''' Test impulse response - short form, cc '''
+ src_data = [1,] + 100*[0,]
+ expected_result = ((-0.029296875+0j), (-0.0302734375+0j),
+ (0.96875+0j), (-0.0302734375+0j),
+ (-0.029296875+0j))
+
+ src = gr.vector_source_c(src_data)
+ op = filter.dc_blocker_cc(32, False)
+ dst = gr.vector_sink_c()
+
+ self.tb.connect (src, op, dst)
+ self.tb.run()
+
+ # only test samples around D-1
+ result_data = dst.data()[29:34]
+ self.assertComplexTuplesAlmostEqual (expected_result, result_data)
+
+
+ def test_003(self):
+ ''' Test impulse response - long form, ff '''
+ src_data = [1,] + 100*[0,]
+ expected_result = ((-0.02072429656982422), (-0.02081298828125),
+ (0.979156494140625), (-0.02081298828125),
+ (-0.02072429656982422))
+
+ src = gr.vector_source_f(src_data)
+ op = filter.dc_blocker_ff(32, True)
+ dst = gr.vector_sink_f()
+
+ self.tb.connect (src, op, dst)
+ self.tb.run()
+
+ # only test samples around 2D-2
+ result_data = dst.data()[60:65]
+ self.assertFloatTuplesAlmostEqual (expected_result, result_data)
+
+ def test_004(self):
+ ''' Test impulse response - short form, ff '''
+ src_data = [1,] + 100*[0,]
+ expected_result = ((-0.029296875), (-0.0302734375),
+ (0.96875), (-0.0302734375),
+ (-0.029296875))
+
+ src = gr.vector_source_f(src_data)
+ op = filter.dc_blocker_ff(32, False)
+ dst = gr.vector_sink_f()
+
+ self.tb.connect (src, op, dst)
+ self.tb.run()
+
+ # only test samples around D-1
+ result_data = dst.data()[29:34]
+ self.assertFloatTuplesAlmostEqual (expected_result, result_data)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_dc_blocker, "test_dc_blocker.xml")
+
diff --git a/gr-filter/python/qa_fft_filter.py b/gr-filter/python/qa_fft_filter.py
new file mode 100755
index 000000000..cb5416373
--- /dev/null
+++ b/gr-filter/python/qa_fft_filter.py
@@ -0,0 +1,380 @@
+#!/usr/bin/env python
+#
+# Copyright 2004,2005,2007,2010,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+import sys
+import random
+
+def make_random_complex_tuple(L):
+ result = []
+ for x in range(L):
+ result.append(complex(2*random.random()-1,
+ 2*random.random()-1))
+ return tuple(result)
+
+def make_random_float_tuple(L):
+ result = []
+ for x in range(L):
+ result.append(float(int(2*random.random()-1)))
+ return tuple(result)
+
+
+def reference_filter_ccc(dec, taps, input):
+ """
+ compute result using conventional fir filter
+ """
+ tb = gr.top_block()
+ #src = gr.vector_source_c(((0,) * (len(taps) - 1)) + input)
+ src = gr.vector_source_c(input)
+ op = filter.fir_filter_ccc(dec, taps)
+ dst = gr.vector_sink_c()
+ tb.connect(src, op, dst)
+ tb.run()
+ return dst.data()
+
+def reference_filter_fff(dec, taps, input):
+ """
+ compute result using conventional fir filter
+ """
+ tb = gr.top_block()
+ #src = gr.vector_source_f(((0,) * (len(taps) - 1)) + input)
+ src = gr.vector_source_f(input)
+ op = filter.fir_filter_fff(dec, taps)
+ dst = gr.vector_sink_f()
+ tb.connect(src, op, dst)
+ tb.run()
+ return dst.data()
+
+
+def print_complex(x):
+ for i in x:
+ i = complex(i)
+ sys.stdout.write("(%6.3f,%6.3fj), " % (i.real, i.imag))
+ sys.stdout.write('\n')
+
+
+class test_fft_filter(gr_unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def assert_fft_ok2(self, expected_result, result_data):
+ expected_result = expected_result[:len(result_data)]
+ self.assertComplexTuplesAlmostEqual2 (expected_result, result_data,
+ abs_eps=1e-9, rel_eps=4e-4)
+
+ def assert_fft_float_ok2(self, expected_result, result_data, abs_eps=1e-9, rel_eps=4e-4):
+ expected_result = expected_result[:len(result_data)]
+ self.assertFloatTuplesAlmostEqual2 (expected_result, result_data,
+ abs_eps, rel_eps)
+
+ def test_ccc_001(self):
+ tb = gr.top_block()
+ src_data = (0,1,2,3,4,5,6,7)
+ taps = (1,)
+ expected_result = tuple([complex(x) for x in (0,1,2,3,4,5,6,7)])
+ src = gr.vector_source_c(src_data)
+ op = filter.fft_filter_ccc(1, taps)
+ dst = gr.vector_sink_c()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+ #print 'expected:', expected_result
+ #print 'results: ', result_data
+ self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5)
+
+
+ def test_ccc_002(self):
+ # Test nthreads
+ tb = gr.top_block()
+ src_data = (0,1,2,3,4,5,6,7)
+ taps = (2,)
+ nthreads = 2
+ expected_result = tuple([2 * complex(x) for x in (0,1,2,3,4,5,6,7)])
+ src = gr.vector_source_c(src_data)
+ op = filter.fft_filter_ccc(1, taps, nthreads)
+ dst = gr.vector_sink_c()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+ #print 'expected:', expected_result
+ #print 'results: ', result_data
+ self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5)
+
+ def test_ccc_003(self):
+ tb = gr.top_block()
+ src_data = (0,1,2,3,4,5,6,7)
+ taps = (2,)
+ expected_result = tuple([2 * complex(x) for x in (0,1,2,3,4,5,6,7)])
+ src = gr.vector_source_c(src_data)
+ op = filter.fft_filter_ccc(1, taps)
+ dst = gr.vector_sink_c()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+ #print 'expected:', expected_result
+ #print 'results: ', result_data
+ self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5)
+
+
+ def test_ccc_004(self):
+ random.seed(0)
+ for i in xrange(25):
+ # sys.stderr.write("\n>>> Loop = %d\n" % (i,))
+ src_len = 4*1024
+ src_data = make_random_complex_tuple(src_len)
+ ntaps = int(random.uniform(2, 1000))
+ taps = make_random_complex_tuple(ntaps)
+ expected_result = reference_filter_ccc(1, taps, src_data)
+
+ src = gr.vector_source_c(src_data)
+ op = filter.fft_filter_ccc(1, taps)
+ dst = gr.vector_sink_c()
+ tb = gr.top_block()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+ del tb
+ self.assert_fft_ok2(expected_result, result_data)
+
+ def test_ccc_005(self):
+ random.seed(0)
+ for i in xrange(25):
+ # sys.stderr.write("\n>>> Loop = %d\n" % (i,))
+ dec = i + 1
+ src_len = 4*1024
+ src_data = make_random_complex_tuple(src_len)
+ ntaps = int(random.uniform(2, 100))
+ taps = make_random_complex_tuple(ntaps)
+ expected_result = reference_filter_ccc(dec, taps, src_data)
+
+ src = gr.vector_source_c(src_data)
+ op = filter.fft_filter_ccc(dec, taps)
+ dst = gr.vector_sink_c()
+ tb = gr.top_block()
+ tb.connect(src, op, dst)
+ tb.run()
+ del tb
+ result_data = dst.data()
+
+ self.assert_fft_ok2(expected_result, result_data)
+
+ def test_ccc_006(self):
+ # Test decimating with nthreads=2
+ random.seed(0)
+ nthreads = 2
+ for i in xrange(25):
+ # sys.stderr.write("\n>>> Loop = %d\n" % (i,))
+ dec = i + 1
+ src_len = 4*1024
+ src_data = make_random_complex_tuple(src_len)
+ ntaps = int(random.uniform(2, 100))
+ taps = make_random_complex_tuple(ntaps)
+ expected_result = reference_filter_ccc(dec, taps, src_data)
+
+ src = gr.vector_source_c(src_data)
+ op = filter.fft_filter_ccc(dec, taps, nthreads)
+ dst = gr.vector_sink_c()
+ tb = gr.top_block()
+ tb.connect(src, op, dst)
+ tb.run()
+ del tb
+ result_data = dst.data()
+
+ self.assert_fft_ok2(expected_result, result_data)
+
+ # ----------------------------------------------------------------
+ # test _fff version
+ # ----------------------------------------------------------------
+
+ def test_fff_001(self):
+ tb = gr.top_block()
+ src_data = (0,1,2,3,4,5,6,7)
+ taps = (1,)
+ expected_result = tuple([float(x) for x in (0,1,2,3,4,5,6,7)])
+ src = gr.vector_source_f(src_data)
+ op = filter.fft_filter_fff(1, taps)
+ dst = gr.vector_sink_f()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+ #print 'expected:', expected_result
+ #print 'results: ', result_data
+ self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5)
+
+
+ def test_fff_002(self):
+ tb = gr.top_block()
+ src_data = (0,1,2,3,4,5,6,7)
+ taps = (2,)
+ expected_result = tuple([2 * float(x) for x in (0,1,2,3,4,5,6,7)])
+ src = gr.vector_source_f(src_data)
+ op = filter.fft_filter_fff(1, taps)
+ dst = gr.vector_sink_f()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+ #print 'expected:', expected_result
+ #print 'results: ', result_data
+ self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5)
+
+ def test_fff_003(self):
+ # Test 02 with nthreads
+ tb = gr.top_block()
+ src_data = (0,1,2,3,4,5,6,7)
+ taps = (2,)
+ nthreads = 2
+ expected_result = tuple([2 * float(x) for x in (0,1,2,3,4,5,6,7)])
+ src = gr.vector_source_f(src_data)
+ op = filter.fft_filter_fff(1, taps, nthreads)
+ dst = gr.vector_sink_f()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5)
+
+ def xtest_fff_004(self):
+ random.seed(0)
+ for i in xrange(25):
+ sys.stderr.write("\n>>> Loop = %d\n" % (i,))
+ src_len = 4096
+ src_data = make_random_float_tuple(src_len)
+ ntaps = int(random.uniform(2, 1000))
+ taps = make_random_float_tuple(ntaps)
+ expected_result = reference_filter_fff(1, taps, src_data)
+
+ src = gr.vector_source_f(src_data)
+ op = filter.fft_filter_fff(1, taps)
+ dst = gr.vector_sink_f()
+ tb = gr.top_block()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+
+ #print "src_len =", src_len, " ntaps =", ntaps
+ try:
+ self.assert_fft_float_ok2(expected_result, result_data, abs_eps=1.0)
+ except:
+ expected = open('expected', 'w')
+ for x in expected_result:
+ expected.write(`x` + '\n')
+ actual = open('actual', 'w')
+ for x in result_data:
+ actual.write(`x` + '\n')
+ raise
+
+ def xtest_fff_005(self):
+ random.seed(0)
+ for i in xrange(25):
+ sys.stderr.write("\n>>> Loop = %d\n" % (i,))
+ src_len = 4*1024
+ src_data = make_random_float_tuple(src_len)
+ ntaps = int(random.uniform(2, 1000))
+ taps = make_random_float_tuple(ntaps)
+ expected_result = reference_filter_fff(1, taps, src_data)
+
+ src = gr.vector_source_f(src_data)
+ op = filter.fft_filter_fff(1, taps)
+ dst = gr.vector_sink_f()
+ tb = gr.top_block()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+
+ self.assert_fft_float_ok2(expected_result, result_data, abs_eps=2.0)
+
+ def xtest_fff_006(self):
+ random.seed(0)
+ for i in xrange(25):
+ sys.stderr.write("\n>>> Loop = %d\n" % (i,))
+ dec = i + 1
+ src_len = 4*1024
+ src_data = make_random_float_tuple(src_len)
+ ntaps = int(random.uniform(2, 100))
+ taps = make_random_float_tuple(ntaps)
+ expected_result = reference_filter_fff(dec, taps, src_data)
+
+ src = gr.vector_source_f(src_data)
+ op = filter.fft_filter_fff(dec, taps)
+ dst = gr.vector_sink_f()
+ tb = gr.top_block()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+
+ self.assert_fft_float_ok2(expected_result, result_data)
+
+ def xtest_fff_007(self):
+ # test decimation with nthreads
+ random.seed(0)
+ nthreads = 2
+ for i in xrange(25):
+ sys.stderr.write("\n>>> Loop = %d\n" % (i,))
+ dec = i + 1
+ src_len = 4*1024
+ src_data = make_random_float_tuple(src_len)
+ ntaps = int(random.uniform(2, 100))
+ taps = make_random_float_tuple(ntaps)
+ expected_result = reference_filter_fff(dec, taps, src_data)
+
+ src = gr.vector_source_f(src_data)
+ op = filter.fft_filter_fff(dec, taps, nthreads)
+ dst = gr.vector_sink_f()
+ tb = gr.top_block()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+
+ self.assert_fft_float_ok2(expected_result, result_data)
+
+ def test_fff_get0(self):
+ random.seed(0)
+ for i in xrange(25):
+ ntaps = int(random.uniform(2, 100))
+ taps = make_random_float_tuple(ntaps)
+
+ op = filter.fft_filter_fff(1, taps)
+ result_data = op.taps()
+ #print result_data
+
+ self.assertEqual(taps, result_data)
+
+ def test_ccc_get0(self):
+ random.seed(0)
+ for i in xrange(25):
+ ntaps = int(random.uniform(2, 100))
+ taps = make_random_complex_tuple(ntaps)
+
+ op = filter.fft_filter_ccc(1, taps)
+ result_data = op.taps()
+ #print result_data
+
+ self.assertComplexTuplesAlmostEqual(taps, result_data, 4)
+
+
+if __name__ == '__main__':
+ gr_unittest.run(test_fft_filter, "test_fft_filter.xml")
+
diff --git a/gr-filter/python/qa_filter_delay_fc.py b/gr-filter/python/qa_filter_delay_fc.py
new file mode 100755
index 000000000..57b063e7b
--- /dev/null
+++ b/gr-filter/python/qa_filter_delay_fc.py
@@ -0,0 +1,318 @@
+#!/usr/bin/env python
+#
+# Copyright 2004,2007,2010,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+import math
+
+class test_filter_delay_fc(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_001_filter_delay_one_input(self):
+
+ # expected result
+ expected_result = ( -1.4678005338941702e-11j,
+ -0.0011950774351134896j,
+ -0.0019336787518113852j,
+ -0.0034673355985432863j,
+ -0.0036765895783901215j,
+ -0.004916108213365078j,
+ -0.0042778430506587029j,
+ -0.006028641015291214j,
+ -0.005476709920912981j,
+ -0.0092810001224279404j,
+ -0.0095402700826525688j,
+ -0.016060983762145042j,
+ -0.016446959227323532j,
+ -0.02523401565849781j,
+ -0.024382550269365311j,
+ -0.035477779805660248j,
+ -0.033021725714206696j,
+ -0.048487484455108643j,
+ -0.04543270543217659j,
+ -0.069477587938308716j,
+ -0.066984444856643677j,
+ -0.10703597217798233j,
+ -0.10620346665382385j,
+ -0.1852707713842392j,
+ -0.19357112050056458j,
+ (7.2191945754696007e-09 -0.50004088878631592j),
+ (0.58778399229049683 -0.6155126690864563j),
+ (0.95105588436126709 -0.12377222627401352j),
+ (0.95105588436126709 +0.41524654626846313j),
+ (0.5877838134765625 +0.91611981391906738j),
+ (5.8516356205018383e-09 +1.0670661926269531j),
+ (-0.5877840518951416 +0.87856143712997437j),
+ (-0.95105588436126709 +0.35447561740875244j),
+ (-0.95105588436126709 -0.26055556535720825j),
+ (-0.5877838134765625 -0.77606213092803955j),
+ (-8.7774534307527574e-09 -0.96460390090942383j),
+ (0.58778399229049683 -0.78470128774642944j),
+ (0.95105588436126709 -0.28380891680717468j),
+ (0.95105588436126709 +0.32548999786376953j),
+ (0.5877838134765625 +0.82514488697052002j),
+ (1.4629089051254596e-08 +1.0096219778060913j),
+ (-0.5877840518951416 +0.81836479902267456j),
+ (-0.95105588436126709 +0.31451958417892456j),
+ (-0.95105588436126709 -0.3030143678188324j),
+ (-0.5877838134765625 -0.80480599403381348j),
+ (-1.7554906861505515e-08 -0.99516552686691284j),
+ (0.58778399229049683 -0.80540722608566284j),
+ (0.95105582475662231 -0.30557557940483093j),
+ (0.95105588436126709 +0.31097668409347534j),
+ (0.5877838134765625 +0.81027895212173462j),
+ (2.3406542482007353e-08 +1.0000816583633423j),
+ (-0.5877840518951416 +0.80908381938934326j),
+ (-0.95105588436126709 +0.30904293060302734j),
+ (-0.95105588436126709 -0.30904296040534973j),
+ (-0.5877838134765625 -0.80908387899398804j),
+ (-2.6332360292258272e-08 -1.0000815391540527j),
+ (0.58778399229049683 -0.80908381938934326j),
+ (0.95105582475662231 -0.30904299020767212j),
+ (0.95105588436126709 +0.30904293060302734j),
+ (0.5877838134765625 +0.80908381938934326j),
+ (3.218399768911695e-08 +1.0000815391540527j))
+
+ tb = self.tb
+
+ sampling_freq = 100
+
+ ntaps = 51
+ src1 = gr.sig_source_f(sampling_freq, gr.GR_SIN_WAVE,
+ sampling_freq * 0.10, 1.0)
+ head = gr.head(gr.sizeof_float, int(ntaps + sampling_freq * 0.10))
+ dst2 = gr.vector_sink_c()
+
+ # calculate taps
+ taps = filter.firdes_hilbert(ntaps)
+ hd = filter.filter_delay_fc(taps)
+
+ tb.connect(src1, head)
+ tb.connect(head, hd)
+ tb.connect(hd,dst2)
+
+ tb.run()
+
+ # get output
+ result_data = dst2.data()
+ self.assertComplexTuplesAlmostEqual(expected_result, result_data, 5)
+
+ def test_002_filter_delay_two_inputs(self):
+
+ # giving the same signal to both the inputs should fetch the same results
+ # as above
+
+ # expected result
+ expected_result = ( -1.4678005338941702e-11j,
+ -0.0011950774351134896j,
+ -0.0019336787518113852j,
+ -0.0034673355985432863j,
+ -0.0036765895783901215j,
+ -0.004916108213365078j,
+ -0.0042778430506587029j,
+ -0.006028641015291214j,
+ -0.005476709920912981j,
+ -0.0092810001224279404j,
+ -0.0095402700826525688j,
+ -0.016060983762145042j,
+ -0.016446959227323532j,
+ -0.02523401565849781j,
+ -0.024382550269365311j,
+ -0.035477779805660248j,
+ -0.033021725714206696j,
+ -0.048487484455108643j,
+ -0.04543270543217659j,
+ -0.069477587938308716j,
+ -0.066984444856643677j,
+ -0.10703597217798233j,
+ -0.10620346665382385j,
+ -0.1852707713842392j,
+ -0.19357112050056458j,
+ (7.2191945754696007e-09 -0.50004088878631592j),
+ (0.58778399229049683 -0.6155126690864563j),
+ (0.95105588436126709 -0.12377222627401352j),
+ (0.95105588436126709 +0.41524654626846313j),
+ (0.5877838134765625 +0.91611981391906738j),
+ (5.8516356205018383e-09 +1.0670661926269531j),
+ (-0.5877840518951416 +0.87856143712997437j),
+ (-0.95105588436126709 +0.35447561740875244j),
+ (-0.95105588436126709 -0.26055556535720825j),
+ (-0.5877838134765625 -0.77606213092803955j),
+ (-8.7774534307527574e-09 -0.96460390090942383j),
+ (0.58778399229049683 -0.78470128774642944j),
+ (0.95105588436126709 -0.28380891680717468j),
+ (0.95105588436126709 +0.32548999786376953j),
+ (0.5877838134765625 +0.82514488697052002j),
+ (1.4629089051254596e-08 +1.0096219778060913j),
+ (-0.5877840518951416 +0.81836479902267456j),
+ (-0.95105588436126709 +0.31451958417892456j),
+ (-0.95105588436126709 -0.3030143678188324j),
+ (-0.5877838134765625 -0.80480599403381348j),
+ (-1.7554906861505515e-08 -0.99516552686691284j),
+ (0.58778399229049683 -0.80540722608566284j),
+ (0.95105582475662231 -0.30557557940483093j),
+ (0.95105588436126709 +0.31097668409347534j),
+ (0.5877838134765625 +0.81027895212173462j),
+ (2.3406542482007353e-08 +1.0000816583633423j),
+ (-0.5877840518951416 +0.80908381938934326j),
+ (-0.95105588436126709 +0.30904293060302734j),
+ (-0.95105588436126709 -0.30904296040534973j),
+ (-0.5877838134765625 -0.80908387899398804j),
+ (-2.6332360292258272e-08 -1.0000815391540527j),
+ (0.58778399229049683 -0.80908381938934326j),
+ (0.95105582475662231 -0.30904299020767212j),
+ (0.95105588436126709 +0.30904293060302734j),
+ (0.5877838134765625 +0.80908381938934326j),
+ (3.218399768911695e-08 +1.0000815391540527j))
+
+
+ tb = self.tb
+
+ sampling_freq = 100
+ ntaps = 51
+ src1 = gr.sig_source_f(sampling_freq, gr.GR_SIN_WAVE,
+ sampling_freq * 0.10, 1.0)
+ head = gr.head(gr.sizeof_float, int(ntaps + sampling_freq * 0.10))
+ dst2 = gr.vector_sink_c()
+
+
+ # calculate taps
+ taps = filter.firdes_hilbert(ntaps)
+ hd = filter.filter_delay_fc(taps)
+
+ tb.connect(src1, head)
+ tb.connect(head, (hd,0))
+ tb.connect(head, (hd,1))
+ tb.connect(hd,dst2)
+ tb.run()
+
+ # get output
+ result_data = dst2.data()
+
+ self.assertComplexTuplesAlmostEqual(expected_result, result_data, 5)
+
+
+ def test_003_filter_delay_two_inputs(self):
+
+ # give two different inputs
+
+ # expected result
+ expected_result = ( -0.0020331963896751404j,
+ -0.0016448829555884004j,
+ -0.0032375147566199303j,
+ -0.0014826074475422502j,
+ -0.0033034090884029865j,
+ -0.00051144487224519253j,
+ -0.0043686260469257832j,
+ -0.0010198024101555347j,
+ -0.0082517862319946289j,
+ -0.003456643782556057j,
+ -0.014193611219525337j,
+ -0.005875137634575367j,
+ -0.020293503999710083j,
+ -0.0067503536120057106j,
+ -0.026798896491527557j,
+ -0.0073488112539052963j,
+ -0.037041611969470978j,
+ -0.010557252913713455j,
+ -0.055669989436864853j,
+ -0.018332764506340027j,
+ -0.089904911816120148j,
+ -0.033361352980136871j,
+ -0.16902604699134827j,
+ -0.074318811297416687j,
+ -0.58429563045501709j,
+ (7.2191945754696007e-09 -0.35892376303672791j),
+ (0.58778399229049683 +0.63660913705825806j),
+ (0.95105588436126709 +0.87681591510772705j),
+ (0.95105588436126709 +0.98705857992172241j),
+ (0.5877838134765625 +0.55447429418563843j),
+ (5.8516356205018383e-09 +0.026006083935499191j),
+ (-0.5877840518951416 -0.60616838932037354j),
+ (-0.95105588436126709 -0.9311758279800415j),
+ (-0.95105588436126709 -0.96169203519821167j),
+ (-0.5877838134765625 -0.57292771339416504j),
+ (-8.7774534307527574e-09 -0.0073488391935825348j),
+ (0.58778399229049683 +0.59720659255981445j),
+ (0.95105588436126709 +0.94438445568084717j),
+ (0.95105588436126709 +0.95582199096679688j),
+ (0.5877838134765625 +0.58196049928665161j),
+ (1.4629089051254596e-08 +0.0026587247848510742j),
+ (-0.5877840518951416 -0.59129220247268677j),
+ (-0.95105588436126709 -0.94841635227203369j),
+ (-0.95105588436126709 -0.95215457677841187j),
+ (-0.5877838134765625 -0.58535969257354736j),
+ (-1.7554906861505515e-08 -0.00051158666610717773j),
+ (0.58778399229049683 +0.58867418766021729j),
+ (0.95105582475662231 +0.94965213537216187j),
+ (0.95105588436126709 +0.95050644874572754j),
+ (0.5877838134765625 +0.58619076013565063j),
+ (2.3406542482007353e-08 +1.1920928955078125e-07j),
+ (-0.5877840518951416 -0.58783555030822754j),
+ (-0.95105588436126709 -0.95113480091094971j),
+ (-0.95105588436126709 -0.95113474130630493j),
+ (-0.5877838134765625 -0.58783555030822754j),
+ (-2.6332360292258272e-08 -8.1956386566162109e-08j),
+ (0.58778399229049683 +0.58783555030822754j),
+ (0.95105582475662231 +0.95113474130630493j),
+ (0.95105588436126709 +0.95113474130630493j),
+ (0.5877838134765625 +0.58783560991287231j),
+ (3.218399768911695e-08 +1.1920928955078125e-07j))
+
+ tb = self.tb
+
+ sampling_freq = 100
+ ntaps = 51
+
+ src1 = gr.sig_source_f(sampling_freq, gr.GR_SIN_WAVE,sampling_freq * 0.10, 1.0)
+ src2 = gr.sig_source_f(sampling_freq, gr.GR_COS_WAVE,sampling_freq * 0.10, 1.0)
+
+ head1 = gr.head(gr.sizeof_float, int(ntaps + sampling_freq * 0.10))
+ head2 = gr.head(gr.sizeof_float, int(ntaps + sampling_freq * 0.10))
+
+ taps = filter.firdes_hilbert(ntaps)
+ hd = filter.filter_delay_fc(taps)
+
+ dst2 = gr.vector_sink_c()
+
+ tb.connect(src1, head1)
+ tb.connect(src2, head2)
+
+ tb.connect(head1, (hd,0))
+ tb.connect(head2, (hd,1))
+ tb.connect(hd, dst2)
+
+ tb.run()
+
+ # get output
+ result_data = dst2.data()
+
+ self.assertComplexTuplesAlmostEqual(expected_result, result_data, 5)
+
+
+if __name__ == '__main__':
+ gr_unittest.run(test_filter_delay_fc, "test_filter_delay_fc.xml")
diff --git a/gr-filter/python/qa_fir_filter.py b/gr-filter/python/qa_fir_filter.py
new file mode 100755
index 000000000..2a61498a2
--- /dev/null
+++ b/gr-filter/python/qa_fir_filter.py
@@ -0,0 +1,318 @@
+#!/usr/bin/env python
+#
+# Copyright 2008,2010,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+
+class test_filter(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block ()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_fir_filter_fff_001(self):
+ src_data = 40*[1, 2, 3, 4]
+ expected_data = (0.5, 1.5, 3.0, 5.0, 5.5, 6.5, 8.0, 10.0,
+ 10.5, 11.5, 13.0, 15.0, 15.5, 16.5, 18.0,
+ 20.0, 20.5, 21.5, 23.0, 25.0, 25.5, 26.5,
+ 28.0, 30.0, 30.5, 31.5, 33.0, 35.0, 35.5,
+ 36.5, 38.0, 40.0, 40.5, 41.5, 43.0, 45.0,
+ 45.5, 46.5, 48.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0)
+ src = gr.vector_source_f(src_data)
+ op = filter.fir_filter_fff(1, 20*[0.5, 0.5])
+ dst = gr.vector_sink_f()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual(expected_data, result_data, 5)
+
+ def test_fir_filter_fff_002(self):
+ src_data = 40*[1, 2, 3, 4]
+ expected_data = (0.5, 5.5, 10.5, 15.5, 20.5, 25.5, 30.5, 35.5,
+ 40.5, 45.5, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0,
+ 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0)
+ src = gr.vector_source_f(src_data)
+ op = filter.fir_filter_fff(4, 20*[0.5, 0.5])
+ dst = gr.vector_sink_f()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual(expected_data, result_data, 5)
+
+ def test_fir_filter_ccf_001(self):
+ src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j]
+ expected_data = ((0.5+0.5j), (1.5+1.5j), (3+3j), (5+5j), (5.5+5.5j),
+ (6.5+6.5j), (8+8j), (10+10j), (10.5+10.5j), (11.5+11.5j),
+ (13+13j), (15+15j), (15.5+15.5j), (16.5+16.5j), (18+18j),
+ (20+20j), (20.5+20.5j), (21.5+21.5j), (23+23j), (25+25j),
+ (25.5+25.5j), (26.5+26.5j), (28+28j), (30+30j), (30.5+30.5j),
+ (31.5+31.5j), (33+33j), (35+35j), (35.5+35.5j), (36.5+36.5j),
+ (38+38j), (40+40j), (40.5+40.5j), (41.5+41.5j), (43+43j),
+ (45+45j), (45.5+45.5j), (46.5+46.5j), (48+48j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j))
+
+ src = gr.vector_source_c(src_data)
+ op = filter.fir_filter_ccf(1, 20*[0.5, 0.5])
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
+ def test_fir_filter_ccf_002(self):
+ src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j]
+ expected_data = ((0.5+0.5j), (5.5+5.5j), (10.5+10.5j), (15.5+15.5j),
+ (20.5+20.5j), (25.5+25.5j), (30.5+30.5j), (35.5+35.5j),
+ (40.5+40.5j), (45.5+45.5j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j), (50+50j),
+ (50+50j), (50+50j), (50+50j), (50+50j))
+
+ src = gr.vector_source_c(src_data)
+ op = filter.fir_filter_ccf(4, 20*[0.5, 0.5])
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
+ def test_fir_filter_ccc_001(self):
+ src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j]
+ expected_data = ((-0.5+1.5j), (-1.5+4.5j), (-3+9j), (-5+15j),
+ (-5.5+16.5j), (-6.5+19.5j), (-8+24j), (-10+30j),
+ (-10.5+31.5j), (-11.5+34.5j), (-13+39j), (-15+45j),
+ (-15.5+46.5j), (-16.5+49.5j), (-18+54j), (-20+60j),
+ (-20.5+61.5j), (-21.5+64.5j), (-23+69j), (-25+75j),
+ (-25.5+76.5j), (-26.5+79.5j), (-28+84j), (-30+90j),
+ (-30.5+91.5j), (-31.5+94.5j), (-33+99j), (-35+105j),
+ (-35.5+106.5j), (-36.5+109.5j), (-38+114j), (-40+120j),
+ (-40.5+121.5j), (-41.5+124.5j), (-43+129j), (-45+135j),
+ (-45.5+136.5j), (-46.5+139.5j), (-48+144j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j))
+ src = gr.vector_source_c(src_data)
+ op = filter.fir_filter_ccc(1, 20*[0.5+1j, 0.5+1j])
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
+
+ def test_fir_filter_ccc_002(self):
+ src_data = 10*[1+1j, 2+2j, 3+3j, 4+4j]
+
+ # results derived from original gr.fir_filter_ccc
+ expected_data = ((7.537424837948042e-20+7.537424837948042e-20j), (9.131923434324563e-05+9.131923434324563e-05j), (0.0003317668742965907+0.0003317668742965907j), (0.0007230418268591166+0.0007230418268591166j), (0.0012087896466255188+0.0012087896466255188j), (0.0013292605290189385+0.0013292605290189385j), (0.001120875240303576+0.001120875240303576j), (0.000744672492146492+0.000744672492146492j), (0.000429437990533188+0.000429437990533188j), (2.283908543176949e-05+2.283908543176949e-05j), (-0.0002245186478830874-0.0002245186478830874j), (-0.0001157080550910905-0.0001157080550910905j), (0.00041409023106098175+0.00041409023106098175j), (0.0009017843985930085+0.0009017843985930085j), (0.0012520025484263897+0.0012520025484263897j), (0.0014116164529696107+0.0014116164529696107j), (0.001393353333696723+0.001393353333696723j), (0.000912194955162704+0.000912194955162704j), (0.00022649182938039303+0.00022649182938039303j), (-0.00031363096786662936-0.00031363096786662936j), (-0.0003966730728279799-0.0003966730728279799j), (-0.00023757052258588374-0.00023757052258588374j), (0.00021952332463115454+0.00021952332463115454j), (0.0009092430118471384+0.0009092430118471384j), (0.001662317430600524+0.001662317430600524j), (0.0019024648936465383+0.0019024648936465383j), (0.0015955769922584295+0.0015955769922584295j), (0.0009144138311967254+0.0009144138311967254j), (0.0001872836146503687+0.0001872836146503687j), (-0.000581968342885375-0.000581968342885375j), (-0.0009886166080832481-0.0009886166080832481j), (-0.0007480768254026771-0.0007480768254026771j), (0.00018211957649327815+0.00018211957649327815j), (0.0012042406015098095+0.0012042406015098095j), (0.0020200139842927456+0.0020200139842927456j), (0.0023816542234271765+0.0023816542234271765j), (0.002195809967815876+0.002195809967815876j), (0.0012113333214074373+0.0012113333214074373j), (-0.00014088614261709154-0.00014088614261709154j), (-0.0012574587017297745-0.0012574587017297745j))
+
+ taps = filter.firdes.low_pass(1, 1, 0.1, 0.01)
+ src = gr.vector_source_c(src_data)
+ op = filter.fir_filter_ccc(1, taps)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
+ def test_fir_filter_ccc_003(self):
+ src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j]
+ expected_data = ((-0.5+1.5j), (-5.5+16.5j), (-10.5+31.5j),
+ (-15.5+46.5j), (-20.5+61.5j), (-25.5+76.5j),
+ (-30.5+91.5j), (-35.5+106.5j), (-40.5+121.5j),
+ (-45.5+136.5j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j), (-50+150j),
+ (-50+150j), (-50+150j), (-50+150j))
+ src = gr.vector_source_c(src_data)
+ op = filter.fir_filter_ccc(4, 20*[0.5+1j, 0.5+1j])
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
+
+ def test_fir_filter_scc_001(self):
+ src_data = 40*[1, 2, 3, 4]
+ expected_data = ((0.5+1j), (1.5+3j), (3+6j), (5+10j), (5.5+11j),
+ (6.5+13j), (8+16j), (10+20j), (10.5+21j), (11.5+23j),
+ (13+26j), (15+30j), (15.5+31j), (16.5+33j), (18+36j),
+ (20+40j), (20.5+41j), (21.5+43j), (23+46j), (25+50j),
+ (25.5+51j), (26.5+53j), (28+56j), (30+60j), (30.5+61j),
+ (31.5+63j), (33+66j), (35+70j), (35.5+71j), (36.5+73j),
+ (38+76j), (40+80j), (40.5+81j), (41.5+83j), (43+86j),
+ (45+90j), (45.5+91j), (46.5+93j), (48+96j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j))
+ src = gr.vector_source_s(src_data)
+ op = filter.fir_filter_scc(1, 20*[0.5+1j, 0.5+1j])
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
+
+ def test_fir_filter_scc_002(self):
+ src_data = 40*[1, 2, 3, 4]
+ expected_data = ((0.5+1j), (5.5+11j), (10.5+21j), (15.5+31j), (20.5+41j),
+ (25.5+51j), (30.5+61j), (35.5+71j), (40.5+81j), (45.5+91j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j),
+ (50+100j), (50+100j), (50+100j), (50+100j), (50+100j))
+ src = gr.vector_source_s(src_data)
+ op = filter.fir_filter_scc(4, 20*[0.5+1j, 0.5+1j])
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
+ def test_fir_filter_fsf_001(self):
+ src_data = 40*[1, 2, 3, 4]
+ expected_data =(0, 1, 3, 5, 5, 6, 8, 10, 10, 11, 13, 15, 15, 16, 18, 20, 20,
+ 21, 23, 25, 25, 26, 28, 30, 30, 31, 33, 35, 35, 36, 38, 40, 40,
+ 41, 43, 45, 45, 46, 48, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50)
+ src = gr.vector_source_f(src_data)
+ op = filter.fir_filter_fsf(1, 20*[0.5, 0.5])
+ dst = gr.vector_sink_s()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
+
+ def test_fir_filter_fsf_002(self):
+ src_data = 40*[1, 2, 3, 4]
+ expected_data = (0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50)
+ src = gr.vector_source_f(src_data)
+ op = filter.fir_filter_fsf(4, 20*[0.5, 0.5])
+ dst = gr.vector_sink_s()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_filter, "test_filter.xml")
+
diff --git a/gr-filter/python/qa_firdes.py b/gr-filter/python/qa_firdes.py
new file mode 100755
index 000000000..cfd10435f
--- /dev/null
+++ b/gr-filter/python/qa_firdes.py
@@ -0,0 +1,202 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+import sys
+
+class test_firdes(gr_unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_low_pass(self):
+ known_taps = (0.0030193300917744637, -0.004960992839187384,
+ 0.006678304169327021, -1.132049690556083e-17,
+ -0.0251916591078043, 0.07206480950117111,
+ -0.13062666356563568, 0.18007083237171173,
+ 0.7978920936584473, 0.18007083237171173,
+ -0.13062666356563568, 0.07206480950117111,
+ -0.0251916591078043, -1.132049690556083e-17,
+ 0.006678304169327021, -0.004960992839187384,
+ 0.0030193300917744637)
+ new_taps = filter.firdes.low_pass(1, 1, 0.4, 0.2)
+ self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
+
+ def test_low_pass_2(self):
+ known_taps = (0.0024871660862118006, -4.403502608370943e-18,
+ -0.014456653036177158, 0.0543283149600029,
+ -0.116202212870121, 0.17504146695137024,
+ 0.7976038455963135, 0.17504146695137024,
+ -0.116202212870121, 0.0543283149600029,
+ -0.014456653036177158, -4.403502608370943e-18,
+ 0.0024871660862118006)
+ new_taps = filter.firdes.low_pass_2(1, 1, 0.4, 0.2, 60)
+ self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
+
+ def test_high_pass(self):
+ known_taps = (-0.003062003292143345, 0.005031108390539885,
+ -0.0067726909182965755, 1.1480492661182674e-17,
+ 0.025547700002789497, -0.0730833187699318,
+ 0.13247284293174744, -0.18261581659317017,
+ 0.20229223370552063, -0.18261581659317017,
+ 0.13247284293174744, -0.0730833187699318,
+ 0.025547700002789497, 1.1480492661182674e-17,
+ -0.0067726909182965755, 0.005031108390539885,
+ -0.003062003292143345)
+ new_taps = filter.firdes.high_pass(1, 1, 0.4, 0.2)
+ self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
+
+ def test_high_pass_2(self):
+ known_taps = (-0.0027197482995688915, 4.815287179370254e-18,
+ 0.01580853760242462, -0.05940871313214302,
+ 0.1270686239004135, -0.1914101094007492,
+ 0.21804752945899963, -0.1914101094007492,
+ 0.1270686239004135, -0.05940871313214302,
+ 0.01580853760242462, 4.815287179370254e-18,
+ -0.0027197482995688915)
+ new_taps = filter.firdes.high_pass_2(1, 1, 0.4, 0.2, 60)
+ self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
+
+ def test_band_pass(self):
+ known_taps = (0.004961997736245394, -0.008152946829795837,
+ -0.004192151129245758, -5.749020235348687e-18,
+ 0.01581347920000553, 0.11843203753232956,
+ -0.21467317640781403, -0.11303528398275375,
+ 0.40520283579826355, -0.11303528398275375,
+ -0.21467317640781403, 0.11843203753232956,
+ 0.01581347920000553, -5.749020235348687e-18,
+ -0.004192151129245758, -0.008152946829795837,
+ 0.004961997736245394)
+ new_taps = filter.firdes.band_pass(1, 1, 0.2, 0.4, 0.2)
+ self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
+
+ def test_band_pass_2(self):
+ known_taps = (-0.001676854444667697, -2.4018533253972557e-18,
+ 0.009746716357767582, 0.09589414298534393,
+ -0.20510689914226532, -0.11801345646381378,
+ 0.4350462853908539, -0.11801345646381378,
+ -0.20510689914226532, 0.09589414298534393,
+ 0.009746716357767582, -2.4018533253972557e-18,
+ -0.001676854444667697)
+ new_taps = filter.firdes.band_pass_2(1, 1, 0.2, 0.4, 0.2, 60)
+ self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
+
+ def test_complex_band_pass(self):
+ known_taps = ((0.0024772135075181723+0.0017997993854805827j),
+ (-0.004070250317454338+0.002957213670015335j),
+ (-0.0020928815938532352-0.006441210396587849j),
+ (-2.8701231652956686e-18+2.805614574993832e-24j),
+ (0.007894645445048809-0.024297315627336502j),
+ (0.05912570655345917+0.04295721650123596j),
+ (-0.10717268288135529+0.07786571979522705j),
+ (-0.0564316064119339-0.17367789149284363j),
+ (0.20229223370552063-2.4115112751132983e-07j),
+ (-0.05643119290471077+0.17367802560329437j),
+ (-0.10717286914587021-0.07786546647548676j),
+ (0.05912560224533081-0.0429573580622673j),
+ (0.007894691079854965+0.024297300726175308j),
+ (-2.8701231652956686e-18+2.6687109203363464e-24j),
+ (-0.0020928694866597652+0.006441214121878147j),
+ (-0.004070255905389786-0.0029572059866040945j),
+ (0.0024772100150585175-0.0017998040420934558j))
+ new_taps = filter.firdes.complex_band_pass(1, 1, 0.2, 0.4, 0.2)
+ self.assertComplexTuplesAlmostEqual(known_taps, new_taps, 5)
+
+ def test_complex_band_pass_2(self):
+ known_taps = ((-0.0008404505206272006-0.0025866336654871702j),
+ (-1.2038217948425635e-18+1.1767648157397848e-24j),
+ (0.0048850891180336475-0.015034818090498447j),
+ (0.048062704503536224+0.03491950035095215j),
+ (-0.10280057787895203+0.07468919456005096j),
+ (-0.05914920195937157-0.18204176425933838j),
+ (0.21804752945899963-2.5993290364567656e-07j),
+ (-0.059148769825696945+0.18204189836978912j),
+ (-0.10280075669288635-0.07468894869089127j),
+ (0.04806262254714966-0.0349196158349514j),
+ (0.004885117989033461+0.015034808777272701j),
+ (-1.2038217948425635e-18+1.1193430388030685e-24j),
+ (-0.000840445572976023+0.002586635295301676j))
+ new_taps = filter.firdes.complex_band_pass_2(1, 1, 0.2, 0.4, 0.2, 60)
+ self.assertComplexTuplesAlmostEqual(known_taps, new_taps, 5)
+
+ def test_band_reject(self):
+ known_taps = (-0.004915320314466953, 0.008076251484453678,
+ 0.00415271520614624, 5.694938753309664e-18,
+ -0.01566472090780735, -0.11731793731451035,
+ 0.2126537412405014, 0.11197195947170258,
+ 0.6020866632461548, 0.11197195947170258,
+ 0.2126537412405014, -0.11731793731451035,
+ -0.01566472090780735, 5.694938753309664e-18,
+ 0.00415271520614624, 0.008076251484453678,
+ -0.004915320314466953)
+ new_taps = filter.firdes.band_reject(1, 1, 0.2, 0.4, 0.2)
+ self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
+
+ def test_band_reject_2(self):
+ known_taps = (0.0015371545450761914, 2.201753372137003e-18,
+ -0.00893471110612154, -0.08790513873100281,
+ 0.1880193054676056, 0.1081816703081131,
+ 0.5982034206390381, 0.1081816703081131,
+ 0.1880193054676056, -0.08790513873100281,
+ -0.00893471110612154, 2.201753372137003e-18,
+ 0.0015371545450761914)
+ new_taps = filter.firdes.band_reject_2(1, 1, 0.2, 0.4, 0.2, 60)
+ self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
+
+ def test_hilbert(self):
+ known_taps = (-0.010056184604763985, 0.0,
+ -0.08335155993700027, 0.0,
+ -0.5732954144477844, 0.0,
+ 0.5732954144477844, 0.0,
+ 0.08335155993700027, 0.0,
+ 0.010056184604763985)
+ new_taps = filter.firdes.hilbert(11)
+ self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
+
+ def test_root_raised_cosine(self):
+ known_taps = (-0.04609205573797226, -0.02069387212395668,
+ 0.050548505038022995, 0.14850808680057526,
+ 0.23387153446674347, 0.2677156329154968,
+ 0.23387153446674347, 0.14850808680057526,
+ 0.050548505038022995, -0.02069387212395668,
+ -0.04609205573797226)
+ new_taps = filter.firdes.root_raised_cosine(1, 4, 1, 0.35, 11)
+ self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
+
+ def test_gaussian(self):
+ known_taps = (0.0003600157215259969, 0.0031858310103416443,
+ 0.0182281993329525, 0.06743486225605011,
+ 0.16130395233631134, 0.24947398900985718,
+ 0.24947398900985718, 0.16130395233631134,
+ 0.06743486225605011, 0.0182281993329525,
+ 0.0031858310103416443, 0.0003600157215259969,
+ 2.630509879963938e-05)
+ new_taps = filter.firdes.gaussian(1, 4, 0.35, 13)
+ self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_firdes, "test_firdes.xml")
+
diff --git a/gr-filter/python/qa_fractional_interpolator.py b/gr-filter/python/qa_fractional_interpolator.py
new file mode 100755
index 000000000..9e0f685d8
--- /dev/null
+++ b/gr-filter/python/qa_fractional_interpolator.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python
+#
+# Copyright 2007,2010,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+import math
+
+class test_fractional_resampler(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_001_ff(self):
+ N = 10000 # number of samples to use
+ fs = 1000 # baseband sampling rate
+ rrate = 1.123 # resampling rate
+
+ freq = 10
+ signal = gr.sig_source_f(fs, gr.GR_SIN_WAVE, freq, 1)
+ head = gr.head(gr.sizeof_float, N)
+ op = filter.fractional_interpolator_ff(0, rrate)
+ snk = gr.vector_sink_f()
+
+ self.tb.connect(signal, head, op, snk)
+ self.tb.run()
+
+ Ntest = 5000
+ L = len(snk.data())
+ t = map(lambda x: float(x)/(fs/rrate), xrange(L))
+
+ phase = 0.1884
+ expected_data = map(lambda x: math.sin(2.*math.pi*freq*x+phase), t)
+
+ dst_data = snk.data()
+
+ self.assertFloatTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 3)
+
+
+ def test_002_cc(self):
+ N = 10000 # number of samples to use
+ fs = 1000 # baseband sampling rate
+ rrate = 1.123 # resampling rate
+
+ freq = 10
+ signal = gr.sig_source_c(fs, gr.GR_SIN_WAVE, freq, 1)
+ head = gr.head(gr.sizeof_gr_complex, N)
+ op = filter.fractional_interpolator_cc(0.0, rrate)
+ snk = gr.vector_sink_c()
+
+ self.tb.connect(signal, head, op, snk)
+ self.tb.run()
+
+ Ntest = 5000
+ L = len(snk.data())
+ t = map(lambda x: float(x)/(fs/rrate), xrange(L))
+
+ phase = 0.1884
+ expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \
+ 1j*math.sin(2.*math.pi*freq*x+phase), t)
+
+ dst_data = snk.data()
+
+ self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 3)
+
+
+if __name__ == '__main__':
+ gr_unittest.run(test_fractional_resampler, "test_fractional_resampler.xml")
diff --git a/gr-filter/python/qa_freq_xlating_fir_filter.py b/gr-filter/python/qa_freq_xlating_fir_filter.py
new file mode 100755
index 000000000..ee38eb7df
--- /dev/null
+++ b/gr-filter/python/qa_freq_xlating_fir_filter.py
@@ -0,0 +1,445 @@
+#!/usr/bin/env python
+#
+# Copyright 2008,2010,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+import cmath, math
+
+class test_freq_xlating_filter(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block ()
+
+ def tearDown(self):
+ self.tb = None
+
+ def generate_ccf_source(self):
+ self.fs = fs = 1
+ self.fc = fc = 0.3
+ self.bw = bw = 0.1
+ self.taps = filter.firdes.low_pass(1, fs, bw, bw/4)
+ times = xrange(100)
+ self.src_data = map(lambda t: cmath.exp(-2j*cmath.pi*fc/fs*(t/100.0)), times)
+
+ def generate_ccc_source(self):
+ self.fs = fs = 1
+ self.fc = fc = 0.3
+ self.bw = bw = 0.1
+ self.taps = filter.firdes.complex_band_pass(1, fs, -bw/2, bw/2, bw/4)
+ times = xrange(100)
+ self.src_data = map(lambda t: cmath.exp(-2j*cmath.pi*fc/fs*(t/100.0)), times)
+
+ def generate_fcf_source(self):
+ self.fs = fs = 1
+ self.fc = fc = 0.3
+ self.bw = bw = 0.1
+ self.taps = filter.firdes.low_pass(1, fs, bw, bw/4)
+ times = xrange(100)
+ self.src_data = map(lambda t: math.sin(2*cmath.pi*fc/fs*(t/100.0)), times)
+
+ def generate_fcc_source(self):
+ self.fs = fs = 1
+ self.fc = fc = 0.3
+ self.bw = bw = 0.1
+ self.taps = filter.firdes.complex_band_pass(1, fs, -bw/2, bw/2, bw/4)
+ times = xrange(100)
+ self.src_data = map(lambda t: math.sin(2*cmath.pi*fc/fs*(t/100.0)), times)
+
+ def generate_scf_source(self):
+ self.fs = fs = 1
+ self.fc = fc = 0.3
+ self.bw = bw = 0.1
+ self.taps = filter.firdes.low_pass(1, fs, bw, bw/4)
+ times = xrange(100)
+ self.src_data = map(lambda t: int(100*math.sin(2*cmath.pi*fc/fs*(t/100.0))), times)
+
+ def generate_scc_source(self):
+ self.fs = fs = 1
+ self.fc = fc = 0.3
+ self.bw = bw = 0.1
+ self.taps = filter.firdes.complex_band_pass(1, fs, -bw/2, bw/2, bw/4)
+ times = xrange(100)
+ self.src_data = map(lambda t: int(100*math.sin(2*cmath.pi*fc/fs*(t/100.0))), times)
+
+
+ def test_fir_filter_ccf_001(self):
+ self.generate_ccf_source()
+ expected_data = ((0.001697700354270637+0.004312471952289343j),
+ (0.003520616563037038-0.003014103975147009j),
+ (0.004252811893820763-0.008337559178471565j),
+ (0.0030743128154426813-0.010262271389365196j),
+ (0.0007344777695834637-0.007861139252781868j),
+ (-0.0011067686136811972-0.0028924935031682253j),
+ (-0.002371778478845954+0.0019914964213967323j),
+ (-0.003023319412022829+0.005717850290238857j),
+ (-0.0021738125942647457+0.007211698684841394j),
+ (-0.0004628606839105487+0.005501383915543556j),
+ (0.0007428556564264+0.0019867848604917526j),
+ (0.001634795218706131-0.0013514887541532516j),
+ (0.002205110155045986-0.00402155052870512j),
+ (0.0015480631263926625-0.005179159343242645j),
+ (0.00026722141774371266-0.003887997241690755j),
+ (-0.0004911854630336165-0.0013578246580436826j),
+ (-0.0011226939968764782+0.0009080552263185382j),
+ (-0.0016229727771133184+0.0028335191309452057j),
+ (-0.0010890064295381308+0.0037298379465937614j),
+ (-0.00012392725329846144+0.0027196139562875032j))
+ src = gr.vector_source_c(self.src_data)
+ op = filter.freq_xlating_fir_filter_ccf(1, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_ccf_002(self):
+ self.generate_ccf_source()
+ expected_data = ((6.419439159799367e-05-0.0006292851758189499j),
+ (-0.00037074743886478245+0.0013245552545413375j),
+ (0.0006853155209682882-0.0023769831750541925j),
+ (-0.001427714480087161+0.002608160488307476j),
+ (0.0015907397028058767-0.000811046629678458j),
+ (-0.0004226673918310553-0.0024389736354351044j),
+ (-0.0013841050677001476+0.006231029983609915j),
+ (0.0035029184073209763-0.009738259017467499j),
+ (-0.005924836732447147+0.010320881381630898j),
+ (0.006831614300608635-0.003950652200728655j),
+ (-0.0021247887052595615-0.015604906715452671j),
+ (-0.04283163696527481+0.09995654970407486j),
+ (-0.01391829177737236+0.07924056798219681j),
+ (0.010886997915804386-0.02463012933731079j),
+ (-0.0056075905449688435+0.004998659715056419j),
+ (0.0016976913902908564+0.004312459379434586j),
+ (0.0007344821933656931-0.007861112244427204j),
+ (-0.002173811662942171+0.007211671676486731j),
+ (0.0022051059640944004-0.00402153329923749j),
+ (-0.0011226903880015016+0.0009080505697056651j))
+ src = gr.vector_source_c(self.src_data)
+ op = filter.freq_xlating_fir_filter_ccf(4, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_ccc_001(self):
+ self.generate_ccc_source()
+ expected_data = ((0.0036842757836-0.0114002721384j),
+ (0.00324621866457-0.0108166672289j),
+ (0.00206564785913-0.00923090614378j),
+ (0.00109899020754-0.00656201224774j),
+ (0.000506619049702-0.00402844604105j),
+ (-0.000523390364833-0.00166808743961j),
+ (-0.00140534969978+0.00103991874494j),
+ (-0.00154365820345+0.00315759982914j),
+ (-0.00180402118713+0.00427215453237j),
+ (-0.00216706306674+0.00524478312582j),
+ (-0.00178848754149+0.0057489364408j),
+ (-0.00129876169376+0.00512680830434j),
+ (-0.00122803379782+0.00427244976163j),
+ (-0.000722666736692+0.00351428100839j),
+ (5.53092104383e-05+0.00207865727134j),
+ (0.000227351076319+0.000517217209563j),
+ (0.000414477253798-0.000383921898901j),
+ (0.000998671515845-0.00135387131013j),
+ (0.00104933069088-0.00243046949618j),
+ (0.000765930046327-0.0026717747096j))
+ src = gr.vector_source_c(self.src_data)
+ op = filter.freq_xlating_fir_filter_ccc(1, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_ccc_002(self):
+ self.generate_ccc_source()
+ expected_data = ((-0.000650451984257+0.00120697380044j),
+ (-9.59713361226e-05+0.00102412770502j),
+ (0.000958710326813-0.00145424995571j),
+ (0.000901343999431-0.00290832063183j),
+ (-0.000822560978122+0.000296717538731j),
+ (-0.00211223773658+0.00519825471565j),
+ (-0.00037001183955+0.00358242215589j),
+ (0.00327983591706-0.00616005761549j),
+ (0.00356886954978-0.0117237549275j),
+ (-0.00328874029219+0.00182871113066j),
+ (-0.0139285130426+0.0320657044649j),
+ (-0.0198133718222+0.0562113076448j),
+ (-0.0157803222537+0.0530290603638j),
+ (-0.00550725404173+0.0255754813552j),
+ (0.00252919178456-0.00232240976766j),
+ (0.00368427345529-0.0114002330229j),
+ (0.000506620621309-0.00402843113989j),
+ (-0.00180401885882+0.00427213776857j),
+ (-0.00122803344857+0.00427243299782j),
+ (0.000414476031438-0.000383919978049j))
+ src = gr.vector_source_c(self.src_data)
+ op = filter.freq_xlating_fir_filter_ccc(4, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_fcf_001(self):
+ self.generate_fcf_source()
+ expected_data = ((0.000247188087087-0.000157509770361j),
+ (-0.000155229790835-0.000246197130764j),
+ (-0.000264906557277+0.000174603672349j),
+ (6.99016964063e-05+0.000174961372977j),
+ (-5.48477692064e-05-0.0001131295503j),
+ (-0.000237467131228+0.000118011368613j),
+ (0.000136614587973+0.000229531884543j),
+ (0.000229347482673-0.000166581812664j),
+ (-0.000106010869786-0.000150042149471j),
+ (2.92293734674e-05+0.000142060467624j),
+ (0.000228707227507-9.30760797928e-05j),
+ (-0.000124306126963-0.000216641055886j),
+ (-0.000204823678359+0.00016052465071j),
+ (0.00012825592421+0.000133123627165j),
+ (-1.18284006021e-05-0.000159015646204j),
+ (-0.000219973371713+7.5438656495e-05j),
+ (0.000114713984658+0.000205190401175j),
+ (0.000185727752978-0.000154630601173j),
+ (-0.000141745767905-0.000120098840853j),
+ (-3.9850056055e-07+0.000168364742422j))
+ src = gr.vector_source_f(self.src_data)
+ op = filter.freq_xlating_fir_filter_fcf(1, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_fcf_002(self):
+ self.generate_fcf_source()
+ expected_data = ((7.3052920925e-05-3.91741014028e-06j),
+ (3.11913172482e-05-0.000109872074972j),
+ (-0.000128646017401-3.49857727997e-05j),
+ (-5.49546712136e-05+8.96326746442e-05j),
+ (5.14321582159e-05+9.64698920143e-05j),
+ (0.000120189361041+2.4231892894e-05j),
+ (0.000100405508419-0.000223224604269j),
+ (-0.000274751859251-2.33274622587e-05j),
+ (1.52600114234e-06+0.000133301247843j),
+ (3.77224641852e-05+5.29596509296e-05j),
+ (-3.60160379387e-06+0.000247975171078j),
+ (0.00113093166146-0.000663110695314j),
+ (0.00059568521101-0.00099650840275j),
+ (-0.000475480686873+0.000250602373853j),
+ (0.000191397906747+0.000271986238658j),
+ (0.000247183139436-0.000157510468853j),
+ (-5.48357638763e-05-0.000113135029096j),
+ (-0.00010601492977-0.00015005269961j),
+ (-0.000204817260965+0.000160534662427j),
+ (0.000114742244477+0.000205190313864j))
+ src = gr.vector_source_f(self.src_data)
+ op = filter.freq_xlating_fir_filter_fcf(4, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_fcc_001(self):
+ self.generate_fcc_source()
+ expected_data = ((-0.000337088305969+7.46004516259e-05j),
+ (-5.63409266761e-05+0.000301144464174j),
+ (9.16960561881e-05-2.89259278361e-05j),
+ (-0.000231866899412-6.25764005235e-05j),
+ (-0.000116414688819+0.000258557556663j),
+ (0.000206079319469+5.05045172758e-05j),
+ (-3.85114690289e-05-0.00019276549574j),
+ (-0.000146380873048+0.000112079876999j),
+ (0.000215423395275+0.000116706331028j),
+ (0.000136050162837-0.000232611957472j),
+ (-0.000155499437824-5.41604022146e-05j),
+ (0.000106907449663+0.00016310159117j),
+ (0.000224392410018-0.000156331108883j),
+ (-0.000131131906528-0.000172063446371j),
+ (-5.92393880652e-05+0.00016801241145j),
+ (0.000214921761653-5.32235890205e-06j),
+ (-5.96960526309e-05-0.000211164733628j),
+ (-0.000193948610104+0.000113364716526j),
+ (0.000134820176754+0.000142527525895j),
+ (4.74465123261e-05-0.000175131688593j))
+ src = gr.vector_source_f(self.src_data)
+ op = filter.freq_xlating_fir_filter_fcc(1, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_fcc_002(self):
+ self.generate_fcc_source()
+ expected_data = ((-6.94218761055e-05-9.90489479591e-06j),
+ (-2.56973435171e-05+8.05932795629e-05j),
+ (7.01698663761e-05+7.36373840482e-05j),
+ (7.57163215894e-05-4.65324592369e-05j),
+ (-3.01657128148e-05-0.000122838056996j),
+ (-9.53659764491e-05-3.73945695173e-05j),
+ (-2.33501577895e-05+0.000109135726234j),
+ (6.65136758471e-05+0.000125709688291j),
+ (3.08501912514e-05-9.16842873266e-06j),
+ (-2.64703612629e-05-0.000135892929393j),
+ (0.000136643866426-0.000162003751029j),
+ (0.000501801609062-0.000185820827028j),
+ (0.000694551155902-0.000299874518532j),
+ (0.000424396857852-0.00038379128091j),
+ (-9.1786707344e-05-0.000242479465669j),
+ (-0.000337087287335+7.45999423089e-05j),
+ (-0.000116414521472+0.000258556567132j),
+ (0.000215422536712+0.000116706112749j),
+ (0.000224391726078-0.000156330308528j),
+ (-5.96956087975e-05-0.000211163976928j))
+ src = gr.vector_source_f(self.src_data)
+ op = filter.freq_xlating_fir_filter_fcc(4, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_scf_001(self):
+ self.generate_scf_source()
+ expected_data = ((-0.0330070219934+0.101965591311j),
+ (-0.0484239049256+0.0872343629599j),
+ (-0.0214109234512+0.102555386722j),
+ (0.0484058149159+0.0557125210762j),
+ (0.0574690811336-0.0350844524801j),
+ (0.0365394353867-0.0802438184619j),
+ (0.0453781634569-0.130992040038j),
+ (0.00801951438189-0.214278846979j),
+ (-0.0770946145058-0.230616629124j),
+ (-0.105601429939-0.190731987357j),
+ (-0.105361394584-0.177761554718j),
+ (-0.131518915296-0.136102750897j),
+ (-0.103761836886-0.0382263250649j),
+ (-0.0167790111154+0.0152206514031j),
+ (0.0277570039034+0.0300403907895j),
+ (0.056065287441+0.0806603953242j),
+ (0.118084669113+0.104863211513j),
+ (0.128281414509+0.0677760615945j),
+ (0.0748447552323+0.0619902014732j),
+ (0.0512856245041+0.0775099247694j))
+ src = gr.vector_source_s(self.src_data)
+ op = filter.freq_xlating_fir_filter_scf(1, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_scf_002(self):
+ self.generate_scf_source()
+ expected_data = ((0.00824625696987-1.50158575707e-05j),
+ (0.0020101047121-0.0116540221497j),
+ (-0.0126378880814-0.00259830290452j),
+ (-0.00363933457993+0.00837504956871j),
+ (0.00107023562305+0.00915473792702j),
+ (0.0169738996774+0.00422182958573j),
+ (0.00630031805485-0.025423232466j),
+ (-0.0283014029264+0.00104465708137j),
+ (0.00890890974551+0.0115978596732j),
+ (-0.0142687577754+0.00306978379376j),
+ (0.02845691517+0.0331163145602j),
+ (0.0538152232766-0.0908300876617j),
+ (-0.0843691527843-0.0956566259265j),
+ (0.0476895272732+0.0747984498739j),
+ (0.0898786485195+0.082478672266j),
+ (-0.0330070182681+0.101965606213j),
+ (0.0574697069824-0.0350842289627j),
+ (-0.0770940706134-0.230615705252j),
+ (-0.103762261569-0.0382265634835j),
+ (0.11808334291+0.104863762856j))
+ src = gr.vector_source_s(self.src_data)
+ op = filter.freq_xlating_fir_filter_scf(4, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_scc_001(self):
+ self.generate_scc_source()
+ expected_data = ((-0.00775564694777+0.0437113791704j),
+ (0.0108830630779+0.0433648750186j),
+ (0.015553932637-0.0133284125477j),
+ (-0.0264905355871-0.0403266139328j),
+ (-0.0243480335921-0.03030154109j),
+ (-0.000327925226884-0.069333948195j),
+ (-0.0306392069906-0.107313856483j),
+ (-0.0452371090651-0.0854917764664j),
+ (-0.0108894333243-0.0875641107559j),
+ (-0.0182112380862-0.118961036205j),
+ (-0.0447825863957-0.0922874584794j),
+ (-0.0147479763255-0.0572904124856j),
+ (0.00204290449619-0.0721436738968j),
+ (-0.027713002637-0.0548989400268j),
+ (-0.0149045493454-0.00210141134448j),
+ (0.0176361314952-0.00149522523861j),
+ (-0.00527482619509-0.00698099425063j),
+ (-0.0151527002454+0.036265052855j),
+ (0.0199296213686+0.0452499426901j),
+ (0.0122985243797+0.0143278446048j))
+ src = gr.vector_source_s(self.src_data)
+ op = filter.freq_xlating_fir_filter_scc(1, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+ def test_fir_filter_scc_002(self):
+ self.generate_scc_source()
+ expected_data = ((-0.0080680437386-0.00158522999845j),
+ (-0.0037795654498+0.00733159901574j),
+ (0.00842926371843+0.00777021236718j),
+ (0.0112090632319-0.00249325321056j),
+ (-0.0027476802934-0.0115710813552j),
+ (-0.0158688724041-0.00715934624895j),
+ (-0.00802888441831+0.00620818417519j),
+ (0.0131985172629+0.0149175003171j),
+ (0.0190298333764+0.00956719089299j),
+ (-0.00112380902283-0.00936658866704j),
+ (-0.0204226914793-0.0333464704454j),
+ (-0.00695514678955-0.0437445007265j),
+ (0.0314490310848-0.0207983348519j),
+ (0.0529675260186+0.0302227605134j),
+ (0.0317338332534+0.0667510479689j),
+ (-0.00775565672666+0.0437112376094j),
+ (-0.024347923696-0.0303014591336j),
+ (-0.0108893103898-0.0875638127327j),
+ (0.00204296782613-0.0721434056759j),
+ (-0.00527479872108-0.00698097236454j))
+ src = gr.vector_source_s(self.src_data)
+ op = filter.freq_xlating_fir_filter_scc(4, self.taps, self.fc, self.fs)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_freq_xlating_filter, "test_freq_xlating_filter.xml")
+
diff --git a/gr-filter/python/qa_hilbert.py b/gr-filter/python/qa_hilbert.py
new file mode 100755
index 000000000..b460b6438
--- /dev/null
+++ b/gr-filter/python/qa_hilbert.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python
+#
+# Copyright 2004,2007,2010,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+import math
+
+class test_hilbert(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block ()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_hilbert(self):
+ tb = self.tb
+ ntaps = 51
+ sampling_freq = 100
+
+ expected_result = ( -1.4678005338941702e-11j,
+ -0.0011950774351134896j,
+ -0.0019336787518113852j,
+ -0.0034673355985432863j,
+ -0.0036765895783901215j,
+ -0.004916108213365078j,
+ -0.0042778430506587029j,
+ -0.006028641015291214j,
+ -0.005476709920912981j,
+ -0.0092810001224279404j,
+ -0.0095402700826525688j,
+ -0.016060983762145042j,
+ -0.016446959227323532j,
+ -0.02523401565849781j,
+ -0.024382550269365311j,
+ -0.035477779805660248j,
+ -0.033021725714206696j,
+ -0.048487484455108643j,
+ -0.04543270543217659j,
+ -0.069477587938308716j,
+ -0.066984444856643677j,
+ -0.10703597217798233j,
+ -0.10620346665382385j,
+ -0.1852707713842392j,
+ -0.19357112050056458j,
+ (7.2191945754696007e-09 -0.50004088878631592j),
+ (0.58778399229049683 -0.6155126690864563j),
+ (0.95105588436126709 -0.12377222627401352j),
+ (0.95105588436126709 +0.41524654626846313j),
+ (0.5877838134765625 +0.91611981391906738j),
+ (5.8516356205018383e-09 +1.0670661926269531j),
+ (-0.5877840518951416 +0.87856143712997437j),
+ (-0.95105588436126709 +0.35447561740875244j),
+ (-0.95105588436126709 -0.26055556535720825j),
+ (-0.5877838134765625 -0.77606213092803955j),
+ (-8.7774534307527574e-09 -0.96460390090942383j),
+ (0.58778399229049683 -0.78470128774642944j),
+ (0.95105588436126709 -0.28380891680717468j),
+ (0.95105588436126709 +0.32548999786376953j),
+ (0.5877838134765625 +0.82514488697052002j),
+ (1.4629089051254596e-08 +1.0096219778060913j),
+ (-0.5877840518951416 +0.81836479902267456j),
+ (-0.95105588436126709 +0.31451958417892456j),
+ (-0.95105588436126709 -0.3030143678188324j),
+ (-0.5877838134765625 -0.80480599403381348j),
+ (-1.7554906861505515e-08 -0.99516552686691284j),
+ (0.58778399229049683 -0.80540722608566284j),
+ (0.95105582475662231 -0.30557557940483093j),
+ (0.95105588436126709 +0.31097668409347534j),
+ (0.5877838134765625 +0.81027895212173462j),
+ (2.3406542482007353e-08 +1.0000816583633423j),
+ (-0.5877840518951416 +0.80908381938934326j),
+ (-0.95105588436126709 +0.30904293060302734j),
+ (-0.95105588436126709 -0.30904296040534973j),
+ (-0.5877838134765625 -0.80908387899398804j),
+ (-2.6332360292258272e-08 -1.0000815391540527j),
+ (0.58778399229049683 -0.80908381938934326j),
+ (0.95105582475662231 -0.30904299020767212j),
+ (0.95105588436126709 +0.30904293060302734j),
+ (0.5877838134765625 +0.80908381938934326j),
+ (3.218399768911695e-08 +1.0000815391540527j))
+
+
+ src1 = gr.sig_source_f(sampling_freq, gr.GR_SIN_WAVE,
+ sampling_freq * 0.10, 1.0)
+
+ head = gr.head(gr.sizeof_float, int (ntaps + sampling_freq * 0.10))
+ hilb = filter.hilbert_fc(ntaps)
+ dst1 = gr.vector_sink_c()
+ tb.connect(src1, head)
+ tb.connect(head, hilb)
+ tb.connect(hilb, dst1)
+ tb.run()
+ dst_data = dst1.data()
+ self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 5)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_hilbert, "test_hilbert.xml")
diff --git a/gr-filter/python/qa_iir_filter.py b/gr-filter/python/qa_iir_filter.py
new file mode 100755
index 000000000..645c4b66e
--- /dev/null
+++ b/gr-filter/python/qa_iir_filter.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python
+#
+# Copyright 2004,2007,2010 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+
+class test_iir_filter(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_iir_direct_001(self):
+ src_data = (1, 2, 3, 4, 5, 6, 7, 8)
+ fftaps = ()
+ fbtaps = ()
+ expected_result = (0, 0, 0, 0, 0, 0, 0, 0)
+ src = gr.vector_source_f(src_data)
+ op = filter.iir_filter_ffd(fftaps, fbtaps)
+ dst = gr.vector_sink_f()
+ self.tb.connect(src, op)
+ self.tb.connect(op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual(expected_result, result_data)
+
+ def test_iir_direct_002(self):
+ src_data = (1, 2, 3, 4, 5, 6, 7, 8)
+ fftaps = (2,)
+ fbtaps = (0,)
+ expected_result = (2, 4, 6, 8, 10, 12, 14, 16)
+ src = gr.vector_source_f(src_data)
+ op = filter.iir_filter_ffd(fftaps, fbtaps)
+ dst = gr.vector_sink_f()
+ self.tb.connect(src, op)
+ self.tb.connect(op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual(expected_result, result_data)
+
+ def test_iir_direct_003(self):
+ src_data = (1, 2, 3, 4, 5, 6, 7, 8)
+ fftaps = (2, 11)
+ fbtaps = (0, 0)
+ expected_result = (2, 15, 28, 41, 54, 67, 80, 93)
+ src = gr.vector_source_f(src_data)
+ op = filter.iir_filter_ffd(fftaps, fbtaps)
+ dst = gr.vector_sink_f()
+ self.tb.connect(src, op)
+ self.tb.connect(op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual(expected_result, result_data)
+
+ def test_iir_direct_004(self):
+ src_data = (1, 2, 3, 4, 5, 6, 7, 8)
+ fftaps = (2, 11)
+ fbtaps = (0, -1)
+ expected_result = (2, 13, 15, 26, 28, 39, 41, 52)
+ src = gr.vector_source_f(src_data)
+ op = filter.iir_filter_ffd(fftaps, fbtaps)
+ dst = gr.vector_sink_f()
+ self.tb.connect(src, op)
+ self.tb.connect(op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual(expected_result, result_data)
+
+ def test_iir_direct_005(self):
+ src_data = (1, 2, 3, 4, 5, 6, 7, 8)
+ fftaps = (2, 11, 0)
+ fbtaps = (0, -1, 3)
+ expected_result = (2, 13, 21, 59, 58, 186, 68, 583)
+ src = gr.vector_source_f(src_data)
+ op = filter.iir_filter_ffd(fftaps, fbtaps)
+ dst = gr.vector_sink_f()
+ self.tb.connect(src, op)
+ self.tb.connect(op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual(expected_result, result_data)
+
+ def test_iir_direct_006(self):
+ src_data = (1, 2, 3, 4, 5, 6, 7, 8)
+ expected_result = (2, 13, 21, 59, 58, 186, 68, 583)
+ fftaps = (2, 1)
+ fbtaps = (0, -1)
+ src = gr.vector_source_f(src_data)
+ op = filter.iir_filter_ffd(fftaps, fbtaps)
+ fftaps = (2, 11, 0)
+ fbtaps = (0, -1, 3)
+ op.set_taps(fftaps, fbtaps)
+ dst = gr.vector_sink_f()
+ self.tb.connect(src, op)
+ self.tb.connect(op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual(expected_result, result_data)
+
+ def test_iir_direct_007(self):
+ src_data = (1, 2, 3, 4, 5, 6, 7, 8)
+ expected_result = (2,2,5,5,8,8,11,11)
+ fftaps = (2, 1)
+ fbtaps = (0, -1)
+ src = gr.vector_source_f(src_data)
+ op = filter.iir_filter_ffd(fftaps, fbtaps)
+ fftaps = (2,0,1)
+ fbtaps = (0, -1)
+ op.set_taps(fftaps, fbtaps)
+ dst = gr.vector_sink_f()
+ self.tb.connect(src, op)
+ self.tb.connect(op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual(expected_result, result_data)
+
+ def test_iir_direct_008(self):
+ src_data = (1, 2, 3, 4, 5, 6, 7, 8)
+ expected_result = (2,4,4,10,18,14,26,56)
+ fftaps = (2,)
+ fbtaps = (0, 1)
+ src = gr.vector_source_f(src_data)
+ op = filter.iir_filter_ffd(fftaps, fbtaps)
+ fftaps_data = (1)
+ fbtaps = (0,0, -1,3)
+ op.set_taps(fftaps, fbtaps)
+ dst = gr.vector_sink_f()
+ self.tb.connect(src, op)
+ self.tb.connect(op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual (expected_result, result_data)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_iir_filter, "test_iir_filter.xml")
+
diff --git a/gr-filter/python/qa_interp_fir_filter.py b/gr-filter/python/qa_interp_fir_filter.py
new file mode 100755
index 000000000..839330539
--- /dev/null
+++ b/gr-filter/python/qa_interp_fir_filter.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+#
+# Copyright 2004,2007,2010,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+import math
+
+class test_interp_fir_filter(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_fff(self):
+ taps = [1, 10, 100, 1000, 10000]
+ src_data = (0, 2, 3, 5, 7, 11, 13, 17)
+ interpolation = 3
+ xr = (0,0,0,0,
+ 2,20,200,2003,20030,
+ 300,3005,30050,
+ 500,5007,50070,
+ 700,7011,70110,
+ 1100,11013,110130,
+ 1300,13017,130170)
+ expected_result = tuple([float(x) for x in xr])
+
+ src = gr.vector_source_f(src_data)
+ op = filter.interp_fir_filter_fff(interpolation, taps)
+ dst = gr.vector_sink_f()
+ self.tb.connect(src, op)
+ self.tb.connect(op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ L = min(len(result_data), len(expected_result))
+ self.assertEqual(expected_result[0:L], result_data[0:L])
+
+if __name__ == '__main__':
+ gr_unittest.run(test_interp_fir_filter, "test_interp_fir_filter.xml")
+
diff --git a/gr-filter/python/qa_pfb_arb_resampler.py b/gr-filter/python/qa_pfb_arb_resampler.py
new file mode 100755
index 000000000..a4e22f4c0
--- /dev/null
+++ b/gr-filter/python/qa_pfb_arb_resampler.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+import math
+
+class test_pfb_arb_resampler(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_fff_000(self):
+ N = 1000 # number of samples to use
+ fs = 1000 # baseband sampling rate
+ rrate = 1.123 # resampling rate
+
+ nfilts = 32
+ taps = filter.firdes.low_pass_2(nfilts, nfilts*fs, fs/2, fs/10,
+ attenuation_dB=80,
+ window=filter.firdes.WIN_BLACKMAN_hARRIS)
+
+ freq = 100
+ signal = gr.sig_source_f(fs, gr.GR_SIN_WAVE, freq, 1)
+ head = gr.head(gr.sizeof_float, N)
+ pfb = filter.pfb_arb_resampler_fff(rrate, taps)
+ snk = gr.vector_sink_f()
+
+ self.tb.connect(signal, head, pfb, snk)
+ self.tb.run()
+
+ Ntest = 50
+ L = len(snk.data())
+ t = map(lambda x: float(x)/(fs*rrate), xrange(L))
+
+ phase = 0.53013
+ expected_data = map(lambda x: math.sin(2.*math.pi*freq*x+phase), t)
+
+ dst_data = snk.data()
+ self.assertFloatTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 3)
+
+ def test_ccf_000(self):
+ N = 1000 # number of samples to use
+ fs = 1000 # baseband sampling rate
+ rrate = 1.123 # resampling rate
+
+ nfilts = 32
+ taps = filter.firdes.low_pass_2(nfilts, nfilts*fs, fs/2, fs/10,
+ attenuation_dB=80,
+ window=filter.firdes.WIN_BLACKMAN_hARRIS)
+
+ freq = 100
+ signal = gr.sig_source_c(fs, gr.GR_SIN_WAVE, freq, 1)
+ head = gr.head(gr.sizeof_gr_complex, N)
+ pfb = filter.pfb_arb_resampler_ccf(rrate, taps)
+ snk = gr.vector_sink_c()
+
+ self.tb.connect(signal, head, pfb, snk)
+ self.tb.run()
+
+ Ntest = 50
+ L = len(snk.data())
+ t = map(lambda x: float(x)/(fs*rrate), xrange(L))
+
+ phase = 0.53013
+ expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \
+ 1j*math.sin(2.*math.pi*freq*x+phase), t)
+
+ dst_data = snk.data()
+ self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 3)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_pfb_arb_resampler, "test_pfb_arb_resampler.xml")
diff --git a/gr-filter/python/qa_pfb_channelizer.py b/gr-filter/python/qa_pfb_channelizer.py
new file mode 100755
index 000000000..c0ed8327d
--- /dev/null
+++ b/gr-filter/python/qa_pfb_channelizer.py
@@ -0,0 +1,104 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+import math
+
+class test_pfb_channelizer(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_000(self):
+ N = 1000 # number of samples to use
+ M = 5 # Number of channels to channelize
+ fs = 1000 # baseband sampling rate
+ ifs = M*fs # input samp rate to channelizer
+
+ taps = filter.firdes.low_pass_2(1, ifs, 500, 50,
+ attenuation_dB=80,
+ window=filter.firdes.WIN_BLACKMAN_hARRIS)
+
+ signals = list()
+ add = gr.add_cc()
+ freqs = [-200, -100, 0, 100, 200]
+ for i in xrange(len(freqs)):
+ f = freqs[i] + (M/2-M+i+1)*fs
+ signals.append(gr.sig_source_c(ifs, gr.GR_SIN_WAVE, f, 1))
+ self.tb.connect(signals[i], (add,i))
+
+ head = gr.head(gr.sizeof_gr_complex, N)
+ s2ss = gr.stream_to_streams(gr.sizeof_gr_complex, M)
+ pfb = filter.pfb_channelizer_ccf(M, taps, 1)
+
+ self.tb.connect(add, head, s2ss)
+
+ snks = list()
+ for i in xrange(M):
+ snks.append(gr.vector_sink_c())
+ self.tb.connect((s2ss,i), (pfb,i))
+ self.tb.connect((pfb, i), snks[i])
+
+ self.tb.run()
+
+ Ntest = 50
+ L = len(snks[0].data())
+ t = map(lambda x: float(x)/fs, xrange(L))
+
+ # Adjusted phase rotations for data
+ p0 = 0
+ p1 = math.pi*0.51998885
+ p2 = -math.pi*0.96002233
+ p3 = math.pi*0.96002233
+ p4 = -math.pi*0.51998885
+
+ # Create known data as complex sinusoids at the different baseband freqs
+ # the different channel numbering is due to channelizer output order.
+ expected0_data = map(lambda x: math.cos(2.*math.pi*freqs[2]*x+p0) + \
+ 1j*math.sin(2.*math.pi*freqs[2]*x+p0), t)
+ expected1_data = map(lambda x: math.cos(2.*math.pi*freqs[3]*x+p1) + \
+ 1j*math.sin(2.*math.pi*freqs[3]*x+p1), t)
+ expected2_data = map(lambda x: math.cos(2.*math.pi*freqs[4]*x+p2) + \
+ 1j*math.sin(2.*math.pi*freqs[4]*x+p2), t)
+ expected3_data = map(lambda x: math.cos(2.*math.pi*freqs[0]*x+p3) + \
+ 1j*math.sin(2.*math.pi*freqs[0]*x+p3), t)
+ expected4_data = map(lambda x: math.cos(2.*math.pi*freqs[1]*x+p4) + \
+ 1j*math.sin(2.*math.pi*freqs[1]*x+p4), t)
+
+ dst0_data = snks[0].data()
+ dst1_data = snks[1].data()
+ dst2_data = snks[2].data()
+ dst3_data = snks[3].data()
+ dst4_data = snks[4].data()
+
+ self.assertComplexTuplesAlmostEqual(expected0_data[-Ntest:], dst0_data[-Ntest:], 3)
+ self.assertComplexTuplesAlmostEqual(expected1_data[-Ntest:], dst1_data[-Ntest:], 3)
+ self.assertComplexTuplesAlmostEqual(expected2_data[-Ntest:], dst2_data[-Ntest:], 3)
+ self.assertComplexTuplesAlmostEqual(expected3_data[-Ntest:], dst3_data[-Ntest:], 3)
+ self.assertComplexTuplesAlmostEqual(expected4_data[-Ntest:], dst4_data[-Ntest:], 3)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_pfb_channelizer, "test_pfb_channelizer.xml")
diff --git a/gr-filter/python/qa_pfb_decimator.py b/gr-filter/python/qa_pfb_decimator.py
new file mode 100755
index 000000000..063845f63
--- /dev/null
+++ b/gr-filter/python/qa_pfb_decimator.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+import math
+
+class test_pfb_decimator(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_000(self):
+ N = 1000 # number of samples to use
+ M = 5 # Number of channels
+ fs = 1000 # baseband sampling rate
+ ifs = M*fs # input samp rate to decimator
+ channel = 0 # Extract channel 0
+
+ taps = filter.firdes.low_pass_2(1, ifs, fs/2, fs/10,
+ attenuation_dB=80,
+ window=filter.firdes.WIN_BLACKMAN_hARRIS)
+
+ signals = list()
+ add = gr.add_cc()
+ freqs = [-200, -100, 0, 100, 200]
+ for i in xrange(len(freqs)):
+ f = freqs[i] + (M/2-M+i+1)*fs
+ signals.append(gr.sig_source_c(ifs, gr.GR_SIN_WAVE, f, 1))
+ self.tb.connect(signals[i], (add,i))
+
+ head = gr.head(gr.sizeof_gr_complex, N)
+ s2ss = gr.stream_to_streams(gr.sizeof_gr_complex, M)
+ pfb = filter.pfb_decimator_ccf(M, taps, channel)
+ snk = gr.vector_sink_c()
+
+ self.tb.connect(add, head, s2ss)
+ for i in xrange(M):
+ self.tb.connect((s2ss,i), (pfb,i))
+ self.tb.connect(pfb, snk)
+
+ self.tb.run()
+
+ Ntest = 50
+ L = len(snk.data())
+ t = map(lambda x: float(x)/fs, xrange(L))
+
+ # Create known data as complex sinusoids for the baseband freq
+ # of the extracted channel is due to decimator output order.
+ phase = 0
+ expected_data = map(lambda x: math.cos(2.*math.pi*freqs[2]*x+phase) + \
+ 1j*math.sin(2.*math.pi*freqs[2]*x+phase), t)
+
+ dst_data = snk.data()
+
+ self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 4)
+
+ def test_001(self):
+ N = 1000 # number of samples to use
+ M = 5 # Number of channels
+ fs = 1000 # baseband sampling rate
+ ifs = M*fs # input samp rate to decimator
+ channel = 1 # Extract channel 0
+
+ taps = filter.firdes.low_pass_2(1, ifs, fs/2, fs/10,
+ attenuation_dB=80,
+ window=filter.firdes.WIN_BLACKMAN_hARRIS)
+
+ signals = list()
+ add = gr.add_cc()
+ freqs = [-200, -100, 0, 100, 200]
+ for i in xrange(len(freqs)):
+ f = freqs[i] + (M/2-M+i+1)*fs
+ signals.append(gr.sig_source_c(ifs, gr.GR_SIN_WAVE, f, 1))
+ self.tb.connect(signals[i], (add,i))
+
+ head = gr.head(gr.sizeof_gr_complex, N)
+ s2ss = gr.stream_to_streams(gr.sizeof_gr_complex, M)
+ pfb = filter.pfb_decimator_ccf(M, taps, channel)
+ snk = gr.vector_sink_c()
+
+ self.tb.connect(add, head, s2ss)
+ for i in xrange(M):
+ self.tb.connect((s2ss,i), (pfb,i))
+ self.tb.connect(pfb, snk)
+
+ self.tb.run()
+
+ Ntest = 50
+ L = len(snk.data())
+ t = map(lambda x: float(x)/fs, xrange(L))
+
+ # Create known data as complex sinusoids for the baseband freq
+ # of the extracted channel is due to decimator output order.
+ phase = 6.15746
+ expected_data = map(lambda x: math.cos(2.*math.pi*freqs[3]*x+phase) + \
+ 1j*math.sin(2.*math.pi*freqs[3]*x+phase), t)
+ dst_data = snk.data()
+
+ self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 4)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_pfb_decimator, "test_pfb_decimator.xml")
diff --git a/gr-filter/python/qa_pfb_interpolator.py b/gr-filter/python/qa_pfb_interpolator.py
new file mode 100755
index 000000000..5b84b7c64
--- /dev/null
+++ b/gr-filter/python/qa_pfb_interpolator.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+import math
+
+class test_pfb_interpolator(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_000(self):
+ N = 1000 # number of samples to use
+ M = 5 # Number of channels
+ fs = 1000 # baseband sampling rate
+ ifs = M*fs # input samp rate to decimator
+
+ taps = filter.firdes.low_pass_2(M, ifs, fs/2, fs/10,
+ attenuation_dB=80,
+ window=filter.firdes.WIN_BLACKMAN_hARRIS)
+
+ freq = 100
+ signal = gr.sig_source_c(fs, gr.GR_COS_WAVE, freq, 1)
+ head = gr.head(gr.sizeof_gr_complex, N)
+ pfb = filter.pfb_interpolator_ccf(M, taps)
+ snk = gr.vector_sink_c()
+
+ self.tb.connect(signal, head, pfb)
+ self.tb.connect(pfb, snk)
+
+ self.tb.run()
+
+ Ntest = 50
+ L = len(snk.data())
+ t = map(lambda x: float(x)/ifs, xrange(L))
+
+ # Create known data as complex sinusoids at freq
+ # of the channel at the interpolated rate.
+ phase = 0.62833
+ expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \
+ 1j*math.sin(2.*math.pi*freq*x+phase), t)
+
+ dst_data = snk.data()
+
+ self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 4)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_pfb_interpolator, "test_pfb_interpolator.xml")
diff --git a/gr-filter/python/qa_pfb_synthesizer.py b/gr-filter/python/qa_pfb_synthesizer.py
new file mode 100755
index 000000000..e8164d268
--- /dev/null
+++ b/gr-filter/python/qa_pfb_synthesizer.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+import math
+
+class test_pfb_synthesizer(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_000(self):
+ N = 10000 # number of samples to use
+ M = 5 # Number of channels
+ fs = 1000 # baseband sampling rate
+ ofs = M*fs # input samp rate to decimator
+
+ taps = filter.firdes.low_pass_2(M, ofs, fs/2, fs/10,
+ attenuation_dB=80,
+ window=filter.firdes.WIN_BLACKMAN_hARRIS)
+
+ signals = list()
+ freqs = [0, 100, 200, -200, -100]
+ for i in xrange(len(freqs)):
+ signals.append(gr.sig_source_c(fs, gr.GR_SIN_WAVE, freqs[i], 1))
+
+ head = gr.head(gr.sizeof_gr_complex, N)
+ pfb = filter.pfb_synthesizer_ccf(M, taps)
+ snk = gr.vector_sink_c()
+
+ for i in xrange(M):
+ self.tb.connect(signals[i], (pfb,i))
+
+ self.tb.connect(pfb, head, snk)
+
+ self.tb.run()
+
+ Ntest = 1000
+ L = len(snk.data())
+ t = map(lambda x: float(x)/ofs, xrange(L))
+
+ # Create known data as sum of complex sinusoids at freqs
+ # of the output channels.
+ freqs = [-2200, -1100, 0, 1100, 2200]
+ expected_data = len(t)*[0,]
+ for i in xrange(len(t)):
+ expected_data[i] = math.cos(2.*math.pi*freqs[0]*t[i]) + \
+ 1j*math.sin(2.*math.pi*freqs[0]*t[i]) + \
+ math.cos(2.*math.pi*freqs[1]*t[i]) + \
+ 1j*math.sin(2.*math.pi*freqs[1]*t[i]) + \
+ math.cos(2.*math.pi*freqs[2]*t[i]) + \
+ 1j*math.sin(2.*math.pi*freqs[2]*t[i]) + \
+ math.cos(2.*math.pi*freqs[3]*t[i]) + \
+ 1j*math.sin(2.*math.pi*freqs[3]*t[i]) + \
+ math.cos(2.*math.pi*freqs[4]*t[i]) + \
+ 1j*math.sin(2.*math.pi*freqs[4]*t[i])
+ dst_data = snk.data()
+
+ offset = 25
+ self.assertComplexTuplesAlmostEqual(expected_data[2000-offset:2000-offset+Ntest],
+ dst_data[2000:2000+Ntest], 4)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_pfb_synthesizer, "test_pfb_synthesizer.xml")
diff --git a/gr-filter/python/qa_pm_remez.py b/gr-filter/python/qa_pm_remez.py
new file mode 100755
index 000000000..a76e14c93
--- /dev/null
+++ b/gr-filter/python/qa_pm_remez.py
@@ -0,0 +1,188 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+import sys, math
+
+# ----------------------------------------------------------------
+# See optfir for an explanation of these.
+
+def stopband_atten_to_dev (atten_db):
+ """Convert a stopband attenuation in dB to an absolute value"""
+ return 10**(-atten_db/20)
+
+def passband_ripple_to_dev (ripple_db):
+ """Convert passband ripple spec expressed in dB to an absolute value"""
+ return (10**(ripple_db/20)-1)/(10**(ripple_db/20)+1)
+
+# ----------------------------------------------------------------
+
+def remezord (fcuts, mags, devs, fsamp = 2):
+ '''
+ FIR order estimator (lowpass, highpass, bandpass, mulitiband).
+ '''
+
+ # get local copies
+ fcuts = fcuts[:]
+ mags = mags[:]
+ devs = devs[:]
+
+ for i in range (len (fcuts)):
+ fcuts[i] = float (fcuts[i]) / fsamp
+
+ nf = len (fcuts)
+ nm = len (mags)
+ nd = len (devs)
+ nbands = nm
+
+ if nm != nd:
+ raise ValueError, "Length of mags and devs must be equal"
+
+ if nf != 2 * (nbands - 1):
+ raise ValueError, "Length of f must be 2 * len (mags) - 2"
+
+ for i in range (len (mags)):
+ if mags[i] != 0: # if not stopband, get relative deviation
+ devs[i] = devs[i] / mags[i]
+
+ # separate the passband and stopband edges
+ f1 = fcuts[0::2]
+ f2 = fcuts[1::2]
+
+ n = 0
+ min_delta = 2
+ for i in range (len (f1)):
+ if f2[i] - f1[i] < min_delta:
+ n = i
+ min_delta = f2[i] - f1[i]
+
+ if nbands == 2:
+ # lowpass or highpass case (use formula)
+ l = lporder (f1[n], f2[n], devs[0], devs[1])
+ else:
+ # bandpass or multipass case
+ # try different lowpasses and take the worst one that
+ # goes through the BP specs
+ l = 0
+ for i in range (1, nbands-1):
+ l1 = lporder (f1[i-1], f2[i-1], devs[i], devs[i-1])
+ l2 = lporder (f1[i], f2[i], devs[i], devs[i+1])
+ l = max (l, l1, l2)
+
+ n = int (math.ceil (l)) - 1 # need order, not length for remez
+
+ # cook up remez compatible result
+ ff = [0] + fcuts + [1]
+ for i in range (1, len (ff) - 1):
+ ff[i] *= 2
+
+ aa = []
+ for a in mags:
+ aa = aa + [a, a]
+
+ max_dev = max (devs)
+ wts = [1] * len(devs)
+ for i in range (len (wts)):
+ wts[i] = max_dev / devs[i]
+
+ return (n, ff, aa, wts)
+
+
+def lporder (freq1, freq2, delta_p, delta_s):
+ '''
+ FIR lowpass filter length estimator.
+ '''
+ df = abs (freq2 - freq1)
+ ddp = math.log10 (delta_p)
+ dds = math.log10 (delta_s)
+
+ a1 = 5.309e-3
+ a2 = 7.114e-2
+ a3 = -4.761e-1
+ a4 = -2.66e-3
+ a5 = -5.941e-1
+ a6 = -4.278e-1
+
+ b1 = 11.01217
+ b2 = 0.5124401
+
+ t1 = a1 * ddp * ddp
+ t2 = a2 * ddp
+ t3 = a4 * ddp * ddp
+ t4 = a5 * ddp
+
+ dinf=((t1 + t2 + a3) * dds) + (t3 + t4 + a6)
+ ff = b1 + b2 * (ddp - dds)
+ n = dinf / df - ff * df + 1
+ return n
+
+# ----------------------------------------------------------------
+
+class test_pm_remez(gr_unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_low_pass(self):
+ gain = 1
+ Fs = 1
+ freq1 = 0.1
+ freq2 = 0.2
+ passband_ripple_db = 0.01
+ stopband_atten_db = 60
+
+ passband_dev = passband_ripple_to_dev(passband_ripple_db)
+ stopband_dev = stopband_atten_to_dev(stopband_atten_db)
+ desired_ampls = (gain, 0)
+ (n, fo, ao, w) = remezord([freq1, freq2], desired_ampls,
+ [passband_dev, stopband_dev], Fs)
+ new_taps = filter.pm_remez(n + 2, fo, ao, w, "bandpass")
+
+ known_taps = (-0.0008370135734511828, -0.0006622211673134374,
+ 0.0008501079576365787, 0.003059609130249229,
+ 0.003202235537205373, -0.001000899296974219,
+ -0.007589728680590891, -0.009790921118281865,
+ -0.001524210202628562, 0.014373535837200111,
+ 0.02392881326993834, 0.011798133085019008,
+ -0.021954446348997188, -0.05293436740264934,
+ -0.04375787096766848, 0.028038890498420392,
+ 0.14612655590172896, 0.25738578419108626,
+ 0.302967004188747, 0.25738578419108626,
+ 0.14612655590172896, 0.028038890498420392,
+ -0.04375787096766848, -0.05293436740264934,
+ -0.021954446348997188, 0.011798133085019008,
+ 0.02392881326993834, 0.014373535837200111,
+ -0.001524210202628562, -0.009790921118281865,
+ -0.007589728680590891, -0.001000899296974219,
+ 0.003202235537205373, 0.003059609130249229,
+ 0.0008501079576365787, -0.0006622211673134374,
+ -0.0008370135734511828)
+
+ self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_pm_remez, "test_pm_remez.xml")
+
diff --git a/gr-filter/python/qa_rational_resampler.py b/gr-filter/python/qa_rational_resampler.py
new file mode 100755
index 000000000..eb86ef542
--- /dev/null
+++ b/gr-filter/python/qa_rational_resampler.py
@@ -0,0 +1,257 @@
+#!/usr/bin/env python
+#
+# Copyright 2005,2006,2007,2010 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+import math
+import random
+import sys
+
+
+def random_floats(n):
+ r = []
+ for x in xrange(n):
+ # r.append(float(random.randint(-32768, 32768)))
+ r.append(float(random.random()))
+ return tuple(r)
+
+
+def reference_dec_filter(src_data, decim, taps):
+ tb = gr.top_block()
+ src = gr.vector_source_f(src_data)
+ op = filter.fir_filter_fff(decim, taps)
+ dst = gr.vector_sink_f()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+ tb = None
+ return result_data
+
+def reference_interp_filter(src_data, interp, taps):
+ tb = gr.top_block()
+ src = gr.vector_source_f(src_data)
+ op = filter.interp_fir_filter_fff(interp, taps)
+ dst = gr.vector_sink_f()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+ tb = None
+ return result_data
+
+def reference_interp_dec_filter(src_data, interp, decim, taps):
+ tb = gr.top_block()
+ src = gr.vector_source_f(src_data)
+ up = filter.interp_fir_filter_fff(interp, (1,))
+ dn = filter.fir_filter_fff(decim, taps)
+ dst = gr.vector_sink_f()
+ tb.connect(src, up, dn, dst)
+ tb.run()
+ result_data = dst.data()
+ tb = None
+ return result_data
+
+
+class test_rational_resampler (gr_unittest.TestCase):
+
+ def setUp(self):
+ random.seed(0)
+
+ def tearDown(self):
+ pass
+
+
+ def test_000_1_to_1(self):
+ taps = (-4, 5)
+ src_data = (234, -4, 23, -56, 45, 98, -23, -7)
+ xr = (1186, -112, 339, -460, -167, 582)
+ expected_result = tuple([float(x) for x in xr])
+
+ tb = gr.top_block()
+ src = gr.vector_source_f(src_data)
+ op = filter.rational_resampler_base_fff(1, 1, taps)
+ dst = gr.vector_sink_f()
+ tb.connect(src, op)
+ tb.connect(op, dst)
+ tb.run()
+ result_data = dst.data()
+ self.assertEqual(expected_result, result_data)
+
+ def test_001_interp(self):
+ taps = [1, 10, 100, 1000, 10000]
+ src_data = (0, 2, 3, 5, 7, 11, 13, 17)
+ interpolation = 3
+ xr = (0,2,20,200,2003,20030,
+ 300,3005,30050,
+ 500,5007,50070,
+ 700,7011,70110,
+ 1100,11013,110130,
+ 1300,13017,130170,
+ 1700.0,17000.0,170000.0)
+ expected_result = tuple([float(x) for x in xr])
+
+ tb = gr.top_block()
+ src = gr.vector_source_f(src_data)
+ op = filter.rational_resampler_base_fff(interpolation, 1, taps)
+ dst = gr.vector_sink_f()
+ tb.connect(src, op)
+ tb.connect(op, dst)
+ tb.run()
+ result_data = dst.data()
+ self.assertEqual(expected_result, result_data)
+
+ def test_002_interp(self):
+ taps = random_floats(31)
+ src_data = random_floats(10000)
+ interpolation = 3
+
+ expected_result = reference_interp_filter(src_data, interpolation, taps)
+
+ tb = gr.top_block()
+ src = gr.vector_source_f(src_data)
+ op = filter.rational_resampler_base_fff(interpolation, 1, taps)
+ dst = gr.vector_sink_f()
+ tb.connect(src, op)
+ tb.connect(op, dst)
+ tb.run()
+ result_data = dst.data()
+
+ N = 1000
+ offset = len(taps)-1
+ self.assertEqual(expected_result[offset:offset+N], result_data[0:N])
+
+ def xtest_003_interp(self):
+ taps = random_floats(9)
+ src_data = random_floats(10000)
+ decimation = 3
+
+ expected_result = reference_dec_filter(src_data, decimation, taps)
+
+ tb = gr.top_block()
+ src = gr.vector_source_f(src_data)
+ op = filter.rational_resampler_base_fff(1, decimation, taps)
+ dst = gr.vector_sink_f()
+ tb.connect(src, op)
+ tb.connect(op, dst)
+ tb.run()
+ result_data = dst.data()
+
+ N = 10
+ offset = 10#len(taps)-1
+ print expected_result[100+offset:100+offset+N]
+ print result_data[100:100+N]
+ #self.assertEqual(expected_result[offset:offset+N], result_data[0:N])
+
+ # FIXME disabled. Triggers hang on SuSE 10.0
+ def xtest_004_decim_random_vals(self):
+ MAX_TAPS = 9
+ MAX_DECIM = 7
+ OUTPUT_LEN = 9
+
+ random.seed(0) # we want reproducibility
+
+ for ntaps in xrange(1, MAX_TAPS + 1):
+ for decim in xrange(1, MAX_DECIM+1):
+ for ilen in xrange(ntaps + decim, ntaps + OUTPUT_LEN*decim):
+ src_data = random_floats(ilen)
+ taps = random_floats(ntaps)
+ expected_result = reference_dec_filter(src_data, decim, taps)
+
+ tb = gr.top_block()
+ src = gr.vector_source_f(src_data)
+ op = filter.rational_resampler_base_fff(1, decim, taps)
+ dst = gr.vector_sink_f()
+ tb.connect(src, op, dst)
+ tb.run()
+ tb = None
+ result_data = dst.data()
+
+ L1 = len(result_data)
+ L2 = len(expected_result)
+ L = min(L1, L2)
+ if False:
+ sys.stderr.write('delta = %2d: ntaps = %d decim = %d ilen = %d\n' % (L2 - L1, ntaps, decim, ilen))
+ sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' %
+ (len(result_data), len(expected_result)))
+ self.assertEqual(expected_result[0:L], result_data[0:L])
+
+
+ # FIXME disabled. Triggers hang on SuSE 10.0
+ def xtest_005_interp_random_vals(self):
+ MAX_TAPS = 9
+ MAX_INTERP = 7
+ INPUT_LEN = 9
+
+ random.seed(0) # we want reproducibility
+
+ for ntaps in xrange(1, MAX_TAPS + 1):
+ for interp in xrange(1, MAX_INTERP+1):
+ for ilen in xrange(ntaps, ntaps + INPUT_LEN):
+ src_data = random_floats(ilen)
+ taps = random_floats(ntaps)
+ expected_result = reference_interp_filter(src_data, interp, taps)
+
+ tb = gr.top_block()
+ src = gr.vector_source_f(src_data)
+ op = filter.rational_resampler_base_fff(interp, 1, taps)
+ dst = gr.vector_sink_f()
+ tb.connect(src, op, dst)
+ tb.run()
+ tb = None
+ result_data = dst.data()
+ L1 = len(result_data)
+ L2 = len(expected_result)
+ L = min(L1, L2)
+ #if True or abs(L1-L2) > 1:
+ if False:
+ sys.stderr.write('delta = %2d: ntaps = %d interp = %d ilen = %d\n' % (L2 - L1, ntaps, interp, ilen))
+ #sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' %
+ # (len(result_data), len(expected_result)))
+ #self.assertEqual(expected_result[0:L], result_data[0:L])
+ # FIXME check first ntaps+1 answers
+ self.assertEqual(expected_result[ntaps+1:L], result_data[ntaps+1:L])
+
+ def test_006_interp_decim(self):
+ taps = random_floats(31)
+ src_data = random_floats(10000)
+ interp = 3
+ decimation = 2
+
+ expected_result = reference_interp_dec_filter(src_data, interp, decimation, taps)
+
+ tb = gr.top_block()
+ src = gr.vector_source_f(src_data)
+ op = filter.rational_resampler_base_fff(interp, decimation, taps)
+ dst = gr.vector_sink_f()
+ tb.connect(src, op)
+ tb.connect(op, dst)
+ tb.run()
+ result_data = dst.data()
+
+ N = 1000
+ offset = len(taps)/2
+ self.assertFloatTuplesAlmostEqual(expected_result[offset:offset+N], result_data[0:N], 5)
+
+
+if __name__ == '__main__':
+ # FIXME: Disabled, see ticket:210
+ gr_unittest.run(test_rational_resampler, "test_rational_resampler.xml")
+
diff --git a/gr-filter/python/qa_single_pole_iir.py b/gr-filter/python/qa_single_pole_iir.py
new file mode 100755
index 000000000..3608c77f9
--- /dev/null
+++ b/gr-filter/python/qa_single_pole_iir.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+#
+# Copyright 2005,2007,2010 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+
+class test_single_pole_iir_filter(gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_ff_001(self):
+ src_data = (0, 1000, 2000, 3000, 4000, 5000)
+ expected_result = src_data
+ src = gr.vector_source_f(src_data)
+ op = filter.single_pole_iir_filter_ff(1.0)
+ dst = gr.vector_sink_f()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual(expected_result, result_data)
+
+ def test_ff_002(self):
+ src_data = (0, 1000, 2000, 3000, 4000, 5000)
+ expected_result = (0, 125, 359.375, 689.453125, 1103.271484, 1590.36255)
+ src = gr.vector_source_f(src_data)
+ op = filter.single_pole_iir_filter_ff(0.125)
+ dst = gr.vector_sink_f()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual(expected_result, result_data, 3)
+
+ def test_ff_003(self):
+ block_size = 2
+ src_data = (0, 1000, 2000, 3000, 4000, 5000)
+ expected_result = (0, 125, 250, 484.375, 718.75, 1048.828125)
+ src = gr.vector_source_f(src_data)
+ s2p = gr.serial_to_parallel(gr.sizeof_float, block_size)
+ op = filter.single_pole_iir_filter_ff (0.125, block_size)
+ p2s = gr.parallel_to_serial(gr.sizeof_float, block_size)
+ dst = gr.vector_sink_f()
+ self.tb.connect(src, s2p, op, p2s, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual(expected_result, result_data, 3)
+
+ def test_cc_001(self):
+ src_data = (0+0j, 1000+1000j, 2000+2000j, 3000+3000j, 4000+4000j, 5000+5000j)
+ expected_result = src_data
+ src = gr.vector_source_c(src_data)
+ op = filter.single_pole_iir_filter_cc(1.0)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_result, result_data)
+
+ def test_cc_002(self):
+ src_data = (complex(0,0), complex(1000,-1000), complex(2000,-2000),
+ complex(3000,-3000), complex(4000,-4000), complex(5000,-5000))
+ expected_result = (complex(0,0), complex(125,-125), complex(359.375,-359.375),
+ complex(689.453125,-689.453125), complex(1103.271484,-1103.271484),
+ complex(1590.36255,-1590.36255))
+ src = gr.vector_source_c(src_data)
+ op = filter.single_pole_iir_filter_cc(0.125)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_result, result_data, 3)
+
+ def test_cc_003(self):
+ block_size = 2
+ src_data = (complex(0,0), complex(1000,-1000), complex(2000,-2000),
+ complex(3000,-3000), complex(4000,-4000), complex(5000,-5000))
+ expected_result = (complex(0,0), complex(125,-125), complex(250,-250),
+ complex(484.375,-484.375), complex(718.75,-718.75),
+ complex(1048.828125,-1048.828125))
+ src = gr.vector_source_c(src_data)
+ s2p = gr.serial_to_parallel(gr.sizeof_gr_complex, block_size)
+ op = filter.single_pole_iir_filter_cc(0.125, block_size)
+ p2s = gr.parallel_to_serial(gr.sizeof_gr_complex, block_size)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, s2p, op, p2s, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_result, result_data, 3)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_single_pole_iir_filter, "test_single_pole_iir_filter.xml")
+
diff --git a/gr-filter/python/rational_resampler.py b/gr-filter/python/rational_resampler.py
new file mode 100644
index 000000000..312b011d3
--- /dev/null
+++ b/gr-filter/python/rational_resampler.py
@@ -0,0 +1,129 @@
+#
+# Copyright 2005,2007 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gru
+
+_plot = None
+
+def design_filter(interpolation, decimation, fractional_bw):
+ """
+ Given the interpolation rate, decimation rate and a fractional bandwidth,
+ design a set of taps.
+
+ @param interpolation: interpolation factor
+ @type interpolation: integer > 0
+ @param decimation: decimation factor
+ @type decimation: integer > 0
+ @param fractional_bw: fractional bandwidth in (0, 0.5) 0.4 works well.
+ @type fractional_bw: float
+ @returns: sequence of numbers
+ """
+
+ if fractional_bw >= 0.5 or fractional_bw <= 0:
+ raise ValueError, "Invalid fractional_bandwidth, must be in (0, 0.5)"
+
+ beta = 5.0
+ trans_width = 0.5 - fractional_bw
+ mid_transition_band = 0.5 - trans_width/2
+
+ taps = filter.firdes.low_pass(interpolation, # gain
+ 1, # Fs
+ mid_transition_band/interpolation, # trans mid point
+ trans_width/interpolation, # transition width
+ filter.firdes.WIN_KAISER,
+ beta) # beta
+ return taps
+
+
+
+class _rational_resampler_base(gr.hier_block2):
+ """
+ base class for all rational resampler variants.
+ """
+ def __init__(self, resampler_base,
+ interpolation, decimation, taps=None, fractional_bw=None):
+ """
+ Rational resampling polyphase FIR filter.
+
+ Either taps or fractional_bw may be specified, but not both.
+ If neither is specified, a reasonable default, 0.4, is used as
+ the fractional_bw.
+
+ @param interpolation: interpolation factor
+ @type interpolation: integer > 0
+ @param decimation: decimation factor
+ @type decimation: integer > 0
+ @param taps: optional filter coefficients
+ @type taps: sequence
+ @param fractional_bw: fractional bandwidth in (0, 0.5), measured at final freq (use 0.4)
+ @type fractional_bw: float
+ """
+
+ if not isinstance(interpolation, int) or interpolation < 1:
+ raise ValueError, "interpolation must be an integer >= 1"
+
+ if not isinstance(decimation, int) or decimation < 1:
+ raise ValueError, "decimation must be an integer >= 1"
+
+ if taps is None and fractional_bw is None:
+ fractional_bw = 0.4
+
+ d = gru.gcd(interpolation, decimation)
+ interpolation = interpolation // d
+ decimation = decimation // d
+
+ if taps is None:
+ taps = design_filter(interpolation, decimation, fractional_bw)
+
+ resampler = resampler_base(interpolation, decimation, taps)
+ gr.hier_block2.__init__(self, "rational_resampler",
+ gr.io_signature(1, 1, resampler.input_signature().sizeof_stream_item(0)),
+ gr.io_signature(1, 1, resampler.output_signature().sizeof_stream_item(0)))
+
+ self.connect(self, resampler, self)
+
+
+class rational_resampler_fff(_rational_resampler_base):
+ def __init__(self, interpolation, decimation, taps=None, fractional_bw=None):
+ """
+ Rational resampling polyphase FIR filter with
+ float input, float output and float taps.
+ """
+ _rational_resampler_base.__init__(self, filter.rational_resampler_base_fff,
+ interpolation, decimation, taps, fractional_bw)
+
+class rational_resampler_ccf(_rational_resampler_base):
+ def __init__(self, interpolation, decimation, taps=None, fractional_bw=None):
+ """
+ Rational resampling polyphase FIR filter with
+ complex input, complex output and float taps.
+ """
+ _rational_resampler_base.__init__(self, filter.rational_resampler_base_ccf,
+ interpolation, decimation, taps, fractional_bw)
+
+class rational_resampler_ccc(_rational_resampler_base):
+ def __init__(self, interpolation, decimation, taps=None, fractional_bw=None):
+ """
+ Rational resampling polyphase FIR filter with
+ complex input, complex output and complex taps.
+ """
+ _rational_resampler_base.__init__(self, filter.rational_resampler_base_ccc,
+ interpolation, decimation, taps, fractional_bw)
diff --git a/gr-filter/swig/CMakeLists.txt b/gr-filter/swig/CMakeLists.txt
new file mode 100644
index 000000000..3eee3a1ee
--- /dev/null
+++ b/gr-filter/swig/CMakeLists.txt
@@ -0,0 +1,53 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+# Setup swig generation
+########################################################################
+include(GrPython)
+include(GrSwig)
+
+set(GR_SWIG_INCLUDE_DIRS
+ ${GR_FILTER_INCLUDE_DIRS}
+ ${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
+ ${FFT_INCLUDE_DIRS}
+ ${FFTW3F_INCLUDE_DIRS}
+)
+
+# FIXME: rename to filter_swig_doc.i when gnuradio-core is updated
+set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/gr_filter_swig_doc.i)
+set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../lib)
+
+set(GR_SWIG_LIBRARIES gnuradio-filter gnuradio-fft)
+
+GR_SWIG_MAKE(filter_swig filter_swig.i)
+
+GR_SWIG_INSTALL(
+ TARGETS filter_swig
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/filter
+ COMPONENT "filter_python"
+)
+
+install(
+ FILES
+ filter_swig.i
+ ${CMAKE_CURRENT_BINARY_DIR}/gr_filter_swig_doc.i
+ DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig
+ COMPONENT "filter_swig"
+)
diff --git a/gr-filter/swig/filter_swig.i b/gr-filter/swig/filter_swig.i
new file mode 100644
index 000000000..05b84d4d6
--- /dev/null
+++ b/gr-filter/swig/filter_swig.i
@@ -0,0 +1,169 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#define FILTER_API
+
+%include "gnuradio.i"
+
+//load generated python docstrings
+%include "gr_filter_swig_doc.i"
+
+%{
+#include "filter/firdes.h"
+#include "filter/pm_remez.h"
+#include "filter/adaptive_fir_ccc.h"
+#include "filter/adaptive_fir_ccf.h"
+#include "filter/dc_blocker_cc.h"
+#include "filter/dc_blocker_ff.h"
+#include "filter/filter_delay_fc.h"
+#include "filter/fir_filter_ccc.h"
+#include "filter/fir_filter_ccf.h"
+#include "filter/fir_filter_fcc.h"
+#include "filter/fir_filter_fff.h"
+#include "filter/fir_filter_fsf.h"
+#include "filter/fir_filter_scc.h"
+#include "filter/fft_filter_ccc.h"
+#include "filter/fft_filter_fff.h"
+#include "filter/fractional_interpolator_cc.h"
+#include "filter/fractional_interpolator_ff.h"
+#include "filter/freq_xlating_fir_filter_ccc.h"
+#include "filter/freq_xlating_fir_filter_ccf.h"
+#include "filter/freq_xlating_fir_filter_fcc.h"
+#include "filter/freq_xlating_fir_filter_fcf.h"
+#include "filter/freq_xlating_fir_filter_scf.h"
+#include "filter/freq_xlating_fir_filter_scc.h"
+#include "filter/hilbert_fc.h"
+#include "filter/iir_filter_ffd.h"
+#include "filter/interp_fir_filter_ccc.h"
+#include "filter/interp_fir_filter_ccf.h"
+#include "filter/interp_fir_filter_fcc.h"
+#include "filter/interp_fir_filter_fff.h"
+#include "filter/interp_fir_filter_fsf.h"
+#include "filter/interp_fir_filter_scc.h"
+#include "filter/pfb_arb_resampler_ccf.h"
+#include "filter/pfb_arb_resampler_fff.h"
+#include "filter/pfb_channelizer_ccf.h"
+#include "filter/pfb_decimator_ccf.h"
+#include "filter/pfb_interpolator_ccf.h"
+#include "filter/pfb_synthesizer_ccf.h"
+#include "filter/rational_resampler_base_ccc.h"
+#include "filter/rational_resampler_base_ccf.h"
+#include "filter/rational_resampler_base_fcc.h"
+#include "filter/rational_resampler_base_fff.h"
+#include "filter/rational_resampler_base_fsf.h"
+#include "filter/rational_resampler_base_scc.h"
+#include "filter/single_pole_iir_filter_cc.h"
+#include "filter/single_pole_iir_filter_ff.h"
+#include "filter/channel_model.h"
+%}
+
+%include "filter/firdes.h"
+%include "filter/pm_remez.h"
+%include "filter/adaptive_fir_ccc.h"
+%include "filter/adaptive_fir_ccf.h"
+%include "filter/dc_blocker_cc.h"
+%include "filter/dc_blocker_ff.h"
+%include "filter/filter_delay_fc.h"
+%include "filter/fir_filter_ccc.h"
+%include "filter/fir_filter_ccf.h"
+%include "filter/fir_filter_fcc.h"
+%include "filter/fir_filter_fff.h"
+%include "filter/fir_filter_fsf.h"
+%include "filter/fir_filter_scc.h"
+%include "filter/fft_filter_ccc.h"
+%include "filter/fft_filter_fff.h"
+%include "filter/fractional_interpolator_cc.h"
+%include "filter/fractional_interpolator_ff.h"
+%include "filter/freq_xlating_fir_filter_ccc.h"
+%include "filter/freq_xlating_fir_filter_ccf.h"
+%include "filter/freq_xlating_fir_filter_fcc.h"
+%include "filter/freq_xlating_fir_filter_fcf.h"
+%include "filter/freq_xlating_fir_filter_scf.h"
+%include "filter/freq_xlating_fir_filter_scc.h"
+%include "filter/hilbert_fc.h"
+%include "filter/iir_filter_ffd.h"
+%include "filter/interp_fir_filter_ccc.h"
+%include "filter/interp_fir_filter_ccf.h"
+%include "filter/interp_fir_filter_fcc.h"
+%include "filter/interp_fir_filter_fff.h"
+%include "filter/interp_fir_filter_fsf.h"
+%include "filter/interp_fir_filter_scc.h"
+%include "filter/pfb_arb_resampler_ccf.h"
+%include "filter/pfb_arb_resampler_fff.h"
+%include "filter/pfb_channelizer_ccf.h"
+%include "filter/pfb_decimator_ccf.h"
+%include "filter/pfb_interpolator_ccf.h"
+%include "filter/pfb_synthesizer_ccf.h"
+%include "filter/rational_resampler_base_ccc.h"
+%include "filter/rational_resampler_base_ccf.h"
+%include "filter/rational_resampler_base_fcc.h"
+%include "filter/rational_resampler_base_fff.h"
+%include "filter/rational_resampler_base_fsf.h"
+%include "filter/rational_resampler_base_scc.h"
+%include "filter/single_pole_iir_filter_cc.h"
+%include "filter/single_pole_iir_filter_ff.h"
+%include "filter/channel_model.h"
+
+GR_SWIG_BLOCK_MAGIC2(filter, adaptive_fir_ccc);
+GR_SWIG_BLOCK_MAGIC2(filter, adaptive_fir_ccf);
+GR_SWIG_BLOCK_MAGIC2(filter, dc_blocker_cc);
+GR_SWIG_BLOCK_MAGIC2(filter, dc_blocker_ff);
+GR_SWIG_BLOCK_MAGIC2(filter, filter_delay_fc);
+GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_ccc);
+GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_ccf);
+GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_fcc);
+GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_fff);
+GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_fsf);
+GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_scc);
+GR_SWIG_BLOCK_MAGIC2(filter, fft_filter_ccc);
+GR_SWIG_BLOCK_MAGIC2(filter, fft_filter_fff);
+GR_SWIG_BLOCK_MAGIC2(filter, fractional_interpolator_cc);
+GR_SWIG_BLOCK_MAGIC2(filter, fractional_interpolator_ff);
+GR_SWIG_BLOCK_MAGIC2(filter, freq_xlating_fir_filter_ccc);
+GR_SWIG_BLOCK_MAGIC2(filter, freq_xlating_fir_filter_ccf);
+GR_SWIG_BLOCK_MAGIC2(filter, freq_xlating_fir_filter_fcc);
+GR_SWIG_BLOCK_MAGIC2(filter, freq_xlating_fir_filter_fcf);
+GR_SWIG_BLOCK_MAGIC2(filter, freq_xlating_fir_filter_scf);
+GR_SWIG_BLOCK_MAGIC2(filter, freq_xlating_fir_filter_scc);
+GR_SWIG_BLOCK_MAGIC2(filter, hilbert_fc);
+GR_SWIG_BLOCK_MAGIC2(filter, iir_filter_ffd);
+GR_SWIG_BLOCK_MAGIC2(filter, interp_fir_filter_ccc);
+GR_SWIG_BLOCK_MAGIC2(filter, interp_fir_filter_ccf);
+GR_SWIG_BLOCK_MAGIC2(filter, interp_fir_filter_fcc);
+GR_SWIG_BLOCK_MAGIC2(filter, interp_fir_filter_fff);
+GR_SWIG_BLOCK_MAGIC2(filter, interp_fir_filter_fsf);
+GR_SWIG_BLOCK_MAGIC2(filter, interp_fir_filter_scc);
+GR_SWIG_BLOCK_MAGIC2(filter, pfb_arb_resampler_ccf);
+GR_SWIG_BLOCK_MAGIC2(filter, pfb_arb_resampler_fff);
+GR_SWIG_BLOCK_MAGIC2(filter, pfb_channelizer_ccf);
+GR_SWIG_BLOCK_MAGIC2(filter, pfb_decimator_ccf);
+GR_SWIG_BLOCK_MAGIC2(filter, pfb_interpolator_ccf);
+GR_SWIG_BLOCK_MAGIC2(filter, pfb_synthesizer_ccf);
+GR_SWIG_BLOCK_MAGIC2(filter, rational_resampler_base_ccc);
+GR_SWIG_BLOCK_MAGIC2(filter, rational_resampler_base_ccf);
+GR_SWIG_BLOCK_MAGIC2(filter, rational_resampler_base_fcc);
+GR_SWIG_BLOCK_MAGIC2(filter, rational_resampler_base_fff);
+GR_SWIG_BLOCK_MAGIC2(filter, rational_resampler_base_fsf);
+GR_SWIG_BLOCK_MAGIC2(filter, rational_resampler_base_scc);
+GR_SWIG_BLOCK_MAGIC2(filter, single_pole_iir_filter_cc);
+GR_SWIG_BLOCK_MAGIC2(filter, single_pole_iir_filter_ff);
+GR_SWIG_BLOCK_MAGIC2(filter, channel_model);
diff --git a/gr-uhd/include/gr_uhd_usrp_source.h b/gr-uhd/include/gr_uhd_usrp_source.h
index 80d80bcb8..b5acabee4 100644
--- a/gr-uhd/include/gr_uhd_usrp_source.h
+++ b/gr-uhd/include/gr_uhd_usrp_source.h
@@ -60,11 +60,17 @@ class uhd_usrp_source;
*
* The following tag keys will be produced by the work function:
* - pmt::pmt_string_to_symbol("rx_time")
+ * - pmt::pmt_string_to_symbol("rx_rate")
+ * - pmt::pmt_string_to_symbol("rx_freq")
*
* The timstamp tag value is a pmt tuple of the following:
* (uint64 seconds, and double fractional seconds).
* A timestamp tag is produced at start() and after overflows.
*
+ * The sample rate and center frequency tags are doubles,
+ * representing the sample rate in Sps and frequency in Hz.
+ * These tags are produced upon the user changing parameters.
+ *
* See the UHD manual for more detailed documentation:
* http://code.ettus.com/redmine/ettus/projects/uhd/wiki
*
diff --git a/gr-uhd/lib/gr_uhd_usrp_source.cc b/gr-uhd/lib/gr_uhd_usrp_source.cc
index 8aa965401..ad4cb4d81 100644
--- a/gr-uhd/lib/gr_uhd_usrp_source.cc
+++ b/gr-uhd/lib/gr_uhd_usrp_source.cc
@@ -24,10 +24,13 @@
#include <stdexcept>
#include <iostream>
#include <boost/format.hpp>
+#include <boost/thread/thread.hpp>
#include <boost/make_shared.hpp>
#include "gr_uhd_common.h"
static const pmt::pmt_t TIME_KEY = pmt::pmt_string_to_symbol("rx_time");
+static const pmt::pmt_t RATE_KEY = pmt::pmt_string_to_symbol("rx_rate");
+static const pmt::pmt_t FREQ_KEY = pmt::pmt_string_to_symbol("rx_freq");
#include <uhd/convert.hpp>
inline gr_io_signature_sptr args_to_io_sig(const uhd::stream_args_t &args){
@@ -88,6 +91,8 @@ public:
void set_samp_rate(double rate){
_dev->set_rx_rate(rate);
+ _samp_rate = this->get_samp_rate();
+ _tag_now = true;
}
double get_samp_rate(void){
@@ -105,7 +110,10 @@ public:
uhd::tune_result_t set_center_freq(
const uhd::tune_request_t tune_request, size_t chan
){
- return _dev->set_rx_freq(tune_request, chan);
+ const uhd::tune_result_t res = _dev->set_rx_freq(tune_request, chan);
+ _center_freq = this->get_center_freq(chan);
+ _tag_now = true;
+ return res;
}
double get_center_freq(size_t chan){
@@ -330,9 +338,10 @@ public:
//If receive resulted in a timeout condition:
//We now receive a single packet with a large timeout.
- if (_metadata.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT){
+ while (_metadata.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT){
+ if (boost::this_thread::interruption_requested()) return WORK_DONE;
num_samps = _rx_stream->recv(
- output_items, noutput_items, _metadata, 1.0, true/*one pkt*/
+ output_items, noutput_items, _metadata, 0.1, true/*one pkt*/
);
}
#else
@@ -358,9 +367,11 @@ public:
pmt::pmt_from_uint64(_metadata.time_spec.get_full_secs()),
pmt::pmt_from_double(_metadata.time_spec.get_frac_secs())
);
- //create a timestamp tag for each channel
+ //create a tag set for each channel
for (size_t i = 0; i < _nchan; i++){
this->add_item_tag(i, nitems_written(0), TIME_KEY, val, _id);
+ this->add_item_tag(i, nitems_written(0), RATE_KEY, pmt::pmt_from_double(_samp_rate), _id);
+ this->add_item_tag(i, nitems_written(0), FREQ_KEY, pmt::pmt_from_double(_center_freq), _id);
}
}
break;
@@ -508,6 +519,10 @@ private:
uhd::time_spec_t _start_time;
bool _start_time_set;
+
+ //tag shadows
+ double _samp_rate;
+ double _center_freq;
};
diff --git a/gr-wavelet/lib/CMakeLists.txt b/gr-wavelet/lib/CMakeLists.txt
index d0c632800..9594f6a6a 100644
--- a/gr-wavelet/lib/CMakeLists.txt
+++ b/gr-wavelet/lib/CMakeLists.txt
@@ -21,19 +21,16 @@
# Setup the include and linker paths
########################################################################
include_directories(
- ${GNURADIO_CORE_INCLUDE_DIRS}
${GR_WAVELET_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
+ ${GNURADIO_CORE_INCLUDE_DIRS}
+ ${Boost_INCLUDE_DIRS}
+ ${GSL_INCLUDE_DIRS}
)
-include_directories(${WAVELET_INCLUDE_DIRS})
link_directories(${WAVELET_LIBRARY_DIRS})
-
-include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
-
-include_directories(${GSL_INCLUDE_DIRS})
link_directories(${GSL_LIBRARY_DIRS})
add_definitions(${GSL_DEFINITIONS})
diff --git a/gr-wxgui/CMakeLists.txt b/gr-wxgui/CMakeLists.txt
index 0fc26dee1..8150c7d80 100644
--- a/gr-wxgui/CMakeLists.txt
+++ b/gr-wxgui/CMakeLists.txt
@@ -76,7 +76,7 @@ install(
########################################################################
install(
FILES ${CMAKE_CURRENT_SOURCE_DIR}/gr-wxgui.conf
- DESTINATION ${GR_PKG_CONF_DIR}
+ DESTINATION ${GR_PREFSDIR}
COMPONENT "wxgui"
)
diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt
index f54aa4f80..219bbe164 100644
--- a/grc/CMakeLists.txt
+++ b/grc/CMakeLists.txt
@@ -75,7 +75,7 @@ configure_file(
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/grc.conf
- DESTINATION ${GR_PKG_CONF_DIR}
+ DESTINATION ${GR_PREFSDIR}
COMPONENT "grc"
)
diff --git a/grc/blocks/block_tree.xml b/grc/blocks/block_tree.xml
index 0b0b6854e..3b5491a74 100644
--- a/grc/blocks/block_tree.xml
+++ b/grc/blocks/block_tree.xml
@@ -20,6 +20,7 @@
<block>gr_udp_source</block>
<block>gr_wavfile_source</block>
<block>gr_message_source</block>
+ <block>gr_message_burst_source</block>
<block>pad_source</block>
<block>virtual_source</block>
</cat>
@@ -34,6 +35,7 @@
<block>gr_message_sink</block>
<block>pad_sink</block>
<block>virtual_sink</block>
+ <block>gr_tag_debug</block>
</cat>
<cat>
<name>Operators</name>
diff --git a/grc/blocks/gr_message_burst_source.xml b/grc/blocks/gr_message_burst_source.xml
new file mode 100644
index 000000000..e835d2a2c
--- /dev/null
+++ b/grc/blocks/gr_message_burst_source.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Message Burst Source (the sink port is a message)
+###################################################
+ -->
+<block>
+ <name>Message Burst Source</name>
+ <key>gr_message_burst_source</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.message_burst_source($type.size*$vlen, $(id)_msgq_in)</make>
+ <param>
+ <name>Output Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>msg</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_tag_debug.xml b/grc/blocks/gr_tag_debug.xml
new file mode 100644
index 000000000..4af7729be
--- /dev/null
+++ b/grc/blocks/gr_tag_debug.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Tag Debug
+###################################################
+ -->
+<block>
+ <name>Tag Debug</name>
+ <key>gr_tag_debug</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.tag_debug($type.size*$vlen, $name)</make>
+ <callback>set_display($display)</callback>
+ <param>
+ <name>Input Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Name</name>
+ <key>name</key>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Num Inputs</name>
+ <key>num_inputs</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Display</name>
+ <key>display</key>
+ <value>True</value>
+ <type>bool</type>
+ <option>
+ <name>On</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Off</name>
+ <key>False</key>
+ </option>
+ </param>
+ <check>$num_inputs &gt;= 1</check>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_inputs</nports>
+ </sink>
+</block>
diff --git a/gruel/src/include/gruel/CMakeLists.txt b/gruel/src/include/gruel/CMakeLists.txt
index 9818f1c09..d4c36eddb 100644
--- a/gruel/src/include/gruel/CMakeLists.txt
+++ b/gruel/src/include/gruel/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2010-2011 Free Software Foundation, Inc.
+# Copyright 2010-2012 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -18,30 +18,12 @@
# Boston, MA 02110-1301, USA.
########################################################################
-# Generate inet.h header file
-########################################################################
-include(TestBigEndian)
-enable_language(C)
-TEST_BIG_ENDIAN(GR_ARCH_BIGENDIAN)
-
-include(CheckIncludeFileCXX)
-CHECK_INCLUDE_FILE_CXX(byteswap.h GR_HAVE_BYTESWAP)
-CHECK_INCLUDE_FILE_CXX(arpa/inet.h GR_HAVE_ARPA_INET)
-CHECK_INCLUDE_FILE_CXX(netinet/in.h GR_HAVE_NETINET_IN)
-
-configure_file(
- ${CMAKE_CURRENT_SOURCE_DIR}/inet.h.in
- ${CMAKE_CURRENT_BINARY_DIR}/inet.h
-@ONLY)
-
-########################################################################
# Install the headers
########################################################################
install(FILES
api.h
attributes.h
high_res_timer.h
- ${CMAKE_CURRENT_BINARY_DIR}/inet.h
msg_accepter.h
msg_accepter_msgq.h
msg_queue.h
diff --git a/gruel/src/include/gruel/inet.h.in b/gruel/src/include/gruel/inet.h.in
deleted file mode 100644
index 74f14bd92..000000000
--- a/gruel/src/include/gruel/inet.h.in
+++ /dev/null
@@ -1,100 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008, 2009 Free Software Foundation, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef INCLUDED_INET_H
-#define INCLUDED_INET_H
-
-#include <gruel/api.h>
-#include <stdint.h>
-
-#if 1 /* missing htonll or ntohll */
-#if @GR_ARCH_BIGENDIAN@ /* GR_ARCH_BIGENDIAN */
-// Nothing to do...
-static inline uint64_t htonll(uint64_t x){ return x;}
-static inline uint64_t ntohll(uint64_t x){ return x;}
-#else
-#if @GR_HAVE_BYTESWAP@ /* GR_HAVE_BYTESWAP */
-#include <byteswap.h>
-#else
-
-static inline uint64_t
-bswap_64(uint64_t x)
-{
- return ((x & 0x00000000000000ffull) << 56) | ((x & 0x000000000000ff00ull) << 40) |
- ((x & 0x0000000000ff0000ull) << 24) | ((x & 0x00000000ff000000ull) << 8) |
- ((x & 0x000000ff00000000ull) >> 8) | ((x & 0x0000ff0000000000ull) >> 24) |
- ((x & 0x00ff000000000000ull) >> 40) | ((x & 0xff00000000000000ull) >> 56);
-}
-
-#endif /* GR_HAVE_BYTESWAP */
-
-static inline uint64_t htonll(uint64_t x){ return bswap_64(x);}
-static inline uint64_t ntohll(uint64_t x){ return bswap_64(x);}
-
-#endif /* GR_ARCH_BIGENDIAN */
-#endif /* missing htonll or ntohll */
-
-#if @GR_HAVE_ARPA_INET@ /* GR_HAVE_ARPA_INET */
-#include <arpa/inet.h>
-#elif @GR_HAVE_NETINET_IN@ /* GR_HAVE_NETINET_IN */
-#include <netinet/in.h>
-#else
-#include <stdint.h>
-
-#if @GR_ARCH_BIGENDIAN@ /* GR_ARCH_BIGENDIAN */
-// Nothing to do...
-static inline uint32_t htonl(uint32_t x){ return x; }
-static inline uint16_t htons(uint16_t x){ return x; }
-static inline uint32_t ntohl(uint32_t x){ return x; }
-static inline uint16_t ntohs(uint16_t x){ return x; }
-#else
-#if @GR_HAVE_BYTESWAP@ /* GR_HAVE_BYTESWAP */
-#include <byteswap.h>
-#else
-static inline uint16_t
-bswap_16 (uint16_t x)
-{
- return ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8));
-}
-
-static inline uint32_t
-bswap_32 (uint32_t x)
-{
- return ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \
- | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24));
-}
-#endif /* GR_HAVE_BYTESWAP */
-
-static inline uint32_t htonl(uint32_t x){ return bswap_32(x); }
-static inline uint16_t htons(uint16_t x){ return bswap_16(x); }
-static inline uint32_t ntohl(uint32_t x){ return bswap_32(x); }
-static inline uint16_t ntohs(uint16_t x){ return bswap_16(x); }
-#endif /* GR_ARCH_BIGENDIAN */
-
-#endif /* !(GR_HAVE_NETINET_IN || GR_HAVE_ARPA_INET) */
-
-static inline uint8_t ntohx(uint8_t x){ return x; }
-static inline uint16_t ntohx(uint16_t x){ return ntohs(x); }
-static inline uint32_t ntohx(uint32_t x){ return ntohl(x); }
-static inline uint64_t ntohx(uint64_t x){ return ntohll(x);}
-static inline uint8_t htonx(uint8_t x){ return x; }
-static inline uint16_t htonx(uint16_t x){ return htons(x); }
-static inline uint32_t htonx(uint32_t x){ return htonl(x); }
-static inline uint64_t htonx(uint64_t x){ return htonll(x);}
-
-#endif /* INCLUDED_INET_H */
diff --git a/gruel/src/lib/pmt/pmt-serial-tags.scm b/gruel/src/lib/pmt/pmt-serial-tags.scm
index ca25a43a8..4f06bf75f 100644
--- a/gruel/src/lib/pmt/pmt-serial-tags.scm
+++ b/gruel/src/lib/pmt/pmt-serial-tags.scm
@@ -33,6 +33,8 @@
(define pst-dict #x09) ; untagged-int32 n; followed by n key/value tuples
(define pst-uniform-vector #x0a)
+(define pst-uint64 #x0b)
+(define pst-tuple #x0c)
;; u8, s8, u16, s16, u32, s32, u64, s64, f32, f64, c32, c64
;;
diff --git a/gruel/src/lib/pmt/pmt_serialize.cc b/gruel/src/lib/pmt/pmt_serialize.cc
index de9644c3c..a19809a66 100644
--- a/gruel/src/lib/pmt/pmt_serialize.cc
+++ b/gruel/src/lib/pmt/pmt_serialize.cc
@@ -79,7 +79,6 @@ serialize_untagged_f64(double i, std::streambuf &sb)
}
-#if 0
// always writes big-endian
static bool
serialize_untagged_u64(uint64_t i, std::streambuf &sb)
@@ -93,7 +92,6 @@ serialize_untagged_u64(uint64_t i, std::streambuf &sb)
sb.sputc((i >> 8) & 0xff);
return sb.sputc((i >> 0) & 0xff) != std::streambuf::traits_type::eof();
}
-#endif
// ----------------------------------------------------------------
// input primitives
@@ -152,7 +150,6 @@ deserialize_untagged_u32(uint32_t *ip, std::streambuf &sb)
return t != std::streambuf::traits_type::eof();
}
-#if 0
// always reads big-endian
static bool
deserialize_untagged_u64(uint64_t *ip, std::streambuf &sb)
@@ -181,7 +178,6 @@ deserialize_untagged_u64(uint64_t *ip, std::streambuf &sb)
*ip = i;
return t != std::streambuf::traits_type::eof();
}
-#endif
static bool
deserialize_untagged_f64(double *ip, std::streambuf &sb)
@@ -217,6 +213,24 @@ deserialize_untagged_f64(double *ip, std::streambuf &sb)
return t != std::streambuf::traits_type::eof();
}
+static bool
+deserialize_tuple(pmt_t *tuple, std::streambuf &sb)
+{
+ uint32_t nitems;
+ bool ok = deserialize_untagged_u32(&nitems, sb);
+ pmt_t list(PMT_NIL);
+ for(uint32_t i=0; i<nitems; i++){
+ pmt_t item = pmt_deserialize( sb );
+ if(pmt_eq(list, PMT_NIL)){
+ list = pmt_list1(item);
+ } else {
+ list = pmt_list_add(list, item);
+ }
+ }
+ (*tuple) = pmt_to_tuple(list);
+ return ok;
+}
+
/*
* Write portable byte-serial representation of \p obj to \p sb
@@ -260,7 +274,13 @@ pmt_serialize(pmt_t obj, std::streambuf &sb)
}
if (pmt_is_number(obj)){
-
+
+ if (pmt_is_uint64(obj)){
+ uint64_t i = pmt_to_uint64(obj);
+ ok = serialize_untagged_u8(PST_UINT64, sb);
+ ok &= serialize_untagged_u64(i, sb);
+ return ok;
+ } else
if (pmt_is_integer(obj)){
long i = pmt_to_long(obj);
if (sizeof(long) > 4){
@@ -298,6 +318,16 @@ pmt_serialize(pmt_t obj, std::streambuf &sb)
if (pmt_is_dict(obj))
throw pmt_notimplemented("pmt_serialize (dict)", obj);
+ if (pmt_is_tuple(obj)){
+ size_t tuple_len = pmt::pmt_length(obj);
+ ok = serialize_untagged_u8(PST_TUPLE, sb);
+ ok &= serialize_untagged_u32(tuple_len, sb);
+ for(size_t i=0; i<tuple_len; i++){
+ ok &= pmt_serialize(pmt_tuple_ref(obj, i), sb);
+ }
+ return ok;
+ }
+ //throw pmt_notimplemented("pmt_serialize (tuple)", obj);
throw pmt_notimplemented("pmt_serialize (?)", obj);
}
@@ -315,7 +345,7 @@ pmt_deserialize(std::streambuf &sb)
//uint8_t u8;
uint16_t u16;
uint32_t u32;
- //uint32_t u64;
+ uint64_t u64;
double f64;
static char tmpbuf[1024];
@@ -347,6 +377,11 @@ pmt_deserialize(std::streambuf &sb)
goto error;
return pmt_from_long((int32_t) u32);
+ case PST_UINT64:
+ if(!deserialize_untagged_u64(&u64, sb))
+ goto error;
+ return pmt_from_uint64(u64);
+
case PST_PAIR:
return parse_pair(sb);
@@ -362,6 +397,15 @@ pmt_deserialize(std::streambuf &sb)
goto error;
return pmt_make_rectangular( r,i );
}
+
+ case PST_TUPLE:
+ {
+ pmt_t tuple;
+ if(!deserialize_tuple(&tuple, sb)){
+ goto error;
+ }
+ return tuple;
+ }
case PST_VECTOR:
case PST_DICT:
diff --git a/gruel/src/swig/CMakeLists.txt b/gruel/src/swig/CMakeLists.txt
index 968622587..332d5866f 100644
--- a/gruel/src/swig/CMakeLists.txt
+++ b/gruel/src/swig/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2011 Free Software Foundation, Inc.
+# Copyright 2011-2012 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
diff --git a/volk/apps/volk_profile.cc b/volk/apps/volk_profile.cc
index 0b4442108..648f4d878 100644
--- a/volk/apps/volk_profile.cc
+++ b/volk/apps/volk_profile.cc
@@ -33,6 +33,8 @@ int main(int argc, char *argv[]) {
//VOLK_PROFILE(volk_16i_permute_and_scalar_add_a, 1e-4, 0, 2046, 10000, &results);
//VOLK_PROFILE(volk_16i_x4_quad_max_star_16i_a, 1e-4, 0, 2046, 10000, &results);
VOLK_PROFILE(volk_16u_byteswap_a, 0, 0, 204600, 10000, &results);
+ VOLK_PROFILE(volk_16u_byteswap_u, 0, 0, 204600, 10000, &results);
+ VOLK_PROFILE(volk_16i_32fc_dot_prod_32fc_a, 1e-4, 0, 204600, 10000, &results);
VOLK_PROFILE(volk_32f_accumulator_s32f_a, 1e-4, 0, 204600, 10000, &results);
VOLK_PROFILE(volk_32f_x2_add_32f_a, 1e-4, 0, 204600, 10000, &results);
VOLK_PROFILE(volk_32f_x2_add_32f_u, 1e-4, 0, 204600, 10000, &results);
@@ -49,6 +51,7 @@ int main(int argc, char *argv[]) {
VOLK_PROFILE(volk_32fc_deinterleave_real_32f_a, 1e-4, 0, 204600, 5000, &results);
VOLK_PROFILE(volk_32fc_deinterleave_real_64f_a, 1e-4, 0, 204600, 1000, &results);
VOLK_PROFILE(volk_32fc_x2_dot_prod_32fc_a, 1e-4, 0, 204600, 10000, &results);
+ VOLK_PROFILE(volk_32fc_32f_dot_prod_32fc_a, 1e-4, 0, 204600, 10000, &results);
VOLK_PROFILE(volk_32fc_index_max_16u_a, 3, 0, 204600, 10000, &results);
VOLK_PROFILE(volk_32fc_s32f_magnitude_16i_a, 1, 32768, 204600, 100, &results);
VOLK_PROFILE(volk_32fc_magnitude_32f_a, 1e-4, 0, 204600, 1000, &results);
@@ -76,6 +79,7 @@ int main(int argc, char *argv[]) {
VOLK_PROFILE(volk_32f_x2_divide_32f_a, 1e-4, 0, 204600, 2000, &results);
VOLK_PROFILE(volk_32f_x2_dot_prod_32f_a, 1e-4, 0, 204600, 5000, &results);
VOLK_PROFILE(volk_32f_x2_dot_prod_32f_u, 1e-4, 0, 204600, 5000, &results);
+ VOLK_PROFILE(volk_32f_x2_dot_prod_16i_a, 1e-4, 0, 204600, 5000, &results);
//VOLK_PROFILE(volk_32f_s32f_32f_fm_detect_32f_a, 1e-4, 2046, 10000, &results);
VOLK_PROFILE(volk_32f_index_max_16u_a, 3, 0, 204600, 5000, &results);
VOLK_PROFILE(volk_32f_x2_s32f_interleave_16ic_a, 1, 32768, 204600, 3000, &results);
diff --git a/volk/gen/machines.xml b/volk/gen/machines.xml
index 8e3c9c8c2..d88a1a50c 100644
--- a/volk/gen/machines.xml
+++ b/volk/gen/machines.xml
@@ -10,7 +10,7 @@
</machine>
<machine name="sse">
-<archs>generic 32|64| mmx sse orc|</archs>
+<archs>generic 32|64| mmx| sse orc|</archs>
</machine>
-->
@@ -20,7 +20,7 @@
<!-- trailing | bar means generate without either for MSVC -->
<machine name="sse2">
-<archs>generic 32|64| mmx sse sse2 orc|</archs>
+<archs>generic 32|64| mmx| sse sse2 orc|</archs>
</machine>
<machine name="sse3">
@@ -45,7 +45,7 @@
<!-- trailing | bar means generate without either for MSVC -->
<machine name="avx">
-<archs>generic 32|64| mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 popcount avx orc|</archs>
+<archs>generic 32|64| mmx| sse sse2 sse3 ssse3 sse4_1 sse4_2 popcount avx orc|</archs>
</machine>
<machine name="altivec">
diff --git a/volk/include/volk/volk_16i_32fc_dot_prod_32fc_a.h b/volk/include/volk/volk_16i_32fc_dot_prod_32fc_a.h
new file mode 100644
index 000000000..1f6554af8
--- /dev/null
+++ b/volk/include/volk/volk_16i_32fc_dot_prod_32fc_a.h
@@ -0,0 +1,122 @@
+#ifndef INCLUDED_volk_16i_32fc_dot_prod_32fc_a_H
+#define INCLUDED_volk_16i_32fc_dot_prod_32fc_a_H
+
+#include <volk/volk_common.h>
+#include<stdio.h>
+
+
+#ifdef LV_HAVE_GENERIC
+
+
+static inline void volk_16i_32fc_dot_prod_32fc_a_generic(lv_32fc_t* result, const short* input, const lv_32fc_t * taps, unsigned int num_points) {
+
+ static const int N_UNROLL = 4;
+
+ lv_32fc_t acc0 = 0;
+ lv_32fc_t acc1 = 0;
+ lv_32fc_t acc2 = 0;
+ lv_32fc_t acc3 = 0;
+
+ unsigned i = 0;
+ unsigned n = (num_points / N_UNROLL) * N_UNROLL;
+
+ for(i = 0; i < n; i += N_UNROLL) {
+ acc0 += taps[i + 0] * (float)input[i + 0];
+ acc1 += taps[i + 1] * (float)input[i + 1];
+ acc2 += taps[i + 2] * (float)input[i + 2];
+ acc3 += taps[i + 3] * (float)input[i + 3];
+ }
+
+ for(; i < num_points; i++) {
+ acc0 += taps[i] * (float)input[i];
+ }
+
+ *result = acc0 + acc1 + acc2 + acc3;
+}
+
+#endif /*LV_HAVE_GENERIC*/
+
+
+#if LV_HAVE_SSE && LV_HAVE_MMX
+
+
+static inline void volk_16i_32fc_dot_prod_32fc_a_sse( lv_32fc_t* result, const short* input, const lv_32fc_t* taps, unsigned int num_points) {
+
+ unsigned int number = 0;
+ const unsigned int sixteenthPoints = num_points / 8;
+
+ float res[2];
+ float *realpt = &res[0], *imagpt = &res[1];
+ const short* aPtr = input;
+ const float* bPtr = (float*)taps;
+
+ __m64 m0, m1;
+ __m128 f0, f1, f2, f3;
+ __m128 a0Val, a1Val, a2Val, a3Val;
+ __m128 b0Val, b1Val, b2Val, b3Val;
+ __m128 c0Val, c1Val, c2Val, c3Val;
+
+ __m128 dotProdVal0 = _mm_setzero_ps();
+ __m128 dotProdVal1 = _mm_setzero_ps();
+ __m128 dotProdVal2 = _mm_setzero_ps();
+ __m128 dotProdVal3 = _mm_setzero_ps();
+
+ for(;number < sixteenthPoints; number++){
+
+ m0 = _mm_set_pi16(*(aPtr+3), *(aPtr+2), *(aPtr+1), *(aPtr+0));
+ m1 = _mm_set_pi16(*(aPtr+7), *(aPtr+6), *(aPtr+5), *(aPtr+4));
+ f0 = _mm_cvtpi16_ps(m0);
+ f1 = _mm_cvtpi16_ps(m0);
+ f2 = _mm_cvtpi16_ps(m1);
+ f3 = _mm_cvtpi16_ps(m1);
+
+ a0Val = _mm_unpacklo_ps(f0, f1);
+ a1Val = _mm_unpackhi_ps(f0, f1);
+ a2Val = _mm_unpacklo_ps(f2, f3);
+ a3Val = _mm_unpackhi_ps(f2, f3);
+
+ b0Val = _mm_load_ps(bPtr);
+ b1Val = _mm_load_ps(bPtr+4);
+ b2Val = _mm_load_ps(bPtr+8);
+ b3Val = _mm_load_ps(bPtr+12);
+
+ c0Val = _mm_mul_ps(a0Val, b0Val);
+ c1Val = _mm_mul_ps(a1Val, b1Val);
+ c2Val = _mm_mul_ps(a2Val, b2Val);
+ c3Val = _mm_mul_ps(a3Val, b3Val);
+
+ dotProdVal0 = _mm_add_ps(c0Val, dotProdVal0);
+ dotProdVal1 = _mm_add_ps(c1Val, dotProdVal1);
+ dotProdVal2 = _mm_add_ps(c2Val, dotProdVal2);
+ dotProdVal3 = _mm_add_ps(c3Val, dotProdVal3);
+
+ aPtr += 8;
+ bPtr += 16;
+ }
+
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal1);
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal2);
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal3);
+
+ __VOLK_ATTR_ALIGNED(16) float dotProductVector[4];
+
+ _mm_store_ps(dotProductVector,dotProdVal0); // Store the results back into the dot product vector
+
+ *realpt = dotProductVector[0];
+ *imagpt = dotProductVector[1];
+ *realpt += dotProductVector[2];
+ *imagpt += dotProductVector[3];
+
+ number = sixteenthPoints*8;
+ for(;number < num_points; number++){
+ *realpt += ((*aPtr) * (*bPtr++));
+ *imagpt += ((*aPtr++) * (*bPtr++));
+ }
+
+ *result = *(lv_32fc_t*)(&res[0]);
+}
+
+#endif /*LV_HAVE_SSE && LV_HAVE_MMX*/
+
+
+#endif /*INCLUDED_volk_16i_32fc_dot_prod_32fc_a_H*/
diff --git a/volk/include/volk/volk_16u_byteswap_u.h b/volk/include/volk/volk_16u_byteswap_u.h
new file mode 100644
index 000000000..8ef627a62
--- /dev/null
+++ b/volk/include/volk/volk_16u_byteswap_u.h
@@ -0,0 +1,63 @@
+#ifndef INCLUDED_volk_16u_byteswap_u_H
+#define INCLUDED_volk_16u_byteswap_u_H
+
+#include <inttypes.h>
+#include <stdio.h>
+
+#ifdef LV_HAVE_SSE2
+#include <emmintrin.h>
+
+/*!
+ \brief Byteswaps (in-place) an unaligned vector of int16_t's.
+ \param intsToSwap The vector of data to byte swap
+ \param numDataPoints The number of data points
+*/
+static inline void volk_16u_byteswap_u_sse2(uint16_t* intsToSwap, unsigned int num_points){
+ unsigned int number = 0;
+ uint16_t* inputPtr = intsToSwap;
+ __m128i input, left, right, output;
+
+ const unsigned int eighthPoints = num_points / 8;
+ for(;number < eighthPoints; number++){
+ // Load the 16t values, increment inputPtr later since we're doing it in-place.
+ input = _mm_loadu_si128((__m128i*)inputPtr);
+ // Do the two shifts
+ left = _mm_slli_epi16(input, 8);
+ right = _mm_srli_epi16(input, 8);
+ // Or the left and right halves together
+ output = _mm_or_si128(left, right);
+ // Store the results
+ _mm_storeu_si128((__m128i*)inputPtr, output);
+ inputPtr += 8;
+ }
+
+ // Byteswap any remaining points:
+ number = eighthPoints*8;
+ for(; number < num_points; number++){
+ uint16_t outputVal = *inputPtr;
+ outputVal = (((outputVal >> 8) & 0xff) | ((outputVal << 8) & 0xff00));
+ *inputPtr = outputVal;
+ inputPtr++;
+ }
+}
+#endif /* LV_HAVE_SSE2 */
+
+#ifdef LV_HAVE_GENERIC
+/*!
+ \brief Byteswaps (in-place) an unaligned vector of int16_t's.
+ \param intsToSwap The vector of data to byte swap
+ \param numDataPoints The number of data points
+*/
+static inline void volk_16u_byteswap_u_generic(uint16_t* intsToSwap, unsigned int num_points){
+ unsigned int point;
+ uint16_t* inputPtr = intsToSwap;
+ for(point = 0; point < num_points; point++){
+ uint16_t output = *inputPtr;
+ output = (((output >> 8) & 0xff) | ((output << 8) & 0xff00));
+ *inputPtr = output;
+ inputPtr++;
+ }
+}
+#endif /* LV_HAVE_GENERIC */
+
+#endif /* INCLUDED_volk_16u_byteswap_u_H */
diff --git a/volk/include/volk/volk_32f_x2_dot_prod_16i_a.h b/volk/include/volk/volk_32f_x2_dot_prod_16i_a.h
new file mode 100644
index 000000000..961c2418c
--- /dev/null
+++ b/volk/include/volk/volk_32f_x2_dot_prod_16i_a.h
@@ -0,0 +1,98 @@
+#ifndef INCLUDED_volk_32f_x2_dot_prod_16i_a_H
+#define INCLUDED_volk_32f_x2_dot_prod_16i_a_H
+
+#include <volk/volk_common.h>
+#include<stdio.h>
+
+
+#ifdef LV_HAVE_GENERIC
+
+
+static inline void volk_32f_x2_dot_prod_16i_a_generic(int16_t* result, const float* input, const float* taps, unsigned int num_points) {
+
+ float dotProduct = 0;
+ const float* aPtr = input;
+ const float* bPtr= taps;
+ unsigned int number = 0;
+
+ for(number = 0; number < num_points; number++){
+ dotProduct += ((*aPtr++) * (*bPtr++));
+ }
+
+ *result = (int16_t)dotProduct;
+}
+
+#endif /*LV_HAVE_GENERIC*/
+
+
+#ifdef LV_HAVE_SSE
+
+
+static inline void volk_32f_x2_dot_prod_16i_a_sse(int16_t* result, const float* input, const float* taps, unsigned int num_points) {
+
+ unsigned int number = 0;
+ const unsigned int sixteenthPoints = num_points / 16;
+
+ float dotProduct = 0;
+ const float* aPtr = input;
+ const float* bPtr = taps;
+
+ __m128 a0Val, a1Val, a2Val, a3Val;
+ __m128 b0Val, b1Val, b2Val, b3Val;
+ __m128 c0Val, c1Val, c2Val, c3Val;
+
+ __m128 dotProdVal0 = _mm_setzero_ps();
+ __m128 dotProdVal1 = _mm_setzero_ps();
+ __m128 dotProdVal2 = _mm_setzero_ps();
+ __m128 dotProdVal3 = _mm_setzero_ps();
+
+ for(;number < sixteenthPoints; number++){
+
+ a0Val = _mm_load_ps(aPtr);
+ a1Val = _mm_load_ps(aPtr+4);
+ a2Val = _mm_load_ps(aPtr+8);
+ a3Val = _mm_load_ps(aPtr+12);
+ b0Val = _mm_load_ps(bPtr);
+ b1Val = _mm_load_ps(bPtr+4);
+ b2Val = _mm_load_ps(bPtr+8);
+ b3Val = _mm_load_ps(bPtr+12);
+
+ c0Val = _mm_mul_ps(a0Val, b0Val);
+ c1Val = _mm_mul_ps(a1Val, b1Val);
+ c2Val = _mm_mul_ps(a2Val, b2Val);
+ c3Val = _mm_mul_ps(a3Val, b3Val);
+
+ dotProdVal0 = _mm_add_ps(c0Val, dotProdVal0);
+ dotProdVal1 = _mm_add_ps(c1Val, dotProdVal1);
+ dotProdVal2 = _mm_add_ps(c2Val, dotProdVal2);
+ dotProdVal3 = _mm_add_ps(c3Val, dotProdVal3);
+
+ aPtr += 16;
+ bPtr += 16;
+ }
+
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal1);
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal2);
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal3);
+
+ __VOLK_ATTR_ALIGNED(16) float dotProductVector[4];
+
+ _mm_store_ps(dotProductVector,dotProdVal0); // Store the results back into the dot product vector
+
+ dotProduct = dotProductVector[0];
+ dotProduct += dotProductVector[1];
+ dotProduct += dotProductVector[2];
+ dotProduct += dotProductVector[3];
+
+ number = sixteenthPoints*16;
+ for(;number < num_points; number++){
+ dotProduct += ((*aPtr++) * (*bPtr++));
+ }
+
+ *result = (short)dotProduct;
+
+}
+
+#endif /*LV_HAVE_SSE*/
+
+#endif /*INCLUDED_volk_32f_x2_dot_prod_16i_a_H*/
diff --git a/volk/include/volk/volk_32f_x2_dot_prod_32f_a.h b/volk/include/volk/volk_32f_x2_dot_prod_32f_a.h
index 448b2fdc0..067c33ad8 100644
--- a/volk/include/volk/volk_32f_x2_dot_prod_32f_a.h
+++ b/volk/include/volk/volk_32f_x2_dot_prod_32f_a.h
@@ -31,39 +31,60 @@ static inline void volk_32f_x2_dot_prod_32f_a_generic(float * result, const floa
static inline void volk_32f_x2_dot_prod_32f_a_sse( float* result, const float* input, const float* taps, unsigned int num_points) {
unsigned int number = 0;
- const unsigned int quarterPoints = num_points / 4;
+ const unsigned int sixteenthPoints = num_points / 16;
float dotProduct = 0;
const float* aPtr = input;
const float* bPtr = taps;
- __m128 aVal, bVal, cVal;
-
- __m128 dotProdVal = _mm_setzero_ps();
-
- for(;number < quarterPoints; number++){
+ __m128 a0Val, a1Val, a2Val, a3Val;
+ __m128 b0Val, b1Val, b2Val, b3Val;
+ __m128 c0Val, c1Val, c2Val, c3Val;
- aVal = _mm_load_ps(aPtr);
- bVal = _mm_load_ps(bPtr);
+ __m128 dotProdVal0 = _mm_setzero_ps();
+ __m128 dotProdVal1 = _mm_setzero_ps();
+ __m128 dotProdVal2 = _mm_setzero_ps();
+ __m128 dotProdVal3 = _mm_setzero_ps();
- cVal = _mm_mul_ps(aVal, bVal);
-
- dotProdVal = _mm_add_ps(cVal, dotProdVal);
+ for(;number < sixteenthPoints; number++){
- aPtr += 4;
- bPtr += 4;
+ a0Val = _mm_load_ps(aPtr);
+ a1Val = _mm_load_ps(aPtr+4);
+ a2Val = _mm_load_ps(aPtr+8);
+ a3Val = _mm_load_ps(aPtr+12);
+ b0Val = _mm_load_ps(bPtr);
+ b1Val = _mm_load_ps(bPtr+4);
+ b2Val = _mm_load_ps(bPtr+8);
+ b3Val = _mm_load_ps(bPtr+12);
+
+ c0Val = _mm_mul_ps(a0Val, b0Val);
+ c1Val = _mm_mul_ps(a1Val, b1Val);
+ c2Val = _mm_mul_ps(a2Val, b2Val);
+ c3Val = _mm_mul_ps(a3Val, b3Val);
+
+ dotProdVal0 = _mm_add_ps(c0Val, dotProdVal0);
+ dotProdVal1 = _mm_add_ps(c1Val, dotProdVal1);
+ dotProdVal2 = _mm_add_ps(c2Val, dotProdVal2);
+ dotProdVal3 = _mm_add_ps(c3Val, dotProdVal3);
+
+ aPtr += 16;
+ bPtr += 16;
}
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal1);
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal2);
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal3);
+
__VOLK_ATTR_ALIGNED(16) float dotProductVector[4];
- _mm_store_ps(dotProductVector,dotProdVal); // Store the results back into the dot product vector
+ _mm_store_ps(dotProductVector,dotProdVal0); // Store the results back into the dot product vector
dotProduct = dotProductVector[0];
dotProduct += dotProductVector[1];
dotProduct += dotProductVector[2];
dotProduct += dotProductVector[3];
- number = quarterPoints * 4;
+ number = sixteenthPoints*16;
for(;number < num_points; number++){
dotProduct += ((*aPtr++) * (*bPtr++));
}
@@ -80,38 +101,59 @@ static inline void volk_32f_x2_dot_prod_32f_a_sse( float* result, const float*
static inline void volk_32f_x2_dot_prod_32f_a_sse3(float * result, const float * input, const float * taps, unsigned int num_points) {
unsigned int number = 0;
- const unsigned int quarterPoints = num_points / 4;
+ const unsigned int sixteenthPoints = num_points / 16;
float dotProduct = 0;
const float* aPtr = input;
const float* bPtr = taps;
- __m128 aVal, bVal, cVal;
-
- __m128 dotProdVal = _mm_setzero_ps();
-
- for(;number < quarterPoints; number++){
+ __m128 a0Val, a1Val, a2Val, a3Val;
+ __m128 b0Val, b1Val, b2Val, b3Val;
+ __m128 c0Val, c1Val, c2Val, c3Val;
- aVal = _mm_load_ps(aPtr);
- bVal = _mm_load_ps(bPtr);
+ __m128 dotProdVal0 = _mm_setzero_ps();
+ __m128 dotProdVal1 = _mm_setzero_ps();
+ __m128 dotProdVal2 = _mm_setzero_ps();
+ __m128 dotProdVal3 = _mm_setzero_ps();
- cVal = _mm_mul_ps(aVal, bVal);
-
- dotProdVal = _mm_hadd_ps(dotProdVal, cVal);
+ for(;number < sixteenthPoints; number++){
- aPtr += 4;
- bPtr += 4;
+ a0Val = _mm_load_ps(aPtr);
+ a1Val = _mm_load_ps(aPtr+4);
+ a2Val = _mm_load_ps(aPtr+8);
+ a3Val = _mm_load_ps(aPtr+12);
+ b0Val = _mm_load_ps(bPtr);
+ b1Val = _mm_load_ps(bPtr+4);
+ b2Val = _mm_load_ps(bPtr+8);
+ b3Val = _mm_load_ps(bPtr+12);
+
+ c0Val = _mm_mul_ps(a0Val, b0Val);
+ c1Val = _mm_mul_ps(a1Val, b1Val);
+ c2Val = _mm_mul_ps(a2Val, b2Val);
+ c3Val = _mm_mul_ps(a3Val, b3Val);
+
+ dotProdVal0 = _mm_add_ps(dotProdVal0, c0Val);
+ dotProdVal1 = _mm_add_ps(dotProdVal1, c1Val);
+ dotProdVal2 = _mm_add_ps(dotProdVal2, c2Val);
+ dotProdVal3 = _mm_add_ps(dotProdVal3, c3Val);
+
+ aPtr += 16;
+ bPtr += 16;
}
- __VOLK_ATTR_ALIGNED(16) float dotProductVector[4];
- dotProdVal = _mm_hadd_ps(dotProdVal, dotProdVal);
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal1);
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal2);
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal3);
- _mm_store_ps(dotProductVector,dotProdVal); // Store the results back into the dot product vector
+ __VOLK_ATTR_ALIGNED(16) float dotProductVector[4];
+ _mm_store_ps(dotProductVector,dotProdVal0); // Store the results back into the dot product vector
dotProduct = dotProductVector[0];
dotProduct += dotProductVector[1];
+ dotProduct += dotProductVector[2];
+ dotProduct += dotProductVector[3];
- number = quarterPoints * 4;
+ number = sixteenthPoints*16;
for(;number < num_points; number++){
dotProduct += ((*aPtr++) * (*bPtr++));
}
@@ -182,4 +224,67 @@ static inline void volk_32f_x2_dot_prod_32f_a_sse4_1(float * result, const float
#endif /*LV_HAVE_SSE4_1*/
+#ifdef LV_HAVE_AVX
+
+#include <immintrin.h>
+
+static inline void volk_32f_x2_dot_prod_32f_a_avx( float* result, const float* input, const float* taps, unsigned int num_points) {
+
+ unsigned int number = 0;
+ const unsigned int sixteenthPoints = num_points / 16;
+
+ float dotProduct = 0;
+ const float* aPtr = input;
+ const float* bPtr = taps;
+
+ __m256 a0Val, a1Val;
+ __m256 b0Val, b1Val;
+ __m256 c0Val, c1Val;
+
+ __m256 dotProdVal0 = _mm256_setzero_ps();
+ __m256 dotProdVal1 = _mm256_setzero_ps();
+
+ for(;number < sixteenthPoints; number++){
+
+ a0Val = _mm256_load_ps(aPtr);
+ a1Val = _mm256_load_ps(aPtr+8);
+ b0Val = _mm256_load_ps(bPtr);
+ b1Val = _mm256_load_ps(bPtr+8);
+
+ c0Val = _mm256_mul_ps(a0Val, b0Val);
+ c1Val = _mm256_mul_ps(a1Val, b1Val);
+
+ dotProdVal0 = _mm256_add_ps(c0Val, dotProdVal0);
+ dotProdVal1 = _mm256_add_ps(c1Val, dotProdVal1);
+
+ aPtr += 16;
+ bPtr += 16;
+ }
+
+ dotProdVal0 = _mm256_add_ps(dotProdVal0, dotProdVal1);
+
+ __VOLK_ATTR_ALIGNED(32) float dotProductVector[8];
+
+ _mm256_store_ps(dotProductVector,dotProdVal0); // Store the results back into the dot product vector
+
+ dotProduct = dotProductVector[0];
+ dotProduct += dotProductVector[1];
+ dotProduct += dotProductVector[2];
+ dotProduct += dotProductVector[3];
+ dotProduct += dotProductVector[4];
+ dotProduct += dotProductVector[5];
+ dotProduct += dotProductVector[6];
+ dotProduct += dotProductVector[7];
+
+ number = sixteenthPoints*16;
+ for(;number < num_points; number++){
+ dotProduct += ((*aPtr++) * (*bPtr++));
+ }
+
+ *result = dotProduct;
+
+}
+
+#endif /*LV_HAVE_AVX*/
+
#endif /*INCLUDED_volk_32f_x2_dot_prod_32f_a_H*/
diff --git a/volk/include/volk/volk_32f_x2_dot_prod_32f_u.h b/volk/include/volk/volk_32f_x2_dot_prod_32f_u.h
index 3b7284b57..b24e8b1f7 100644
--- a/volk/include/volk/volk_32f_x2_dot_prod_32f_u.h
+++ b/volk/include/volk/volk_32f_x2_dot_prod_32f_u.h
@@ -1,6 +1,7 @@
#ifndef INCLUDED_volk_32f_x2_dot_prod_32f_u_H
#define INCLUDED_volk_32f_x2_dot_prod_32f_u_H
+#include <volk/volk_common.h>
#include<stdio.h>
@@ -30,39 +31,60 @@ static inline void volk_32f_x2_dot_prod_32f_u_generic(float * result, const floa
static inline void volk_32f_x2_dot_prod_32f_u_sse( float* result, const float* input, const float* taps, unsigned int num_points) {
unsigned int number = 0;
- const unsigned int quarterPoints = num_points / 4;
+ const unsigned int sixteenthPoints = num_points / 16;
float dotProduct = 0;
const float* aPtr = input;
const float* bPtr = taps;
- __m128 aVal, bVal, cVal;
-
- __m128 dotProdVal = _mm_setzero_ps();
-
- for(;number < quarterPoints; number++){
+ __m128 a0Val, a1Val, a2Val, a3Val;
+ __m128 b0Val, b1Val, b2Val, b3Val;
+ __m128 c0Val, c1Val, c2Val, c3Val;
- aVal = _mm_loadu_ps(aPtr);
- bVal = _mm_loadu_ps(bPtr);
+ __m128 dotProdVal0 = _mm_setzero_ps();
+ __m128 dotProdVal1 = _mm_setzero_ps();
+ __m128 dotProdVal2 = _mm_setzero_ps();
+ __m128 dotProdVal3 = _mm_setzero_ps();
- cVal = _mm_mul_ps(aVal, bVal);
-
- dotProdVal = _mm_add_ps(cVal, dotProdVal);
+ for(;number < sixteenthPoints; number++){
- aPtr += 4;
- bPtr += 4;
+ a0Val = _mm_loadu_ps(aPtr);
+ a1Val = _mm_loadu_ps(aPtr+4);
+ a2Val = _mm_loadu_ps(aPtr+8);
+ a3Val = _mm_loadu_ps(aPtr+12);
+ b0Val = _mm_loadu_ps(bPtr);
+ b1Val = _mm_loadu_ps(bPtr+4);
+ b2Val = _mm_loadu_ps(bPtr+8);
+ b3Val = _mm_loadu_ps(bPtr+12);
+
+ c0Val = _mm_mul_ps(a0Val, b0Val);
+ c1Val = _mm_mul_ps(a1Val, b1Val);
+ c2Val = _mm_mul_ps(a2Val, b2Val);
+ c3Val = _mm_mul_ps(a3Val, b3Val);
+
+ dotProdVal0 = _mm_add_ps(c0Val, dotProdVal0);
+ dotProdVal1 = _mm_add_ps(c1Val, dotProdVal1);
+ dotProdVal2 = _mm_add_ps(c2Val, dotProdVal2);
+ dotProdVal3 = _mm_add_ps(c3Val, dotProdVal3);
+
+ aPtr += 16;
+ bPtr += 16;
}
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal1);
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal2);
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal3);
+
__VOLK_ATTR_ALIGNED(16) float dotProductVector[4];
- _mm_store_ps(dotProductVector,dotProdVal); // Store the results back into the dot product vector
+ _mm_store_ps(dotProductVector,dotProdVal0); // Store the results back into the dot product vector
dotProduct = dotProductVector[0];
dotProduct += dotProductVector[1];
dotProduct += dotProductVector[2];
dotProduct += dotProductVector[3];
- number = quarterPoints * 4;
+ number = sixteenthPoints*16;
for(;number < num_points; number++){
dotProduct += ((*aPtr++) * (*bPtr++));
}
@@ -79,38 +101,59 @@ static inline void volk_32f_x2_dot_prod_32f_u_sse( float* result, const float*
static inline void volk_32f_x2_dot_prod_32f_u_sse3(float * result, const float * input, const float * taps, unsigned int num_points) {
unsigned int number = 0;
- const unsigned int quarterPoints = num_points / 4;
+ const unsigned int sixteenthPoints = num_points / 16;
float dotProduct = 0;
const float* aPtr = input;
const float* bPtr = taps;
- __m128 aVal, bVal, cVal;
-
- __m128 dotProdVal = _mm_setzero_ps();
-
- for(;number < quarterPoints; number++){
+ __m128 a0Val, a1Val, a2Val, a3Val;
+ __m128 b0Val, b1Val, b2Val, b3Val;
+ __m128 c0Val, c1Val, c2Val, c3Val;
- aVal = _mm_loadu_ps(aPtr);
- bVal = _mm_loadu_ps(bPtr);
+ __m128 dotProdVal0 = _mm_setzero_ps();
+ __m128 dotProdVal1 = _mm_setzero_ps();
+ __m128 dotProdVal2 = _mm_setzero_ps();
+ __m128 dotProdVal3 = _mm_setzero_ps();
- cVal = _mm_mul_ps(aVal, bVal);
-
- dotProdVal = _mm_hadd_ps(dotProdVal, cVal);
+ for(;number < sixteenthPoints; number++){
- aPtr += 4;
- bPtr += 4;
+ a0Val = _mm_loadu_ps(aPtr);
+ a1Val = _mm_loadu_ps(aPtr+4);
+ a2Val = _mm_loadu_ps(aPtr+8);
+ a3Val = _mm_loadu_ps(aPtr+12);
+ b0Val = _mm_loadu_ps(bPtr);
+ b1Val = _mm_loadu_ps(bPtr+4);
+ b2Val = _mm_loadu_ps(bPtr+8);
+ b3Val = _mm_loadu_ps(bPtr+12);
+
+ c0Val = _mm_mul_ps(a0Val, b0Val);
+ c1Val = _mm_mul_ps(a1Val, b1Val);
+ c2Val = _mm_mul_ps(a2Val, b2Val);
+ c3Val = _mm_mul_ps(a3Val, b3Val);
+
+ dotProdVal0 = _mm_add_ps(dotProdVal0, c0Val);
+ dotProdVal1 = _mm_add_ps(dotProdVal1, c1Val);
+ dotProdVal2 = _mm_add_ps(dotProdVal2, c2Val);
+ dotProdVal3 = _mm_add_ps(dotProdVal3, c3Val);
+
+ aPtr += 16;
+ bPtr += 16;
}
- __VOLK_ATTR_ALIGNED(16) float dotProductVector[4];
- dotProdVal = _mm_hadd_ps(dotProdVal, dotProdVal);
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal1);
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal2);
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal3);
- _mm_store_ps(dotProductVector,dotProdVal); // Store the results back into the dot product vector
+ __VOLK_ATTR_ALIGNED(16) float dotProductVector[4];
+ _mm_store_ps(dotProductVector,dotProdVal0); // Store the results back into the dot product vector
dotProduct = dotProductVector[0];
dotProduct += dotProductVector[1];
+ dotProduct += dotProductVector[2];
+ dotProduct += dotProductVector[3];
- number = quarterPoints * 4;
+ number = sixteenthPoints*16;
for(;number < num_points; number++){
dotProduct += ((*aPtr++) * (*bPtr++));
}
@@ -181,4 +224,67 @@ static inline void volk_32f_x2_dot_prod_32f_u_sse4_1(float * result, const float
#endif /*LV_HAVE_SSE4_1*/
+#ifdef LV_HAVE_AVX
+
+#include <immintrin.h>
+
+static inline void volk_32f_x2_dot_prod_32f_u_avx( float* result, const float* input, const float* taps, unsigned int num_points) {
+
+ unsigned int number = 0;
+ const unsigned int sixteenthPoints = num_points / 16;
+
+ float dotProduct = 0;
+ const float* aPtr = input;
+ const float* bPtr = taps;
+
+ __m256 a0Val, a1Val;
+ __m256 b0Val, b1Val;
+ __m256 c0Val, c1Val;
+
+ __m256 dotProdVal0 = _mm256_setzero_ps();
+ __m256 dotProdVal1 = _mm256_setzero_ps();
+
+ for(;number < sixteenthPoints; number++){
+
+ a0Val = _mm256_loadu_ps(aPtr);
+ a1Val = _mm256_loadu_ps(aPtr+8);
+ b0Val = _mm256_loadu_ps(bPtr);
+ b1Val = _mm256_loadu_ps(bPtr+8);
+
+ c0Val = _mm256_mul_ps(a0Val, b0Val);
+ c1Val = _mm256_mul_ps(a1Val, b1Val);
+
+ dotProdVal0 = _mm256_add_ps(c0Val, dotProdVal0);
+ dotProdVal1 = _mm256_add_ps(c1Val, dotProdVal1);
+
+ aPtr += 16;
+ bPtr += 16;
+ }
+
+ dotProdVal0 = _mm256_add_ps(dotProdVal0, dotProdVal1);
+
+ __VOLK_ATTR_ALIGNED(32) float dotProductVector[8];
+
+ _mm256_storeu_ps(dotProductVector,dotProdVal0); // Store the results back into the dot product vector
+
+ dotProduct = dotProductVector[0];
+ dotProduct += dotProductVector[1];
+ dotProduct += dotProductVector[2];
+ dotProduct += dotProductVector[3];
+ dotProduct += dotProductVector[4];
+ dotProduct += dotProductVector[5];
+ dotProduct += dotProductVector[6];
+ dotProduct += dotProductVector[7];
+
+ number = sixteenthPoints*16;
+ for(;number < num_points; number++){
+ dotProduct += ((*aPtr++) * (*bPtr++));
+ }
+
+ *result = dotProduct;
+
+}
+
+#endif /*LV_HAVE_AVX*/
+
#endif /*INCLUDED_volk_32f_x2_dot_prod_32f_u_H*/
diff --git a/volk/include/volk/volk_32fc_32f_dot_prod_32fc_a.h b/volk/include/volk/volk_32fc_32f_dot_prod_32fc_a.h
new file mode 100644
index 000000000..109b787e8
--- /dev/null
+++ b/volk/include/volk/volk_32fc_32f_dot_prod_32fc_a.h
@@ -0,0 +1,111 @@
+#ifndef INCLUDED_volk_32fc_32f_dot_prod_32fc_a_H
+#define INCLUDED_volk_32fc_32f_dot_prod_32fc_a_H
+
+#include <volk/volk_common.h>
+#include<stdio.h>
+
+
+#ifdef LV_HAVE_GENERIC
+
+
+static inline void volk_32fc_32f_dot_prod_32fc_a_generic(lv_32fc_t* result, const lv_32fc_t* input, const float * taps, unsigned int num_points) {
+
+ float res[2];
+ float *realpt = &res[0], *imagpt = &res[1];
+ const float* aPtr = (float*)input;
+ const float* bPtr= taps;
+ unsigned int number = 0;
+
+ *realpt = 0;
+ *imagpt = 0;
+
+ for(number = 0; number < num_points; number++){
+ *realpt += ((*aPtr++) * (*bPtr));
+ *imagpt += ((*aPtr++) * (*bPtr++));
+ }
+
+ *result = *(lv_32fc_t*)(&res[0]);
+}
+
+#endif /*LV_HAVE_GENERIC*/
+
+
+#ifdef LV_HAVE_SSE
+
+
+static inline void volk_32fc_32f_dot_prod_32fc_a_sse( lv_32fc_t* result, const lv_32fc_t* input, const float* taps, unsigned int num_points) {
+
+ unsigned int number = 0;
+ const unsigned int sixteenthPoints = num_points / 8;
+
+ float res[2];
+ float *realpt = &res[0], *imagpt = &res[1];
+ const float* aPtr = (float*)input;
+ const float* bPtr = taps;
+
+ __m128 a0Val, a1Val, a2Val, a3Val;
+ __m128 b0Val, b1Val, b2Val, b3Val;
+ __m128 x0Val, x1Val, x2Val, x3Val;
+ __m128 c0Val, c1Val, c2Val, c3Val;
+
+ __m128 dotProdVal0 = _mm_setzero_ps();
+ __m128 dotProdVal1 = _mm_setzero_ps();
+ __m128 dotProdVal2 = _mm_setzero_ps();
+ __m128 dotProdVal3 = _mm_setzero_ps();
+
+ for(;number < sixteenthPoints; number++){
+
+ a0Val = _mm_load_ps(aPtr);
+ a1Val = _mm_load_ps(aPtr+4);
+ a2Val = _mm_load_ps(aPtr+8);
+ a3Val = _mm_load_ps(aPtr+12);
+
+ x0Val = _mm_load_ps(bPtr);
+ x1Val = _mm_load_ps(bPtr);
+ x2Val = _mm_load_ps(bPtr+4);
+ x3Val = _mm_load_ps(bPtr+4);
+ b0Val = _mm_unpacklo_ps(x0Val, x1Val);
+ b1Val = _mm_unpackhi_ps(x0Val, x1Val);
+ b2Val = _mm_unpacklo_ps(x2Val, x3Val);
+ b3Val = _mm_unpackhi_ps(x2Val, x3Val);
+
+ c0Val = _mm_mul_ps(a0Val, b0Val);
+ c1Val = _mm_mul_ps(a1Val, b1Val);
+ c2Val = _mm_mul_ps(a2Val, b2Val);
+ c3Val = _mm_mul_ps(a3Val, b3Val);
+
+ dotProdVal0 = _mm_add_ps(c0Val, dotProdVal0);
+ dotProdVal1 = _mm_add_ps(c1Val, dotProdVal1);
+ dotProdVal2 = _mm_add_ps(c2Val, dotProdVal2);
+ dotProdVal3 = _mm_add_ps(c3Val, dotProdVal3);
+
+ aPtr += 16;
+ bPtr += 8;
+ }
+
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal1);
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal2);
+ dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal3);
+
+ __VOLK_ATTR_ALIGNED(16) float dotProductVector[4];
+
+ _mm_store_ps(dotProductVector,dotProdVal0); // Store the results back into the dot product vector
+
+ *realpt = dotProductVector[0];
+ *imagpt = dotProductVector[1];
+ *realpt += dotProductVector[2];
+ *imagpt += dotProductVector[3];
+
+ number = sixteenthPoints*8;
+ for(;number < num_points; number++){
+ *realpt += ((*aPtr++) * (*bPtr));
+ *imagpt += ((*aPtr++) * (*bPtr++));
+ }
+
+ *result = *(lv_32fc_t*)(&res[0]);
+}
+
+#endif /*LV_HAVE_SSE*/
+
+
+#endif /*INCLUDED_volk_32fc_32f_dot_prod_32fc_a_H*/
diff --git a/volk/include/volk/volk_32fc_s32fc_x2_rotator_32fc_a.h b/volk/include/volk/volk_32fc_s32fc_x2_rotator_32fc_a.h
index 08db99373..51b6041ec 100644
--- a/volk/include/volk/volk_32fc_s32fc_x2_rotator_32fc_a.h
+++ b/volk/include/volk/volk_32fc_s32fc_x2_rotator_32fc_a.h
@@ -171,12 +171,10 @@ static inline void volk_32fc_s32fc_x2_rotator_32fc_a_avx(lv_32fc_t* outVector, c
printf("%f, %f\n", lv_creal(phase_Ptr[2]), lv_cimag(phase_Ptr[2]));
printf("%f, %f\n", lv_creal(phase_Ptr[3]), lv_cimag(phase_Ptr[3]));
printf("incr: %f, %f\n", lv_creal(incr), lv_cimag(incr));*/
- __m256 aVal, phase_Val, inc_Val, yl, yh, tmp1, tmp2, z, ylp, yhp, tmp1p, tmp2p, negated, zeros;
+ __m256 aVal, phase_Val, inc_Val, yl, yh, tmp1, tmp2, z, ylp, yhp, tmp1p, tmp2p;
phase_Val = _mm256_loadu_ps((float*)phase_Ptr);
inc_Val = _mm256_set_ps(lv_cimag(incr), lv_creal(incr),lv_cimag(incr), lv_creal(incr),lv_cimag(incr), lv_creal(incr),lv_cimag(incr), lv_creal(incr));
- zeros = _mm256_set1_ps(0.0);
- negated = _mm256_set1_ps(-1.0);
const unsigned int fourthPoints = num_points / 4;
diff --git a/volk/include/volk/volk_32fc_x2_dot_prod_32fc_a.h b/volk/include/volk/volk_32fc_x2_dot_prod_32fc_a.h
index cb2ac4c67..caef3e6f0 100644
--- a/volk/include/volk/volk_32fc_x2_dot_prod_32fc_a.h
+++ b/volk/include/volk/volk_32fc_x2_dot_prod_32fc_a.h
@@ -18,40 +18,26 @@ static inline void volk_32fc_x2_dot_prod_32fc_a_generic(lv_32fc_t* result, const
unsigned int n_2_ccomplex_blocks = num_bytes >> 4;
unsigned int isodd = (num_bytes >> 3) &1;
-
-
float sum0[2] = {0,0};
float sum1[2] = {0,0};
unsigned int i = 0;
-
for(i = 0; i < n_2_ccomplex_blocks; ++i) {
-
-
sum0[0] += in[0] * tp[0] - in[1] * tp[1];
sum0[1] += in[0] * tp[1] + in[1] * tp[0];
sum1[0] += in[2] * tp[2] - in[3] * tp[3];
sum1[1] += in[2] * tp[3] + in[3] * tp[2];
-
in += 4;
tp += 4;
-
}
-
res[0] = sum0[0] + sum1[0];
res[1] = sum0[1] + sum1[1];
-
-
for(i = 0; i < isodd; ++i) {
-
-
*result += input[(num_bytes >> 3) - 1] * taps[(num_bytes >> 3) - 1];
-
}
-
}
#endif /*LV_HAVE_GENERIC*/
@@ -177,14 +163,8 @@ static inline void volk_32fc_x2_dot_prod_32fc_a_sse_64(lv_32fc_t* result, const
);
- int getem = num_bytes % 16;
-
-
- for(; getem > 0; getem -= 8) {
-
-
+ if(((num_bytes >> 3) & 1)) {
*result += (input[(num_bytes >> 3) - 1] * taps[(num_bytes >> 3) - 1]);
-
}
return;
@@ -363,7 +343,7 @@ static inline void volk_32fc_x2_dot_prod_32fc_a_sse3(lv_32fc_t* result, const lv
dotProduct += ( dotProductVector[0] + dotProductVector[1] );
- if((num_bytes >> 2) != 0) {
+ if(((num_bytes >> 3) & 1) != 0) {
dotProduct += (*a) * (*b);
}
@@ -377,9 +357,7 @@ static inline void volk_32fc_x2_dot_prod_32fc_a_sse3(lv_32fc_t* result, const lv
#include <smmintrin.h>
static inline void volk_32fc_x2_dot_prod_32fc_a_sse4_1(lv_32fc_t* result, const lv_32fc_t* input, const lv_32fc_t* taps, unsigned int num_bytes) {
- volk_32fc_x2_dot_prod_32fc_a_sse3(result, input, taps, num_bytes);
- // SSE3 version runs twice as fast as the SSE4.1 version, so turning off SSE4 version for now
- /*
+
__m128 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, real0, real1, im0, im1;
float *p_input, *p_taps;
__m64 *p_result;
@@ -442,11 +420,7 @@ static inline void volk_32fc_x2_dot_prod_32fc_a_sse4_1(lv_32fc_t* result, const
}
-
-
-
- real1 = _mm_xor_ps(real1, (__m128)neg);
-
+ real1 = _mm_xor_ps(real1, bit128_p(&neg)->float_vec);
im0 = _mm_add_ps(im0, im1);
real0 = _mm_add_ps(real0, real1);
@@ -459,7 +433,6 @@ static inline void volk_32fc_x2_dot_prod_32fc_a_sse4_1(lv_32fc_t* result, const
*result += input[i] * taps[i];
}
- */
}
#endif /*LV_HAVE_SSE4_1*/
diff --git a/volk/lib/CMakeLists.txt b/volk/lib/CMakeLists.txt
index 328a4e087..d9aeb797c 100644
--- a/volk/lib/CMakeLists.txt
+++ b/volk/lib/CMakeLists.txt
@@ -150,6 +150,12 @@ if(NOT CROSSCOMPILE_MULTILIB AND CPU_IS_x86)
if (${SIZEOF_CPU} EQUAL 32)
OVERRULE_ARCH(64 "CPU width is 32 bits")
endif()
+
+ #MSVC 64 bit does not have MMX, overrule it
+ if (${SIZEOF_CPU} EQUAL 64 AND MSVC)
+ OVERRULE_ARCH(mmx "No MMX for Win64")
+ endif()
+
endif()
########################################################################
@@ -174,7 +180,7 @@ execute_process(
# When this occurs, eliminate the redundant machines
# to avoid unnecessary compilation of subset machines.
########################################################################
-foreach(arch orc 64 32)
+foreach(arch mmx orc 64 32)
foreach(machine_name ${available_machines})
string(REPLACE "_${arch}" "" machine_name_no_arch ${machine_name})
if (${machine_name} STREQUAL ${machine_name_no_arch})
diff --git a/volk/lib/testqa.cc b/volk/lib/testqa.cc
index aac676729..2e41c25da 100644
--- a/volk/lib/testqa.cc
+++ b/volk/lib/testqa.cc
@@ -20,6 +20,8 @@ VOLK_RUN_TESTS(volk_16i_convert_8i_u, 0, 0, 20460, 1);
//VOLK_RUN_TESTS(volk_16i_permute_and_scalar_add_a, 1e-4, 0, 2046, 1000);
//VOLK_RUN_TESTS(volk_16i_x4_quad_max_star_16i_a, 1e-4, 0, 2046, 1000);
VOLK_RUN_TESTS(volk_16u_byteswap_a, 0, 0, 20460, 1);
+VOLK_RUN_TESTS(volk_16u_byteswap_u, 0, 0, 20460, 1);
+//VOLK_RUN_TESTS(volk_16i_32fc_dot_prod_32fc_a, 1e-4, 0, 204600, 1);
VOLK_RUN_TESTS(volk_32f_accumulator_s32f_a, 1e-4, 0, 20460, 1);
VOLK_RUN_TESTS(volk_32f_x2_add_32f_a, 1e-4, 0, 20460, 1);
VOLK_RUN_TESTS(volk_32f_x2_add_32f_u, 1e-4, 0, 20460, 1);
@@ -34,7 +36,8 @@ VOLK_RUN_TESTS(volk_32fc_deinterleave_64f_x2_a, 1e-4, 0, 20460, 1);
VOLK_RUN_TESTS(volk_32fc_s32f_deinterleave_real_16i_a, 0, 32768, 20460, 1);
VOLK_RUN_TESTS(volk_32fc_deinterleave_real_32f_a, 1e-4, 0, 20460, 1);
VOLK_RUN_TESTS(volk_32fc_deinterleave_real_64f_a, 1e-4, 0, 20460, 1);
-VOLK_RUN_TESTS(volk_32fc_x2_dot_prod_32fc_a, 1e-4, 0, 204600, 1);
+VOLK_RUN_TESTS(volk_32fc_x2_dot_prod_32fc_a, 1e-4, 0, 2046000, 1);
+VOLK_RUN_TESTS(volk_32fc_32f_dot_prod_32fc_a, 1e-4, 0, 204600, 1);
VOLK_RUN_TESTS(volk_32fc_index_max_16u_a, 3, 0, 20460, 1);
VOLK_RUN_TESTS(volk_32fc_s32f_magnitude_16i_a, 1, 32768, 20460, 1);
VOLK_RUN_TESTS(volk_32fc_magnitude_32f_a, 1e-4, 0, 20460, 1);
@@ -53,6 +56,7 @@ VOLK_RUN_TESTS(volk_32fc_x2_s32f_square_dist_scalar_mult_32f_a, 1e-4, 10, 20460,
VOLK_RUN_TESTS(volk_32f_x2_divide_32f_a, 1e-4, 0, 20460, 1);
VOLK_RUN_TESTS(volk_32f_x2_dot_prod_32f_a, 1e-4, 0, 204600, 1);
VOLK_RUN_TESTS(volk_32f_x2_dot_prod_32f_u, 1e-4, 0, 204600, 1);
+VOLK_RUN_TESTS(volk_32f_x2_dot_prod_16i_a, 1e-4, 0, 204600, 1);
//VOLK_RUN_TESTS(volk_32f_s32f_32f_fm_detect_32f_a, 1e-4, 2046, 10000);
VOLK_RUN_TESTS(volk_32f_index_max_16u_a, 3, 0, 20460, 1);
VOLK_RUN_TESTS(volk_32f_x2_s32f_interleave_16ic_a, 1, 32767, 20460, 1);