summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt33
-rw-r--r--docs/doxygen/other/stream_tags.dox27
-rw-r--r--gnuradio-runtime/include/gnuradio/block.h50
-rw-r--r--gnuradio-runtime/include/gnuradio/flowgraph.h6
-rw-r--r--gnuradio-runtime/include/gnuradio/hier_block2.h7
-rw-r--r--gnuradio-runtime/lib/block.cc56
-rw-r--r--gnuradio-runtime/lib/flowgraph.cc33
-rw-r--r--gnuradio-runtime/lib/hier_block2.cc7
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/hier_block2.py6
-rwxr-xr-xgnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py30
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/tag_utils.py66
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/top_block.py28
-rw-r--r--gnuradio-runtime/swig/hier_block2.i2
-rw-r--r--gnuradio-runtime/swig/top_block.i9
-rw-r--r--gr-blocks/grc/blocks_abs_xx.xml49
-rw-r--r--gr-blocks/grc/blocks_block_tree.xml1
-rw-r--r--gr-blocks/grc/blocks_null_sink.xml17
-rw-r--r--gr-blocks/grc/blocks_null_source.xml16
-rw-r--r--gr-blocks/grc/blocks_sub_xx.xml2
-rw-r--r--gr-blocks/include/gnuradio/blocks/CMakeLists.txt1
-rw-r--r--gr-blocks/include/gnuradio/blocks/abs_XX.h.t58
-rw-r--r--gr-blocks/include/gnuradio/blocks/message_strobe_random.h19
-rw-r--r--gr-blocks/include/gnuradio/blocks/tagged_stream_to_pdu.h17
-rw-r--r--gr-blocks/include/gnuradio/blocks/vector_source_X.h.t30
-rw-r--r--gr-blocks/lib/CMakeLists.txt1
-rw-r--r--gr-blocks/lib/abs_XX_impl.cc.t62
-rw-r--r--gr-blocks/lib/abs_XX_impl.h.t46
-rw-r--r--gr-blocks/lib/null_sink_impl.cc4
-rw-r--r--gr-blocks/lib/null_source_impl.cc9
-rw-r--r--gr-blocks/lib/tagged_stream_to_pdu_impl.cc99
-rw-r--r--gr-blocks/lib/tagged_stream_to_pdu_impl.h13
-rwxr-xr-xgr-blocks/python/blocks/qa_pdu.py43
-rw-r--r--gr-blocks/swig/blocks_swig2.i9
-rw-r--r--gr-fec/lib/reed-solomon/char.h1
-rw-r--r--gr-fec/lib/reed-solomon/encode_rs.c14
-rw-r--r--gr-fec/lib/reed-solomon/init_rs.c23
-rwxr-xr-xgr-filter/examples/reconstruction.py6
-rw-r--r--gr-filter/grc/filter_fft_filter_xxx.xml9
-rw-r--r--gr-filter/grc/filter_pfb_channelizer.xml13
-rw-r--r--gr-filter/grc/filter_pfb_decimator.xml34
-rw-r--r--gr-filter/grc/filter_pfb_synthesizer.xml8
-rw-r--r--gr-filter/include/gnuradio/filter/CMakeLists.txt1
-rw-r--r--gr-filter/include/gnuradio/filter/fft_filter.h110
-rw-r--r--gr-filter/include/gnuradio/filter/fft_filter_ccf.h89
-rw-r--r--gr-filter/include/gnuradio/filter/pfb_channelizer_ccf.h12
-rw-r--r--gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h13
-rw-r--r--gr-filter/include/gnuradio/filter/pfb_synthesizer_ccf.h55
-rw-r--r--gr-filter/include/gnuradio/filter/polyphase_filterbank.h12
-rw-r--r--gr-filter/lib/CMakeLists.txt1
-rw-r--r--gr-filter/lib/fft_filter.cc166
-rw-r--r--gr-filter/lib/fft_filter_ccf_impl.cc120
-rw-r--r--gr-filter/lib/fft_filter_ccf_impl.h62
-rw-r--r--gr-filter/lib/pfb_channelizer_ccf_impl.cc72
-rw-r--r--gr-filter/lib/pfb_channelizer_ccf_impl.h2
-rw-r--r--gr-filter/lib/pfb_decimator_ccf_impl.cc183
-rw-r--r--gr-filter/lib/pfb_decimator_ccf_impl.h26
-rw-r--r--gr-filter/lib/pfb_interpolator_ccf_impl.cc4
-rw-r--r--gr-filter/lib/pfb_synthesizer_ccf_impl.cc268
-rw-r--r--gr-filter/lib/polyphase_filterbank.cc33
-rw-r--r--gr-filter/python/filter/pfb.py18
-rwxr-xr-xgr-filter/python/filter/qa_fft_filter.py131
-rwxr-xr-xgr-filter/python/filter/qa_pfb_channelizer.py16
-rwxr-xr-xgr-filter/python/filter/qa_pfb_decimator.py77
-rwxr-xr-xgr-filter/python/filter/qa_pfb_interpolator.py20
-rwxr-xr-xgr-filter/python/filter/qa_pfb_synthesizer.py34
-rw-r--r--gr-filter/swig/filter_swig.i3
-rw-r--r--gr-qtgui/CMakeLists.txt9
-rw-r--r--gr-qtgui/doc/qtgui.dox22
-rw-r--r--gr-qtgui/gr-qtgui.conf10
-rw-r--r--gr-qtgui/lib/const_sink_c_impl.cc10
-rw-r--r--gr-qtgui/lib/freq_sink_c_impl.cc5
-rw-r--r--gr-qtgui/lib/freq_sink_c_impl.h2
-rw-r--r--gr-qtgui/lib/freq_sink_f_impl.cc3
-rw-r--r--gr-qtgui/lib/histogram_sink_f_impl.cc10
-rw-r--r--gr-qtgui/lib/sink_c_impl.cc3
-rw-r--r--gr-qtgui/lib/sink_f_impl.cc3
-rw-r--r--gr-qtgui/lib/time_raster_sink_b_impl.cc9
-rw-r--r--gr-qtgui/lib/time_raster_sink_f_impl.cc9
-rw-r--r--gr-qtgui/lib/time_sink_c_impl.cc9
-rw-r--r--gr-qtgui/lib/time_sink_f_impl.cc9
-rw-r--r--gr-qtgui/lib/waterfall_sink_c_impl.cc4
-rw-r--r--gr-qtgui/lib/waterfall_sink_f_impl.cc3
-rw-r--r--gr-vocoder/doc/vocoder.dox10
-rw-r--r--gr-vocoder/examples/loopback-codec2.grc1184
-rw-r--r--gr-vocoder/examples/loopback-gsmfr.grc1078
-rw-r--r--gr-vocoder/grc/vocoder_codec2_decode_ps.xml1
-rw-r--r--gr-vocoder/grc/vocoder_codec2_encode_sp.xml2
-rw-r--r--gr-vocoder/grc/vocoder_gsm_fr_decode_ps.xml1
-rw-r--r--gr-vocoder/grc/vocoder_gsm_fr_encode_sp.xml1
-rw-r--r--gr-vocoder/include/gnuradio/vocoder/codec2_decode_ps.h10
-rw-r--r--gr-vocoder/include/gnuradio/vocoder/codec2_encode_sp.h15
-rw-r--r--gr-vocoder/include/gnuradio/vocoder/cvsd_decode_bs.h5
-rw-r--r--gr-vocoder/include/gnuradio/vocoder/cvsd_encode_sb.h6
-rw-r--r--gr-vocoder/include/gnuradio/vocoder/gsm_fr_decode_ps.h5
-rw-r--r--gr-vocoder/include/gnuradio/vocoder/gsm_fr_encode_sp.h9
-rw-r--r--gr-vocoder/lib/codec2/codec2.h1
-rw-r--r--gr-vocoder/lib/codec2_decode_ps_impl.cc23
-rw-r--r--gr-vocoder/lib/codec2_decode_ps_impl.h7
-rw-r--r--gr-vocoder/lib/codec2_encode_sp_impl.cc23
-rw-r--r--gr-vocoder/lib/codec2_encode_sp_impl.h7
-rw-r--r--gr-vocoder/lib/gsm_fr_encode_sp_impl.cc2
-rwxr-xr-xgr-vocoder/python/vocoder/qa_codec2_vocoder.py4
-rw-r--r--grc/python/flow_graph.tmpl1
-rw-r--r--volk/apps/volk_profile.cc264
-rw-r--r--volk/kernels/volk/volk_16i_32fc_dot_prod_32fc.h90
-rw-r--r--volk/kernels/volk/volk_32f_x2_dot_prod_16i.h75
-rw-r--r--volk/kernels/volk/volk_32fc_32f_dot_prod_32fc.h76
-rw-r--r--volk/lib/CMakeLists.txt19
-rw-r--r--volk/lib/qa_utils.cc9
-rw-r--r--volk/lib/qa_utils.h6
-rw-r--r--volk/lib/volk_malloc.c4
-rw-r--r--volk/python/volk_modtool/volk_modtool_generate.py24
112 files changed, 4921 insertions, 653 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cab3efaed3..7e8688be6a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2010-2012 Free Software Foundation, Inc.
+# Copyright 2010-2012,2014 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -58,6 +58,7 @@ ENDIF()
if(ENABLE_GR_CTRLPORT)
set(GR_CTRLPORT True)
+ add_definitions(-DGR_CTRLPORT)
endif(ENABLE_GR_CTRLPORT)
########################################################################
@@ -106,10 +107,26 @@ endif(MSVC)
# Record Compiler Info for record
STRING(TOUPPER ${CMAKE_BUILD_TYPE} GRCBTU)
set(COMPILER_INFO "")
-execute_process(COMMAND ${CMAKE_C_COMPILER} --version
- OUTPUT_VARIABLE cmake_c_compiler_version)
-execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version
- OUTPUT_VARIABLE cmake_cxx_compiler_version)
+IF(MSVC)
+ IF(MSVC90) #Visual Studio 9
+ SET(cmake_c_compiler_version "Microsoft Visual Studio 9.0")
+ SET(cmake_cxx_compiler_version "Microsoft Visual Studio 9.0")
+ ELSE(MSVC10) #Visual Studio 10
+ SET(cmake_c_compiler_version "Microsoft Visual Studio 10.0")
+ SET(cmake_cxx_compiler_version "Microsoft Visual Studio 10.0")
+ ELSE(MSVC11) #Visual Studio 11
+ SET(cmake_c_compiler_version "Microsoft Visual Studio 11.0")
+ SET(cmake_cxx_compiler_version "Microsoft Visual Studio 11.0")
+ ELSE(MSVC12) #Visual Studio 12
+ SET(cmake_c_compiler_version "Microsoft Visual Studio 12.0")
+ SET(cmake_cxx_compiler_version "Microsoft Visual Studio 12.0")
+ ENDIF()
+ELSE()
+ execute_process(COMMAND ${CMAKE_C_COMPILER} --version
+ OUTPUT_VARIABLE cmake_c_compiler_version)
+ execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version
+ OUTPUT_VARIABLE cmake_cxx_compiler_version)
+ENDIF(MSVC)
set(COMPILER_INFO "${CMAKE_C_COMPILER}:::${CMAKE_C_FLAGS_${GRCBTU}} ${CMAKE_C_FLAGS}\n${CMAKE_CXX_COMPILER}:::${CMAKE_CXX_FLAGS_${GRCBTU}} ${CMAKE_CXX_FLAGS}\n" )
# Convert to a C string to compile and display properly
@@ -325,7 +342,7 @@ configure_file(
${CMAKE_BINARY_DIR}/cmake/Modules/GnuradioConfigVersion.cmake
@ONLY)
-SET(cmake_configs
+SET(cmake_configs
${CMAKE_SOURCE_DIR}/cmake/Modules/GnuradioConfig.cmake
${CMAKE_BINARY_DIR}/cmake/Modules/GnuradioConfigVersion.cmake
)
@@ -360,13 +377,13 @@ message(STATUS "Building for version: ${VERSION} / ${LIBVER}")
# Create a config.h with some definitions to export to other projects.
CONFIGURE_FILE(
${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
- ${CMAKE_CURRENT_BINARY_DIR}/config.h
+ ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-runtime/include/gnuradio/config.h
)
# Install config.h in include/gnuradio
install(
FILES
- ${CMAKE_CURRENT_BINARY_DIR}/config.h
+ ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-runtime/include/gnuradio/config.h
DESTINATION ${GR_INCLUDE_DIR}/gnuradio
COMPONENT "runtime_devel"
)
diff --git a/docs/doxygen/other/stream_tags.dox b/docs/doxygen/other/stream_tags.dox
index 2a03c9629c..851740984e 100644
--- a/docs/doxygen/other/stream_tags.dox
+++ b/docs/doxygen/other/stream_tags.dox
@@ -63,15 +63,26 @@ at <em>nitems_written(0)+i</em> for the 0th output port.
The stream tags API consists of four functions, two to add and two to
get the stream tags. These functions are:
-\li add_item_tag: Adds an item tag to a particular output port using a
+\li gr::block::add_item_tag: Adds an item tag to a particular output port using a
gr::tag_t data type.
-\li add_item_tag: Adds an item tag to a particular output port where
-each value of the tag is explicitly given.
-\li get_tags_in_range: Gets all tags from a particular input port between
-a certain range of items (in absolute item time).
-\li get_tags_in_range: Gets any tag that has a specified key from a
-particular input port between a certain range of items (in absolute
-item time).
+
+\li gr::block::add_item_tag: Adds an item tag to a particular output
+port where each value of the tag is explicitly given.
+
+\li gr::block::get_tags_in_range: Gets all tags from a particular
+input port between a certain range of items (in absolute item time).
+
+\li gr::block::get_tags_in_range: Gets any tag that has a specified
+key from a particular input port between a certain range of items (in
+absolute item time).
+
+\li gr::block::get_tags_in_window: Gets all tags from a particular
+input port between a certain range of items (in relative item time
+within the work function).
+
+\li gr::block::get_tags_in_range: Gets any tag that has a specified
+key from a particular input port between a certain range of items (in
+relative item time within the work function).
\subsection add_item_tag Adding a Tag to a Stream
diff --git a/gnuradio-runtime/include/gnuradio/block.h b/gnuradio-runtime/include/gnuradio/block.h
index 112d251587..7390e93bc0 100644
--- a/gnuradio-runtime/include/gnuradio/block.h
+++ b/gnuradio-runtime/include/gnuradio/block.h
@@ -562,7 +562,7 @@ namespace gr {
int set_thread_priority(int priority);
bool update_rate() const;
-
+
// ----------------------------------------------------------------------------
private:
@@ -699,6 +699,50 @@ namespace gr {
uint64_t abs_end,
const pmt::pmt_t &key);
+ /*!
+ * \brief Gets all tags within the relative window of the current call to work.
+ *
+ * \details
+ *
+ * This opperates much like get_tags_in_range but allows us to
+ * work within the current window of items. Item range is
+ * therefore within the possible range of 0 to
+ * ninput_items[whic_input].
+ *
+ * Range of items counts from \p rel_start to \p rel_end-1 within
+ * current window.
+ *
+ * Tags are tuples of:
+ * (item count, source id, key, value)
+ *
+ * \param v a vector reference to return tags into
+ * \param which_input an integer of which input stream to pull from
+ * \param rel_start a uint64 count of the start of the range of interest
+ * \param rel_end a uint64 count of the end of the range of interest
+ */
+ void get_tags_in_window(std::vector<tag_t> &v,
+ unsigned int which_input,
+ uint64_t rel_start,
+ uint64_t rel_end);
+
+ /*!
+ * \brief Operates like gr::block::get_tags_in_window with the
+ * ability to only return tags with the specified \p key.
+ *
+ * \details
+ *
+ * \param v a vector reference to return tags into
+ * \param which_input an integer of which input stream to pull from
+ * \param rel_start a uint64 count of the start of the range of interest
+ * \param rel_end a uint64 count of the end of the range of interest
+ * \param key a PMT symbol key to filter only tags of this key
+ */
+ void get_tags_in_window(std::vector<tag_t> &v,
+ unsigned int which_input,
+ uint64_t rel_start,
+ uint64_t rel_end,
+ const pmt::pmt_t &key);
+
void enable_update_rate(bool en);
std::vector<long> d_max_output_buffer;
@@ -708,11 +752,11 @@ namespace gr {
* setting/resetting of parameters thread-safe.
*
* Used by calling gr::thread::scoped_lock l(d_setlock);
- */
+ */
gr::thread::mutex d_setlock;
/*! Used by blocks to access the logger system.
- */
+ */
gr::logger_ptr d_logger;
gr::logger_ptr d_debug_logger;
diff --git a/gnuradio-runtime/include/gnuradio/flowgraph.h b/gnuradio-runtime/include/gnuradio/flowgraph.h
index 1271c2d60e..1c04a5f21d 100644
--- a/gnuradio-runtime/include/gnuradio/flowgraph.h
+++ b/gnuradio-runtime/include/gnuradio/flowgraph.h
@@ -165,7 +165,7 @@ namespace gr {
// Connect two msg endpoints
void connect(const msg_endpoint &src, const msg_endpoint &dst);
-
+
// Disconnect two msg endpoints
void disconnect(const msg_endpoint &src, const msg_endpoint &dst);
@@ -177,7 +177,7 @@ namespace gr {
// Return vector of edges
const edge_vector_t &edges() const { return d_edges; }
-
+
// Return vector of msg edges
const msg_edge_vector_t &msg_edges() const { return d_msg_edges; }
@@ -265,6 +265,8 @@ namespace gr {
return os;
}
+ std::string dot_graph_fg (flowgraph_sptr fg);
+
} /* namespace gr */
#endif /* INCLUDED_GR_RUNTIME_FLOWGRAPH_H */
diff --git a/gnuradio-runtime/include/gnuradio/hier_block2.h b/gnuradio-runtime/include/gnuradio/hier_block2.h
index 3f41930d16..1bf8dddc1a 100644
--- a/gnuradio-runtime/include/gnuradio/hier_block2.h
+++ b/gnuradio-runtime/include/gnuradio/hier_block2.h
@@ -179,7 +179,7 @@ namespace gr {
bool has_msg_port(pmt::pmt_t which_port) {
return message_port_is_hier(which_port) || basic_block::has_msg_port(which_port);
}
-
+
bool message_port_is_hier(pmt::pmt_t port_id) {
return message_port_is_hier_in(port_id) || message_port_is_hier_out(port_id);
}
@@ -235,6 +235,11 @@ namespace gr {
std::vector<int> processor_affinity();
};
+ /*!
+ * \brief Return hierarchical block's flow graph represented in dot language
+ */
+ GR_RUNTIME_API std::string dot_graph(hier_block2_sptr hierblock2);
+
inline hier_block2_sptr cast_to_hier_block2_sptr(basic_block_sptr block) {
return boost::dynamic_pointer_cast<hier_block2, basic_block>(block);
}
diff --git a/gnuradio-runtime/lib/block.cc b/gnuradio-runtime/lib/block.cc
index 442f8dde77..7a1364def9 100644
--- a/gnuradio-runtime/lib/block.cc
+++ b/gnuradio-runtime/lib/block.cc
@@ -29,6 +29,7 @@
#include <gnuradio/block_detail.h>
#include <gnuradio/buffer.h>
#include <gnuradio/prefs.h>
+#include <gnuradio/config.h>
#include <stdexcept>
#include <iostream>
@@ -288,19 +289,42 @@ namespace gr {
void
block::get_tags_in_range(std::vector<tag_t> &v,
- unsigned int which_output,
+ unsigned int which_input,
uint64_t start, uint64_t end)
{
- d_detail->get_tags_in_range(v, which_output, start, end, unique_id());
+ d_detail->get_tags_in_range(v, which_input, start, end, unique_id());
}
void
block::get_tags_in_range(std::vector<tag_t> &v,
- unsigned int which_output,
+ unsigned int which_input,
uint64_t start, uint64_t end,
const pmt::pmt_t &key)
{
- d_detail->get_tags_in_range(v, which_output, start, end, key, unique_id());
+ d_detail->get_tags_in_range(v, which_input, start, end, key, unique_id());
+ }
+
+ void
+ block::get_tags_in_window(std::vector<tag_t> &v,
+ unsigned int which_input,
+ uint64_t start, uint64_t end)
+ {
+ d_detail->get_tags_in_range(v, which_input,
+ nitems_read(which_input) + start,
+ nitems_read(which_input) + end,
+ unique_id());
+ }
+
+ void
+ block::get_tags_in_window(std::vector<tag_t> &v,
+ unsigned int which_input,
+ uint64_t start, uint64_t end,
+ const pmt::pmt_t &key)
+ {
+ d_detail->get_tags_in_range(v, which_input,
+ nitems_read(which_input) + start,
+ nitems_read(which_input) + end,
+ key, unique_id());
}
block::tag_propagation_policy_t
@@ -361,7 +385,7 @@ namespace gr {
}
}
- int
+ int
block::active_thread_priority()
{
if(d_detail) {
@@ -370,13 +394,13 @@ namespace gr {
return -1;
}
- int
+ int
block::thread_priority()
{
return d_priority;
}
- int
+ int
block::set_thread_priority(int priority)
{
d_priority = priority;
@@ -402,10 +426,10 @@ namespace gr {
throw std::invalid_argument("basic_block::max_output_buffer: port out of range.");
return d_max_output_buffer[i];
}
-
+
void
block::set_max_output_buffer(long max_output_buffer)
- {
+ {
for(int i = 0; i < output_signature()->max_streams(); i++) {
set_max_output_buffer(i, max_output_buffer);
}
@@ -417,9 +441,9 @@ namespace gr {
if((size_t)port >= d_max_output_buffer.size())
d_max_output_buffer.push_back(max_output_buffer);
else
- d_max_output_buffer[port] = max_output_buffer;
+ d_max_output_buffer[port] = max_output_buffer;
}
-
+
long
block::min_output_buffer(size_t i)
{
@@ -427,7 +451,7 @@ namespace gr {
throw std::invalid_argument("basic_block::min_output_buffer: port out of range.");
return d_min_output_buffer[i];
}
-
+
void
block::set_min_output_buffer(long min_output_buffer)
{
@@ -436,14 +460,14 @@ namespace gr {
set_min_output_buffer(i, min_output_buffer);
}
}
-
+
void
block::set_min_output_buffer(int port, long min_output_buffer)
{
if((size_t)port >= d_min_output_buffer.size())
d_min_output_buffer.push_back(min_output_buffer);
else
- d_min_output_buffer[port] = min_output_buffer;
+ d_min_output_buffer[port] = min_output_buffer;
}
@@ -713,7 +737,7 @@ namespace gr {
block::setup_pc_rpc()
{
d_pc_rpc_set = true;
-#ifdef GR_CTRLPORT
+#if defined(GR_CTRLPORT) && defined(GR_PERFORMANCE_COUNTERS)
d_rpc_vars.push_back(
rpcbasic_sptr(new rpcbasic_register_get<block, float>(
alias(), "noutput_items", &block::pc_noutput_items,
@@ -825,7 +849,7 @@ namespace gr {
pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0),
"", "Var. of how full output buffers are", RPC_PRIVLVL_MIN,
DISPTIME | DISPOPTSTRIP)));
-#endif /* GR_CTRLPORT */
+#endif /* defined(GR_CTRLPORT) && defined(GR_PERFORMANCE_COUNTERS) */
}
std::ostream&
diff --git a/gnuradio-runtime/lib/flowgraph.cc b/gnuradio-runtime/lib/flowgraph.cc
index 634236dea0..3d8dfea65a 100644
--- a/gnuradio-runtime/lib/flowgraph.cc
+++ b/gnuradio-runtime/lib/flowgraph.cc
@@ -149,7 +149,7 @@ namespace gr {
}
}
- void
+ void
flowgraph::check_valid_port(const msg_endpoint &e)
{
if(FLOWGRAPH_DEBUG)
@@ -496,7 +496,7 @@ namespace gr {
check_valid_port(src);
check_valid_port(dst);
for(msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) {
- if(p->src() == src && p->dst() == dst){
+ if(p->src() == src && p->dst() == dst){
throw std::runtime_error("connect called on already connected edge!");
}
}
@@ -517,4 +517,33 @@ namespace gr {
throw std::runtime_error("disconnect called on non-connected edge!");
}
+ std::string
+ dot_graph_fg(flowgraph_sptr fg)
+ {
+ basic_block_vector_t blocks = fg->calc_used_blocks();
+ edge_vector_t edges = fg->edges();
+
+ std::stringstream out;
+
+ out << "digraph flowgraph {" << std::endl;
+
+ // Define nodes and set labels
+ for(basic_block_viter_t block = blocks.begin(); block != blocks.end(); ++block) {
+ out << (*block)->unique_id()
+ << " [ label=\"" << (*block)->name() << "\" ]"
+ << std::endl;
+ }
+
+ // Define edges
+ for(edge_viter_t edge = edges.begin(); edge != edges.end(); ++edge) {
+ out << edge->src().block()->unique_id()
+ << " -> "
+ << edge->dst().block()->unique_id() << std::endl;
+ }
+
+ out << "}" << std::endl;
+
+ return out.str();
+ }
+
} /* namespace gr */
diff --git a/gnuradio-runtime/lib/hier_block2.cc b/gnuradio-runtime/lib/hier_block2.cc
index e0acba30a0..f145b9344b 100644
--- a/gnuradio-runtime/lib/hier_block2.cc
+++ b/gnuradio-runtime/lib/hier_block2.cc
@@ -26,6 +26,7 @@
#include <gnuradio/hier_block2.h>
#include <gnuradio/io_signature.h>
+#include <gnuradio/flowgraph.h>
#include "hier_block2_detail.h"
#include <iostream>
@@ -175,4 +176,10 @@ namespace gr {
return d_detail->processor_affinity();
}
+ std::string
+ dot_graph(hier_block2_sptr hierblock2)
+ {
+ return dot_graph_fg(hierblock2->flatten());
+ }
+
} /* namespace gr */
diff --git a/gnuradio-runtime/python/gnuradio/gr/hier_block2.py b/gnuradio-runtime/python/gnuradio/gr/hier_block2.py
index a254a58c72..d7cea3a9a3 100644
--- a/gnuradio-runtime/python/gnuradio/gr/hier_block2.py
+++ b/gnuradio-runtime/python/gnuradio/gr/hier_block2.py
@@ -19,7 +19,7 @@
# Boston, MA 02110-1301, USA.
#
-from runtime_swig import hier_block2_swig
+from runtime_swig import hier_block2_swig, dot_graph
import pmt
#
@@ -126,3 +126,7 @@ class hier_block2(object):
def message_port_register_hier_out(self, portname):
self.primitive_message_port_register_hier_out(pmt.intern(portname));
+ def dot_graph(self):
+ '''Return graph representation in dot language'''
+ return dot_graph(self._hb)
+
diff --git a/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py b/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py
index 56797a46dd..1a08ac5ae6 100755
--- a/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py
+++ b/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py
@@ -47,6 +47,36 @@ class test_tag_utils (gr_unittest.TestCase):
self.assertEqual(pt.value, 23)
self.assertEqual(pt.offset, 10)
+ def test_002(self):
+ offset = 10
+ key = pmt.string_to_symbol('key')
+ value = pmt.from_long(23)
+ srcid = pmt.from_bool(False)
+
+ format_dict = {'offset': offset,
+ 'key': key,
+ 'value': value,
+ 'srcid': srcid}
+ format_list = [offset, key, value, srcid]
+ format_tuple = (offset, key, value, srcid)
+
+ t_dict = gr.python_to_tag(format_dict)
+ t_list = gr.python_to_tag(format_list)
+ t_tuple = gr.python_to_tag(format_tuple)
+
+ self.assertTrue(pmt.equal(t_dict.key, key))
+ self.assertTrue(pmt.equal(t_dict.value, value))
+ self.assertEqual(t_dict.offset, offset)
+
+ self.assertTrue(pmt.equal(t_list.key, key))
+ self.assertTrue(pmt.equal(t_list.value, value))
+ self.assertEqual(t_list.offset, offset)
+
+ self.assertTrue(pmt.equal(t_tuple.key, key))
+ self.assertTrue(pmt.equal(t_tuple.value, value))
+ self.assertEqual(t_tuple.offset, offset)
+
+
if __name__ == '__main__':
print 'hi'
diff --git a/gnuradio-runtime/python/gnuradio/gr/tag_utils.py b/gnuradio-runtime/python/gnuradio/gr/tag_utils.py
index ad80bff23a..cbca9d44ae 100644
--- a/gnuradio-runtime/python/gnuradio/gr/tag_utils.py
+++ b/gnuradio-runtime/python/gnuradio/gr/tag_utils.py
@@ -28,4 +28,70 @@ def tag_to_pmt(tag):
newtag.srcid = pmt.from_python(tag.srcid)
return newtag
+def python_to_tag(tag_struct):
+ """
+ Convert a Python list/tuple/dictionary to a stream tag.
+
+ When using a list or tuple format, this function expects the format:
+ tag_struct[0] --> tag's offset (as an integer)
+ tag_struct[1] --> tag's key (as a PMT)
+ tag_struct[2] --> tag's value (as a PMT)
+ tag_struct[3] --> tag's srcid (as a PMT)
+
+ When using a dictionary, we specify the dictionary keys using:
+ tag_struct['offset'] --> tag's offset (as an integer)
+ tag_struct['key'] --> tag's key (as a PMT)
+ tag_struct['value'] --> tag's value (as a PMT)
+ tag_struct['srcid'] --> tag's srcid (as a PMT)
+
+ If the function can take the Python object and successfully
+ construct a tag, it will return the tag. Otherwise, it will return
+ None.
+ """
+ good = False
+ tag = gr.tag_t()
+ if(type(tag_struct) == dict):
+ if(tag_struct.has_key('offset')):
+ if(isinstance(tag_struct['offset'], (int,long))):
+ tag.offset = tag_struct['offset']
+ good = True
+
+ if(tag_struct.has_key('key')):
+ if(isinstance(tag_struct['key'], pmt.pmt_swig.swig_int_ptr)):
+ tag.key = tag_struct['key']
+ good = True
+
+ if(tag_struct.has_key('value')):
+ if(isinstance(tag_struct['value'], pmt.pmt_swig.swig_int_ptr)):
+ tag.value = tag_struct['value']
+ good = True
+
+ if(tag_struct.has_key('srcid')):
+ if(isinstance(tag_struct['srcid'], pmt.pmt_swig.swig_int_ptr)):
+ tag.srcid = tag_struct['srcid']
+ good = True
+
+ elif(type(tag_struct) == list or type(tag_struct) == tuple):
+ if(len(tag_struct) == 4):
+ if(isinstance(tag_struct[0], (int,long))):
+ tag.offset = tag_struct[0]
+ good = True
+
+ if(isinstance(tag_struct[1], pmt.pmt_swig.swig_int_ptr)):
+ tag.key = tag_struct[1]
+ good = True
+
+ if(isinstance(tag_struct[2], pmt.pmt_swig.swig_int_ptr)):
+ tag.value = tag_struct[2]
+ good = True
+
+ if(isinstance(tag_struct[3], pmt.pmt_swig.swig_int_ptr)):
+ tag.srcid = tag_struct[3]
+ good = True
+
+ if(good):
+ return tag
+ else:
+ return None
+
diff --git a/gnuradio-runtime/python/gnuradio/gr/top_block.py b/gnuradio-runtime/python/gnuradio/gr/top_block.py
index e4d1f4194a..58332c3421 100644
--- a/gnuradio-runtime/python/gnuradio/gr/top_block.py
+++ b/gnuradio-runtime/python/gnuradio/gr/top_block.py
@@ -21,7 +21,8 @@
from runtime_swig import top_block_swig, \
top_block_wait_unlocked, top_block_run_unlocked, \
- top_block_start_unlocked, top_block_stop_unlocked
+ top_block_start_unlocked, top_block_stop_unlocked, \
+ dot_graph_tb
#import gnuradio.gr.gr_threading as _threading
import gr_threading as _threading
@@ -92,18 +93,18 @@ class top_block(object):
python subclassing.
"""
def __init__(self, name="top_block"):
- self._tb = top_block_swig(name)
+ self._tb = top_block_swig(name)
def __getattr__(self, name):
if not hasattr(self, "_tb"):
raise RuntimeError("top_block: invalid state--did you forget to call gr.top_block.__init__ in a derived class?")
- return getattr(self._tb, name)
+ return getattr(self._tb, name)
def start(self, max_noutput_items=10000000):
- top_block_start_unlocked(self._tb, max_noutput_items)
+ top_block_start_unlocked(self._tb, max_noutput_items)
def stop(self):
- top_block_stop_unlocked(self._tb)
+ top_block_stop_unlocked(self._tb)
def run(self, max_noutput_items=10000000):
self.start(max_noutput_items)
@@ -122,16 +123,16 @@ class top_block(object):
'''
if len (points) < 1:
raise ValueError, ("connect requires at least one endpoint; %d provided." % (len (points),))
- else:
- if len(points) == 1:
- self._tb.primitive_connect(points[0].to_basic_block())
- else:
- for i in range (1, len (points)):
- self._connect(points[i-1], points[i])
+ else:
+ if len(points) == 1:
+ self._tb.primitive_connect(points[0].to_basic_block())
+ else:
+ for i in range (1, len (points)):
+ self._connect(points[i-1], points[i])
def msg_connect(self, src, srcport, dst, dstport):
self.primitive_msg_connect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport);
-
+
def msg_disconnect(self, src, srcport, dst, dstport):
self.primitive_msg_disconnect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport);
@@ -169,3 +170,6 @@ class top_block(object):
self._tb.primitive_disconnect(src_block.to_basic_block(), src_port,
dst_block.to_basic_block(), dst_port)
+ def dot_graph(self):
+ '''Return graph representation in dot language'''
+ return dot_graph_tb(self._tb)
diff --git a/gnuradio-runtime/swig/hier_block2.i b/gnuradio-runtime/swig/hier_block2.i
index 87c936544a..053f24721d 100644
--- a/gnuradio-runtime/swig/hier_block2.i
+++ b/gnuradio-runtime/swig/hier_block2.i
@@ -93,4 +93,6 @@ namespace gr {
gr::hier_block2_sptr to_hier_block2(); // Needed for Python type coercion
};
+
+ std::string dot_graph(hier_block2_sptr hierblock2);
}
diff --git a/gnuradio-runtime/swig/top_block.i b/gnuradio-runtime/swig/top_block.i
index 485159972b..60c9e1a232 100644
--- a/gnuradio-runtime/swig/top_block.i
+++ b/gnuradio-runtime/swig/top_block.i
@@ -53,7 +53,7 @@ namespace gr {
gr::top_block_sptr to_top_block(); // Needed for Python type coercion
};
}
-
+
#ifdef SWIGPYTHON
%inline %{
@@ -88,6 +88,13 @@ void top_block_stop_unlocked(gr::top_block_sptr r) throw (std::runtime_error)
r->stop();
)
}
+
+std::string
+dot_graph_tb(gr::top_block_sptr r)
+{
+ return dot_graph(r);
+}
+
%}
#endif
diff --git a/gr-blocks/grc/blocks_abs_xx.xml b/gr-blocks/grc/blocks_abs_xx.xml
new file mode 100644
index 0000000000..65ef97ddff
--- /dev/null
+++ b/gr-blocks/grc/blocks_abs_xx.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Abs Block
+###################################################
+ -->
+<block>
+ <name>Abs</name>
+ <key>blocks_abs_xx</key>
+ <import>from gnuradio import blocks</import>
+ <make>blocks.abs_$(type.fcn)()</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:ii</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:ss</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Inputs</name>
+ <key>num_inputs</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_inputs &gt;= 1</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <nports>$num_inputs</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <nports>$num_inputs</nports>
+ </source>
+</block>
diff --git a/gr-blocks/grc/blocks_block_tree.xml b/gr-blocks/grc/blocks_block_tree.xml
index bf0c55ff2e..22d0e5c7c8 100644
--- a/gr-blocks/grc/blocks_block_tree.xml
+++ b/gr-blocks/grc/blocks_block_tree.xml
@@ -87,6 +87,7 @@
</cat>
<cat>
<name>Math Operators</name>
+ <block>blocks_abs_xx</block>
<block>blocks_add_xx</block>
<block>blocks_add_const_vxx</block>
<block>blocks_divide_xx</block>
diff --git a/gr-blocks/grc/blocks_null_sink.xml b/gr-blocks/grc/blocks_null_sink.xml
index 2ae20e619a..f2907d20bd 100644
--- a/gr-blocks/grc/blocks_null_sink.xml
+++ b/gr-blocks/grc/blocks_null_sink.xml
@@ -45,10 +45,27 @@
<value>1</value>
<type>int</type>
</param>
+ <param>
+ <name>Num Inputs</name>
+ <key>num_inputs</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Bus Connections</name>
+ <key>bus_conns</key>
+ <value>[[0,],]</value>
+ <type>raw</type>
+ <hide>part</hide>
+ </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>
+ <bus_structure_sink>$bus_conns</bus_structure_sink>
</block>
+
diff --git a/gr-blocks/grc/blocks_null_source.xml b/gr-blocks/grc/blocks_null_source.xml
index 01d3905cab..9c109e651f 100644
--- a/gr-blocks/grc/blocks_null_source.xml
+++ b/gr-blocks/grc/blocks_null_source.xml
@@ -45,10 +45,26 @@
<value>1</value>
<type>int</type>
</param>
+ <param>
+ <name>Num Outputs</name>
+ <key>num_outputs</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Bus Connections</name>
+ <key>bus_conns</key>
+ <value>[[0,],]</value>
+ <type>raw</type>
+ <hide>part</hide>
+ </param>
+ <check>$num_outputs &gt;= 1</check>
<check>$vlen &gt; 0</check>
<source>
<name>out</name>
<type>$type</type>
<vlen>$vlen</vlen>
+ <nports>$num_outputs</nports>
</source>
+ <bus_structure_source>$bus_conns</bus_structure_source>
</block>
diff --git a/gr-blocks/grc/blocks_sub_xx.xml b/gr-blocks/grc/blocks_sub_xx.xml
index ae01cf74aa..88b5ccbb57 100644
--- a/gr-blocks/grc/blocks_sub_xx.xml
+++ b/gr-blocks/grc/blocks_sub_xx.xml
@@ -48,7 +48,7 @@
<type>int</type>
</param>
<check>$vlen &gt; 0</check>
- <check>$num_inputs &gt;= 2</check>
+ <check>$num_inputs &gt;= 1</check>
<sink>
<name>in</name>
<type>$type</type>
diff --git a/gr-blocks/include/gnuradio/blocks/CMakeLists.txt b/gr-blocks/include/gnuradio/blocks/CMakeLists.txt
index c120242c01..7b8a0d6dc4 100644
--- a/gr-blocks/include/gnuradio/blocks/CMakeLists.txt
+++ b/gr-blocks/include/gnuradio/blocks/CMakeLists.txt
@@ -64,6 +64,7 @@ endmacro(expand_h)
########################################################################
# Invoke macro to generate various sources
########################################################################
+expand_h(abs_XX ss ii ff)
expand_h(add_XX ss ii cc)
expand_h(add_const_XX bb ss ii ff cc)
expand_h(add_const_vXX bb ss ii ff cc)
diff --git a/gr-blocks/include/gnuradio/blocks/abs_XX.h.t b/gr-blocks/include/gnuradio/blocks/abs_XX.h.t
new file mode 100644
index 0000000000..a30e752b4b
--- /dev/null
+++ b/gr-blocks/include/gnuradio/blocks/abs_XX.h.t
@@ -0,0 +1,58 @@
+/* -*- 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.
+ */
+
+// @WARNING@
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
+
+#include <gnuradio/blocks/api.h>
+#include <gnuradio/sync_block.h>
+
+namespace gr {
+ namespace blocks {
+
+ /*!
+ * \brief output[m] = abs(input[m]) for all M streams.
+ * \ingroup boolean_operators_blk
+ *
+ * \details
+ * absolute value of data stream (Strip sign)
+ */
+ class BLOCKS_API @NAME@ : virtual public sync_block
+ {
+
+ public:
+
+ // gr::blocks::@NAME@::sptr
+ typedef boost::shared_ptr<@NAME@> sptr;
+
+ /*!
+ * \brief Create an instance of @NAME@
+ */
+ static sptr make();
+ };
+
+ } /* namespace blocks */
+} /* namespace gr */
+
+#endif /* @GUARD_NAME@ */
diff --git a/gr-blocks/include/gnuradio/blocks/message_strobe_random.h b/gr-blocks/include/gnuradio/blocks/message_strobe_random.h
index f399f637d1..8f5a20e1b3 100644
--- a/gr-blocks/include/gnuradio/blocks/message_strobe_random.h
+++ b/gr-blocks/include/gnuradio/blocks/message_strobe_random.h
@@ -43,8 +43,11 @@ namespace gr {
* \ingroup message_tools_blk
*
* \details
- * Takes a PMT message and sends it out every \p period_ms
- * milliseconds. Useful for testing/debugging the message system.
+
+ * Takes a PMT message and sends it out every at random
+ * intervals. The interval is basedon a random distribution, \p
+ * dist, with specified mean (\p mean_ms) and variance (\p
+ * std_ms). Useful for testing/debugging the message system.
*/
class BLOCKS_API message_strobe_random : virtual public block
{
@@ -53,12 +56,14 @@ namespace gr {
typedef boost::shared_ptr<message_strobe_random> sptr;
/*!
- * Make a message stobe block to send message \p msg every \p
- * period_ms milliseconds.
+ * Make a message stobe block to sends message \p msg at random
+ * intervals defined by the distribution \p dist with mean \p
+ * mean_ms and standard deviation \p std_ms.
*
* \param msg The message to send as a PMT.
- * \param period_ms the time period in milliseconds in which to
- * send \p msg.
+ * \param dist The random distribution from which to draw events.
+ * \param mean_ms The mean of the distribution.
+ * \param std_ms The standard deviation of the distribution.
*/
static sptr make(pmt::pmt_t msg, message_strobe_random_distribution_t dist, float mean_ms, float std_ms);
@@ -104,7 +109,7 @@ namespace gr {
* Get the std of strobe_random.
*/
virtual float std() const = 0;
-
+
};
} /* namespace blocks */
diff --git a/gr-blocks/include/gnuradio/blocks/tagged_stream_to_pdu.h b/gr-blocks/include/gnuradio/blocks/tagged_stream_to_pdu.h
index 9d5f509952..af3279217e 100644
--- a/gr-blocks/include/gnuradio/blocks/tagged_stream_to_pdu.h
+++ b/gr-blocks/include/gnuradio/blocks/tagged_stream_to_pdu.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2013 Free Software Foundation, Inc.
+ * Copyright 2013,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -25,16 +25,21 @@
#include <gnuradio/blocks/api.h>
#include <gnuradio/blocks/pdu.h>
-#include <gnuradio/sync_block.h>
+#include <gnuradio/tagged_stream_block.h>
namespace gr {
namespace blocks {
/*!
- * \brief Turns received stream data and tags into PDUs
+ * \brief Turns received stream data and tags into PDUs and sends
+ * them through a message port.
* \ingroup message_tools_blk
+ *
+ * The sent message is a PMT-pair (created by pmt::cons()). The
+ * first element is a dictionary containing all the tags. The
+ * second is a vector containing the actual data.
*/
- class BLOCKS_API tagged_stream_to_pdu : virtual public sync_block
+ class BLOCKS_API tagged_stream_to_pdu : virtual public tagged_stream_block
{
public:
// gr::blocks::tagged_stream_to_pdu::sptr
@@ -43,8 +48,8 @@ namespace gr {
/*!
* \brief Construct a tagged_stream_to_pdu block
* \param type PDU type of pdu::vector_type
- * \param lengthtagname The name of the tag that specifies how long the packet is.
- * Defaults to 'packet_len'.
+ * \param lengthtagname The name of the tag that specifies
+ * how long the packet is.
*/
static sptr make(pdu::vector_type type,
const std::string& lengthtagname="packet_len");
diff --git a/gr-blocks/include/gnuradio/blocks/vector_source_X.h.t b/gr-blocks/include/gnuradio/blocks/vector_source_X.h.t
index 7ff18ad083..d5298e8b47 100644
--- a/gr-blocks/include/gnuradio/blocks/vector_source_X.h.t
+++ b/gr-blocks/include/gnuradio/blocks/vector_source_X.h.t
@@ -32,8 +32,36 @@ namespace gr {
namespace blocks {
/*!
- * \brief source of @TYPE@'s that gets its data from a vector
+ * \brief Source that streams @TYPE@ items based on the input \p data vector.
* \ingroup misc_blk
+ *
+ * \details
+ * This block produces a stream of samples based on an input
+ * vector. In C++, this is a std::vector<@TYPE@>, and in Python,
+ * this is either a list or tuple. The data can repeat infinitely
+ * until the flowgraph is terminated by some other event or, the
+ * default, run the data once and stop.
+ *
+ * The vector source can also produce stream tags with the
+ * data. Pass in a vector of gr::tag_t objects and they will be
+ * emitted based on the specified offset of the tag.
+ *
+ * GNU Radio provides a utility Python module in gr.tag_utils to
+ * convert between tags and Python objects:
+ * gr.tag_utils.python_to_tag.
+ *
+ * We can create tags as Python lists (or tuples) using the list
+ * structure [int offset, pmt key, pmt value, pmt srcid]. It is
+ * important to define the list/tuple with the values in the
+ * correct order and with the correct data type. A python
+ * dictionary can also be used using the keys: "offset", "key",
+ * "value", and "srcid" with the same data types as for the lists.
+ *
+ * When given a list of tags, the vector source will emit the tags
+ * repeatedly by updating the offset relative to the vector stream
+ * length. That is, if the vector has 500 items and a tag has an
+ * offset of 0, that tag will be placed on item 0, 500, 1000,
+ * 1500, etc.
*/
class BLOCKS_API @NAME@ : virtual public sync_block
{
diff --git a/gr-blocks/lib/CMakeLists.txt b/gr-blocks/lib/CMakeLists.txt
index fba0e4b771..0e7aab5e7c 100644
--- a/gr-blocks/lib/CMakeLists.txt
+++ b/gr-blocks/lib/CMakeLists.txt
@@ -90,6 +90,7 @@ endmacro(expand_cc_h_impl)
########################################################################
# Invoke macro to generate various sources
########################################################################
+expand_cc_h_impl(abs_XX ss ii ff)
expand_cc_h_impl(add_XX ss ii cc)
expand_cc_h_impl(add_const_XX bb ss ii ff cc)
expand_cc_h_impl(add_const_vXX bb ss ii ff cc)
diff --git a/gr-blocks/lib/abs_XX_impl.cc.t b/gr-blocks/lib/abs_XX_impl.cc.t
new file mode 100644
index 0000000000..2a701add19
--- /dev/null
+++ b/gr-blocks/lib/abs_XX_impl.cc.t
@@ -0,0 +1,62 @@
+/* -*- 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.
+ */
+
+// @WARNING@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <@NAME_IMPL@.h>
+#include <gnuradio/io_signature.h>
+
+namespace gr {
+ namespace blocks {
+
+ @NAME@::sptr @NAME@::make()
+ {
+ return gnuradio::get_initial_sptr(new @NAME_IMPL@());
+ }
+
+ @NAME_IMPL@::@NAME_IMPL@()
+ : sync_block ("@NAME@",
+ io_signature::make (1, 1, sizeof (@I_TYPE@)),
+ io_signature::make (1, 1, sizeof (@O_TYPE@)))
+ {
+ }
+
+ int
+ @NAME_IMPL@::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ @I_TYPE@ *iptr = (@I_TYPE@ *) input_items[0];
+ @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0];
+
+ for(int i=0; i<noutput_items; i++)
+ optr[i] = abs(iptr[i]);
+
+ return noutput_items;
+ }
+
+ } /* namespace blocks */
+} /* namespace gr */
diff --git a/gr-blocks/lib/abs_XX_impl.h.t b/gr-blocks/lib/abs_XX_impl.h.t
new file mode 100644
index 0000000000..b31ef5fb31
--- /dev/null
+++ b/gr-blocks/lib/abs_XX_impl.h.t
@@ -0,0 +1,46 @@
+/* -*- 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.
+ */
+
+// @WARNING@
+
+#ifndef @GUARD_NAME_IMPL@
+#define @GUARD_NAME_IMPL@
+
+#include <gnuradio/blocks/@NAME@.h>
+
+namespace gr {
+ namespace blocks {
+
+ class BLOCKS_API @NAME_IMPL@ : public @NAME@
+ {
+ public:
+ @NAME_IMPL@();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace blocks */
+} /* namespace gr */
+
+#endif /* @GUARD_NAME_IMPL@ */
diff --git a/gr-blocks/lib/null_sink_impl.cc b/gr-blocks/lib/null_sink_impl.cc
index 41adeea0fd..14dd5eff24 100644
--- a/gr-blocks/lib/null_sink_impl.cc
+++ b/gr-blocks/lib/null_sink_impl.cc
@@ -39,8 +39,8 @@ namespace gr {
null_sink_impl::null_sink_impl(size_t sizeof_stream_item)
: sync_block("null_sink",
- io_signature::make(1, 1, sizeof_stream_item),
- io_signature::make(0, 0, 0))
+ io_signature::make(1, -1, sizeof_stream_item),
+ io_signature::make(0, 0, 0))
{
}
diff --git a/gr-blocks/lib/null_source_impl.cc b/gr-blocks/lib/null_source_impl.cc
index edf0104da1..9550dd6bce 100644
--- a/gr-blocks/lib/null_source_impl.cc
+++ b/gr-blocks/lib/null_source_impl.cc
@@ -41,7 +41,7 @@ namespace gr {
null_source_impl::null_source_impl (size_t sizeof_stream_item)
: sync_block("null_source",
io_signature::make(0, 0, 0),
- io_signature::make(1, 1, sizeof_stream_item))
+ io_signature::make(1, -1, sizeof_stream_item))
{
}
@@ -54,8 +54,11 @@ namespace gr {
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
- void *optr = (void*)output_items[0];
- memset(optr, 0, noutput_items * output_signature()->sizeof_stream_item(0));
+ void *optr;
+ for(size_t n = 0; n < input_items.size(); n++) {
+ optr = (void*)output_items[n];
+ memset(optr, 0, noutput_items * output_signature()->sizeof_stream_item(n));
+ }
return noutput_items;
}
diff --git a/gr-blocks/lib/tagged_stream_to_pdu_impl.cc b/gr-blocks/lib/tagged_stream_to_pdu_impl.cc
index da8940359a..04871aef8f 100644
--- a/gr-blocks/lib/tagged_stream_to_pdu_impl.cc
+++ b/gr-blocks/lib/tagged_stream_to_pdu_impl.cc
@@ -38,100 +38,43 @@ namespace gr {
}
tagged_stream_to_pdu_impl::tagged_stream_to_pdu_impl(pdu::vector_type type, const std::string& lengthtagname)
- : sync_block("tagged_stream_to_pdu",
+ : tagged_stream_block("tagged_stream_to_pdu",
io_signature::make(1, 1, pdu::itemsize(type)),
- io_signature::make(0, 0, 0)),
- d_itemsize(pdu::itemsize(type)),
- d_inpdu(false),
+ io_signature::make(0, 0, 0), lengthtagname),
d_type(type),
d_pdu_meta(pmt::PMT_NIL),
- d_pdu_vector(pmt::PMT_NIL),
- d_tag(pmt::mp(lengthtagname))
+ d_pdu_vector(pmt::PMT_NIL)
{
message_port_register_out(PDU_PORT_ID);
}
int
- tagged_stream_to_pdu_impl::work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
+ tagged_stream_to_pdu_impl::work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
{
const uint8_t *in = (const uint8_t*) input_items[0];
- uint64_t abs_N = nitems_read(0);
- // if we are not in a pdu already, start a new one
- if (!d_inpdu) {
- bool found_length_tag(false);
-
- get_tags_in_range(d_tags, 0, abs_N, abs_N+1);
-
- for (d_tags_itr = d_tags.begin(); (d_tags_itr != d_tags.end()) && (!found_length_tag); d_tags_itr++) {
- if (pmt::eq((*d_tags_itr).key, d_tag)) {
-
- if ((*d_tags_itr).offset != abs_N )
- throw std::runtime_error("expected next pdu length tag on a different item...");
-
- found_length_tag = true;
- d_pdu_length = pmt::to_long((*d_tags_itr).value);
- d_pdu_remain = d_pdu_length;
- d_pdu_meta = pmt::make_dict();
- break;
- } // if have length tag
- } // iter over tags
-
- if (!found_length_tag)
- throw std::runtime_error("tagged stream does not contain a pdu_length tag");
+ // Grab tags, throw them into dict
+ get_tags_in_range(d_tags, 0,
+ nitems_read(0),
+ nitems_read(0) + ninput_items[0]
+ );
+ d_pdu_meta = pmt::make_dict();
+ for (d_tags_itr = d_tags.begin(); d_tags_itr != d_tags.end(); d_tags_itr++) {
+ d_pdu_meta = dict_add(d_pdu_meta, (*d_tags_itr).key, (*d_tags_itr).value);
}
- size_t ncopy = std::min((size_t)noutput_items, d_pdu_remain);
-
- // copy any tags in this range into our meta object
- get_tags_in_range(d_tags, 0, abs_N, abs_N+ncopy);
- for (d_tags_itr = d_tags.begin(); d_tags_itr != d_tags.end(); d_tags_itr++)
- if(!pmt::eq((*d_tags_itr).key, d_tag ))
- d_pdu_meta = dict_add(d_pdu_meta, (*d_tags_itr).key, (*d_tags_itr).value);
+ // Grab data, throw into vector
+ d_pdu_vector = pdu::make_pdu_vector(d_type, in, ninput_items[0]);
- // copy samples for this vector into either a pmt or our save buffer
- if (ncopy == d_pdu_remain) { // we will send this pdu
- if (d_save.size() == 0) {
- d_pdu_vector = pdu::make_pdu_vector(d_type, in, ncopy);
- send_message();
- }
- else {
- size_t oldsize = d_save.size()/d_itemsize;
- d_save.resize((oldsize + ncopy)*d_itemsize, 0);
- memcpy(&d_save[oldsize*d_itemsize], in, ncopy*d_itemsize);
- d_pdu_vector = pdu::make_pdu_vector(d_type, &d_save[0], d_pdu_length);
- send_message();
- d_save.clear();
- }
- }
- else {
- size_t oldsize = d_save.size()/d_itemsize;
- d_inpdu = true;
- d_save.resize((oldsize+ncopy)*d_itemsize);
- memcpy(&d_save[oldsize*d_itemsize], in, ncopy*d_itemsize);
- d_pdu_remain -= ncopy;
- }
-
- return ncopy;
- }
-
- void
- tagged_stream_to_pdu_impl::send_message()
- {
- if (pmt::length(d_pdu_vector) != d_pdu_length)
- throw std::runtime_error("msg length not correct");
-
+ // Send msg
pmt::pmt_t msg = pmt::cons(d_pdu_meta, d_pdu_vector);
message_port_pub(PDU_PORT_ID, msg);
-
- d_pdu_meta = pmt::PMT_NIL;
- d_pdu_vector = pmt::PMT_NIL;
- d_pdu_length = 0;
- d_pdu_remain = 0;
- d_inpdu = false;
+
+ return ninput_items[0];
}
-
+
} /* namespace blocks */
} /* namespace gr */
diff --git a/gr-blocks/lib/tagged_stream_to_pdu_impl.h b/gr-blocks/lib/tagged_stream_to_pdu_impl.h
index 9620778a91..0a83a87beb 100644
--- a/gr-blocks/lib/tagged_stream_to_pdu_impl.h
+++ b/gr-blocks/lib/tagged_stream_to_pdu_impl.h
@@ -30,27 +30,20 @@ namespace gr {
class BLOCKS_API tagged_stream_to_pdu_impl : public tagged_stream_to_pdu
{
- size_t d_itemsize;
- size_t d_pdu_length;
- size_t d_pdu_remain;
- bool d_inpdu;
pdu::vector_type d_type;
- std::vector<uint8_t> d_save;
pmt::pmt_t d_pdu_meta;
pmt::pmt_t d_pdu_vector;
-
- pmt::pmt_t d_tag;
std::vector<tag_t>::iterator d_tags_itr;
- std::vector<tag_t> d_tags;
-
+ std::vector<tag_t> d_tags;
+
public:
tagged_stream_to_pdu_impl(pdu::vector_type type, const std::string& lengthtagname);
int work(int noutput_items,
+ gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
- void send_message();
};
} /* namespace blocks */
diff --git a/gr-blocks/python/blocks/qa_pdu.py b/gr-blocks/python/blocks/qa_pdu.py
index 0bd838b9c0..81cd8cf71c 100755
--- a/gr-blocks/python/blocks/qa_pdu.py
+++ b/gr-blocks/python/blocks/qa_pdu.py
@@ -86,27 +86,58 @@ class test_pdu(gr_unittest.TestCase):
actual_data = 16*[0xFF,]
self.assertEqual(actual_data, list(result_data))
self.assertEqual(actual_data, msg_data)
-
+
def test_001(self):
#Test the overflow buffer in pdu_to_tagged_stream
src_data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
src = blocks.pdu_to_tagged_stream(blocks.float_t)
snk = blocks.vector_sink_f()
-
+
self.tb.connect(src, snk)
port = pmt.intern("pdus")
-
+
msg = pmt.cons( pmt.PMT_NIL, pmt.init_f32vector(10, src_data))
src.to_basic_block()._post(port, msg)
-
+
src.set_max_noutput_items(5)
-
+
self.tb.start()
#ideally, would wait until we get ten samples
time.sleep(0.2)
self.tb.stop()
-
+
self.assertEqual(src_data, list(snk.data()) )
+
+ def test_002_tags_plus_data(self):
+ packet_len = 16
+ src_data = range(packet_len)
+ tag1 = gr.tag_t()
+ tag1.offset = 0
+ tag1.key = pmt.string_to_symbol('spam')
+ tag1.value = pmt.from_long(23)
+ tag2 = gr.tag_t()
+ tag2.offset = 10 # Must be < packet_len
+ tag2.key = pmt.string_to_symbol('eggs')
+ tag2.value = pmt.from_long(42)
+ src = blocks.vector_source_f(src_data, tags=(tag1, tag2))
+ s2ts = blocks.stream_to_tagged_stream(gr.sizeof_float, vlen=1, packet_len=packet_len, len_tag_key="packet_len")
+ ts2pdu = blocks.tagged_stream_to_pdu(blocks.float_t, "packet_len")
+ dbg = blocks.message_debug()
+ self.tb.connect(src, s2ts, ts2pdu)
+ self.tb.msg_connect(ts2pdu, "pdus", dbg, "store")
+ self.tb.start()
+ while dbg.num_messages() < 1:
+ time.sleep(0.1)
+ self.tb.stop()
+ self.tb.wait()
+ result_msg = dbg.get_message(0)
+ metadata = pmt.to_python(pmt.car(result_msg))
+ vector = pmt.f32vector_elements(pmt.cdr(result_msg))
+ self.assertEqual(metadata, {'eggs': 42, 'spam': 23})
+ self.assertFloatTuplesAlmostEqual(tuple(vector), src_data)
+
+
if __name__ == '__main__':
gr_unittest.run(test_pdu, "test_pdu.xml")
+
diff --git a/gr-blocks/swig/blocks_swig2.i b/gr-blocks/swig/blocks_swig2.i
index f22af806e6..fddeab401d 100644
--- a/gr-blocks/swig/blocks_swig2.i
+++ b/gr-blocks/swig/blocks_swig2.i
@@ -31,6 +31,9 @@
%include "feval.i"
%{
+#include "gnuradio/blocks/abs_ff.h"
+#include "gnuradio/blocks/abs_ss.h"
+#include "gnuradio/blocks/abs_ii.h"
#include "gnuradio/blocks/add_ff.h"
#include "gnuradio/blocks/add_ss.h"
#include "gnuradio/blocks/add_ii.h"
@@ -74,6 +77,9 @@
#include "gnuradio/blocks/divide_cc.h"
%}
+%include "gnuradio/blocks/abs_ff.h"
+%include "gnuradio/blocks/abs_ss.h"
+%include "gnuradio/blocks/abs_ii.h"
%include "gnuradio/blocks/add_ff.h"
%include "gnuradio/blocks/add_ss.h"
%include "gnuradio/blocks/add_ii.h"
@@ -116,6 +122,9 @@
%include "gnuradio/blocks/divide_ii.h"
%include "gnuradio/blocks/divide_cc.h"
+GR_SWIG_BLOCK_MAGIC2(blocks, abs_ff);
+GR_SWIG_BLOCK_MAGIC2(blocks, abs_ss);
+GR_SWIG_BLOCK_MAGIC2(blocks, abs_ii);
GR_SWIG_BLOCK_MAGIC2(blocks, add_ff);
GR_SWIG_BLOCK_MAGIC2(blocks, add_ss);
GR_SWIG_BLOCK_MAGIC2(blocks, add_ii);
diff --git a/gr-fec/lib/reed-solomon/char.h b/gr-fec/lib/reed-solomon/char.h
index f76ad95cd4..4d3f22e5db 100644
--- a/gr-fec/lib/reed-solomon/char.h
+++ b/gr-fec/lib/reed-solomon/char.h
@@ -19,6 +19,7 @@ struct rs {
unsigned char fcr; /* First consecutive root, index form */
unsigned char prim; /* Primitive element, index form */
unsigned char iprim; /* prim-th root of 1, index form */
+ int *modnn_table; /* modnn lookup table, 512 entries */
};
static inline unsigned int modnn(struct rs *rs, unsigned int x){
diff --git a/gr-fec/lib/reed-solomon/encode_rs.c b/gr-fec/lib/reed-solomon/encode_rs.c
index cd31f32c6e..992aa3f4df 100644
--- a/gr-fec/lib/reed-solomon/encode_rs.c
+++ b/gr-fec/lib/reed-solomon/encode_rs.c
@@ -35,12 +35,26 @@ DTYPE *data, DTYPE *bb){
feedback = MODNN(NN - GENPOLY[NROOTS] + feedback);
#endif
for(j=1;j<NROOTS;j++)
+#ifdef FIXED
+ bb[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS-j])];
+#elif defined(BIGSYM)
+ // Same as above; keeping as a separate line in case these change.
bb[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS-j])];
+#else
+ bb[j] ^= ALPHA_TO[rs->modnn_table[feedback + GENPOLY[NROOTS-j]]];
+#endif
}
/* Shift */
memmove(&bb[0],&bb[1],sizeof(DTYPE)*(NROOTS-1));
if(feedback != A0)
+#ifdef FIXED
+ bb[NROOTS-1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])];
+#elif defined(BIGSYM)
+ // Same as above; keeping as a separate line in case these change.
bb[NROOTS-1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])];
+#else
+ bb[NROOTS-1] = ALPHA_TO[rs->modnn_table[feedback + GENPOLY[0]]];
+#endif
else
bb[NROOTS-1] = 0;
}
diff --git a/gr-fec/lib/reed-solomon/init_rs.c b/gr-fec/lib/reed-solomon/init_rs.c
index f50592b55a..c3d8921616 100644
--- a/gr-fec/lib/reed-solomon/init_rs.c
+++ b/gr-fec/lib/reed-solomon/init_rs.c
@@ -23,6 +23,11 @@ void FREE_RS(void *p){
free(rs->alpha_to);
free(rs->index_of);
free(rs->genpoly);
+#ifdef FIXED
+#elif defined(BIGSYM)
+#else
+ free(rs->modnn_table);
+#endif
free(rs);
}
@@ -120,6 +125,24 @@ void *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned fcr,unsigned pri
for (i = 0; i <= nroots; i++)
rs->genpoly[i] = rs->index_of[rs->genpoly[i]];
+#ifdef FIXED
+#elif defined(BIGSYM)
+#else
+ /* Form modnn lookup table */
+ rs->modnn_table = (int *)malloc(sizeof(int)*(2<<((sizeof(unsigned char))*8)));
+ if(rs->modnn_table == NULL){
+ free(rs->genpoly);
+ free(rs->alpha_to);
+ free(rs->index_of);
+ free(rs);
+ return NULL;
+ }
+ for(i = 0; i < (2<<((sizeof(unsigned char))*8)); i++){
+ j = i;
+ rs->modnn_table[i] = modnn(rs,j);
+ }
+#endif
+
#if 0
printf ("genpoly:\n");
for (i = nroots; i >= 0; i--){
diff --git a/gr-filter/examples/reconstruction.py b/gr-filter/examples/reconstruction.py
index fd8ba87a2f..0a83b5a4e0 100755
--- a/gr-filter/examples/reconstruction.py
+++ b/gr-filter/examples/reconstruction.py
@@ -72,7 +72,7 @@ def main():
src = blocks.vector_source_b(data.astype(scipy.uint8).tolist(), False)
mod = digital.bpsk_mod(samples_per_symbol=2)
- chan = filter.channel_model(npwr)
+ chan = channels.channel_model(npwr)
rrc = filter.fft_filter_ccc(1, rrc_taps)
# Split it up into pieces
@@ -122,7 +122,7 @@ def main():
s12.set_title("Original Signal in Time")
start = 1
- skip = 4
+ skip = 2
s13 = f1.add_subplot(2,2,3)
s13.plot(sin.real[start::skip], sin.imag[start::skip], "o")
s13.set_title("Constellation")
@@ -153,7 +153,7 @@ def main():
s32.plot(sout.imag[1000:1500], "o-r")
s32.set_title("Reconstructed Signal in Time")
- start = 2
+ start = 0
skip = 4
s33 = f3.add_subplot(2,2,3)
s33.plot(sout.real[start::skip], sout.imag[start::skip], "o")
diff --git a/gr-filter/grc/filter_fft_filter_xxx.xml b/gr-filter/grc/filter_fft_filter_xxx.xml
index 99b02cbab8..f843af2024 100644
--- a/gr-filter/grc/filter_fft_filter_xxx.xml
+++ b/gr-filter/grc/filter_fft_filter_xxx.xml
@@ -26,11 +26,18 @@ self.$(id).declare_sample_delay($samp_delay)
<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:float_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>
+ <opt>taps:float_vector</opt>
</option>
</param>
<param>
diff --git a/gr-filter/grc/filter_pfb_channelizer.xml b/gr-filter/grc/filter_pfb_channelizer.xml
index 26349cd10d..f8a51d2204 100644
--- a/gr-filter/grc/filter_pfb_channelizer.xml
+++ b/gr-filter/grc/filter_pfb_channelizer.xml
@@ -16,14 +16,13 @@
$atten)
self.$(id).set_channel_map($ch_map)
</make>
- <!-- Set taps not implemented yet
- <callback>set_taps($taps)</callback>
- -->
+ <callback>set_taps($taps)</callback>
<callback>set_channel_map($ch_map)</callback>
<param>
<name>Channels</name>
<key>nchans</key>
+ <value>1</value>
<type>int</type>
</param>
<param>
@@ -50,6 +49,13 @@ self.$(id).set_channel_map($ch_map)
<value>[]</value>
<type>int_vector</type>
</param>
+ <param>
+ <name>Bus Connections</name>
+ <key>bus_conns</key>
+ <value>[[0,],]</value>
+ <type>raw</type>
+ <hide>part</hide>
+ </param>
<sink>
<name>in</name>
<type>complex</type>
@@ -59,4 +65,5 @@ self.$(id).set_channel_map($ch_map)
<type>complex</type>
<nports>$nchans</nports>
</source>
+ <bus_structure_source>$bus_conns</bus_structure_source>
</block>
diff --git a/gr-filter/grc/filter_pfb_decimator.xml b/gr-filter/grc/filter_pfb_decimator.xml
index d57119636c..3a828762a0 100644
--- a/gr-filter/grc/filter_pfb_decimator.xml
+++ b/gr-filter/grc/filter_pfb_decimator.xml
@@ -13,7 +13,9 @@
$decim,
$taps,
$channel,
- $atten)
+ $atten,
+ $fft_rot,
+ $fft_filts)
</make>
<callback>set_taps($taps)</callback>
<callback>set_channel(int($channel))</callback>
@@ -40,6 +42,36 @@
<value>100</value>
<type>real</type>
</param>
+ <param>
+ <name>Use FFT Rotator</name>
+ <key>fft_rot</key>
+ <value>True</value>
+ <type>raw</type>
+ <hide>part</hide>
+ <option>
+ <name>True</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>False</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Use FFT Filters</name>
+ <key>fft_filts</key>
+ <value>True</value>
+ <type>raw</type>
+ <hide>part</hide>
+ <option>
+ <name>True</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>False</name>
+ <key>False</key>
+ </option>
+ </param>
<sink>
<name>in</name>
<type>complex</type>
diff --git a/gr-filter/grc/filter_pfb_synthesizer.xml b/gr-filter/grc/filter_pfb_synthesizer.xml
index e84b25e62e..e7e1ae3951 100644
--- a/gr-filter/grc/filter_pfb_synthesizer.xml
+++ b/gr-filter/grc/filter_pfb_synthesizer.xml
@@ -45,6 +45,13 @@ self.$(id).set_channel_map($ch_map)
<value>[]</value>
<type>int_vector</type>
</param>
+ <param>
+ <name>Bus Connections</name>
+ <key>bus_conns</key>
+ <value>[[0,],]</value>
+ <type>raw</type>
+ <hide>part</hide>
+ </param>
<sink>
<name>in</name>
<type>complex</type>
@@ -54,4 +61,5 @@ self.$(id).set_channel_map($ch_map)
<name>out</name>
<type>complex</type>
</source>
+ <bus_structure_sink>$bus_conns</bus_structure_sink>
</block>
diff --git a/gr-filter/include/gnuradio/filter/CMakeLists.txt b/gr-filter/include/gnuradio/filter/CMakeLists.txt
index d039af9b00..9dbc227887 100644
--- a/gr-filter/include/gnuradio/filter/CMakeLists.txt
+++ b/gr-filter/include/gnuradio/filter/CMakeLists.txt
@@ -94,6 +94,7 @@ install(FILES
dc_blocker_ff.h
filter_delay_fc.h
fft_filter_ccc.h
+ fft_filter_ccf.h
fft_filter_fff.h
fractional_interpolator_cc.h
fractional_interpolator_ff.h
diff --git a/gr-filter/include/gnuradio/filter/fft_filter.h b/gr-filter/include/gnuradio/filter/fft_filter.h
index 76271d9abf..24f6ce3134 100644
--- a/gr-filter/include/gnuradio/filter/fft_filter.h
+++ b/gr-filter/include/gnuradio/filter/fft_filter.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2010,2012 Free Software Foundation, Inc.
+ * Copyright 2010,2012,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -49,7 +49,7 @@ namespace gr {
std::vector<float> d_tail; // state carried between blocks for overlap-add
std::vector<float> d_taps; // stores time domain taps
gr_complex *d_xformed_taps; // Fourier xformed taps
-
+
void compute_sizes(int ntaps);
int tailsize() const { return d_ntaps - 1; }
@@ -77,7 +77,7 @@ namespace gr {
* \param taps The filter taps (complex)
*/
int set_taps(const std::vector<float> &taps);
-
+
/*!
* \brief Set number of threads to use.
*/
@@ -92,12 +92,12 @@ namespace gr {
* \brief Returns the number of taps in the filter.
*/
unsigned int ntaps() const;
-
+
/*!
* \brief Get number of threads being used.
*/
int nthreads() const;
-
+
/*!
l * \brief Perform the filter operation
*
@@ -108,7 +108,7 @@ l * \brief Perform 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
@@ -126,7 +126,7 @@ l * \brief Perform the filter operation
std::vector<gr_complex> d_tail; // state carried between blocks for overlap-add
std::vector<gr_complex> d_taps; // stores time domain taps
gr_complex *d_xformed_taps; // Fourier xformed taps
-
+
void compute_sizes(int ntaps);
int tailsize() const { return d_ntaps - 1; }
@@ -154,12 +154,12 @@ l * \brief Perform the filter operation
* \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 Returns the taps.
*/
@@ -169,12 +169,100 @@ l * \brief Perform the filter operation
* \brief Returns the number of taps in the filter.
*/
unsigned int ntaps() const;
-
+
+ /*!
+ * \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);
+ };
+
+
+
+ /*!
+ * \brief Fast FFT filter with gr_complex input, gr_complex output and float taps
+ * \ingroup filter_blk
+ */
+ class FILTER_API fft_filter_ccf
+ {
+ 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<float> d_taps; // stores time domain 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_ccf).
+ *
+ * \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_ccf(int decimation,
+ const std::vector<float> &taps,
+ int nthreads=1);
+
+ ~fft_filter_ccf();
+
+ /*!
+ * \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 Returns the taps.
+ */
+ std::vector<float> taps() const;
+
+ /*!
+ * \brief Returns the number of taps in the filter.
+ */
+ unsigned int ntaps() const;
+
+ /*!
+ * \brief Returns the actual size of the filter.
+ *
+ * \details This value could be equal to ntaps, but we ofter
+ * build a longer filter to allow us to calculate a more
+ * efficient FFT. This value is the actual size of the filters
+ * used in the calculation of the overlap-and-save operation.
+ */
+ unsigned int filtersize() const;
+
/*!
* \brief Get number of threads being used.
*/
int nthreads() const;
-
+
/*!
* \brief Perform the filter operation
*
diff --git a/gr-filter/include/gnuradio/filter/fft_filter_ccf.h b/gr-filter/include/gnuradio/filter/fft_filter_ccf.h
new file mode 100644
index 0000000000..b0230f8263
--- /dev/null
+++ b/gr-filter/include/gnuradio/filter/fft_filter_ccf.h
@@ -0,0 +1,89 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2014 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_CCF_H
+#define INCLUDED_FILTER_FFT_FILTER_CCF_H
+
+#include <gnuradio/filter/api.h>
+#include <gnuradio/sync_decimator.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief Fast FFT filter with gr_complex input, gr_complex output and float taps
+ * \ingroup filter_blk
+ *
+ * \details
+ * 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.
+ */
+ class FILTER_API fft_filter_ccf : virtual public sync_decimator
+ {
+ public:
+ // gr::filter::fft_filter_ccf::sptr
+ typedef boost::shared_ptr<fft_filter_ccf> sptr;
+
+ /*!
+ * Build an FFT filter blocks.
+ *
+ * \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<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_CCF_H */
diff --git a/gr-filter/include/gnuradio/filter/pfb_channelizer_ccf.h b/gr-filter/include/gnuradio/filter/pfb_channelizer_ccf.h
index f199f85b83..96ffd60daa 100644
--- a/gr-filter/include/gnuradio/filter/pfb_channelizer_ccf.h
+++ b/gr-filter/include/gnuradio/filter/pfb_channelizer_ccf.h
@@ -101,8 +101,14 @@ namespace gr {
* <B><EM>f. harris, "Multirate Signal Processing for Communication
* Systems," Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
*
+ * When dealing with oversampling, the above book is still a good
+ * reference along with this paper:
+ *
+ * <B><EM>E. Venosa, X. Chen, and fred harris, “Polyphase analysis
+ * filter bank down-converts unequal channel bandwidths with
+ * arbitrary center frequencies - design I,” in SDR’10-WinnComm,
+ * 2010.</EM></B>
*/
-
class FILTER_API pfb_channelizer_ccf : virtual public block
{
public:
@@ -151,7 +157,7 @@ namespace gr {
* Print all of the filterbank taps to screen.
*/
virtual void print_taps() = 0;
-
+
/*!
* Return a vector<vector<>> of the filterbank taps
*/
@@ -189,7 +195,7 @@ namespace gr {
* 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.
*/
diff --git a/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h b/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h
index da4eb2bd34..06f329a03e 100644
--- a/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h
+++ b/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h
@@ -99,10 +99,19 @@ namespace gr {
* \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].
+ * \param use_fft_rotator (bool) Rotate channels using FFT method instead of exp(phi).
+ * For larger values of \p channel, the FFT method will perform better.
+ * Generally, this value of \p channel is small (~5), but could be
+ * architecture-specific (Default: true).
+ * \param use_fft_filters (bool) Use FFT filters (fast convolution) instead of FIR filters.
+ * FFT filters perform better for larger numbers of taps but is
+ * architecture-specific (Default: true).
*/
static sptr make(unsigned int decim,
- const std::vector<float> &taps,
- unsigned int channel);
+ const std::vector<float> &taps,
+ unsigned int channel,
+ bool use_fft_rotator=true,
+ bool use_fft_filters=true);
/*!
* Resets the filterbank's filter taps with the new prototype filter
diff --git a/gr-filter/include/gnuradio/filter/pfb_synthesizer_ccf.h b/gr-filter/include/gnuradio/filter/pfb_synthesizer_ccf.h
index f1fbad7272..32465b61ac 100644
--- a/gr-filter/include/gnuradio/filter/pfb_synthesizer_ccf.h
+++ b/gr-filter/include/gnuradio/filter/pfb_synthesizer_ccf.h
@@ -34,6 +34,57 @@ namespace gr {
* \brief Polyphase synthesis filterbank with
* gr_complex input, gr_complex output and float taps
* \ingroup channelizers_blk
+ *
+ * \details
+ *
+ * The PFB sythesis filterbank combines multiple baseband signals
+ * into a single channelized signal. Each input stream is,
+ * essentially, modulated onto an output channel according the the
+ * channel mapping (see set_channel_map for details).
+ *
+ * Setting this filterbank up means selecting the number of output
+ * channels, the prototype filter, and whether to handle channels
+ * at 2x the sample rate (this is generally used only for
+ * reconstruction filtering).
+ *
+ * The number of channels sets the maximum number of channels to
+ * use, but not all input streams must be connected. For M total
+ * channels, we can connect inputs 0 to N where N < M-1. Because
+ * of the way GNU Radio handles stream connections, we must
+ * connect the channels consecutively, and so we must use the
+ * set_channel_map if the desired output channels are not the same
+ * as the the default mapping. This features gives us the
+ * flexibility to output to any given channel. Generally, we try
+ * to not use the channels at the edge of the spectrum to avoid
+ * issues with filtering and roll-off of the transmitter or
+ * receiver.
+ *
+ * When using the 2x sample rate mode, we specify the number of
+ * channels that will be used. However, the actual output signal
+ * will be twice this number of channels. This is mainly important
+ * to know when setting the channel map. For M channels, the
+ * channel mapping can specy from 0 to 2M-1 channels to output
+ * onto.
+ *
+ * For more details about this and the concepts of reconstruction
+ * filtering, see:
+ *
+ * <B><EM>f. harris, "Multirate Signal Processing for Communication
+ * Systems," Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
+ *
+ * <B><EM>X. Chen, E. Venosa, and fred harris, “Polyphase analysis
+ * filter bank up-converts unequal channel bandwidths with
+ * arbitrary center frequencies - design ii,” in SDR’10-WinnComm,
+ * 2010.</EM></B>
+ *
+ * <B><EM>E. Venosa, X. Chen, and fred harris, “Polyphase analysis
+ * filter bank down-converts unequal channel bandwidths with
+ * arbitrary center frequencies - design I,” in SDR’10-WinnComm,
+ * 2010.</EM></B>
+ *
+ * <B><EM>f. j. harris, C. Dick, X. Chen, and E. Venosa, “Wideband 160-
+ * channel polyphase filter bank cable TV channeliser,” in IET
+ * Signal Processing, 2010.</EM></B>
*/
class FILTER_API pfb_synthesizer_ccf : virtual public sync_interpolator
{
@@ -50,8 +101,8 @@ namespace gr {
* \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);
+ const std::vector<float> &taps,
+ bool twox=false);
/*!
* Resets the filterbank's filter taps with the new prototype filter
diff --git a/gr-filter/include/gnuradio/filter/polyphase_filterbank.h b/gr-filter/include/gnuradio/filter/polyphase_filterbank.h
index fad04e3294..1745a470ab 100644
--- a/gr-filter/include/gnuradio/filter/polyphase_filterbank.h
+++ b/gr-filter/include/gnuradio/filter/polyphase_filterbank.h
@@ -26,6 +26,7 @@
#include <gnuradio/filter/api.h>
#include <gnuradio/filter/fir_filter.h>
+#include <gnuradio/filter/fft_filter.h>
#include <gnuradio/fft/fft.h>
namespace gr {
@@ -101,11 +102,12 @@ namespace gr {
{
protected:
unsigned int d_nfilts;
- std::vector<kernel::fir_filter_ccf*> d_filters;
+ std::vector<kernel::fir_filter_ccf*> d_fir_filters;
+ std::vector<kernel::fft_filter_ccf*> d_fft_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.
@@ -113,9 +115,11 @@ namespace gr {
* channels <EM>M</EM>
* \param taps (vector/list of floats) The prototype filter to
* populate the filterbank.
+ * \param fft_forward (bool) use a forward or inverse FFT (default=false).
*/
polyphase_filterbank(unsigned int nfilts,
- const std::vector<float> &taps);
+ const std::vector<float> &taps,
+ bool fft_forward=false);
~polyphase_filterbank();
@@ -126,7 +130,7 @@ namespace gr {
* \param taps (vector/list of floats) The prototype filter to
* populate the filterbank.
*/
- void set_taps(const std::vector<float> &taps);
+ virtual void set_taps(const std::vector<float> &taps);
/*!
* Print all of the filterbank taps to screen.
diff --git a/gr-filter/lib/CMakeLists.txt b/gr-filter/lib/CMakeLists.txt
index 9f17092bb1..9889a4ddc1 100644
--- a/gr-filter/lib/CMakeLists.txt
+++ b/gr-filter/lib/CMakeLists.txt
@@ -128,6 +128,7 @@ list(APPEND filter_sources
dc_blocker_ff_impl.cc
filter_delay_fc_impl.cc
fft_filter_ccc_impl.cc
+ fft_filter_ccf_impl.cc
fft_filter_fff_impl.cc
fractional_interpolator_cc_impl.cc
fractional_interpolator_ff_impl.cc
diff --git a/gr-filter/lib/fft_filter.cc b/gr-filter/lib/fft_filter.cc
index 94f0a8894b..433b1a4d97 100644
--- a/gr-filter/lib/fft_filter.cc
+++ b/gr-filter/lib/fft_filter.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2010,2012 Free Software Foundation, Inc.
+ * Copyright 2010,2012,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -345,6 +345,170 @@ namespace gr {
return nitems;
}
+
+ /**************************************************************/
+
+
+ fft_filter_ccf::fft_filter_ccf(int decimation,
+ const std::vector<float> &taps,
+ int nthreads)
+ : d_fftsize(-1), d_decimation(decimation), d_fwdfft(NULL),
+ d_invfft(NULL), d_nthreads(nthreads), d_xformed_taps(NULL)
+ {
+ set_taps(taps);
+ }
+
+ fft_filter_ccf::~fft_filter_ccf()
+ {
+ delete d_fwdfft;
+ delete d_invfft;
+ if(d_xformed_taps != NULL)
+ volk_free(d_xformed_taps);
+ }
+
+ /*
+ * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps
+ */
+ int
+ fft_filter_ccf::set_taps(const std::vector<float> &taps)
+ {
+ int i = 0;
+ d_taps = taps;
+ 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] = gr_complex(taps[i] * scale, 0.0f);
+
+ for(; i < d_fftsize; i++)
+ in[i] = gr_complex(0.0f, 0.0f);
+
+ 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_ccf::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_ccf: 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;
+ if(d_xformed_taps != NULL)
+ volk_free(d_xformed_taps);
+ 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 = (gr_complex*)volk_malloc(sizeof(gr_complex)*d_fftsize,
+ volk_get_alignment());
+ }
+ }
+
+ void
+ fft_filter_ccf::set_nthreads(int n)
+ {
+ d_nthreads = n;
+ if(d_fwdfft)
+ d_fwdfft->set_nthreads(n);
+ if(d_invfft)
+ d_invfft->set_nthreads(n);
+ }
+
+ std::vector<float>
+ fft_filter_ccf::taps() const
+ {
+ return d_taps;
+ }
+
+ unsigned int
+ fft_filter_ccf::ntaps() const
+ {
+ return d_ntaps;
+ }
+
+ unsigned int
+ fft_filter_ccf::filtersize() const
+ {
+ return d_fftsize;
+ }
+
+ int
+ fft_filter_ccf::nthreads() const
+ {
+ return d_nthreads;
+ }
+
+ int
+ fft_filter_ccf::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_ccf_impl.cc b/gr-filter/lib/fft_filter_ccf_impl.cc
new file mode 100644
index 0000000000..00e1842fff
--- /dev/null
+++ b/gr-filter/lib/fft_filter_ccf_impl.cc
@@ -0,0 +1,120 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2014 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_ccf_impl.h"
+#include <gnuradio/io_signature.h>
+
+#include <math.h>
+#include <assert.h>
+#include <stdexcept>
+
+namespace gr {
+ namespace filter {
+
+ fft_filter_ccf::sptr
+ fft_filter_ccf::make(int decimation,
+ const std::vector<float> &taps,
+ int nthreads)
+ {
+ return gnuradio::get_initial_sptr
+ (new fft_filter_ccf_impl
+ (decimation, taps, nthreads));
+ }
+
+ fft_filter_ccf_impl::fft_filter_ccf_impl(int decimation,
+ const std::vector<float> &taps,
+ int nthreads)
+ : sync_decimator("fft_filter_ccf",
+ io_signature::make(1, 1, sizeof(gr_complex)),
+ io_signature::make(1, 1, sizeof(gr_complex)),
+ decimation),
+ d_updated(false)
+ {
+ set_history(1);
+
+ d_filter = new kernel::fft_filter_ccf(decimation, taps, nthreads);
+
+ d_new_taps = taps;
+ d_nsamples = d_filter->set_taps(taps);
+ set_output_multiple(d_nsamples);
+ }
+
+ fft_filter_ccf_impl::~fft_filter_ccf_impl()
+ {
+ delete d_filter;
+ }
+
+ void
+ fft_filter_ccf_impl::set_taps(const std::vector<float> &taps)
+ {
+ d_new_taps = taps;
+ d_updated = true;
+ }
+
+ std::vector<float>
+ fft_filter_ccf_impl::taps() const
+ {
+ return d_new_taps;
+ }
+
+ void
+ fft_filter_ccf_impl::set_nthreads(int n)
+ {
+ if(d_filter)
+ d_filter->set_nthreads(n);
+ }
+
+ int
+ fft_filter_ccf_impl::nthreads() const
+ {
+ if(d_filter)
+ return d_filter->nthreads();
+ else
+ return 0;
+ }
+
+ int
+ fft_filter_ccf_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_ccf_impl.h b/gr-filter/lib/fft_filter_ccf_impl.h
new file mode 100644
index 0000000000..2e0ddd46fb
--- /dev/null
+++ b/gr-filter/lib/fft_filter_ccf_impl.h
@@ -0,0 +1,62 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2014 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_CCF_IMPL_H
+#define INCLUDED_FILTER_FFT_FILTER_CCF_IMPL_H
+
+#include <gnuradio/filter/api.h>
+#include <gnuradio/filter/fft_filter.h>
+#include <gnuradio/filter/fft_filter_ccf.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API fft_filter_ccf_impl : public fft_filter_ccf
+ {
+ private:
+ int d_nsamples;
+ bool d_updated;
+ kernel::fft_filter_ccf *d_filter;
+ std::vector<float> d_new_taps;
+
+ public:
+ fft_filter_ccf_impl(int decimation,
+ const std::vector<float> &taps,
+ int nthreads=1);
+
+ ~fft_filter_ccf_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_CCF_IMPL_H */
diff --git a/gr-filter/lib/pfb_channelizer_ccf_impl.cc b/gr-filter/lib/pfb_channelizer_ccf_impl.cc
index c28434b6cb..62223e40da 100644
--- a/gr-filter/lib/pfb_channelizer_ccf_impl.cc
+++ b/gr-filter/lib/pfb_channelizer_ccf_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2009,2010,2012 Free Software Foundation, Inc.
+ * Copyright 2009,2010,2012,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -26,25 +26,28 @@
#include "pfb_channelizer_ccf_impl.h"
#include <gnuradio/io_signature.h>
+#include <stdio.h>
namespace gr {
namespace filter {
-
- pfb_channelizer_ccf::sptr pfb_channelizer_ccf::make(unsigned int nfilts,
- const std::vector<float> &taps,
- float oversample_rate)
+
+ 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));
+ 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)
: block("pfb_channelizer_ccf",
- io_signature::make(nfilts, nfilts, sizeof(gr_complex)),
- io_signature::make(1, nfilts, sizeof(gr_complex))),
- polyphase_filterbank(nfilts, taps),
+ io_signature::make(nfilts, nfilts, sizeof(gr_complex)),
+ io_signature::make(1, nfilts, sizeof(gr_complex))),
+ polyphase_filterbank(nfilts, taps, false),
d_updated(false), d_oversample_rate(oversample_rate)
{
// The over sampling rate must be rationally related to the number of channels
@@ -59,15 +62,22 @@ namespace gr {
set_relative_rate(1.0/intp);
- // Default channel map
+ // Default channel map. The channel map specifies which input
+ // goes to which output channel; so out[0] comes from
+ // channel_map[0].
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.
+ // We use a look up table to set the index of the FFT input
+ // buffer, which equivalently performs the FFT shift operation
+ // on every other turn when the rate_ratio>1. Also, this
+ // performs the index 'flip' where the first input goes into the
+ // last filter. In the pfb_decimator_ccf, we directly index the
+ // input_items buffers starting with this last; here we start
+ // with the first and put it into the fft object properly for
+ // the same effect.
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++) {
@@ -81,10 +91,8 @@ namespace gr {
d_output_multiple++;
set_output_multiple(d_output_multiple);
- // History is the length of each filter arm plus 1.
- // The +1 comes from the channel mapping in the work function
- // where we start n=1 so that we can look at in[n-1]
- set_history(d_taps_per_filter+1);
+ // Use set_taps to also set the history requirement
+ set_taps(taps);
}
pfb_channelizer_ccf_impl::~pfb_channelizer_ccf_impl()
@@ -118,7 +126,7 @@ namespace gr {
pfb_channelizer_ccf_impl::set_channel_map(const std::vector<int> &map)
{
gr::thread::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) {
@@ -142,9 +150,9 @@ namespace gr {
{
gr::thread::scoped_lock guard(d_mutex);
- gr_complex *in = (gr_complex *) input_items[0];
- gr_complex *out = (gr_complex *) output_items[0];
-
+ 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.
@@ -152,6 +160,18 @@ namespace gr {
size_t noutputs = output_items.size();
+ // The following algorithm looks more complex in order to handle
+ // the cases where we want more that 1 sps for each
+ // channel. Otherwise, this would boil down into a single loop
+ // that operates from input_items[0] to [d_nfilts].
+
+ // When dealing with osps>1, we start not at the last filter,
+ // but nfilts/osps and then wrap around to the next symbol into
+ // the other set of filters.
+ // For details of this operation, see:
+ // fred harris, Multirate Signal Processing For Communication
+ // Systems. Upper Saddle River, NJ: Prentice Hall, 2004.
+
int n=1, i=-1, j=0, oo=0, last;
int toconsume = (int)rintf(noutput_items/d_oversample_rate);
while(n <= toconsume) {
@@ -159,16 +179,16 @@ namespace gr {
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]);
+ in = (gr_complex*)input_items[j];
+ d_fft->get_inbuf()[d_idxlut[j]] = d_fir_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]);
+ in = (gr_complex*)input_items[j];
+ d_fft->get_inbuf()[d_idxlut[j]] = d_fir_filters[i]->filter(&in[n-1]);
j++;
i--;
}
diff --git a/gr-filter/lib/pfb_channelizer_ccf_impl.h b/gr-filter/lib/pfb_channelizer_ccf_impl.h
index 6d727676b2..bfc53f8848 100644
--- a/gr-filter/lib/pfb_channelizer_ccf_impl.h
+++ b/gr-filter/lib/pfb_channelizer_ccf_impl.h
@@ -31,7 +31,7 @@
namespace gr {
namespace filter {
-
+
class FILTER_API pfb_channelizer_ccf_impl : public pfb_channelizer_ccf, kernel::polyphase_filterbank
{
private:
diff --git a/gr-filter/lib/pfb_decimator_ccf_impl.cc b/gr-filter/lib/pfb_decimator_ccf_impl.cc
index 19cf20f410..7b4bf73b39 100644
--- a/gr-filter/lib/pfb_decimator_ccf_impl.cc
+++ b/gr-filter/lib/pfb_decimator_ccf_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2009,2010,2012 Free Software Foundation, Inc.
+ * Copyright 2009,2010,2012,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -26,34 +26,53 @@
#include "pfb_decimator_ccf_impl.h"
#include <gnuradio/io_signature.h>
+#include <gnuradio/expj.h>
+#include <volk/volk.h>
namespace gr {
namespace filter {
-
+
pfb_decimator_ccf::sptr
pfb_decimator_ccf::make(unsigned int decim,
const std::vector<float> &taps,
- unsigned int channel)
+ unsigned int channel,
+ bool use_fft_rotator,
+ bool use_fft_filters)
{
return gnuradio::get_initial_sptr
- (new pfb_decimator_ccf_impl(decim, taps, channel));
+ (new pfb_decimator_ccf_impl(decim, taps, channel,
+ use_fft_rotator,
+ use_fft_filters));
}
-
pfb_decimator_ccf_impl::pfb_decimator_ccf_impl(unsigned int decim,
const std::vector<float> &taps,
- unsigned int channel)
+ unsigned int channel,
+ bool use_fft_rotator,
+ bool use_fft_filters)
: sync_block("pfb_decimator_ccf",
- io_signature::make(decim, decim, sizeof(gr_complex)),
- io_signature::make(1, 1, sizeof(gr_complex))),
+ io_signature::make(decim, decim, sizeof(gr_complex)),
+ io_signature::make(1, 1, sizeof(gr_complex))),
polyphase_filterbank(decim, taps),
- d_updated(false), d_chan(channel)
+ d_updated(false), d_chan(channel),
+ d_use_fft_rotator(use_fft_rotator),
+ d_use_fft_filters(use_fft_filters)
{
d_rate = decim;
d_rotator = new gr_complex[d_rate];
+ for(unsigned int i = 0; i < d_rate; i++) {
+ d_rotator[i] = gr_expj(i*d_chan*2*M_PI/d_rate);
+ }
set_relative_rate(1.0/(float)decim);
- set_history(d_taps_per_filter);
+
+ if(d_use_fft_filters) {
+ set_history(1);
+ set_output_multiple(d_fft_filters[0]->filtersize() - d_fft_filters[0]->ntaps() + 1);
+ }
+ else {
+ set_history(d_taps_per_filter);
+ }
}
pfb_decimator_ccf_impl::~pfb_decimator_ccf_impl()
@@ -90,8 +109,6 @@ namespace gr {
d_chan = chan;
}
-#define ROTATEFFT
-
int
pfb_decimator_ccf_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
@@ -99,47 +116,145 @@ namespace gr {
{
gr::thread::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.
}
+ if(d_use_fft_rotator) {
+ if(d_use_fft_filters) {
+ return work_fft_fft(noutput_items, input_items, output_items);
+ }
+ else {
+ return work_fir_fft(noutput_items, input_items, output_items);
+ }
+ }
+ else {
+ if(d_use_fft_filters) {
+ return work_fft_exp(noutput_items, input_items, output_items);
+ }
+ else {
+ return work_fir_exp(noutput_items, input_items, output_items);
+ }
+ }
+ }
+
+ int
+ pfb_decimator_ccf_impl::work_fir_exp(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ gr_complex *in;
+ gr_complex *out = (gr_complex *)output_items[0];
+
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
+ // Take items from M-1 to 0; filter and rotate
in = (gr_complex*)input_items[d_rate - 1 - j];
+ out[i] += d_fir_filters[j]->filter(&in[i])*d_rotator[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
+ return noutput_items;
+ }
+
+ int
+ pfb_decimator_ccf_impl::work_fir_fft(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ gr_complex *in;
+ gr_complex *out = (gr_complex *)output_items[0];
+
+ int i;
+ for(i = 0; i < noutput_items; i++) {
+ // Move through filters from bottom to top
+ out[i] = 0;
+ for(unsigned int j = 0; j < d_rate; j++) {
+ // Take in the items from the first input stream to d_rate
+ in = (gr_complex*)input_items[d_rate-1-j];
+ d_fft->get_inbuf()[j] = d_fir_filters[j]->filter(&in[i]);
}
-#ifdef ROTATEFFT
- // Perform the FFT to do the complex multiply despinning for all channels
- d_fft->execute();
+ // 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
+ // Select only the desired channel out
+ out[i] = d_fft->get_outbuf()[d_chan];
+ }
+
+ return noutput_items;
+ }
+
+ int
+ pfb_decimator_ccf_impl::work_fft_exp(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ gr_complex *in;
+ gr_complex *out = (gr_complex *)output_items[0];
+
+ int i;
+ gr_complex *tmp = fft::malloc_complex(noutput_items*d_rate);
+
+ // Filter each input stream by the FFT filters; do all
+ // noutput_items at once to avoid repeated calls to the FFT
+ // setup and operation.
+ for(unsigned int j = 0; j < d_rate; j++) {
+ in = (gr_complex*)input_items[d_rate-j-1];
+ d_fft_filters[j]->filter(noutput_items, in, &(tmp[j*noutput_items]));
+ }
+
+ // Rotate and add filter outputs (k=channel number; M=number of
+ // channels; and x[j] is the output of filter j.
+ // y[i] = \sum_{j=0}{M-1} (x[j][i]*exp(2j \pi j k / M))
+ for(i = 0; i < noutput_items; i++) {
+ out[i] = 0;
+ for(unsigned int j = 0; j < d_rate; j++) {
+ out[i] += tmp[j*noutput_items+i]*d_rotator[j];
+ }
}
return noutput_items;
}
+ int
+ pfb_decimator_ccf_impl::work_fft_fft(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ gr_complex *in;
+ gr_complex *out = (gr_complex *)output_items[0];
+
+ int i;
+ gr_complex *tmp = fft::malloc_complex(noutput_items*d_rate);
+
+ for(unsigned int j = 0; j < d_rate; j++) {
+ in = (gr_complex*)input_items[d_rate-j-1];
+ d_fft_filters[j]->filter(noutput_items, in, &tmp[j*noutput_items]);
+ }
+
+ // Performs the rotate and add operations by implementing it as
+ // an FFT.
+ for(i = 0; i < noutput_items; i++) {
+ for(unsigned int j = 0; j < d_rate; j++) {
+ d_fft->get_inbuf()[j] = tmp[j*noutput_items + i];
+ }
+
+ // 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];
+ }
+
+ fft::free(tmp);
+ 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
index 2df8a506f0..3397701cf9 100644
--- a/gr-filter/lib/pfb_decimator_ccf_impl.h
+++ b/gr-filter/lib/pfb_decimator_ccf_impl.h
@@ -26,26 +26,42 @@
#include <gnuradio/filter/pfb_decimator_ccf.h>
#include <gnuradio/filter/polyphase_filterbank.h>
-#include <gnuradio/filter/fir_filter.h>
-#include <gnuradio/fft/fft.h>
#include <gnuradio/thread/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;
+ bool d_use_fft_rotator;
+ bool d_use_fft_filters;
gr_complex *d_rotator;
gr::thread::mutex d_mutex; // mutex to protect set/work access
-
+
+ inline int work_fir_exp(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ inline int work_fir_fft(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ inline int work_fft_exp(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ inline int work_fft_fft(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+
public:
pfb_decimator_ccf_impl(unsigned int decim,
const std::vector<float> &taps,
- unsigned int channel);
+ unsigned int channel,
+ bool use_fft_rotator=true,
+ bool use_fft_filters=true);
~pfb_decimator_ccf_impl();
diff --git a/gr-filter/lib/pfb_interpolator_ccf_impl.cc b/gr-filter/lib/pfb_interpolator_ccf_impl.cc
index a0ed73fd4e..cf79c103d3 100644
--- a/gr-filter/lib/pfb_interpolator_ccf_impl.cc
+++ b/gr-filter/lib/pfb_interpolator_ccf_impl.cc
@@ -29,7 +29,7 @@
namespace gr {
namespace filter {
-
+
pfb_interpolator_ccf::sptr
pfb_interpolator_ccf::make(unsigned int interp,
const std::vector<float> &taps)
@@ -94,7 +94,7 @@ namespace gr {
while(i < noutput_items) {
for(unsigned int j = 0; j < d_rate; j++) {
- out[i] = d_filters[j]->filter(&in[count]);
+ out[i] = d_fir_filters[j]->filter(&in[count]);
i++;
}
count++;
diff --git a/gr-filter/lib/pfb_synthesizer_ccf_impl.cc b/gr-filter/lib/pfb_synthesizer_ccf_impl.cc
index 5f0e330ab4..88c3fcedf6 100644
--- a/gr-filter/lib/pfb_synthesizer_ccf_impl.cc
+++ b/gr-filter/lib/pfb_synthesizer_ccf_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2010,2012 Free Software Foundation, Inc.
+ * Copyright 2010,2012,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -33,45 +33,43 @@ namespace gr {
pfb_synthesizer_ccf::sptr
pfb_synthesizer_ccf::make(unsigned int numchans,
- const std::vector<float> &taps,
- bool twox)
+ const std::vector<float> &taps, bool twox)
{
return gnuradio::get_initial_sptr
- (new pfb_synthesizer_ccf_impl(numchans, taps, twox));
+ (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)
+ pfb_synthesizer_ccf_impl::pfb_synthesizer_ccf_impl
+ (unsigned int numchans, const std::vector<float> &taps, bool twox)
: sync_interpolator("pfb_synthesizer_ccf",
- io_signature::make(1, numchans, sizeof(gr_complex)),
- io_signature::make(1, 1, sizeof(gr_complex)),
- (twox ? numchans/2 : numchans)),
- d_updated(false), d_numchans(numchans), d_state(0)
+ io_signature::make(1, numchans, sizeof(gr_complex)),
+ io_signature::make(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");
+ throw std::invalid_argument("pfb_synthesizer_ccf_impl: number of channels must be even for 2x oversampling.\n");
}
- d_filters = std::vector<kernel::fir_filter_with_buffer_ccf*>(d_numchans);
- d_channel_map.resize(d_numchans);
+ 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_numchans);
- for(unsigned int i = 0; i < d_numchans; i++) {
- d_filters[i] = new kernel::fir_filter_with_buffer_ccf(vtaps);
- d_channel_map[i] = i;
+ // Create an FIR filter for each channel and zero out the taps
+ // and set the default channel map
+ 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_numchans, false);
- memset(d_fft->get_inbuf(), 0, d_numchans*sizeof(gr_complex));
+ 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);
}
@@ -79,8 +77,8 @@ namespace gr {
pfb_synthesizer_ccf_impl::~pfb_synthesizer_ccf_impl()
{
delete d_fft;
- for(unsigned int i = 0; i < d_numchans; i++) {
- delete d_filters[i];
+ for(unsigned int i = 0; i < d_twox*d_numchans; i++) {
+ delete d_filters[i];
}
}
@@ -89,20 +87,29 @@ namespace gr {
{
gr::thread::scoped_lock guard(d_mutex);
+ // The different modes, 1x or 2x the sampling rate, have
+ // different filtering partitions.
if(d_twox == 1)
- set_taps1(taps);
+ 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);
+ set_taps2(taps);
+ // Because we keep our own buffers inside the filters, we don't
+ // need history.
+ set_history(1);
d_updated = true;
}
void
pfb_synthesizer_ccf_impl::set_taps1(const std::vector<float> &taps)
{
+ // In this partitioning, we do a normal polyphase paritioning by
+ // deinterleaving the taps into each filter:
+ //
+ // Prototype filter: [t0, t1, t2, t3, t4, t5, t6]
+ // filter 0: [t0, t3, t6]
+ // filter 1: [t1, t4, 0 ]
+ // filter 2: [t2, t5, 0 ]
unsigned int i,j;
unsigned int ntaps = taps.size();
@@ -113,70 +120,77 @@ namespace gr {
// 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;
+ std::vector<float> tmp_taps = taps;
while((float)(tmp_taps.size()) < d_numchans*d_taps_per_filter) {
- tmp_taps.push_back(0.0);
+ 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]);
+ // 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
+ }
+
+ // Set the filter taps for each channel
+ d_filters[i]->set_taps(d_taps[i]);
}
}
void
- pfb_synthesizer_ccf_impl::set_taps2 (const std::vector<float> &taps)
+ pfb_synthesizer_ccf_impl::set_taps2(const std::vector<float> &taps)
{
+ // In this partitioning, create 2M filters each in Z^2; the
+ // second half of the filters are also delayed by Z^1:
+ //
+ // Prototype filter: [t0, t1, t2, t3, t4, t5, t6]
+ // filter 0: [t0, 0, t6]
+ // filter 1: [t2, 0, 0]
+ // filter 2: [t4, 0, 0]
+ // filter 3: [ 0, t1, 0]
+ // filter 4: [ 0, t3, 0 ]
+ // filter 5: [ 0, t5, 0 ]
+
unsigned int i,j;
int state = 0;
- unsigned int ntaps = 2*taps.size();
+ 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);
+ 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;
+ std::vector<float> tmp_taps = taps;
while((float)(tmp_taps.size()) < d_numchans*d_taps_per_filter) {
- tmp_taps.push_back(0.0);
+ tmp_taps.push_back(0.0);
+ //tmp_taps.insert(tmp_taps.begin(), 0.0);
}
// Partition the filter
- unsigned int halfchans = d_numchans/2;
- for(i = 0; i < halfchans; 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[halfchans+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*halfchans];
- d_taps[halfchans + i][j] = 0;
- state = 1;
- }
- else {
- d_taps[i][j] = 0;
- d_taps[halfchans + i][j] = tmp_taps[i + j*halfchans];
- 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[halfchans + i]->set_taps(d_taps[halfchans + i]);
+ 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++) {
+ if(state == 0) {
+ d_taps[i][j] = 0;
+ d_taps[d_numchans + i][j] = tmp_taps[i + j*d_numchans];
+ state = 1;
+ }
+ else {
+ d_taps[i][j] = tmp_taps[i + j*d_numchans];
+ d_taps[d_numchans + i][j] = 0;
+ state = 0;
+ }
+ }
+
+ // Set the filter taps for each channel
+ d_filters[i]->set_taps(d_taps[i]);
+ d_filters[d_numchans + i]->set_taps(d_taps[d_numchans + i]);
}
}
@@ -184,15 +198,16 @@ namespace gr {
pfb_synthesizer_ccf_impl::print_taps()
{
unsigned int i, j;
- for(i = 0; i < 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");
+ 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
{
@@ -205,14 +220,15 @@ namespace gr {
gr::thread::scoped_lock guard(d_mutex);
if(map.size() > 0) {
- unsigned int max = (unsigned int)*std::max_element(map.begin(), map.end());
- if(max >= 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_numchans*sizeof(gr_complex));
+ int max = *std::max_element(map.begin(), map.end());
+ int min = *std::min_element(map.begin(), map.end());
+ if((max >= static_cast<int>(d_twox*d_numchans)) || (min < 0)) {
+ throw std::invalid_argument("pfb_synthesizer_ccf_impl::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));
}
}
@@ -224,63 +240,63 @@ namespace gr {
int
pfb_synthesizer_ccf_impl::work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
{
gr::thread::scoped_lock guard(d_mutex);
- gr_complex *in = (gr_complex*)input_items[0];
- gr_complex *out = (gr_complex*)output_items[0];
+ 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.
+ 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
+ // Algorithm 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;
- }
+ 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 {
- unsigned int halfchans = d_numchans/2;
- for(n = 0; n < noutput_items/halfchans; 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 < halfchans; i++) {
- out[i] = d_filters[i]->filter(d_fft->get_outbuf()[d_state*halfchans+i]);
- out[i] += d_filters[halfchans+i]->filter(d_fft->get_outbuf()[(d_state^1)*halfchans+i]);
- }
- d_state ^= 1;
-
- out += halfchans;
- }
+ for(n = 0; n < noutput_items/d_numchans; n++) {
+ for(i = 0; i < ninputs; i++) {
+ //in = (gr_complex*)input_items[ninputs-i-1];
+ 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;
diff --git a/gr-filter/lib/polyphase_filterbank.cc b/gr-filter/lib/polyphase_filterbank.cc
index ab978e8aaf..5fffc02dce 100644
--- a/gr-filter/lib/polyphase_filterbank.cc
+++ b/gr-filter/lib/polyphase_filterbank.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2012 Free Software Foundation, Inc.
+ * Copyright 2012,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -32,29 +32,33 @@ namespace gr {
namespace kernel {
polyphase_filterbank::polyphase_filterbank(unsigned int nfilts,
- const std::vector<float> &taps)
+ const std::vector<float> &taps,
+ bool fft_forward)
: d_nfilts(nfilts)
{
- d_filters = std::vector<kernel::fir_filter_ccf*>(d_nfilts);
+ d_fir_filters = std::vector<kernel::fir_filter_ccf*>(d_nfilts);
+ d_fft_filters = std::vector<kernel::fft_filter_ccf*>(d_nfilts);
// Create an FIR filter for each channel and zero out the taps
- std::vector<float> vtaps(0, d_nfilts);
+ std::vector<float> vtaps(1, 0.0f);
for(unsigned int i = 0; i < d_nfilts; i++) {
- d_filters[i] = new kernel::fir_filter_ccf(1, vtaps);
+ d_fir_filters[i] = new kernel::fir_filter_ccf(1, vtaps);
+ d_fft_filters[i] = new kernel::fft_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);
+ d_fft = new fft::fft_complex(d_nfilts, fft_forward);
}
polyphase_filterbank::~polyphase_filterbank()
{
delete d_fft;
for(unsigned int i = 0; i < d_nfilts; i++) {
- delete d_filters[i];
+ delete d_fir_filters[i];
+ delete d_fft_filters[i];
}
}
@@ -62,7 +66,6 @@ namespace gr {
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);
@@ -71,16 +74,11 @@ namespace gr {
// 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;
+ std::vector<float> tmp_taps = taps;
while((float)(tmp_taps.size()) < d_nfilts*d_taps_per_filter) {
- tmp_taps.push_back(0.0);
+ tmp_taps.push_back(0.0);
}
- // Reverse taps here; set_taps in filter will then re-reverse,
- // but order them propely, anyways.
- std::reverse(tmp_taps.begin(), tmp_taps.end());
-
// 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
@@ -89,8 +87,9 @@ namespace gr {
d_taps[i][j] = tmp_taps[i + j*d_nfilts];
}
- // Build a filter for each channel and add it's taps to it
- d_filters[i]->set_taps(d_taps[i]);
+ // Set the filter taps for each channel
+ d_fir_filters[i]->set_taps(d_taps[i]);
+ d_fft_filters[i]->set_taps(d_taps[i]);
}
}
diff --git a/gr-filter/python/filter/pfb.py b/gr-filter/python/filter/pfb.py
index 7f7375cb7f..732812ef2a 100644
--- a/gr-filter/python/filter/pfb.py
+++ b/gr-filter/python/filter/pfb.py
@@ -77,7 +77,11 @@ class channelizer_ccf(gr.hier_block2):
def set_channel_map(self, newmap):
self.pfb.set_channel_map(newmap)
+ def set_taps(self, taps):
+ self.pfb.set_taps(taps)
+ def taps(self):
+ return self.pfb.taps()
class interpolator_ccf(gr.hier_block2):
'''
@@ -122,6 +126,8 @@ class interpolator_ccf(gr.hier_block2):
self.connect(self, self.pfb)
self.connect(self.pfb, self)
+ def set_taps(self, taps):
+ self.pfb.set_taps(taps)
class decimator_ccf(gr.hier_block2):
'''
@@ -130,10 +136,11 @@ class decimator_ccf(gr.hier_block2):
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))
+ def __init__(self, decim, taps=None, channel=0, atten=100,
+ use_fft_rotators=True, use_fft_filters=True):
+ 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
@@ -160,7 +167,8 @@ class decimator_ccf(gr.hier_block2):
raise RuntimeError("optfir could not generate an appropriate filter.")
self.s2ss = blocks.stream_to_streams(gr.sizeof_gr_complex, self._decim)
- self.pfb = filter.pfb_decimator_ccf(self._decim, self._taps, self._channel)
+ self.pfb = filter.pfb_decimator_ccf(self._decim, self._taps, self._channel,
+ use_fft_rotators, use_fft_filters)
self.connect(self, self.s2ss)
diff --git a/gr-filter/python/filter/qa_fft_filter.py b/gr-filter/python/filter/qa_fft_filter.py
index fafd2330ae..172b945441 100755
--- a/gr-filter/python/filter/qa_fft_filter.py
+++ b/gr-filter/python/filter/qa_fft_filter.py
@@ -65,6 +65,18 @@ def reference_filter_fff(dec, taps, input):
tb.run()
return dst.data()
+def reference_filter_ccf(dec, taps, input):
+ """
+ compute result using conventional fir filter
+ """
+ tb = gr.top_block()
+ src = blocks.vector_source_c(input)
+ op = filter.fir_filter_ccf(dec, taps)
+ dst = blocks.vector_sink_c()
+ tb.connect(src, op, dst)
+ tb.run()
+ return dst.data()
+
def print_complex(x):
for i in x:
@@ -207,6 +219,125 @@ class test_fft_filter(gr_unittest.TestCase):
self.assert_fft_ok2(expected_result, result_data)
# ----------------------------------------------------------------
+ # test _ccf version
+ # ----------------------------------------------------------------
+
+ def test_ccf_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 = blocks.vector_source_c(src_data)
+ op = filter.fft_filter_ccf(1, taps)
+ dst = blocks.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_ccf_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 = blocks.vector_source_c(src_data)
+ op = filter.fft_filter_ccf(1, taps, nthreads)
+ dst = blocks.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_ccf_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 = blocks.vector_source_c(src_data)
+ op = filter.fft_filter_ccf(1, taps)
+ dst = blocks.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_ccf_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_float_tuple(ntaps)
+ expected_result = reference_filter_ccf(1, taps, src_data)
+
+ src = blocks.vector_source_c(src_data)
+ op = filter.fft_filter_ccf(1, taps)
+ dst = blocks.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_ccf_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_float_tuple(ntaps)
+ expected_result = reference_filter_ccf(dec, taps, src_data)
+
+ src = blocks.vector_source_c(src_data)
+ op = filter.fft_filter_ccf(dec, taps)
+ dst = blocks.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_ccf_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_float_tuple(ntaps)
+ expected_result = reference_filter_ccf(dec, taps, src_data)
+
+ src = blocks.vector_source_c(src_data)
+ op = filter.fft_filter_ccc(dec, taps, nthreads)
+ dst = blocks.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
# ----------------------------------------------------------------
diff --git a/gr-filter/python/filter/qa_pfb_channelizer.py b/gr-filter/python/filter/qa_pfb_channelizer.py
index 4c108e8443..46c6e7b5ae 100755
--- a/gr-filter/python/filter/qa_pfb_channelizer.py
+++ b/gr-filter/python/filter/qa_pfb_channelizer.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2012,2013 Free Software Foundation, Inc.
+# Copyright 2012-2014 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -67,18 +67,18 @@ class test_pfb_channelizer(gr_unittest.TestCase):
self.tb.connect((s2ss,i), (pfb,i))
self.tb.connect((pfb, i), snks[i])
- self.tb.run()
+ self.tb.run()
Ntest = 50
L = len(snks[0].data())
# Adjusted phase rotations for data
- p0 = -2*math.pi * 0 / M
- p1 = -2*math.pi * 1 / M
- p2 = -2*math.pi * 2 / M
- p3 = -2*math.pi * 3 / M
- p4 = -2*math.pi * 4 / M
-
+ p0 = 0.11058379158914133
+ p1 = 4.5108246571401693
+ p2 = 3.9739891674564594
+ p3 = 2.2820531095511924
+ p4 = 1.3782797467397869
+
# Filter delay is the normal delay of each arm
tpf = math.ceil(len(taps) / float(M))
delay = -(tpf - 1.0) / 2.0
diff --git a/gr-filter/python/filter/qa_pfb_decimator.py b/gr-filter/python/filter/qa_pfb_decimator.py
index ea7a15570c..4366e85eec 100755
--- a/gr-filter/python/filter/qa_pfb_decimator.py
+++ b/gr-filter/python/filter/qa_pfb_decimator.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2012,2013 Free Software Foundation, Inc.
+# Copyright 2012-2014 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -29,7 +29,7 @@ def sig_source_c(samp_rate, freq, amp, N):
1j*math.sin(2.*math.pi*freq*x), t)
return y
-def run_test(tb, channel):
+def run_test(tb, channel, fft_rotate, fft_filter):
N = 1000 # number of samples to use
M = 5 # Number of channels
fs = 5000.0 # baseband sampling rate
@@ -50,19 +50,24 @@ def run_test(tb, channel):
tb.connect(signals[i], (add,i))
s2ss = blocks.stream_to_streams(gr.sizeof_gr_complex, M)
- pfb = filter.pfb_decimator_ccf(M, taps, channel)
+ pfb = filter.pfb_decimator_ccf(M, taps, channel, fft_rotate, fft_filter)
snk = blocks.vector_sink_c()
tb.connect(add, s2ss)
for i in xrange(M):
tb.connect((s2ss,i), (pfb,i))
tb.connect(pfb, snk)
- tb.run()
+ tb.run()
L = len(snk.data())
- # Each channel is rotated by 2pi/M
- phase = -2*math.pi * channel / M
+ # Adjusted phase rotations for data
+ phase = [ 0.11058476216852586,
+ 4.5108246571401693,
+ 3.9739891674564594,
+ 2.2820531095511924,
+ 1.3782797467397869]
+ phase = phase[channel]
# Filter delay is the normal delay of each arm
tpf = math.ceil(len(taps) / float(M))
@@ -90,33 +95,63 @@ class test_pfb_decimator(gr_unittest.TestCase):
def test_000(self):
Ntest = 50
- dst_data, expected_data = run_test(self.tb, 0)
-
- self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 4)
+ dst_data0, expected_data0 = run_test(self.tb, 0, False, False)
+ dst_data1, expected_data1 = run_test(self.tb, 0, False, True)
+ dst_data2, expected_data2 = run_test(self.tb, 0, True, False)
+ dst_data3, expected_data3 = run_test(self.tb, 0, True, True)
+
+ self.assertComplexTuplesAlmostEqual(expected_data0[-Ntest:], dst_data0[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data1[-Ntest:], dst_data1[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data2[-Ntest:], dst_data2[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data3[-Ntest:], dst_data3[-Ntest:], 4)
def test_001(self):
Ntest = 50
- dst_data, expected_data = run_test(self.tb, 1)
-
- self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 4)
+ dst_data0, expected_data0 = run_test(self.tb, 1, False, False)
+ dst_data1, expected_data1 = run_test(self.tb, 1, False, True)
+ dst_data2, expected_data2 = run_test(self.tb, 1, True, False)
+ dst_data3, expected_data3 = run_test(self.tb, 1, True, True)
+
+ self.assertComplexTuplesAlmostEqual(expected_data0[-Ntest:], dst_data0[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data1[-Ntest:], dst_data1[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data2[-Ntest:], dst_data2[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data3[-Ntest:], dst_data3[-Ntest:], 4)
def test_002(self):
Ntest = 50
- dst_data, expected_data = run_test(self.tb, 2)
-
- self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 4)
+ dst_data0, expected_data0 = run_test(self.tb, 2, False, False)
+ dst_data1, expected_data1 = run_test(self.tb, 2, False, True)
+ dst_data2, expected_data2 = run_test(self.tb, 2, True, False)
+ dst_data3, expected_data3 = run_test(self.tb, 2, True, True)
+
+ self.assertComplexTuplesAlmostEqual(expected_data0[-Ntest:], dst_data0[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data1[-Ntest:], dst_data1[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data2[-Ntest:], dst_data2[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data3[-Ntest:], dst_data3[-Ntest:], 4)
def test_003(self):
Ntest = 50
- dst_data, expected_data = run_test(self.tb, 3)
-
- self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 4)
+ dst_data0, expected_data0 = run_test(self.tb, 3, False, False)
+ dst_data1, expected_data1 = run_test(self.tb, 3, False, True)
+ dst_data2, expected_data2 = run_test(self.tb, 3, True, False)
+ dst_data3, expected_data3 = run_test(self.tb, 3, True, True)
+
+ self.assertComplexTuplesAlmostEqual(expected_data0[-Ntest:], dst_data0[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data1[-Ntest:], dst_data1[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data2[-Ntest:], dst_data2[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data3[-Ntest:], dst_data3[-Ntest:], 4)
def test_004(self):
Ntest = 50
- dst_data, expected_data = run_test(self.tb, 4)
-
- self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 4)
+ dst_data0, expected_data0 = run_test(self.tb, 4, False, False)
+ dst_data1, expected_data1 = run_test(self.tb, 4, False, True)
+ dst_data2, expected_data2 = run_test(self.tb, 4, True, False)
+ dst_data3, expected_data3 = run_test(self.tb, 4, True, True)
+
+ self.assertComplexTuplesAlmostEqual(expected_data0[-Ntest:], dst_data0[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data1[-Ntest:], dst_data1[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data2[-Ntest:], dst_data2[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data3[-Ntest:], dst_data3[-Ntest:], 4)
if __name__ == '__main__':
gr_unittest.run(test_pfb_decimator, "test_pfb_decimator.xml")
diff --git a/gr-filter/python/filter/qa_pfb_interpolator.py b/gr-filter/python/filter/qa_pfb_interpolator.py
index 33c22675af..b7ed4feef6 100755
--- a/gr-filter/python/filter/qa_pfb_interpolator.py
+++ b/gr-filter/python/filter/qa_pfb_interpolator.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2012,2013 Free Software Foundation, Inc.
+# Copyright 2012-2014 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -42,9 +42,9 @@ class test_pfb_interpolator(gr_unittest.TestCase):
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
+ ofs = M*fs # output samp rate of interpolator
- taps = filter.firdes.low_pass_2(M, ifs, fs/2, fs/10,
+ taps = filter.firdes.low_pass_2(M, ofs, fs/4, fs/10,
attenuation_dB=80,
window=filter.firdes.WIN_BLACKMAN_hARRIS)
@@ -57,20 +57,16 @@ class test_pfb_interpolator(gr_unittest.TestCase):
self.tb.connect(signal, pfb)
self.tb.connect(pfb, snk)
- self.tb.run()
+ self.tb.run()
Ntest = 50
L = len(snk.data())
- # Can only get channel 0 out; no phase rotation
- phase = 0
+ # Phase rotation through the filters
+ phase = 4.8870112969978994
- # Calculate the filter delay
- delay = -(len(taps) - 1) / 2.0 - (M-1)
- delay = int(delay)
-
- # Create a time scale that's delayed to match the filter delay
- t = map(lambda x: float(x)/ifs, xrange(delay, L+delay))
+ # Create a time scale
+ t = map(lambda x: float(x)/ofs, xrange(0, L))
# Create known data as complex sinusoids for the baseband freq
# of the extracted channel is due to decimator output order.
diff --git a/gr-filter/python/filter/qa_pfb_synthesizer.py b/gr-filter/python/filter/qa_pfb_synthesizer.py
index baba904088..0b3f8b27a2 100755
--- a/gr-filter/python/filter/qa_pfb_synthesizer.py
+++ b/gr-filter/python/filter/qa_pfb_synthesizer.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2012,2013 Free Software Foundation, Inc.
+# Copyright 2012-2014 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -62,7 +62,14 @@ class test_pfb_synthesizer(gr_unittest.TestCase):
self.tb.connect(pfb, snk)
- self.tb.run()
+ self.tb.run()
+
+ # Adjusted phase rotations for data
+ p0 = 0
+ p1 = 2*math.pi*1.0/M
+ p2 = 2*math.pi*2.0/M
+ p3 = 2*math.pi*3.0/M
+ p4 = 2*math.pi*4.0/M
Ntest = 1000
L = len(snk.data())
@@ -73,20 +80,19 @@ class test_pfb_synthesizer(gr_unittest.TestCase):
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])
+ expected_data[i] = math.cos(2.*math.pi*freqs[0]*t[i] + p3) + \
+ 1j*math.sin(2.*math.pi*freqs[0]*t[i] + p3) + \
+ math.cos(2.*math.pi*freqs[1]*t[i] + p4) + \
+ 1j*math.sin(2.*math.pi*freqs[1]*t[i] + p4) + \
+ math.cos(2.*math.pi*freqs[2]*t[i] + p0) + \
+ 1j*math.sin(2.*math.pi*freqs[2]*t[i] + p0) + \
+ math.cos(2.*math.pi*freqs[3]*t[i] + p1) + \
+ 1j*math.sin(2.*math.pi*freqs[3]*t[i] + p1) + \
+ math.cos(2.*math.pi*freqs[4]*t[i] + p2) + \
+ 1j*math.sin(2.*math.pi*freqs[4]*t[i] + p2)
dst_data = snk.data()
- offset = 25
- self.assertComplexTuplesAlmostEqual(expected_data[2000-offset:2000-offset+Ntest],
+ self.assertComplexTuplesAlmostEqual(expected_data[2000:2000+Ntest],
dst_data[2000:2000+Ntest], 4)
if __name__ == '__main__':
diff --git a/gr-filter/swig/filter_swig.i b/gr-filter/swig/filter_swig.i
index bc9f204850..3eb3f3c634 100644
--- a/gr-filter/swig/filter_swig.i
+++ b/gr-filter/swig/filter_swig.i
@@ -40,6 +40,7 @@
#include "gnuradio/filter/fir_filter_fsf.h"
#include "gnuradio/filter/fir_filter_scc.h"
#include "gnuradio/filter/fft_filter_ccc.h"
+#include "gnuradio/filter/fft_filter_ccf.h"
#include "gnuradio/filter/fft_filter_fff.h"
#include "gnuradio/filter/fractional_interpolator_cc.h"
#include "gnuradio/filter/fractional_interpolator_ff.h"
@@ -88,6 +89,7 @@
%include "gnuradio/filter/fir_filter_fsf.h"
%include "gnuradio/filter/fir_filter_scc.h"
%include "gnuradio/filter/fft_filter_ccc.h"
+%include "gnuradio/filter/fft_filter_ccf.h"
%include "gnuradio/filter/fft_filter_fff.h"
%include "gnuradio/filter/fractional_interpolator_cc.h"
%include "gnuradio/filter/fractional_interpolator_ff.h"
@@ -133,6 +135,7 @@ 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_ccf);
GR_SWIG_BLOCK_MAGIC2(filter, fft_filter_fff);
GR_SWIG_BLOCK_MAGIC2(filter, fractional_interpolator_cc);
GR_SWIG_BLOCK_MAGIC2(filter, fractional_interpolator_ff);
diff --git a/gr-qtgui/CMakeLists.txt b/gr-qtgui/CMakeLists.txt
index a3a72dce43..13cbfb2e1f 100644
--- a/gr-qtgui/CMakeLists.txt
+++ b/gr-qtgui/CMakeLists.txt
@@ -132,4 +132,13 @@ install(
COMPONENT "qtgui_devel"
)
+########################################################################
+# Install the conf file
+########################################################################
+install(
+ FILES ${CMAKE_CURRENT_SOURCE_DIR}/gr-qtgui.conf
+ DESTINATION ${GR_PREFSDIR}
+ COMPONENT "qtgui"
+)
+
endif(ENABLE_GR_QTGUI)
diff --git a/gr-qtgui/doc/qtgui.dox b/gr-qtgui/doc/qtgui.dox
index beb1055e90..cbe5b831fb 100644
--- a/gr-qtgui/doc/qtgui.dox
+++ b/gr-qtgui/doc/qtgui.dox
@@ -181,4 +181,26 @@ style, markers, etc.), the ability to start and stop the display, the
ability to save to a file, and other plot-specific controls (FFT size
for the frequency and waterfall plots, etc.).
+\section Configuration
+
+There is currently a single configuration option in the preferences
+files to set the rendering engine of the QTGUI sinks. Located in
+etc/gnuradio/conf.d/gr-qtgui.conf:
+
+\verbatim
+[qtgui]
+style = raster
+\endverbatim
+
+The available styles are:
+
+\li opengl: the fastest but not likely to always work
+\li raster: fast and stable; terrible X forwarding performance
+\li native: most compute intensive; very good over X
+
+We default this setting to raster for the mix of performance and
+usability. When using QTGUI sinks through an X-forwarding session over
+SSH, switch to using 'native' for a significant speed boost on the
+remote end.
+
*/
diff --git a/gr-qtgui/gr-qtgui.conf b/gr-qtgui/gr-qtgui.conf
new file mode 100644
index 0000000000..66354cfd4b
--- /dev/null
+++ b/gr-qtgui/gr-qtgui.conf
@@ -0,0 +1,10 @@
+# This file contains system wide configuration data for GNU Radio.
+# You may override any setting on a per-user basis by editing
+# ~/.gnuradio/config.conf
+
+[qtgui]
+# 'raster', 'native', or 'opengl'
+# - 'opengl' is the fastest but not likely to always work
+# - 'raster' is fast and stable; terrible X forwarding performance
+# - 'native' most compute intensive; very good over X
+style = raster
diff --git a/gr-qtgui/lib/const_sink_c_impl.cc b/gr-qtgui/lib/const_sink_c_impl.cc
index fd9338f111..8b1a804fd2 100644
--- a/gr-qtgui/lib/const_sink_c_impl.cc
+++ b/gr-qtgui/lib/const_sink_c_impl.cc
@@ -26,14 +26,14 @@
#include "const_sink_c_impl.h"
#include <gnuradio/io_signature.h>
+#include <gnuradio/prefs.h>
#include <string.h>
#include <volk/volk.h>
-#include <gnuradio/fft/fft.h>
#include <qwt_symbol.h>
namespace gr {
namespace qtgui {
-
+
const_sink_c::sptr
const_sink_c::make(int size,
const std::string &name,
@@ -110,6 +110,8 @@ namespace gr {
d_qApplication = qApp;
}
else {
+ std::string style = prefs::singleton()->get_string("qtgui", "style", "raster");
+ QApplication::setGraphicsSystem(QString(style.c_str()));
d_qApplication = new QApplication(d_argc, &d_argv);
}
@@ -272,8 +274,8 @@ namespace gr {
memset(d_residbufs_imag[i], 0, newsize*sizeof(double));
}
- // Set new size and reset buffer index
- // (throws away any currently held data, but who cares?)
+ // Set new size and reset buffer index
+ // (throws away any currently held data, but who cares?)
d_size = newsize;
d_index = 0;
diff --git a/gr-qtgui/lib/freq_sink_c_impl.cc b/gr-qtgui/lib/freq_sink_c_impl.cc
index e86974fa31..ff375976fb 100644
--- a/gr-qtgui/lib/freq_sink_c_impl.cc
+++ b/gr-qtgui/lib/freq_sink_c_impl.cc
@@ -26,6 +26,7 @@
#include "freq_sink_c_impl.h"
#include <gnuradio/io_signature.h>
+#include <gnuradio/prefs.h>
#include <string.h>
#include <volk/volk.h>
#include <qwt_symbol.h>
@@ -132,7 +133,9 @@ namespace gr {
d_qApplication = qApp;
}
else {
- d_qApplication = new QApplication(d_argc, &d_argv);
+ std::string style = prefs::singleton()->get_string("qtgui", "style", "raster");
+ QApplication::setGraphicsSystem(QString(style.c_str()));
+ d_qApplication = new QApplication(d_argc, &d_argv);
}
d_main_gui = new FreqDisplayForm(d_nconnections, d_parent);
diff --git a/gr-qtgui/lib/freq_sink_c_impl.h b/gr-qtgui/lib/freq_sink_c_impl.h
index 8079c816f6..f068e657f5 100644
--- a/gr-qtgui/lib/freq_sink_c_impl.h
+++ b/gr-qtgui/lib/freq_sink_c_impl.h
@@ -32,7 +32,7 @@
namespace gr {
namespace qtgui {
-
+
class QTGUI_API freq_sink_c_impl : public freq_sink_c
{
private:
diff --git a/gr-qtgui/lib/freq_sink_f_impl.cc b/gr-qtgui/lib/freq_sink_f_impl.cc
index 8dca8151d7..f2dfb4f56c 100644
--- a/gr-qtgui/lib/freq_sink_f_impl.cc
+++ b/gr-qtgui/lib/freq_sink_f_impl.cc
@@ -26,6 +26,7 @@
#include "freq_sink_f_impl.h"
#include <gnuradio/io_signature.h>
+#include <gnuradio/prefs.h>
#include <string.h>
#include <volk/volk.h>
#include <qwt_symbol.h>
@@ -132,6 +133,8 @@ namespace gr {
d_qApplication = qApp;
}
else {
+ std::string style = prefs::singleton()->get_string("qtgui", "style", "raster");
+ QApplication::setGraphicsSystem(QString(style.c_str()));
d_qApplication = new QApplication(d_argc, &d_argv);
}
diff --git a/gr-qtgui/lib/histogram_sink_f_impl.cc b/gr-qtgui/lib/histogram_sink_f_impl.cc
index 8a3ba6987e..07620a1246 100644
--- a/gr-qtgui/lib/histogram_sink_f_impl.cc
+++ b/gr-qtgui/lib/histogram_sink_f_impl.cc
@@ -26,14 +26,14 @@
#include "histogram_sink_f_impl.h"
#include <gnuradio/io_signature.h>
+#include <gnuradio/prefs.h>
#include <string.h>
#include <volk/volk.h>
-#include <gnuradio/fft/fft.h>
#include <qwt_symbol.h>
namespace gr {
namespace qtgui {
-
+
histogram_sink_f::sptr
histogram_sink_f::make(int size, int bins,
double xmin, double xmax,
@@ -109,6 +109,8 @@ namespace gr {
d_qApplication = qApp;
}
else {
+ std::string style = prefs::singleton()->get_string("qtgui", "style", "raster");
+ QApplication::setGraphicsSystem(QString(style.c_str()));
d_qApplication = new QApplication(d_argc, &d_argv);
}
@@ -270,8 +272,8 @@ namespace gr {
memset(d_residbufs[i], 0, newsize*sizeof(double));
}
- // Set new size and reset buffer index
- // (throws away any currently held data, but who cares?)
+ // Set new size and reset buffer index
+ // (throws away any currently held data, but who cares?)
d_size = newsize;
d_index = 0;
diff --git a/gr-qtgui/lib/sink_c_impl.cc b/gr-qtgui/lib/sink_c_impl.cc
index d9341bab88..b810a450b6 100644
--- a/gr-qtgui/lib/sink_c_impl.cc
+++ b/gr-qtgui/lib/sink_c_impl.cc
@@ -26,6 +26,7 @@
#include "sink_c_impl.h"
#include <gnuradio/io_signature.h>
+#include <gnuradio/prefs.h>
#include <string.h>
#include <volk/volk.h>
@@ -122,6 +123,8 @@ namespace gr {
d_qApplication = qApp;
}
else {
+ std::string style = prefs::singleton()->get_string("qtgui", "style", "raster");
+ QApplication::setGraphicsSystem(QString(style.c_str()));
d_qApplication = new QApplication(d_argc, &d_argv);
}
diff --git a/gr-qtgui/lib/sink_f_impl.cc b/gr-qtgui/lib/sink_f_impl.cc
index 178eb1b971..ef194f9ead 100644
--- a/gr-qtgui/lib/sink_f_impl.cc
+++ b/gr-qtgui/lib/sink_f_impl.cc
@@ -26,6 +26,7 @@
#include "sink_f_impl.h"
#include <gnuradio/io_signature.h>
+#include <gnuradio/prefs.h>
#include <string.h>
#include <volk/volk.h>
@@ -122,6 +123,8 @@ namespace gr {
d_qApplication = qApp;
}
else {
+ std::string style = prefs::singleton()->get_string("qtgui", "style", "raster");
+ QApplication::setGraphicsSystem(QString(style.c_str()));
d_qApplication = new QApplication(d_argc, &d_argv);
}
diff --git a/gr-qtgui/lib/time_raster_sink_b_impl.cc b/gr-qtgui/lib/time_raster_sink_b_impl.cc
index 26daffe7bb..84f702b3d5 100644
--- a/gr-qtgui/lib/time_raster_sink_b_impl.cc
+++ b/gr-qtgui/lib/time_raster_sink_b_impl.cc
@@ -26,12 +26,13 @@
#include "time_raster_sink_b_impl.h"
#include <gnuradio/io_signature.h>
+#include <gnuradio/prefs.h>
#include <string.h>
#include <volk/volk.h>
namespace gr {
namespace qtgui {
-
+
time_raster_sink_b::sptr
time_raster_sink_b::make(double samp_rate,
double rows, double cols,
@@ -84,7 +85,7 @@ namespace gr {
d_tmpflt = (float*)volk_malloc(d_icols*sizeof(float),
volk_get_alignment());
memset(d_tmpflt, 0, d_icols*sizeof(float));
-
+
for(int i = 0; i < d_nconnections; i++) {
d_residbufs.push_back((double*)volk_malloc(d_icols*sizeof(double),
volk_get_alignment()));
@@ -123,6 +124,8 @@ namespace gr {
d_qApplication = qApp;
}
else {
+ std::string style = prefs::singleton()->get_string("qtgui", "style", "raster");
+ QApplication::setGraphicsSystem(QString(style.c_str()));
d_qApplication = new QApplication(d_argc, &d_argv);
}
@@ -417,7 +420,7 @@ namespace gr {
volk_32f_convert_64f_u(&d_residbufs[n][d_index],
d_tmpflt, resid);
}
-
+
if(gr::high_res_timer_now() - d_last_time > d_update_time) {
d_last_time = gr::high_res_timer_now();
d_qApplication->postEvent(d_main_gui,
diff --git a/gr-qtgui/lib/time_raster_sink_f_impl.cc b/gr-qtgui/lib/time_raster_sink_f_impl.cc
index 10b7f762ca..beb2937b83 100644
--- a/gr-qtgui/lib/time_raster_sink_f_impl.cc
+++ b/gr-qtgui/lib/time_raster_sink_f_impl.cc
@@ -26,12 +26,13 @@
#include "time_raster_sink_f_impl.h"
#include <gnuradio/io_signature.h>
+#include <gnuradio/prefs.h>
#include <string.h>
#include <volk/volk.h>
namespace gr {
namespace qtgui {
-
+
time_raster_sink_f::sptr
time_raster_sink_f::make(double samp_rate,
double rows, double cols,
@@ -82,7 +83,7 @@ namespace gr {
d_tmpflt = (float*)volk_malloc(d_icols*sizeof(float),
volk_get_alignment());
memset(d_tmpflt, 0, d_icols*sizeof(float));
-
+
for(int i = 0; i < d_nconnections; i++) {
d_residbufs.push_back((double*)volk_malloc(d_icols*sizeof(double),
volk_get_alignment()));
@@ -121,6 +122,8 @@ namespace gr {
d_qApplication = qApp;
}
else {
+ std::string style = prefs::singleton()->get_string("qtgui", "style", "raster");
+ QApplication::setGraphicsSystem(QString(style.c_str()));
d_qApplication = new QApplication(d_argc, &d_argv);
}
@@ -413,7 +416,7 @@ namespace gr {
volk_32f_convert_64f_u(&d_residbufs[n][d_index],
d_tmpflt, resid);
}
-
+
// Update the plot if its time
if(gr::high_res_timer_now() - d_last_time > d_update_time) {
d_last_time = gr::high_res_timer_now();
diff --git a/gr-qtgui/lib/time_sink_c_impl.cc b/gr-qtgui/lib/time_sink_c_impl.cc
index f24657830f..6cd314697c 100644
--- a/gr-qtgui/lib/time_sink_c_impl.cc
+++ b/gr-qtgui/lib/time_sink_c_impl.cc
@@ -26,6 +26,7 @@
#include "time_sink_c_impl.h"
#include <gnuradio/io_signature.h>
+#include <gnuradio/prefs.h>
#include <string.h>
#include <volk/volk.h>
#include <gnuradio/fft/fft.h>
@@ -33,7 +34,7 @@
namespace gr {
namespace qtgui {
-
+
time_sink_c::sptr
time_sink_c::make(int size, double samp_rate,
const std::string &name,
@@ -112,6 +113,8 @@ namespace gr {
d_qApplication = qApp;
}
else {
+ std::string style = prefs::singleton()->get_string("qtgui", "style", "raster");
+ QApplication::setGraphicsSystem(QString(style.c_str()));
d_qApplication = new QApplication(d_argc, &d_argv);
}
@@ -292,8 +295,8 @@ namespace gr {
if(newsize != d_size) {
gr::thread::scoped_lock lock(d_mutex);
- // Set new size and reset buffer index
- // (throws away any currently held data, but who cares?)
+ // Set new size and reset buffer index
+ // (throws away any currently held data, but who cares?)
d_size = newsize;
d_buffer_size = 2*d_size;
diff --git a/gr-qtgui/lib/time_sink_f_impl.cc b/gr-qtgui/lib/time_sink_f_impl.cc
index 596a416541..7bbda19d13 100644
--- a/gr-qtgui/lib/time_sink_f_impl.cc
+++ b/gr-qtgui/lib/time_sink_f_impl.cc
@@ -28,6 +28,7 @@
#include <gnuradio/io_signature.h>
#include <gnuradio/block_detail.h>
#include <gnuradio/buffer.h>
+#include <gnuradio/prefs.h>
#include <string.h>
#include <volk/volk.h>
#include <gnuradio/fft/fft.h>
@@ -35,7 +36,7 @@
namespace gr {
namespace qtgui {
-
+
time_sink_f::sptr
time_sink_f::make(int size, double samp_rate,
const std::string &name,
@@ -114,6 +115,8 @@ namespace gr {
d_qApplication = qApp;
}
else {
+ std::string style = prefs::singleton()->get_string("qtgui", "style", "raster");
+ QApplication::setGraphicsSystem(QString(style.c_str()));
d_qApplication = new QApplication(d_argc, &d_argv);
}
@@ -294,8 +297,8 @@ namespace gr {
if(newsize != d_size) {
gr::thread::scoped_lock lock(d_mutex);
- // Set new size and reset buffer index
- // (throws away any currently held data, but who cares?)
+ // Set new size and reset buffer index
+ // (throws away any currently held data, but who cares?)
d_size = newsize;
d_buffer_size = 2*d_size;
diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.cc b/gr-qtgui/lib/waterfall_sink_c_impl.cc
index e3ac3cc8e2..54e4c9532a 100644
--- a/gr-qtgui/lib/waterfall_sink_c_impl.cc
+++ b/gr-qtgui/lib/waterfall_sink_c_impl.cc
@@ -26,6 +26,7 @@
#include "waterfall_sink_c_impl.h"
#include <gnuradio/io_signature.h>
+#include <gnuradio/prefs.h>
#include <string.h>
#include <volk/volk.h>
#include <qwt_symbol.h>
@@ -131,6 +132,8 @@ namespace gr {
d_qApplication = qApp;
}
else {
+ std::string style = prefs::singleton()->get_string("qtgui", "style", "raster");
+ QApplication::setGraphicsSystem(QString(style.c_str()));
d_qApplication = new QApplication(d_argc, &d_argv);
}
@@ -332,7 +335,6 @@ namespace gr {
volk_32fc_s32f_x2_power_spectral_density_32f(data_out, d_fft->get_outbuf(),
size, 1.0, size);
-
// Perform shift operation
unsigned int len = (unsigned int)(floor(size/2.0));
float *tmp = (float*)malloc(sizeof(float)*len);
diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.cc b/gr-qtgui/lib/waterfall_sink_f_impl.cc
index 4164a1844f..9f7bb37f95 100644
--- a/gr-qtgui/lib/waterfall_sink_f_impl.cc
+++ b/gr-qtgui/lib/waterfall_sink_f_impl.cc
@@ -26,6 +26,7 @@
#include "waterfall_sink_f_impl.h"
#include <gnuradio/io_signature.h>
+#include <gnuradio/prefs.h>
#include <string.h>
#include <volk/volk.h>
@@ -130,6 +131,8 @@ namespace gr {
d_qApplication = qApp;
}
else {
+ std::string style = prefs::singleton()->get_string("qtgui", "style", "raster");
+ QApplication::setGraphicsSystem(QString(style.c_str()));
d_qApplication = new QApplication(d_argc, &d_argv);
}
diff --git a/gr-vocoder/doc/vocoder.dox b/gr-vocoder/doc/vocoder.dox
index 3973ca56fc..0e12566a80 100644
--- a/gr-vocoder/doc/vocoder.dox
+++ b/gr-vocoder/doc/vocoder.dox
@@ -20,4 +20,14 @@ by using:
help(vocoder)
\endcode
+\section using Using the vocoders
+
+Note that most vocoders use short inputs instead of floats. This means you
+must convert audio signals from float to short by using a type conversion
+and a scaling factor. See the examples.
+
+The format of the encoded audio is different for every encoder. See the
+individual block's documention for the data format. Encoded data is usually
+a vector of fixed length, and can either be packed or unpacked.
+
*/
diff --git a/gr-vocoder/examples/loopback-codec2.grc b/gr-vocoder/examples/loopback-codec2.grc
new file mode 100644
index 0000000000..4d22c8fc74
--- /dev/null
+++ b/gr-vocoder/examples/loopback-codec2.grc
@@ -0,0 +1,1184 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+ <timestamp>Fri Mar 7 18:08:43 2014</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>loopback_codec2</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>Codec2 Looback Test</value>
+ </param>
+ <param>
+ <key>author</key>
+ <value>Martin Braun</value>
+ </param>
+ <param>
+ <key>description</key>
+ <value>An example how to use the Codec2 Vocoder</value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>qt_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>(0, -1)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>scale</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>2**13</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(301, -1)</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>48000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(186, 0)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_float_to_short</key>
+ <param>
+ <key>id</key>
+ <value>blocks_float_to_short_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>scale</key>
+ <value>scale</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(417, 119)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_time_sink_x</key>
+ <param>
+ <key>id</key>
+ <value>qtgui_time_sink_x_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>Audio Pre-Encoding</value>
+ </param>
+ <param>
+ <key>size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>srate</key>
+ <value>8000</value>
+ </param>
+ <param>
+ <key>ymin</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>ymax</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>nconnections</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_FREE</value>
+ </param>
+ <param>
+ <key>tr_slope</key>
+ <value>qtgui.TRIG_SLOPE_POS</value>
+ </param>
+ <param>
+ <key>tr_level</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>tr_delay</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_chan</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_tag</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>entags</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(434, 202)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>rational_resampler_xxx</key>
+ <param>
+ <key>id</key>
+ <value>rational_resampler_xxx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>fff</value>
+ </param>
+ <param>
+ <key>interp</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>decim</key>
+ <value>6</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value></value>
+ </param>
+ <param>
+ <key>fbw</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(204, 94)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_source</key>
+ <param>
+ <key>id</key>
+ <value>virtual_source_1_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Decoded Speech</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(3, 449)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_qtgui_check_box</key>
+ <param>
+ <key>id</key>
+ <value>play_encoded</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Encode Audio</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>int</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>true</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>false</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(834, 0)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blks2_selector</key>
+ <param>
+ <key>id</key>
+ <value>blks2_selector_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>num_outputs</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>input_index</key>
+ <value>play_encoded</value>
+ </param>
+ <param>
+ <key>output_index</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(280, 411)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>rational_resampler_xxx</key>
+ <param>
+ <key>id</key>
+ <value>rational_resampler_xxx_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>fff</value>
+ </param>
+ <param>
+ <key>interp</key>
+ <value>6</value>
+ </param>
+ <param>
+ <key>decim</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value></value>
+ </param>
+ <param>
+ <key>fbw</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(478, 400)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>audio_sink</key>
+ <param>
+ <key>id</key>
+ <value>audio_sink_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>48000</value>
+ </param>
+ <param>
+ <key>device_name</key>
+ <value></value>
+ </param>
+ <param>
+ <key>ok_to_block</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(706, 424)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>vocoder_codec2_encode_sp</key>
+ <param>
+ <key>id</key>
+ <value>vocoder_codec2_encode_sp_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(590, 123)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_vector_to_stream</key>
+ <param>
+ <key>id</key>
+ <value>blocks_vector_to_stream_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>num_items</key>
+ <value>50</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(822, 119)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_source</key>
+ <param>
+ <key>id</key>
+ <value>virtual_source_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Encoded Speech</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(0, 298)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_stream_to_vector</key>
+ <param>
+ <key>id</key>
+ <value>blocks_stream_to_vector_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>num_items</key>
+ <value>50</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(444, 298)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>vocoder_codec2_decode_ps</key>
+ <param>
+ <key>id</key>
+ <value>vocoder_codec2_decode_ps_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(641, 302)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_short_to_float</key>
+ <param>
+ <key>id</key>
+ <value>blocks_short_to_float_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>scale</key>
+ <value>scale</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(735, 361)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_sink</key>
+ <param>
+ <key>id</key>
+ <value>virtual_sink_2</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Decoded Speech</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(960, 393)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_time_sink_x</key>
+ <param>
+ <key>id</key>
+ <value>qtgui_time_sink_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>Audio Post-Encoding</value>
+ </param>
+ <param>
+ <key>size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>srate</key>
+ <value>8000</value>
+ </param>
+ <param>
+ <key>ymin</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>ymax</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>nconnections</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_FREE</value>
+ </param>
+ <param>
+ <key>tr_slope</key>
+ <value>qtgui.TRIG_SLOPE_POS</value>
+ </param>
+ <param>
+ <key>tr_level</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>tr_delay</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_chan</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_tag</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>entags</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(960, 283)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>audio_source</key>
+ <param>
+ <key>id</key>
+ <value>audio_source_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>48000</value>
+ </param>
+ <param>
+ <key>device_name</key>
+ <value></value>
+ </param>
+ <param>
+ <key>ok_to_block</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>num_outputs</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(0, 117)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_wavfile_source</key>
+ <param>
+ <key>id</key>
+ <value>blocks_wavfile_source_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>file</key>
+ <value>/home/mbr0wn/12345.wav</value>
+ </param>
+ <param>
+ <key>repeat</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>nchan</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(-1, 225)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_packed_to_unpacked_xx</key>
+ <param>
+ <key>id</key>
+ <value>blocks_packed_to_unpacked_xx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>bits_per_chunk</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>endianness</key>
+ <value>gr.GR_LSB_FIRST</value>
+ </param>
+ <param>
+ <key>num_ports</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(229, 290)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_sink</key>
+ <param>
+ <key>id</key>
+ <value>virtual_sink_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Encoded Speech</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(908, 207)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_unpacked_to_packed_xx</key>
+ <param>
+ <key>id</key>
+ <value>blocks_unpacked_to_packed_xx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>bits_per_chunk</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>endianness</key>
+ <value>gr.GR_LSB_FIRST</value>
+ </param>
+ <param>
+ <key>num_ports</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(694, 199)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_sink</key>
+ <param>
+ <key>id</key>
+ <value>virtual_sink_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Raw Audio</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(508, 25)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_source</key>
+ <param>
+ <key>id</key>
+ <value>virtual_source_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Raw Audio</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(-1, 389)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>audio_source_0</source_block_id>
+ <sink_block_id>rational_resampler_xxx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>rational_resampler_xxx_0</source_block_id>
+ <sink_block_id>blocks_float_to_short_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_float_to_short_0</source_block_id>
+ <sink_block_id>vocoder_codec2_encode_sp_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_wavfile_source_0</source_block_id>
+ <sink_block_id>rational_resampler_xxx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>rational_resampler_xxx_0</source_block_id>
+ <sink_block_id>qtgui_time_sink_x_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>rational_resampler_xxx_0</source_block_id>
+ <sink_block_id>virtual_sink_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>virtual_source_1</source_block_id>
+ <sink_block_id>blks2_selector_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>virtual_source_1_0</source_block_id>
+ <sink_block_id>blks2_selector_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>rational_resampler_xxx_1</source_block_id>
+ <sink_block_id>audio_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blks2_selector_0</source_block_id>
+ <sink_block_id>rational_resampler_xxx_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>vocoder_codec2_encode_sp_0</source_block_id>
+ <sink_block_id>blocks_vector_to_stream_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_vector_to_stream_0</source_block_id>
+ <sink_block_id>blocks_unpacked_to_packed_xx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_unpacked_to_packed_xx_0</source_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>blocks_short_to_float_0</source_block_id>
+ <sink_block_id>virtual_sink_2</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_short_to_float_0</source_block_id>
+ <sink_block_id>qtgui_time_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>vocoder_codec2_decode_ps_0</source_block_id>
+ <sink_block_id>blocks_short_to_float_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_stream_to_vector_0</source_block_id>
+ <sink_block_id>vocoder_codec2_decode_ps_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>blocks_packed_to_unpacked_xx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_packed_to_unpacked_xx_0</source_block_id>
+ <sink_block_id>blocks_stream_to_vector_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gr-vocoder/examples/loopback-gsmfr.grc b/gr-vocoder/examples/loopback-gsmfr.grc
new file mode 100644
index 0000000000..f1c0e06bd6
--- /dev/null
+++ b/gr-vocoder/examples/loopback-gsmfr.grc
@@ -0,0 +1,1078 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+ <timestamp>Fri Mar 7 16:29:26 2014</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>loopback_gsmfr</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>GSM Full-Rate 06.10 Codec Looback Test</value>
+ </param>
+ <param>
+ <key>author</key>
+ <value>Martin Braun</value>
+ </param>
+ <param>
+ <key>description</key>
+ <value>An example how to use the GSM-FR Vocoder</value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>qt_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>(0, -1)</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>48000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(186, 0)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>scale</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>2**12</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(301, -1)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_time_sink_x</key>
+ <param>
+ <key>id</key>
+ <value>qtgui_time_sink_x_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>Audio Pre-Encoding</value>
+ </param>
+ <param>
+ <key>size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>srate</key>
+ <value>8000</value>
+ </param>
+ <param>
+ <key>ymin</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>ymax</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>nconnections</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_FREE</value>
+ </param>
+ <param>
+ <key>tr_slope</key>
+ <value>qtgui.TRIG_SLOPE_POS</value>
+ </param>
+ <param>
+ <key>tr_level</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>tr_delay</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_chan</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_tag</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>entags</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(434, 202)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>rational_resampler_xxx</key>
+ <param>
+ <key>id</key>
+ <value>rational_resampler_xxx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>fff</value>
+ </param>
+ <param>
+ <key>interp</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>decim</key>
+ <value>6</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value></value>
+ </param>
+ <param>
+ <key>fbw</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(204, 94)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_sink</key>
+ <param>
+ <key>id</key>
+ <value>virtual_sink_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Unencoded Speech</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(508, 25)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_source</key>
+ <param>
+ <key>id</key>
+ <value>virtual_source_1_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Decoded Speech</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(3, 449)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_source</key>
+ <param>
+ <key>id</key>
+ <value>virtual_source_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Unencoded Speech</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(-1, 389)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_qtgui_check_box</key>
+ <param>
+ <key>id</key>
+ <value>play_encoded</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Encode Audio</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>int</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>true</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>false</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(834, 0)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blks2_selector</key>
+ <param>
+ <key>id</key>
+ <value>blks2_selector_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>num_outputs</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>input_index</key>
+ <value>play_encoded</value>
+ </param>
+ <param>
+ <key>output_index</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(280, 411)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>rational_resampler_xxx</key>
+ <param>
+ <key>id</key>
+ <value>rational_resampler_xxx_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>fff</value>
+ </param>
+ <param>
+ <key>interp</key>
+ <value>6</value>
+ </param>
+ <param>
+ <key>decim</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value></value>
+ </param>
+ <param>
+ <key>fbw</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(478, 400)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>audio_sink</key>
+ <param>
+ <key>id</key>
+ <value>audio_sink_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>48000</value>
+ </param>
+ <param>
+ <key>device_name</key>
+ <value></value>
+ </param>
+ <param>
+ <key>ok_to_block</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(706, 424)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_float_to_short</key>
+ <param>
+ <key>id</key>
+ <value>blocks_float_to_short_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>scale</key>
+ <value>scale</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(417, 119)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>audio_source</key>
+ <param>
+ <key>id</key>
+ <value>audio_source_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>48000</value>
+ </param>
+ <param>
+ <key>device_name</key>
+ <value></value>
+ </param>
+ <param>
+ <key>ok_to_block</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>num_outputs</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(0, 117)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_wavfile_source</key>
+ <param>
+ <key>id</key>
+ <value>blocks_wavfile_source_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>file</key>
+ <value>speech_audio_at_48_kHz.wav</value>
+ </param>
+ <param>
+ <key>repeat</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>nchan</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(-1, 225)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>vocoder_gsm_fr_encode_sp</key>
+ <param>
+ <key>id</key>
+ <value>vocoder_gsm_fr_encode_sp_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(592, 123)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_vector_to_stream</key>
+ <param>
+ <key>id</key>
+ <value>blocks_vector_to_stream_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>num_items</key>
+ <value>33</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(857, 119)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_sink</key>
+ <param>
+ <key>id</key>
+ <value>virtual_sink_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Encoded Speech</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1052, 119)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_stream_to_vector</key>
+ <param>
+ <key>id</key>
+ <value>blocks_stream_to_vector_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>num_items</key>
+ <value>33</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(272, 312)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_source</key>
+ <param>
+ <key>id</key>
+ <value>virtual_source_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Encoded Speech</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(-1, 312)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>vocoder_gsm_fr_decode_ps</key>
+ <param>
+ <key>id</key>
+ <value>vocoder_gsm_fr_decode_ps_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(485, 316)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>virtual_sink</key>
+ <param>
+ <key>id</key>
+ <value>virtual_sink_2</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>stream_id</key>
+ <value>Decoded Speech</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1012, 364)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_time_sink_x</key>
+ <param>
+ <key>id</key>
+ <value>qtgui_time_sink_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>Audio Post-Encoding</value>
+ </param>
+ <param>
+ <key>size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>srate</key>
+ <value>8000</value>
+ </param>
+ <param>
+ <key>ymin</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>ymax</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>nconnections</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_FREE</value>
+ </param>
+ <param>
+ <key>tr_slope</key>
+ <value>qtgui.TRIG_SLOPE_POS</value>
+ </param>
+ <param>
+ <key>tr_level</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>tr_delay</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_chan</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_tag</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>entags</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1012, 240)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_short_to_float</key>
+ <param>
+ <key>id</key>
+ <value>blocks_short_to_float_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>scale</key>
+ <value>scale</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(762, 312)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>audio_source_0</source_block_id>
+ <sink_block_id>rational_resampler_xxx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>rational_resampler_xxx_0</source_block_id>
+ <sink_block_id>blocks_float_to_short_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_wavfile_source_0</source_block_id>
+ <sink_block_id>rational_resampler_xxx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>rational_resampler_xxx_0</source_block_id>
+ <sink_block_id>qtgui_time_sink_x_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>rational_resampler_xxx_0</source_block_id>
+ <sink_block_id>virtual_sink_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>virtual_source_1</source_block_id>
+ <sink_block_id>blks2_selector_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>virtual_source_1_0</source_block_id>
+ <sink_block_id>blks2_selector_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_short_to_float_0</source_block_id>
+ <sink_block_id>virtual_sink_2</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>rational_resampler_xxx_1</source_block_id>
+ <sink_block_id>audio_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blks2_selector_0</source_block_id>
+ <sink_block_id>rational_resampler_xxx_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_float_to_short_0</source_block_id>
+ <sink_block_id>vocoder_gsm_fr_encode_sp_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>vocoder_gsm_fr_decode_ps_0</source_block_id>
+ <sink_block_id>blocks_short_to_float_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>vocoder_gsm_fr_encode_sp_1</source_block_id>
+ <sink_block_id>blocks_vector_to_stream_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_vector_to_stream_0</source_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>virtual_source_0</source_block_id>
+ <sink_block_id>blocks_stream_to_vector_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_stream_to_vector_0</source_block_id>
+ <sink_block_id>vocoder_gsm_fr_decode_ps_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_short_to_float_0</source_block_id>
+ <sink_block_id>qtgui_time_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gr-vocoder/grc/vocoder_codec2_decode_ps.xml b/gr-vocoder/grc/vocoder_codec2_decode_ps.xml
index 708882151b..8b5f348671 100644
--- a/gr-vocoder/grc/vocoder_codec2_decode_ps.xml
+++ b/gr-vocoder/grc/vocoder_codec2_decode_ps.xml
@@ -12,6 +12,7 @@
<sink>
<name>in</name>
<type>byte</type>
+ <vlen>50</vlen>
</sink>
<source>
<name>out</name>
diff --git a/gr-vocoder/grc/vocoder_codec2_encode_sp.xml b/gr-vocoder/grc/vocoder_codec2_encode_sp.xml
index 7a56ac6332..0fb0ecc2ff 100644
--- a/gr-vocoder/grc/vocoder_codec2_encode_sp.xml
+++ b/gr-vocoder/grc/vocoder_codec2_encode_sp.xml
@@ -16,7 +16,7 @@
<source>
<name>out</name>
<type>byte</type>
+ <vlen>50</vlen>
</source>
</block>
-
diff --git a/gr-vocoder/grc/vocoder_gsm_fr_decode_ps.xml b/gr-vocoder/grc/vocoder_gsm_fr_decode_ps.xml
index 44290f891e..bef07fb822 100644
--- a/gr-vocoder/grc/vocoder_gsm_fr_decode_ps.xml
+++ b/gr-vocoder/grc/vocoder_gsm_fr_decode_ps.xml
@@ -12,6 +12,7 @@
<sink>
<name>in</name>
<type>byte</type>
+ <vlen>33</vlen>
</sink>
<source>
<name>out</name>
diff --git a/gr-vocoder/grc/vocoder_gsm_fr_encode_sp.xml b/gr-vocoder/grc/vocoder_gsm_fr_encode_sp.xml
index 13f6f3f2d0..4c3eab71a8 100644
--- a/gr-vocoder/grc/vocoder_gsm_fr_encode_sp.xml
+++ b/gr-vocoder/grc/vocoder_gsm_fr_encode_sp.xml
@@ -16,6 +16,7 @@
<source>
<name>out</name>
<type>byte</type>
+ <vlen>33</vlen>
</source>
</block>
diff --git a/gr-vocoder/include/gnuradio/vocoder/codec2_decode_ps.h b/gr-vocoder/include/gnuradio/vocoder/codec2_decode_ps.h
index e90e7b9560..041877174b 100644
--- a/gr-vocoder/include/gnuradio/vocoder/codec2_decode_ps.h
+++ b/gr-vocoder/include/gnuradio/vocoder/codec2_decode_ps.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2011,2013 Free Software Foundation, Inc.
+ * Copyright 2011,2013,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -32,13 +32,19 @@ namespace gr {
/*!
* \brief CODEC2 Vocoder Decoder
* \ingroup audio_blk
+ *
+ * Input: A vector of 50 unpacked bits forming a Codec2 frame.
+ *
+ * Output: 16-bit short values of an audio signal with sampling rate 8 kHz.
+ *
+ * See also gr::vocoder::codec2_encode_sp.
*/
class VOCODER_API codec2_decode_ps : virtual public sync_interpolator
{
public:
// gr::vocoder::codec2_decode_ps::sptr
typedef boost::shared_ptr<codec2_decode_ps> sptr;
-
+
/*!
* \brief Make Codec2 decoder block.
*/
diff --git a/gr-vocoder/include/gnuradio/vocoder/codec2_encode_sp.h b/gr-vocoder/include/gnuradio/vocoder/codec2_encode_sp.h
index 9fe1c2dd43..12b91b0428 100644
--- a/gr-vocoder/include/gnuradio/vocoder/codec2_encode_sp.h
+++ b/gr-vocoder/include/gnuradio/vocoder/codec2_encode_sp.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2005,2013 Free Software Foundation, Inc.
+ * Copyright 2005,2013,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -32,13 +32,24 @@ namespace gr {
/*!
* \brief CODEC2 Vocoder Encoder
* \ingroup audio_blk
+ *
+ * Input: Speech (audio) signal as 16-bit shorts, sampling rate 8 kHz.
+ *
+ * Output: Vector of 50 unpacked bits, forming one Codec2 frame, per 160 input samples.
+ *
+ * Note that the Codec2 library produces 7 bytes with a total of 50 bits
+ * per frame. The bits are MSB-first on these 7 bytes, so the first item
+ * of the output vector is the MSB of the first byte of the frame.
+ * If this block is combined with the gr::vocoder::codec2_decode_ps block,
+ * this will work out of the box.
+ *
*/
class VOCODER_API codec2_encode_sp : virtual public sync_decimator
{
public:
// gr::vocoder::codec2_encode_sp::sptr
typedef boost::shared_ptr<codec2_encode_sp> sptr;
-
+
/*!
* \brief Make Codec2 encoder block.
*/
diff --git a/gr-vocoder/include/gnuradio/vocoder/cvsd_decode_bs.h b/gr-vocoder/include/gnuradio/vocoder/cvsd_decode_bs.h
index 324dcea1a1..6e931683c4 100644
--- a/gr-vocoder/include/gnuradio/vocoder/cvsd_decode_bs.h
+++ b/gr-vocoder/include/gnuradio/vocoder/cvsd_decode_bs.h
@@ -75,12 +75,15 @@ namespace gr {
* the CVSD encoder.
*
* References:
+ *
* 1. Continuously Variable Slope Delta Modulation (CVSD) A Tutorial,
* Available: http://www.eetkorea.com/ARTICLES/2003AUG/A/2003AUG29_NTEK_RFD_AN02.PDF.
+ *
* 2. Specification of The Bluetooth System
* Available: http://grouper.ieee.org/groups/802/15/Bluetooth/core_10_b.pdf.
+ *
* 3. McGarrity, S., Bluetooth Full Duplex Voice and Data Transmission. 2002.
- * Bluetooth Voice Simulink� Model, Available:
+ * Bluetooth Voice Simulink Model, Available:
* http://www.mathworks.com/company/newsletters/digest/nov01/bluetooth.html
*/
class VOCODER_API cvsd_decode_bs : virtual public sync_interpolator
diff --git a/gr-vocoder/include/gnuradio/vocoder/cvsd_encode_sb.h b/gr-vocoder/include/gnuradio/vocoder/cvsd_encode_sb.h
index 7b7cea712e..d0b3afaab1 100644
--- a/gr-vocoder/include/gnuradio/vocoder/cvsd_encode_sb.h
+++ b/gr-vocoder/include/gnuradio/vocoder/cvsd_encode_sb.h
@@ -81,7 +81,7 @@ namespace gr {
* Available: http://grouper.ieee.org/groups/802/15/Bluetooth/core_10_b.pdf.
*
* 3. McGarrity, S., Bluetooth Full Duplex Voice and Data Transmission. 2002.
- * Bluetooth Voice Simulink� Model, Available:
+ * Bluetooth Voice Simulink Model, Available:
* http://www.mathworks.com/company/newsletters/digest/nov01/bluetooth.html
*/
class VOCODER_API cvsd_encode_sb : virtual public sync_decimator
@@ -89,7 +89,7 @@ namespace gr {
public:
// gr::vocoder::cvsd_encode_sb::sptr
typedef boost::shared_ptr<cvsd_encode_sb> sptr;
-
+
/*!
* \brief Constructor parameters to initialize the CVSD encoder.
* The default values are modeled after the Bluetooth standard and
@@ -116,7 +116,7 @@ namespace gr {
short pos_accum_max=32767, short neg_accum_max=-32767);
virtual short min_step() = 0;
- virtual short max_step() = 0;
+ virtual short max_step() = 0;
virtual double step_decay() = 0;
virtual double accum_decay() = 0;
virtual int K() = 0;
diff --git a/gr-vocoder/include/gnuradio/vocoder/gsm_fr_decode_ps.h b/gr-vocoder/include/gnuradio/vocoder/gsm_fr_decode_ps.h
index 9979763e60..b9aa664a77 100644
--- a/gr-vocoder/include/gnuradio/vocoder/gsm_fr_decode_ps.h
+++ b/gr-vocoder/include/gnuradio/vocoder/gsm_fr_decode_ps.h
@@ -32,13 +32,16 @@ namespace gr {
/*!
* \brief GSM 06.10 Full Rate Vocoder Decoder
* \ingroup audio_blk
+ *
+ * Input: Vector of 33 bytes per 160 input samples
+ * Output: 16-bit shorts representing speech samples
*/
class VOCODER_API gsm_fr_decode_ps : virtual public sync_interpolator
{
public:
// gr::vocoder::gsm_fr_decode_ps::sptr
typedef boost::shared_ptr<gsm_fr_decode_ps> sptr;
-
+
/*!
* \brief Make GSM decoder block.
*/
diff --git a/gr-vocoder/include/gnuradio/vocoder/gsm_fr_encode_sp.h b/gr-vocoder/include/gnuradio/vocoder/gsm_fr_encode_sp.h
index 98d88bba1f..5cfbc653cd 100644
--- a/gr-vocoder/include/gnuradio/vocoder/gsm_fr_encode_sp.h
+++ b/gr-vocoder/include/gnuradio/vocoder/gsm_fr_encode_sp.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2005,2011,2013 Free Software Foundation, Inc.
+ * Copyright 2005,2011,2013,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -33,14 +33,15 @@ namespace gr {
* \brief GSM 06.10 Full Rate Vocoder Encoder
* \ingroup audio_blk
*
- * shorts in; 33 byte packets out
+ * Input: 16-bit shorts representing speech samples
+ * Output: Vector of 33 bytes per 160 input samples
*/
class VOCODER_API gsm_fr_encode_sp : virtual public sync_decimator
{
public:
// gr::vocoder::gsm_fr_encode_sp::sptr
typedef boost::shared_ptr<gsm_fr_encode_sp> sptr;
-
+
/*!
* \brief Make GSM encoder block.
*/
@@ -48,6 +49,6 @@ namespace gr {
};
} /* namespace vocoder */
-} /* namespace gr */
+} /* namespace gr */
#endif /* INCLUDED_VOCODER_GSM_FR_ENCODE_SP_H */
diff --git a/gr-vocoder/lib/codec2/codec2.h b/gr-vocoder/lib/codec2/codec2.h
index 88e68814fa..f812a05983 100644
--- a/gr-vocoder/lib/codec2/codec2.h
+++ b/gr-vocoder/lib/codec2/codec2.h
@@ -31,6 +31,7 @@
#define CODEC2_SAMPLES_PER_FRAME 160
#define CODEC2_BITS_PER_FRAME 50
+#define CODEC2_BYTES_PER_FRAME ((CODEC2_BITS_PER_FRAME + 7) / 8) // == 8 bytes when packing the 50 bits
void *codec2_create();
void codec2_destroy(void *codec2_state);
diff --git a/gr-vocoder/lib/codec2_decode_ps_impl.cc b/gr-vocoder/lib/codec2_decode_ps_impl.cc
index 57ab62422e..a4f7cccf82 100644
--- a/gr-vocoder/lib/codec2_decode_ps_impl.cc
+++ b/gr-vocoder/lib/codec2_decode_ps_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2005,2011,2013 Free Software Foundation, Inc.
+ * Copyright 2005,2011,2013,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -49,7 +49,8 @@ namespace gr {
: sync_interpolator("vocoder_codec2_decode_ps",
io_signature::make(1, 1, CODEC2_BITS_PER_FRAME * sizeof(char)),
io_signature::make (1, 1, sizeof(short)),
- CODEC2_SAMPLES_PER_FRAME)
+ CODEC2_SAMPLES_PER_FRAME),
+ d_frame_buf(CODEC2_BYTES_PER_FRAME, 0)
{
if((d_codec2 = codec2_create()) == 0)
throw std::runtime_error("codec2_decode_ps_impl: codec2_create failed");
@@ -71,7 +72,8 @@ namespace gr {
assert((noutput_items % CODEC2_SAMPLES_PER_FRAME) == 0);
for(int i = 0; i < noutput_items; i += CODEC2_SAMPLES_PER_FRAME) {
- codec2_decode (d_codec2, out, const_cast<unsigned char*>(in));
+ pack_frame(in, &d_frame_buf[0]);
+ codec2_decode (d_codec2, out, const_cast<unsigned char*>(&d_frame_buf[0]));
in += CODEC2_BITS_PER_FRAME * sizeof (char);
out += CODEC2_SAMPLES_PER_FRAME;
}
@@ -79,5 +81,20 @@ namespace gr {
return noutput_items;
}
+ void
+ codec2_decode_ps_impl::pack_frame(const unsigned char *in_unpacked, unsigned char *out_packed)
+ {
+ memset((void *) &d_frame_buf[0], 0x00, CODEC2_BYTES_PER_FRAME);
+
+ int byte_idx = 0, bit_idx = 0;
+ for(int k = 0; k < CODEC2_BITS_PER_FRAME; k++) {
+ out_packed[byte_idx] |= ((in_unpacked[k] & 0x01) << (7-bit_idx));
+ bit_idx = (bit_idx + 1) % 8;
+ if (bit_idx == 0) {
+ byte_idx++;
+ }
+ }
+ }
+
} /* namespace vocoder */
} /* namespace gr */
diff --git a/gr-vocoder/lib/codec2_decode_ps_impl.h b/gr-vocoder/lib/codec2_decode_ps_impl.h
index 54b3744adf..b9591dce74 100644
--- a/gr-vocoder/lib/codec2_decode_ps_impl.h
+++ b/gr-vocoder/lib/codec2_decode_ps_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2011,2013 Free Software Foundation, Inc.
+ * Copyright 2011,2013,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -32,6 +32,9 @@ namespace gr {
{
private:
void *d_codec2;
+ std::vector<unsigned char> d_frame_buf; //!< Store 1 packed frame for decoding
+
+ void pack_frame(const unsigned char *in_unpacked, unsigned char *out_packed); //!< Pack the bytes from unpacked bits for codec2
public:
codec2_decode_ps_impl();
@@ -43,6 +46,6 @@ namespace gr {
};
} /* namespace vocoder */
-} /* namespace gr */
+} /* namespace gr */
#endif /* INCLUDED_VOCODER_CODEC2_DECODE_PS_IMPL_H */
diff --git a/gr-vocoder/lib/codec2_encode_sp_impl.cc b/gr-vocoder/lib/codec2_encode_sp_impl.cc
index 3f79e06409..fc0b3eee19 100644
--- a/gr-vocoder/lib/codec2_encode_sp_impl.cc
+++ b/gr-vocoder/lib/codec2_encode_sp_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2005,2011 Free Software Foundation, Inc.
+ * Copyright 2005,2011,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -32,6 +32,8 @@ extern "C" {
#include <gnuradio/io_signature.h>
#include <stdexcept>
+#include <iostream>
+#include <iomanip>
namespace gr {
namespace vocoder {
@@ -47,7 +49,8 @@ namespace gr {
: sync_decimator("vocoder_codec2_encode_sp",
io_signature::make(1, 1, sizeof(short)),
io_signature::make(1, 1, CODEC2_BITS_PER_FRAME * sizeof(char)),
- CODEC2_SAMPLES_PER_FRAME)
+ CODEC2_SAMPLES_PER_FRAME),
+ d_frame_buf(CODEC2_BYTES_PER_FRAME, 0)
{
if((d_codec2 = codec2_create()) == 0)
throw std::runtime_error("codec2_encode_sp_impl: codec2_create failed");
@@ -67,7 +70,8 @@ namespace gr {
unsigned char *out = (unsigned char*)output_items[0];
for(int i = 0; i < noutput_items; i++) {
- codec2_encode(d_codec2, out, const_cast<short*>(in));
+ codec2_encode(d_codec2, &d_frame_buf[0], const_cast<short*>(in));
+ unpack_frame((const unsigned char *) &d_frame_buf[0], out);
in += CODEC2_SAMPLES_PER_FRAME;
out += CODEC2_BITS_PER_FRAME * sizeof(char);
}
@@ -75,5 +79,18 @@ namespace gr {
return noutput_items;
}
+ void
+ codec2_encode_sp_impl::unpack_frame(const unsigned char *packed, unsigned char *out)
+ {
+ int byte_idx = 0, bit_idx = 0;
+ for(int k = 0; k < CODEC2_BITS_PER_FRAME; k++) {
+ out[k] = (packed[byte_idx] >> (7-bit_idx)) & 0x01;
+ bit_idx = (bit_idx + 1) % 8;
+ if (bit_idx == 0) {
+ byte_idx++;
+ }
+ }
+ }
+
} /* namespace vocoder */
} /* namespace gr */
diff --git a/gr-vocoder/lib/codec2_encode_sp_impl.h b/gr-vocoder/lib/codec2_encode_sp_impl.h
index 354bcc4718..7402d09f90 100644
--- a/gr-vocoder/lib/codec2_encode_sp_impl.h
+++ b/gr-vocoder/lib/codec2_encode_sp_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2005,2013 Free Software Foundation, Inc.
+ * Copyright 2005,2013,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -32,6 +32,9 @@ namespace gr {
{
private:
void *d_codec2;
+ std::vector<unsigned char> d_frame_buf; //!< Save 1 CODEC2 frame
+
+ void unpack_frame(const unsigned char *packed, unsigned char *out); //!< Unpack the bytes from codec2 into unpacked bits
public:
codec2_encode_sp_impl();
@@ -43,6 +46,6 @@ namespace gr {
};
} /* namespace vocoder */
-} /* namespace gr */
+} /* namespace gr */
#endif /* INCLUDED_VOCODER_CODEC2_ENCODE_SP_IMPL_H */
diff --git a/gr-vocoder/lib/gsm_fr_encode_sp_impl.cc b/gr-vocoder/lib/gsm_fr_encode_sp_impl.cc
index 143a73bce7..0c3afe8f59 100644
--- a/gr-vocoder/lib/gsm_fr_encode_sp_impl.cc
+++ b/gr-vocoder/lib/gsm_fr_encode_sp_impl.cc
@@ -71,4 +71,4 @@ namespace gr {
}
} /* namespace vocoder */
-} /* namespace gr */
+} /* namespace gr */
diff --git a/gr-vocoder/python/vocoder/qa_codec2_vocoder.py b/gr-vocoder/python/vocoder/qa_codec2_vocoder.py
index b2ed734888..0e29401c7a 100755
--- a/gr-vocoder/python/vocoder/qa_codec2_vocoder.py
+++ b/gr-vocoder/python/vocoder/qa_codec2_vocoder.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2011,2013 Free Software Foundation, Inc.
+# Copyright 2011,2013,2014 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -54,4 +54,6 @@ class test_codec2_vocoder (gr_unittest.TestCase):
self.assertEqual(expected_data, actual_result)
if __name__ == '__main__':
+ # Note: The Vocoder is stateful, which means this test will produce failure when removing the xml option.
+ # Perhaps this is not the best way to test such a vocoder.
gr_unittest.run(test_codec2_vocoder, "test_codec2_vocoder.xml")
diff --git a/grc/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl
index fe1155bb50..7c6998ab73 100644
--- a/grc/python/flow_graph.tmpl
+++ b/grc/python/flow_graph.tmpl
@@ -315,6 +315,7 @@ if __name__ == '__main__':
tb.Wait()
#end if
#elif $generate_options == 'qt_gui'
+ Qt.QApplication.setGraphicsSystem(gr.prefs().get_string('qtgui','style','raster'))
qapp = Qt.QApplication(sys.argv)
tb = $(class_name)($(', '.join($params_eq_list)))
#if $flow_graph.get_option('run')
diff --git a/volk/apps/volk_profile.cc b/volk/apps/volk_profile.cc
index 3986cb6e62..97b0a5b7a8 100644
--- a/volk/apps/volk_profile.cc
+++ b/volk/apps/volk_profile.cc
@@ -16,147 +16,175 @@
namespace fs = boost::filesystem;
int main(int argc, char *argv[]) {
+ // Adding program options
boost::program_options::options_description desc("Options");
desc.add_options()
("help,h", "Print help messages")
- ("benchmark,b", boost::program_options::value<bool>()->default_value( false ), "run all kernels (benchmark mode)");
- //("benchmark,b", boost::program_options::value<bool>(&benchmark_mode)->default_value( false ), "run all kernels (benchmark mode)");
+ ("benchmark,b",
+ boost::program_options::value<bool>()->default_value( false )
+ ->implicit_value( true ),
+ "Run all kernels (benchmark mode)")
+ ("tests-regex,R",
+ boost::program_options::value<std::string>(),
+ "Run tests matching regular expression.")
+ ;
+
+ // Handle the options that were given
boost::program_options::variables_map vm;
- bool benchmark_mode = false;
+ bool benchmark_mode;
+ std::string kernel_regex;
+ bool store_results = true;
try {
- boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
+ boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
boost::program_options::notify(vm);
benchmark_mode = vm.count("benchmark")?vm["benchmark"].as<bool>():false;
+ if ( vm.count("tests-regex" ) ) {
+ kernel_regex = vm["tests-regex"].as<std::string>();
+ store_results = false;
+ std::cout << "Warning: using a regexp will not save results to a config" << std::endl;
+ }
+ else {
+ kernel_regex = ".*";
+ store_results = true;
+ }
} catch (boost::program_options::error& error) {
std::cerr << "Error: " << error.what() << std::endl << std::endl;
std::cerr << desc << std::endl;
return 1;
}
/** --help option
- */
- if ( vm.count("help") )
- {
- std::cout << "Basic Command Line Parameter App" << std::endl
- << desc << std::endl;
- return 0;
- }
+*/
+ if ( vm.count("help") )
+ {
+ std::cout << "The VOLK profiler." << std::endl
+ << desc << std::endl;
+ return 0;
+ }
+ // Run tests
std::vector<std::string> results;
- //VOLK_PROFILE(volk_16i_x5_add_quad_16i_x4, 1e-4, 2046, 10000, &results, benchmark_mode);
- //VOLK_PROFILE(volk_16i_branch_4_state_8, 1e-4, 2046, 10000, &results, benchmark_mode);
- VOLK_PUPPET_PROFILE(volk_32fc_s32fc_rotatorpuppet_32fc, volk_32fc_s32fc_x2_rotator_32fc, 1e-2, (lv_32fc_t)lv_cmake(0.953939201, 0.3), 20462, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_16ic_s32f_deinterleave_real_32f, 1e-5, 32768.0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_16ic_deinterleave_real_8i, 0, 0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_16ic_deinterleave_16i_x2, 0, 0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_16ic_s32f_deinterleave_32f_x2, 1e-4, 32768.0, 204602, 1000, &results, benchmark_mode);
- VOLK_PROFILE(volk_16ic_deinterleave_real_16i, 0, 0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_16ic_magnitude_16i, 1, 0, 204602, 100, &results, benchmark_mode);
- VOLK_PROFILE(volk_16ic_s32f_magnitude_32f, 1e-5, 32768.0, 204602, 1000, &results, benchmark_mode);
- VOLK_PROFILE(volk_16i_s32f_convert_32f, 1e-4, 32768.0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_16i_convert_8i, 0, 0, 204602, 10000, &results, benchmark_mode);
- //VOLK_PROFILE(volk_16i_max_star_16i, 0, 0, 204602, 10000, &results, benchmark_mode);
- //VOLK_PROFILE(volk_16i_max_star_horizontal_16i, 0, 0, 204602, 10000, &results, benchmark_mode);
- //VOLK_PROFILE(volk_16i_permute_and_scalar_add, 1e-4, 0, 2046, 10000, &results, benchmark_mode);
- //VOLK_PROFILE(volk_16i_x4_quad_max_star_16i, 1e-4, 0, 2046, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_16u_byteswap, 0, 0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_16i_32fc_dot_prod_32fc, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_accumulator_s32f, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_x2_add_32f, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_32f_multiply_32fc, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_s32f_power_32fc, 1e-4, 0, 204602, 50, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_s32f_calc_spectral_noise_floor_32f, 1e-4, 20.0, 204602, 1000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_s32f_atan2_32f, 1e-4, 10.0, 204602, 100, &results, benchmark_mode);
- //VOLK_PROFILE(volk_32fc_x2_conjugate_dot_prod_32fc, 1e-4, 0, 2046, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_x2_conjugate_dot_prod_32fc, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_deinterleave_32f_x2, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_deinterleave_64f_x2, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_s32f_deinterleave_real_16i, 0, 32768, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_deinterleave_imag_32f, 1e-4, 0, 204602, 5000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_deinterleave_real_32f, 1e-4, 0, 204602, 5000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_deinterleave_real_64f, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_x2_dot_prod_32fc, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_32f_dot_prod_32fc, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_index_max_16u, 3, 0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_s32f_magnitude_16i, 1, 32768, 204602, 100, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_magnitude_32f, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_magnitude_squared_32f, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_x2_multiply_32fc, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_x2_multiply_conjugate_32fc, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_conjugate_32fc, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_s32f_convert_16i, 1, 32768, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_s32f_convert_32i, 1, 1<<31, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_convert_64f, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_s32f_convert_8i, 1, 128, 204602, 10000, &results, benchmark_mode);
- //VOLK_PROFILE(volk_32fc_s32f_x2_power_spectral_density_32f, 1e-4, 2046, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_s32f_power_spectrum_32f, 1e-4, 0, 20462, 100, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_x2_square_dist_32f, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_x2_s32f_square_dist_scalar_mult_32f, 1e-4, 10, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_x2_divide_32f, 1e-4, 0, 204602, 2000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_x2_dot_prod_32f, 1e-4, 0, 204602, 5000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_x2_dot_prod_16i, 1e-4, 0, 204602, 5000, &results, benchmark_mode);
- //VOLK_PROFILE(volk_32f_s32f_32f_fm_detect_32f, 1e-4, 2046, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_index_max_16u, 3, 0, 204602, 5000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_x2_s32f_interleave_16ic, 1, 32768, 204602, 3000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_x2_interleave_32fc, 0, 0, 204602, 5000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_x2_max_32f, 1e-4, 0, 204602, 2000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_x2_min_32f, 1e-4, 0, 204602, 2000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_x2_multiply_32f, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_s32f_normalize, 1e-4, 100, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_s32f_power_32f, 1e-4, 4, 204602, 100, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_sqrt_32f, 1e-4, 0, 204602, 100, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_s32f_stddev_32f, 1e-4, 100, 204602, 3000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_stddev_and_mean_32f_x2, 1e-4, 0, 204602, 3000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_x2_subtract_32f, 1e-4, 0, 204602, 5000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_x3_sum_of_poly_32f, 1e-2, 0, 204602, 5000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32i_x2_and_32i, 0, 0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32i_s32f_convert_32f, 1e-4, 100, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32i_x2_or_32i, 0, 0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32u_byteswap, 0, 0, 204602, 2000, &results, benchmark_mode);
- //VOLK_PROFILE(volk_32u_popcnt, 0, 0, 2046, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_64f_convert_32f, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_64f_x2_max_64f, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
- VOLK_PROFILE(volk_64f_x2_min_64f, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
- VOLK_PROFILE(volk_64u_byteswap, 0, 0, 204602, 1000, &results, benchmark_mode);
- //VOLK_PROFILE(volk_64u_popcnt, 0, 0, 2046, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_8ic_deinterleave_16i_x2, 0, 0, 204602, 3000, &results, benchmark_mode);
- VOLK_PROFILE(volk_8ic_s32f_deinterleave_32f_x2, 1e-4, 100, 204602, 3000, &results, benchmark_mode);
- VOLK_PROFILE(volk_8ic_deinterleave_real_16i, 0, 256, 204602, 3000, &results, benchmark_mode);
- VOLK_PROFILE(volk_8ic_s32f_deinterleave_real_32f, 1e-4, 100, 204602, 3000, &results, benchmark_mode);
- VOLK_PROFILE(volk_8ic_deinterleave_real_8i, 0, 0, 204602, 10000, &results, benchmark_mode);
- VOLK_PROFILE(volk_8ic_x2_multiply_conjugate_16ic, 0, 0, 204602, 400, &results, benchmark_mode);
- VOLK_PROFILE(volk_8ic_x2_s32f_multiply_conjugate_32fc, 1e-4, 100, 204602, 400, &results, benchmark_mode);
- VOLK_PROFILE(volk_8i_convert_16i, 0, 0, 204602, 20000, &results, benchmark_mode);
- VOLK_PROFILE(volk_8i_s32f_convert_32f, 1e-4, 100, 204602, 2000, &results, benchmark_mode);
- //VOLK_PROFILE(volk_32fc_s32fc_multiply_32fc, 1e-4, lv_32fc_t(1.0, 0.5), 204602, 1000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32fc_s32fc_multiply_32fc, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
- VOLK_PROFILE(volk_32f_s32f_multiply_32f, 1e-4, 1.0, 204602, 10000, &results, benchmark_mode);
+ //VOLK_PROFILE(volk_16i_x5_add_quad_16i_x4, 1e-4, 2046, 10000, &results, benchmark_mode, kernel_regex);
+ //VOLK_PROFILE(volk_16i_branch_4_state_8, 1e-4, 2046, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PUPPET_PROFILE(volk_32fc_s32fc_rotatorpuppet_32fc, volk_32fc_s32fc_x2_rotator_32fc, 1e-2, (lv_32fc_t)lv_cmake(0.953939201, 0.3), 20462, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_16ic_s32f_deinterleave_real_32f, 1e-5, 32768.0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_16ic_deinterleave_real_8i, 0, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_16ic_deinterleave_16i_x2, 0, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_16ic_s32f_deinterleave_32f_x2, 1e-4, 32768.0, 204602, 1000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_16ic_deinterleave_real_16i, 0, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_16ic_magnitude_16i, 1, 0, 204602, 100, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_16ic_s32f_magnitude_32f, 1e-5, 32768.0, 204602, 1000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_16i_s32f_convert_32f, 1e-4, 32768.0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_16i_convert_8i, 0, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ //VOLK_PROFILE(volk_16i_max_star_16i, 0, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ //VOLK_PROFILE(volk_16i_max_star_horizontal_16i, 0, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ //VOLK_PROFILE(volk_16i_permute_and_scalar_add, 1e-4, 0, 2046, 10000, &results, benchmark_mode, kernel_regex);
+ //VOLK_PROFILE(volk_16i_x4_quad_max_star_16i, 1e-4, 0, 2046, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_16u_byteswap, 0, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_16i_32fc_dot_prod_32fc, 1e-4, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_accumulator_s32f, 1e-4, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_x2_add_32f, 1e-4, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_32f_multiply_32fc, 1e-4, 0, 204602, 1000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_s32f_power_32fc, 1e-4, 0, 204602, 50, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_s32f_calc_spectral_noise_floor_32f, 1e-4, 20.0, 204602, 1000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_s32f_atan2_32f, 1e-4, 10.0, 204602, 100, &results, benchmark_mode, kernel_regex);
+ //VOLK_PROFILE(volk_32fc_x2_conjugate_dot_prod_32fc, 1e-4, 0, 2046, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_x2_conjugate_dot_prod_32fc, 1e-4, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_deinterleave_32f_x2, 1e-4, 0, 204602, 1000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_deinterleave_64f_x2, 1e-4, 0, 204602, 1000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_s32f_deinterleave_real_16i, 0, 32768, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_deinterleave_imag_32f, 1e-4, 0, 204602, 5000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_deinterleave_real_32f, 1e-4, 0, 204602, 5000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_deinterleave_real_64f, 1e-4, 0, 204602, 1000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_x2_dot_prod_32fc, 1e-4, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_32f_dot_prod_32fc, 1e-4, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_index_max_16u, 3, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_s32f_magnitude_16i, 1, 32768, 204602, 100, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_magnitude_32f, 1e-4, 0, 204602, 1000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_magnitude_squared_32f, 1e-4, 0, 204602, 1000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_x2_multiply_32fc, 1e-4, 0, 204602, 1000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_x2_multiply_conjugate_32fc, 1e-4, 0, 204602, 1000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_conjugate_32fc, 1e-4, 0, 204602, 1000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_s32f_convert_16i, 1, 32768, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_s32f_convert_32i, 1, 1<<31, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_convert_64f, 1e-4, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_s32f_convert_8i, 1, 128, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ //VOLK_PROFILE(volk_32fc_s32f_x2_power_spectral_density_32f, 1e-4, 2046, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_s32f_power_spectrum_32f, 1e-4, 0, 20462, 100, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_x2_square_dist_32f, 1e-4, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_x2_s32f_square_dist_scalar_mult_32f, 1e-4, 10, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_x2_divide_32f, 1e-4, 0, 204602, 2000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_x2_dot_prod_32f, 1e-4, 0, 204602, 5000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_x2_dot_prod_16i, 1e-4, 0, 204602, 5000, &results, benchmark_mode, kernel_regex);
+ //VOLK_PROFILE(volk_32f_s32f_32f_fm_detect_32f, 1e-4, 2046, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_index_max_16u, 3, 0, 204602, 5000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_x2_s32f_interleave_16ic, 1, 32768, 204602, 3000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_x2_interleave_32fc, 0, 0, 204602, 5000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_x2_max_32f, 1e-4, 0, 204602, 2000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_x2_min_32f, 1e-4, 0, 204602, 2000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_x2_multiply_32f, 1e-4, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_s32f_normalize, 1e-4, 100, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_s32f_power_32f, 1e-4, 4, 204602, 100, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_sqrt_32f, 1e-4, 0, 204602, 100, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_s32f_stddev_32f, 1e-4, 100, 204602, 3000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_stddev_and_mean_32f_x2, 1e-4, 0, 204602, 3000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_x2_subtract_32f, 1e-4, 0, 204602, 5000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_x3_sum_of_poly_32f, 1e-2, 0, 204602, 5000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32i_x2_and_32i, 0, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32i_s32f_convert_32f, 1e-4, 100, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32i_x2_or_32i, 0, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32u_byteswap, 0, 0, 204602, 2000, &results, benchmark_mode, kernel_regex);
+ //VOLK_PROFILE(volk_32u_popcnt, 0, 0, 2046, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_64f_convert_32f, 1e-4, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_64f_x2_max_64f, 1e-4, 0, 204602, 1000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_64f_x2_min_64f, 1e-4, 0, 204602, 1000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_64u_byteswap, 0, 0, 204602, 1000, &results, benchmark_mode, kernel_regex);
+ //VOLK_PROFILE(volk_64u_popcnt, 0, 0, 2046, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_8ic_deinterleave_16i_x2, 0, 0, 204602, 3000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_8ic_s32f_deinterleave_32f_x2, 1e-4, 100, 204602, 3000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_8ic_deinterleave_real_16i, 0, 256, 204602, 3000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_8ic_s32f_deinterleave_real_32f, 1e-4, 100, 204602, 3000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_8ic_deinterleave_real_8i, 0, 0, 204602, 10000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_8ic_x2_multiply_conjugate_16ic, 0, 0, 204602, 400, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_8ic_x2_s32f_multiply_conjugate_32fc, 1e-4, 100, 204602, 400, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_8i_convert_16i, 0, 0, 204602, 20000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_8i_s32f_convert_32f, 1e-4, 100, 204602, 2000, &results, benchmark_mode, kernel_regex);
+ //VOLK_PROFILE(volk_32fc_s32fc_multiply_32fc, 1e-4, lv_32fc_t(1.0, 0.5), 204602, 1000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32fc_s32fc_multiply_32fc, 1e-4, 0, 204602, 1000, &results, benchmark_mode, kernel_regex);
+ VOLK_PROFILE(volk_32f_s32f_multiply_32f, 1e-4, 1.0, 204602, 10000, &results, benchmark_mode, kernel_regex);
- char path[1024];
- volk_get_config_path(path);
+ // Until we can update the config on a kernel by kernel basis
+ // do not overwrite volk_config when using a regex.
+ if(store_results) {
+ char path[1024];
+ volk_get_config_path(path);
- const fs::path config_path(path);
+ const fs::path config_path(path);
- if (not fs::exists(config_path.branch_path()))
- {
- std::cout << "Creating " << config_path.branch_path() << "..." << std::endl;
- fs::create_directories(config_path.branch_path());
- }
+ if (not fs::exists(config_path.branch_path()))
+ {
+ std::cout << "Creating " << config_path.branch_path() << "..." << std::endl;
+ fs::create_directories(config_path.branch_path());
+ }
- std::cout << "Writing " << config_path << "..." << std::endl;
- std::ofstream config(config_path.string().c_str());
- if(!config.is_open()) { //either we don't have write access or we don't have the dir yet
- std::cout << "Error opening file " << config_path << std::endl;
- }
+ std::cout << "Writing " << config_path << "..." << std::endl;
+ std::ofstream config(config_path.string().c_str());
+ if(!config.is_open()) { //either we don't have write access or we don't have the dir yet
+ std::cout << "Error opening file " << config_path << std::endl;
+ }
- config << "\
-#this file is generated by volk_profile.\n\
-#the function name is followed by the preferred architecture.\n\
+ config << "\
+#thi s file is generated by volk_profile.\n\
+#the function name is followed by the preferred architecture.\n\
";
- BOOST_FOREACH(std::string result, results) {
- config << result << std::endl;
+ BOOST_FOREACH(std::string result, results) {
+ config << result << std::endl;
+ }
+ config.close();
+ }
+ else {
+ std::cout << "Warning: config not generated" << std::endl;
}
- config.close();
}
diff --git a/volk/kernels/volk/volk_16i_32fc_dot_prod_32fc.h b/volk/kernels/volk/volk_16i_32fc_dot_prod_32fc.h
index 8bc1569f61..8c66892fd9 100644
--- a/volk/kernels/volk/volk_16i_32fc_dot_prod_32fc.h
+++ b/volk/kernels/volk/volk_16i_32fc_dot_prod_32fc.h
@@ -1,5 +1,5 @@
-#ifndef INCLUDED_volk_16i_32fc_dot_prod_32fc_a_H
-#define INCLUDED_volk_16i_32fc_dot_prod_32fc_a_H
+#ifndef INCLUDED_volk_16i_32fc_dot_prod_32fc_H
+#define INCLUDED_volk_16i_32fc_dot_prod_32fc_H
#include <volk/volk_common.h>
#include<stdio.h>
@@ -37,6 +37,90 @@ static inline void volk_16i_32fc_dot_prod_32fc_generic(lv_32fc_t* result, const
#endif /*LV_HAVE_GENERIC*/
+
+#if LV_HAVE_SSE && LV_HAVE_MMX
+
+static inline void volk_16i_32fc_dot_prod_32fc_u_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_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 += 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*/
+
+
+
+
#if LV_HAVE_SSE && LV_HAVE_MMX
@@ -119,4 +203,4 @@ static inline void volk_16i_32fc_dot_prod_32fc_a_sse( lv_32fc_t* result, const
#endif /*LV_HAVE_SSE && LV_HAVE_MMX*/
-#endif /*INCLUDED_volk_16i_32fc_dot_prod_32fc_a_H*/
+#endif /*INCLUDED_volk_16i_32fc_dot_prod_32fc_H*/
diff --git a/volk/kernels/volk/volk_32f_x2_dot_prod_16i.h b/volk/kernels/volk/volk_32f_x2_dot_prod_16i.h
index 8fcc7deaed..b637f17777 100644
--- a/volk/kernels/volk/volk_32f_x2_dot_prod_16i.h
+++ b/volk/kernels/volk/volk_32f_x2_dot_prod_16i.h
@@ -1,5 +1,5 @@
-#ifndef INCLUDED_volk_32f_x2_dot_prod_16i_a_H
-#define INCLUDED_volk_32f_x2_dot_prod_16i_a_H
+#ifndef INCLUDED_volk_32f_x2_dot_prod_16i_H
+#define INCLUDED_volk_32f_x2_dot_prod_16i_H
#include <volk/volk_common.h>
#include<stdio.h>
@@ -27,7 +27,6 @@ static inline void volk_32f_x2_dot_prod_16i_generic(int16_t* result, const float
#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;
@@ -90,9 +89,77 @@ static inline void volk_32f_x2_dot_prod_16i_a_sse(int16_t* result, const float*
}
*result = (short)dotProduct;
+}
+
+#endif /*LV_HAVE_SSE*/
+
+
+#ifdef LV_HAVE_SSE
+
+static inline void volk_32f_x2_dot_prod_16i_u_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_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,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*/
+#endif /*INCLUDED_volk_32f_x2_dot_prod_16i_H*/
diff --git a/volk/kernels/volk/volk_32fc_32f_dot_prod_32fc.h b/volk/kernels/volk/volk_32fc_32f_dot_prod_32fc.h
index 8341129fef..f567ede516 100644
--- a/volk/kernels/volk/volk_32fc_32f_dot_prod_32fc.h
+++ b/volk/kernels/volk/volk_32fc_32f_dot_prod_32fc.h
@@ -284,5 +284,81 @@ static inline void volk_32fc_32f_dot_prod_32fc_u_avx( lv_32fc_t* result, const l
#endif /*LV_HAVE_AVX*/
+#ifdef LV_HAVE_SSE
+
+static inline void volk_32fc_32f_dot_prod_32fc_u_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_loadu_ps(aPtr);
+ a1Val = _mm_loadu_ps(aPtr+4);
+ a2Val = _mm_loadu_ps(aPtr+8);
+ a3Val = _mm_loadu_ps(aPtr+12);
+
+ x0Val = _mm_loadu_ps(bPtr);
+ x1Val = _mm_loadu_ps(bPtr);
+ x2Val = _mm_loadu_ps(bPtr+4);
+ x3Val = _mm_loadu_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_H*/
diff --git a/volk/lib/CMakeLists.txt b/volk/lib/CMakeLists.txt
index dbebac067f..d2e4e62212 100644
--- a/volk/lib/CMakeLists.txt
+++ b/volk/lib/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2011-2012 Free Software Foundation, Inc.
+# Copyright 2011-2012,2014 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
@@ -308,8 +308,21 @@ STRING(TOUPPER ${CMAKE_BUILD_TYPE} CBTU)
MESSAGE(STATUS BUILT TYPE ${CBTU})
MESSAGE(STATUS "Base cflags = ${CMAKE_C_FLAGS_${CBTU}} ${CMAKE_C_FLAGS}")
set(COMPILER_INFO "")
-execute_process(COMMAND ${CMAKE_C_COMPILER} --version
- OUTPUT_VARIABLE cmake_c_compiler_version)
+IF(MSVC)
+ IF(MSVC90) #Visual Studio 9
+ SET(cmake_c_compiler_version "Microsoft Visual Studio 9.0")
+ ELSE(MSVC10) #Visual Studio 10
+ SET(cmake_c_compiler_version "Microsoft Visual Studio 10.0")
+ ELSE(MSVC11) #Visual Studio 11
+ SET(cmake_c_compiler_version "Microsoft Visual Studio 11.0")
+ ELSE(MSVC12) #Visual Studio 12
+ SET(cmake_c_compiler_version "Microsoft Visual Studio 12.0")
+ ENDIF()
+ELSE()
+ execute_process(COMMAND ${CMAKE_C_COMPILER} --version
+ OUTPUT_VARIABLE cmake_c_compiler_version)
+ENDIF(MSVC)
+set(COMPILER_INFO "${CMAKE_C_COMPILER}:::${CMAKE_C_FLAGS_${GRCBTU}} ${CMAKE_C_FLAGS}\n${CMAKE_CXX_COMPILER}:::${CMAKE_CXX_FLAGS_${GRCBTU}} ${CMAKE_CXX_FLAGS}\n" )
foreach(machine_name ${available_machines})
#generate machine source
diff --git a/volk/lib/qa_utils.cc b/volk/lib/qa_utils.cc
index 8b95d7d6b0..8007fe75a6 100644
--- a/volk/lib/qa_utils.cc
+++ b/volk/lib/qa_utils.cc
@@ -3,6 +3,7 @@
#include <boost/foreach.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/tokenizer.hpp>
+#include <boost/xpressive/xpressive.hpp>
#include <iostream>
#include <vector>
#include <list>
@@ -322,8 +323,14 @@ bool run_volk_tests(volk_func_desc_t desc,
int iter,
std::vector<std::string> *best_arch_vector = 0,
std::string puppet_master_name = "NULL",
- bool benchmark_mode
+ bool benchmark_mode,
+ std::string kernel_regex
) {
+ boost::xpressive::sregex kernel_expression = boost::xpressive::sregex::compile(kernel_regex);
+ if( !boost::xpressive::regex_search(name, kernel_expression) ) {
+ // in this case we have a regex and are only looking to test one kernel
+ return false;
+ }
std::cout << "RUN_VOLK_TESTS: " << name << "(" << vlen << "," << iter << ")" << std::endl;
// The multiply and lv_force_cast_hf are work arounds for GNU Radio bugs 582 and 583
diff --git a/volk/lib/qa_utils.h b/volk/lib/qa_utils.h
index 0ede962e41..fc1a0239eb 100644
--- a/volk/lib/qa_utils.h
+++ b/volk/lib/qa_utils.h
@@ -21,12 +21,12 @@ volk_type_t volk_type_from_string(std::string);
float uniform(void);
void random_floats(float *buf, unsigned n);
-bool run_volk_tests(volk_func_desc_t, void(*)(), std::string, float, lv_32fc_t, int, int, std::vector<std::string> *, std::string, bool benchmark_mode=false);
+bool run_volk_tests(volk_func_desc_t, void(*)(), std::string, float, lv_32fc_t, int, int, std::vector<std::string> *, std::string, bool benchmark_mode=false, std::string kernel_regex="");
#define VOLK_RUN_TESTS(func, tol, scalar, len, iter) BOOST_AUTO_TEST_CASE(func##_test) { BOOST_CHECK_EQUAL(run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, 0, "NULL"), 0); }
-#define VOLK_PROFILE(func, tol, scalar, len, iter, results, bnmode) run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, results, "NULL", bnmode)
-#define VOLK_PUPPET_PROFILE(func, puppet_master_func, tol, scalar, len, iter, results, bnmode) run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, results, std::string(#puppet_master_func), bnmode)
+#define VOLK_PROFILE(func, tol, scalar, len, iter, results, bnmode, kernel_regex) run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, results, "NULL", bnmode, kernel_regex)
+#define VOLK_PUPPET_PROFILE(func, puppet_master_func, tol, scalar, len, iter, results, bnmode, kernel_regex) run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, results, std::string(#puppet_master_func), bnmode, kernel_regex)
typedef void (*volk_fn_1arg)(void *, unsigned int, const char*); //one input, operate in place
typedef void (*volk_fn_2arg)(void *, void *, unsigned int, const char*);
typedef void (*volk_fn_3arg)(void *, void *, void *, unsigned int, const char*);
diff --git a/volk/lib/volk_malloc.c b/volk/lib/volk_malloc.c
index 1333345800..65cb5eb8e9 100644
--- a/volk/lib/volk_malloc.c
+++ b/volk/lib/volk_malloc.c
@@ -111,7 +111,11 @@ volk_malloc(size_t size, size_t alignment)
// Find and return the first aligned boundary of the pointer
void *aptr = ptr;
if((unsigned long)ptr % alignment != 0)
+#ifdef _MSC_VER
+ aptr = (void*)((unsigned long)ptr + (alignment - ((unsigned long)ptr % alignment)));
+#else
aptr = ptr + (alignment - ((unsigned long)ptr % alignment));
+#endif
// Store original pointer and aligned pointers
mbuf *n = (mbuf*)malloc(sizeof(mbuf));
diff --git a/volk/python/volk_modtool/volk_modtool_generate.py b/volk/python/volk_modtool/volk_modtool_generate.py
index 80c2aed598..637d4892ae 100644
--- a/volk/python/volk_modtool/volk_modtool_generate.py
+++ b/volk/python/volk_modtool/volk_modtool_generate.py
@@ -20,6 +20,7 @@
#
import os
+import glob
import sys
import re
import glob
@@ -150,12 +151,24 @@ class volk_modtool:
newrelpath = re.sub(oldvolk, 'volk_' + self.my_dict['name'], relpath);
dest = os.path.join(self.my_dict['destination'], 'volk_' + self.my_dict['name'], os.path.dirname(newrelpath), newname);
-
-
if not os.path.exists(os.path.dirname(dest)):
os.makedirs(os.path.dirname(dest))
open(dest, 'w+').write(outstring);
+ # copy orc proto-kernels if they exist
+ for orcfile in glob.glob(inpath + '/orc/' + top + name + '*.orc'):
+ if os.path.isfile(orcfile):
+ instring = open(orcfile, 'r').read();
+ outstring = re.sub(oldvolk, 'volk_' + self.my_dict['name'], instring);
+ newname = 'volk_' + self.my_dict['name'] + '_' + name + '.orc';
+ relpath = os.path.relpath(orcfile, base);
+ newrelpath = re.sub(oldvolk, 'volk_' + self.my_dict['name'], relpath);
+ dest = os.path.join(self.my_dict['destination'], 'volk_' + self.my_dict['name'], os.path.dirname(newrelpath), newname);
+ if not os.path.exists(os.path.dirname(dest)):
+ os.makedirs(os.path.dirname(dest));
+ open(dest, 'w+').write(outstring)
+
+
def remove_kernel(self, name):
basename = self.my_dict['name'];
if len(basename) > 0:
@@ -215,6 +228,13 @@ class volk_modtool:
print "Removing kernel %s"%(kernel.pattern)
if os.path.exists(infile):
os.remove(infile);
+ # remove the orc proto-kernels if they exist. There are no puppets here
+ # so just need to glob for files matching kernel name
+ print glob.glob(inpath + '/orc/' + top + name + '*.orc');
+ for orcfile in glob.glob(inpath + '/orc/' + top + name + '*.orc'):
+ print orcfile
+ if(os.path.exists(orcfile)):
+ os.remove(orcfile);
def import_kernel(self, name, base):
if not (base):