summaryrefslogtreecommitdiffstats
path: root/host/examples
diff options
context:
space:
mode:
Diffstat (limited to 'host/examples')
-rw-r--r--host/examples/CMakeLists.txt2
-rw-r--r--host/examples/benchmark_rate.cpp236
-rw-r--r--host/examples/benchmark_rx_rate.cpp167
-rw-r--r--host/examples/tx_waveforms.cpp123
4 files changed, 301 insertions, 227 deletions
diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt
index fe9e6409e..10d1fddc3 100644
--- a/host/examples/CMakeLists.txt
+++ b/host/examples/CMakeLists.txt
@@ -19,7 +19,7 @@
# example applications
########################################################################
SET(example_sources
- benchmark_rx_rate.cpp
+ benchmark_rate.cpp
rx_multi_samples.cpp
rx_samples_to_file.cpp
rx_samples_to_udp.cpp
diff --git a/host/examples/benchmark_rate.cpp b/host/examples/benchmark_rate.cpp
new file mode 100644
index 000000000..6927b512b
--- /dev/null
+++ b/host/examples/benchmark_rate.cpp
@@ -0,0 +1,236 @@
+//
+// Copyright 2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/thread_priority.hpp>
+#include <uhd/utils/safe_main.hpp>
+#include <uhd/usrp/multi_usrp.hpp>
+#include <boost/program_options.hpp>
+#include <boost/format.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/math/special_functions/round.hpp>
+#include <iostream>
+#include <complex>
+
+namespace po = boost::program_options;
+
+unsigned long long num_overflows = 0;
+unsigned long long num_underflows = 0;
+unsigned long long num_rx_samps = 0;
+unsigned long long num_tx_samps = 0;
+unsigned long long num_dropped_samps = 0;
+
+/***********************************************************************
+ * Benchmark RX Rate
+ **********************************************************************/
+void benchmark_rx_rate(uhd::usrp::multi_usrp::sptr usrp){
+ uhd::set_thread_priority_safe();
+
+ //print pre-test summary
+ std::cout << boost::format(
+ "Testing receive rate %f Msps"
+ ) % (usrp->get_rx_rate()/1e6) << std::endl;
+
+ //setup variables and allocate buffer
+ uhd::rx_metadata_t md;
+ const size_t max_samps_per_packet = usrp->get_device()->get_max_recv_samps_per_packet();
+ std::vector<std::complex<float> > buff(max_samps_per_packet);
+ bool had_an_overflow = false;
+ uhd::time_spec_t last_time;
+ const double rate = usrp->get_rx_rate();
+
+ usrp->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
+ while (not boost::this_thread::interruption_requested()){
+ num_rx_samps += usrp->get_device()->recv(
+ &buff.front(), buff.size(), md,
+ uhd::io_type_t::COMPLEX_FLOAT32,
+ uhd::device::RECV_MODE_ONE_PACKET
+ );
+
+ //handle the error codes
+ switch(md.error_code){
+ case uhd::rx_metadata_t::ERROR_CODE_NONE:
+ if (had_an_overflow){
+ had_an_overflow = false;
+ num_dropped_samps += boost::math::iround((md.time_spec - last_time).get_real_secs()*rate);
+ }
+ break;
+
+ case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:
+ had_an_overflow = true;
+ last_time = md.time_spec;
+ num_overflows++;
+ break;
+
+ default:
+ std::cerr << "Error code: " << md.error_code << std::endl;
+ std::cerr << "Unexpected error on recv, exit test..." << std::endl;
+ goto loop_done;
+ }
+
+ } loop_done:
+ usrp->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
+}
+
+/***********************************************************************
+ * Benchmark TX Rate
+ **********************************************************************/
+void benchmark_tx_rate(uhd::usrp::multi_usrp::sptr usrp){
+ uhd::set_thread_priority_safe();
+
+ //print pre-test summary
+ std::cout << boost::format(
+ "Testing transmit rate %f Msps"
+ ) % (usrp->get_tx_rate()/1e6) << std::endl;
+
+ //setup variables and allocate buffer
+ uhd::tx_metadata_t md;
+ md.has_time_spec = false;
+ const size_t max_samps_per_packet = usrp->get_device()->get_max_send_samps_per_packet();
+ std::vector<std::complex<float> > buff(max_samps_per_packet);
+
+ while (not boost::this_thread::interruption_requested()){
+ num_tx_samps += usrp->get_device()->send(
+ &buff.front(), buff.size(), md,
+ uhd::io_type_t::COMPLEX_FLOAT32,
+ uhd::device::SEND_MODE_ONE_PACKET
+ );
+ }
+
+ //send a mini EOB packet
+ md.end_of_burst = true;
+ usrp->get_device()->send("", 0, md,
+ uhd::io_type_t::COMPLEX_FLOAT32,
+ uhd::device::SEND_MODE_FULL_BUFF
+ );
+}
+
+void benchmark_tx_rate_async_helper(uhd::usrp::multi_usrp::sptr usrp){
+ //setup variables and allocate buffer
+ uhd::async_metadata_t async_md;
+
+ while (true){
+
+ if (not usrp->get_device()->recv_async_msg(async_md)){
+ if (boost::this_thread::interruption_requested()) return;
+ }
+
+ //handle the error codes
+ switch(async_md.event_code){
+ case uhd::async_metadata_t::EVENT_CODE_BURST_ACK:
+ return;
+
+ case uhd::async_metadata_t::EVENT_CODE_UNDERFLOW:
+ case uhd::async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET:
+ num_underflows++;
+ break;
+
+ default:
+ std::cerr << "Event code: " << async_md.event_code << std::endl;
+ std::cerr << "Unexpected event on async recv, exit test..." << std::endl;
+ return;
+ }
+ }
+}
+
+/***********************************************************************
+ * Main code + dispatcher
+ **********************************************************************/
+int UHD_SAFE_MAIN(int argc, char *argv[]){
+
+ //variables to be set by po
+ std::string args;
+ double duration;
+ double rx_rate, tx_rate;
+
+ //setup the program options
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "help message")
+ ("args", po::value<std::string>(&args)->default_value(""), "single uhd device address args")
+ ("duration", po::value<double>(&duration)->default_value(10.0), "duration for the test in seconds")
+ ("rx_rate", po::value<double>(&rx_rate), "specify to perform a RX rate test (sps)")
+ ("tx_rate", po::value<double>(&tx_rate), "specify to perform a TX rate test (sps)")
+ ;
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ //print the help message
+ if (vm.count("help")){
+ std::cout << boost::format("UHD Benchmark Rate %s") % desc << std::endl;
+ std::cout <<
+ " Specify --rx_rate for a receive-only test.\n"
+ " Specify --tx_rate for a transmit-only test.\n"
+ " Specify both options for a full-duplex test.\n"
+ << std::endl;
+ return ~0;
+ }
+
+ //create a usrp device
+ std::cout << std::endl;
+ uhd::device_addrs_t device_addrs = uhd::device::find(args);
+ if (device_addrs.empty()){
+ std::cerr << "Could not find any devices for: " << args << std::endl;
+ return ~0;
+ }
+ if (device_addrs.at(0).get("type", "") == "usrp1"){
+ std::cerr << "*** Warning! ***" << std::endl;
+ std::cerr << "Benchmark results will be inaccurate on USRP1 due to insufficient features.\n" << std::endl;
+ }
+ std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;
+ uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(device_addrs.at(0));
+ std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl;
+
+ boost::thread_group thread_group;
+
+ //spawn the receive test thread
+ if (vm.count("rx_rate")){
+ usrp->set_rx_rate(rx_rate);
+ thread_group.create_thread(boost::bind(&benchmark_rx_rate, usrp));
+ }
+
+ //spawn the transmit test thread
+ if (vm.count("tx_rate")){
+ usrp->set_tx_rate(tx_rate);
+ thread_group.create_thread(boost::bind(&benchmark_tx_rate, usrp));
+ thread_group.create_thread(boost::bind(&benchmark_tx_rate_async_helper, usrp));
+ }
+
+ //sleep for the required duration
+ const long secs = long(duration);
+ const long usecs = long((duration - secs)*1e6);
+ boost::this_thread::sleep(boost::posix_time::seconds(secs) + boost::posix_time::microseconds(usecs));
+
+ //interrupt and join the threads
+ thread_group.interrupt_all();
+ thread_group.join_all();
+
+ //print summary
+ std::cout << std::endl << boost::format(
+ "Benchmark rate summary:\n"
+ " Num received samples: %u\n"
+ " Num dropped samples: %u\n"
+ " Num overflows detected: %u\n"
+ " Num transmitted samples: %u\n"
+ " Num underflows detected: %u\n"
+ ) % num_rx_samps % num_dropped_samps % num_overflows % num_tx_samps % num_underflows << std::endl;
+
+ //finished
+ std::cout << std::endl << "Done!" << std::endl << std::endl;
+
+ return 0;
+}
diff --git a/host/examples/benchmark_rx_rate.cpp b/host/examples/benchmark_rx_rate.cpp
deleted file mode 100644
index 50af1b98b..000000000
--- a/host/examples/benchmark_rx_rate.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-//
-// Copyright 2010-2011 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#include <uhd/utils/thread_priority.hpp>
-#include <uhd/utils/safe_main.hpp>
-#include <uhd/usrp/multi_usrp.hpp>
-#include <boost/math/special_functions/round.hpp>
-#include <boost/program_options.hpp>
-#include <boost/format.hpp>
-#include <iostream>
-#include <complex>
-
-namespace po = boost::program_options;
-
-static inline void test_device(
- uhd::usrp::multi_usrp::sptr usrp,
- double rx_rate_sps,
- double duration_secs
-){
- const size_t max_samps_per_packet = usrp->get_device()->get_max_recv_samps_per_packet();
- std::cout << boost::format("Testing receive rate %f Msps (%f second run)") % (rx_rate_sps/1e6) % duration_secs << std::endl;
-
- //allocate recv buffer and metatdata
- uhd::rx_metadata_t md;
- std::vector<std::complex<float> > buff(max_samps_per_packet);
-
- //flush the buffers in the recv path
- while(usrp->get_device()->recv(
- &buff.front(), buff.size(), md,
- uhd::io_type_t::COMPLEX_FLOAT32,
- uhd::device::RECV_MODE_ONE_PACKET
- )){
- /* NOP */
- };
-
- //declare status variables
- bool got_first_packet = false;
- size_t total_recv_packets = 0;
- size_t total_lost_samples = 0;
- size_t total_recv_samples = 0;
- uhd::time_spec_t initial_time_spec;
- uhd::time_spec_t next_expected_time_spec;
-
- usrp->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
- do {
- size_t num_rx_samps = usrp->get_device()->recv(
- &buff.front(), buff.size(), md,
- uhd::io_type_t::COMPLEX_FLOAT32,
- uhd::device::RECV_MODE_ONE_PACKET
- );
-
- //handle the error codes
- switch(md.error_code){
- case uhd::rx_metadata_t::ERROR_CODE_NONE:
- case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:
- break;
-
- default:
- std::cerr << "Error code: " << md.error_code << std::endl;
- std::cerr << "Unexpected error on recv, exit test..." << std::endl;
- return;
- }
-
- if (not md.has_time_spec){
- std::cerr << "Metadata missing time spec, exit test..." << std::endl;
- return;
- }
-
- total_recv_samples += num_rx_samps;
- total_recv_packets++;
-
- if (not got_first_packet){
- initial_time_spec = md.time_spec;
- next_expected_time_spec = initial_time_spec;
- got_first_packet = true;
- }
-
- double approx_lost_samps = rx_rate_sps*(md.time_spec - next_expected_time_spec).get_real_secs();
- total_lost_samples += std::max(0, boost::math::iround(approx_lost_samps));
- next_expected_time_spec = md.time_spec + uhd::time_spec_t(0, num_rx_samps, rx_rate_sps);
-
- } while((next_expected_time_spec - initial_time_spec) < uhd::time_spec_t(duration_secs));
- usrp->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
-
- //print a summary
- std::cout << std::endl; //go to newline, recv may spew SXSYSZ...
- std::cout << boost::format(" Received packets: %d") % total_recv_packets << std::endl;
- std::cout << boost::format(" Received samples: %d") % total_recv_samples << std::endl;
- std::cout << boost::format(" Lost samples: %d") % total_lost_samples << std::endl;
- size_t packets_lost = boost::math::iround(double(total_lost_samples)/max_samps_per_packet);
- std::cout << boost::format(" Lost packets: %d (approximate)") % packets_lost << std::endl;
- double actual_rx_rate_sps = (total_recv_samples*rx_rate_sps)/(total_recv_samples+total_lost_samples);
- std::cout << boost::format(" Sustained receive rate: %f Msps") % (actual_rx_rate_sps/1e6) << std::endl;
- std::cout << std::endl << std::endl;
-}
-
-int UHD_SAFE_MAIN(int argc, char *argv[]){
- uhd::set_thread_priority_safe();
-
- //variables to be set by po
- std::string args;
- double duration;
- double rate;
-
- //setup the program options
- po::options_description desc("Allowed options");
- desc.add_options()
- ("help", "help message")
- ("args", po::value<std::string>(&args)->default_value(""), "single uhd device address args")
- ("duration", po::value<double>(&duration)->default_value(10.0), "duration for each test in seconds")
- ("rate", po::value<double>(&rate), "specify to perform a single test as this rate (sps)")
- ;
- po::variables_map vm;
- po::store(po::parse_command_line(argc, argv, desc), vm);
- po::notify(vm);
-
- //print the help message
- if (vm.count("help")){
- std::cout << boost::format("UHD Benchmark RX Rate %s") % desc << std::endl;
- return ~0;
- }
-
- //verify that rate was specified
- if (not vm.count("rate")){
- std::cerr << "Please specify the sample rate with --rate" << std::endl;
- return ~0;
- }
-
- //create a usrp device
- std::cout << std::endl;
- uhd::device_addrs_t device_addrs = uhd::device::find(args);
- if (device_addrs.empty()){
- std::cerr << "Could not find any devices for: " << args << std::endl;
- return ~0;
- }
- if (device_addrs.at(0).get("type", "") == "usrp1"){
- std::cerr << "*** Warning! ***" << std::endl;
- std::cerr << "Benchmark RX results will be inaccurate on USRP1 due to soft-time control.\n" << std::endl;
- }
- std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;
- uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(device_addrs.at(0));
- std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl;
-
- //start the test
- usrp->set_rx_rate(rate);
- rate = usrp->get_rx_rate();
- test_device(usrp, rate, duration);
-
- //finished
- std::cout << std::endl << "Done!" << std::endl << std::endl;
-
- return 0;
-}
diff --git a/host/examples/tx_waveforms.cpp b/host/examples/tx_waveforms.cpp
index f150f520a..b78cc7d0a 100644
--- a/host/examples/tx_waveforms.cpp
+++ b/host/examples/tx_waveforms.cpp
@@ -23,7 +23,6 @@
#include <boost/math/special_functions/round.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
-#include <boost/function.hpp>
#include <iostream>
#include <complex>
#include <csignal>
@@ -31,36 +30,61 @@
namespace po = boost::program_options;
+/***********************************************************************
+ * Signal handlers
+ **********************************************************************/
static bool stop_signal_called = false;
void sig_int_handler(int){stop_signal_called = true;}
/***********************************************************************
* Waveform generators
**********************************************************************/
-float gen_const(float){
- return 1;
-}
-
-float gen_square(float x){
- return float((std::fmod(x, 1) < float(0.5))? 0 : 1);
-}
+static const size_t wave_table_len = 8192;
+
+class wave_table_class{
+public:
+ wave_table_class(const std::string &wave_type, const float ampl):
+ _wave_table(wave_table_len)
+ {
+ //compute real wave table with 1.0 amplitude
+ std::vector<double> real_wave_table(wave_table_len);
+ if (wave_type == "CONST"){
+ for (size_t i = 0; i < wave_table_len; i++)
+ real_wave_table[i] = 1.0;
+ }
+ else if (wave_type == "SQUARE"){
+ for (size_t i = 0; i < wave_table_len; i++)
+ real_wave_table[i] = (i < wave_table_len/2)? 0.0 : 1.0;
+ }
+ else if (wave_type == "RAMP"){
+ for (size_t i = 0; i < wave_table_len; i++)
+ real_wave_table[i] = 2.0*i/(wave_table_len-1) - 1.0;
+ }
+ else if (wave_type == "SINE"){
+ static const double tau = 2*std::acos(-1.0);
+ for (size_t i = 0; i < wave_table_len; i++)
+ real_wave_table[i] = std::sin((tau*i)/wave_table_len);
+ }
+ else throw std::runtime_error("unknown waveform type: " + wave_type);
-float gen_ramp(float x){
- return std::fmod(x, 1)*2 - 1;
-}
+ //compute i and q pairs with 90% offset and scale to amplitude
+ for (size_t i = 0; i < wave_table_len; i++){
+ const size_t q = (i+(3*wave_table_len)/4)%wave_table_len;
+ _wave_table[i] = std::complex<float>(ampl*real_wave_table[i], ampl*real_wave_table[q]);
+ }
+ }
-#define sine_table_len 2048
-static float sine_table[sine_table_len];
-UHD_STATIC_BLOCK(gen_sine_table){
- static const double tau = 2*std::acos(-1.0);
- for (size_t i = 0; i < sine_table_len; i++)
- sine_table[i] = float(std::sin((tau*i)/sine_table_len));
-}
+ inline std::complex<float> operator()(const double theta) const{
+ return _wave_table[unsigned(boost::math::iround(theta*wave_table_len))%wave_table_len];
+ }
-float gen_sine(float x){
- return sine_table[size_t(x*sine_table_len)%sine_table_len];
-}
+private:
+ std::vector<std::complex<float> > _wave_table;
+};
+/***********************************************************************
+ * Main function
+ **********************************************************************/
int UHD_SAFE_MAIN(int argc, char *argv[]){
uhd::set_thread_priority_safe();
@@ -144,9 +168,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
if (vm.count("ant")) usrp->set_tx_antenna(ant, chan);
}
- std::cout << boost::format("Setting device timestamp to 0...") << std::endl;
- usrp->set_time_now(uhd::time_spec_t(0.0));
-
//for the const wave, set the wave freq for small samples per period
if (wave_freq == 0 and wave_type == "CONST"){
wave_freq = usrp->get_tx_rate()/2;
@@ -156,49 +177,37 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
if (std::abs(wave_freq) > usrp->get_tx_rate()/2){
throw std::runtime_error("wave freq out of Nyquist zone");
}
- if (usrp->get_tx_rate()/std::abs(wave_freq) > sine_table_len/2 and wave_type == "SINE"){
- throw std::runtime_error("sine freq too small for table");
+ if (usrp->get_tx_rate()/std::abs(wave_freq) > wave_table_len/2){
+ throw std::runtime_error("wave freq too small for table");
}
- //store the generator function for the selected waveform
- boost::function<float(float)> wave_gen;
- if (wave_type == "CONST") wave_gen = &gen_const;
- else if (wave_type == "SQUARE") wave_gen = &gen_square;
- else if (wave_type == "RAMP") wave_gen = &gen_ramp;
- else if (wave_type == "SINE") wave_gen = &gen_sine;
- else throw std::runtime_error("unknown waveform type: " + wave_type);
+ //pre-compute the waveform values
+ const wave_table_class wave_table(wave_type, ampl);
+ const double cps = wave_freq/usrp->get_tx_rate();
+ double theta = 0;
- //allocate the buffer and precalculate values
- const float cps = float(wave_freq/usrp->get_tx_rate());
- const float i_off = (wave_freq > 0)? float(0.25) : 0;
- const float q_off = (wave_freq < 0)? float(0.25) : 0;
- float theta = 0;
-
- std::vector<std::complex<float> *> buffs;
- for(size_t i=0; i < usrp->get_num_mboards(); i++)
- buffs.push_back(new std::complex<float>[spb]);
+ //allocate a buffer which we re-use for each channel
+ std::vector<std::complex<float> > buff(spb);
+ std::vector<std::complex<float> *> buffs(usrp->get_tx_num_channels(), &buff.front());
//setup the metadata flags
uhd::tx_metadata_t md;
- md.start_of_burst = false; //no for continuous streaming
+ md.start_of_burst = true;
md.end_of_burst = false;
- md.has_time_spec = true;
+ md.has_time_spec = true;
md.time_spec = uhd::time_spec_t(0.1);
+ std::cout << boost::format("Setting device timestamp to 0...") << std::endl;
+ usrp->set_time_now(uhd::time_spec_t(0.0));
+
std::signal(SIGINT, &sig_int_handler);
std::cout << "Press Ctrl + C to stop streaming..." << std::endl;
//send data until the signal handler gets called
while(not stop_signal_called){
//fill the buffer with the waveform
- for (size_t n = 0; n < spb; n++){
- BOOST_FOREACH(std::complex<float> *buff, buffs) {
- buff[n] = std::complex<float>(
- ampl*wave_gen(i_off + theta),
- ampl*wave_gen(q_off + theta)
- );
- }
- theta += cps;
+ for (size_t n = 0; n < buff.size(); n++){
+ buff[n] = wave_table(theta += cps);
}
//bring the theta back into range [0, 1)
@@ -206,16 +215,17 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//send the entire contents of the buffer
usrp->get_device()->send(
- buffs, spb, md,
+ buffs, buff.size(), md,
uhd::io_type_t::COMPLEX_FLOAT32,
uhd::device::SEND_MODE_FULL_BUFF
);
+ md.start_of_burst = false;
md.has_time_spec = false;
}
//send a mini EOB packet
- md.end_of_burst = true;
+ md.end_of_burst = true;
usrp->get_device()->send("", 0, md,
uhd::io_type_t::COMPLEX_FLOAT32,
uhd::device::SEND_MODE_FULL_BUFF
@@ -223,10 +233,5 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//finished
std::cout << std::endl << "Done!" << std::endl << std::endl;
-
- BOOST_FOREACH(std::complex<float> *buff, buffs){
- delete buff;
- }
-
return 0;
}