> > > On Sat, Mar 28, 2009 at 9:27 AM, Karthik <karthik1...@gmail.com> wrote: > >> 2009/3/27 Mikhail Tadjikov <mtadji...@ucla.edu> >> >> Hello, >>> >>> I'm trying to build several signal processing blocks for a project that >>> I'm doing using USRP2. I was going through the examples and sample code >>> along with browsing the source code and I can't seem to find exactly what I >>> need. I'm trying to do an average of a vector of length N: >>> >>> Input vector size N >>> Output vector size 1 >>> I'm doing it for floats. >>> >>> ------------------------------ >>> #ifndef INCLUDED_CORES_WEIGHTED_AVG_FF_H >>> #define INCLUDED_CORES_WEIGHTED_AVG_FF_H >>> #include <gr_sync_block.h> >>> class cores_weighted_avg_ff; >>> >>> typedef boost::shared_ptr<cores_weighted_avg_ff> >>> cores_weighted_avg_ff_sptr; >>> cores_weighted_avg_ff_sptr cores_make_weighted_avg_ff (unsigned int >>> vlen); >>> >>> class cores_weighted_avg_ff : public gr_sync_block >>> { >>> private: >>> friend cores_weighted_avg_ff_sptr cores_make_weighted_avg_ff (unsigned >>> int vlen); >>> cores_weighted_avg_ff (unsigned int vlen); // private constructor >>> unsigned int d_vlen; >>> >>> public: >>> int general_work (int noutput_items, >>> gr_vector_int &ninput_items, >>> gr_vector_const_void_star &input_items, >>> gr_vector_void_star &output_items); >>> }; >>> #endif >>> >>> ---------------------------------------------------------------------------------------------------------- >>> and source >>> >>> ------------------------------------------------------------------------------------------- >>> #ifdef HAVE_CONFIG_H >>> #include "config.h" >>> #endif >>> #include <cores_weighted_avg_ff.h> >>> #include <gr_io_signature.h> >>> >>> cores_weighted_avg_ff_sptr >>> cores_make_weighted_avg_ff (unsigned int vlen) >>> { return cores_weighted_avg_ff_sptr (new cores_weighted_avg_ff (vlen));} >>> >>> cores_weighted_avg_ff::cores_weighted_avg_ff (unsigned int vlen) >>> : gr_decimator_block ("weighed_avg_ff", >>> gr_make_io_signature (1, 1, sizeof (float) * vlen), >>> gr_make_io_signature (1, 1, sizeof (float))), >>> d_vlen(vlen) >>> { >>> } >>> int >>> cores_weighted_avg_ff::int general_work (int noutput_items, >>> gr_vector_int &ninput_items, >>> gr_vector_const_void_star &input_items, >>> gr_vector_void_star &output_items); >>> { >>> const float *in = (const float *) input_items[0]; >>> float *out = (float *) output_items[0]; >>> int noi = noutput_items * d_vlen; >>> >>> for (int i = 0; i < noi; i++){ >>> out += in[i]*i; >>> } >>> out /= d_vlen; >>> consume(noutput_items,d_vlen) >>> >>> return noutput_items; >>> } >>> >>> ------------------------------------------------------------------------------------------------ >>> >>> I'm not sure if the code is correct what I want to do (input is more than >>> welcome), when I compile this code I get a weird error: >>> cores_weighted_avg_ff.h: In function ‘PyObject* >>> _wrap_weighted_avg_ff(PyObject*, PyObject*)’: >>> cores_weighted_avg_ff.h:63: error: too few arguments to function >>> ‘cores_weighted_avg_ff_sptr cores_make_weighted_avg_ff(unsigned int)’ >>> cores.cc:4326: error: at this point in file >>> make[4]: *** [cores.lo] Error 1 >>> >>> Any help would be greatly appreciated. >> >> >> With gr_sync_block you only need to write work() and not general_work(). >> The example at the end of this tutorial will be helpful >> http://www.gnu.org/software/gnuradio/doc/howto-write-a-block.html. Also, >> there is a "#endif" sitting in the middle of your code, it might be a typo. >> >> btw, if you are trying to get moving averages, there is a block already >> available gr_moving_averages() >> >> Karthik >> >> >> > Thanks, but I'm trying to get weighted average specifically. I've looked at > the code for moving_average... it's close to what I need, but its 1:1 in/out > ratio, but I need N:1 ratio. That's the part I'm particular unclear about. >
I have done something very similar in the past. I derive my block from gr_sync_decimator to keep things simple. The value of 'N' is an input to the block and is assumed to be constant. In the myblock_ff.h file define a std::vector<float> d_buffer. in the myblock_ff.cc you will have a line such as myblock_ff::myblock_ff(int N) : gr_sync_decimator("myblock",gr_io_sig...,gr_io_sig...,N) Here, N sets the decimation factor. In the work() function, you loop over all inputs and keep stuffing your inputs into d_buffer, using d_buffer.push_back(). Once the length reaches N, you do your average or other calculations, write an output and do d_buffer.clear(). This will work even if your number of inputs is not a multiple of N since your buffer will continue filling up from where you left the next time the work() function is called. I have attached the source from my code, but it has a lot going on in there and isn't really commented. Line #152 in the .cc file does exactly what you want to do, although in a different context. Hope this helps. Karthik
#ifdef HAVE_CONFIG_H #include "config.h" #endif #include <afm_fft2_ff.h> #include <gr_io_signature.h> #include <math.h> #ifndef min #define min(X,Y) ((X) < (Y) ? : (X) , (Y)) #endif #ifndef max #define max(X,Y) ((X) > (Y) ? : (X) , (Y)) #endif afm_fft2_ff_sptr afm_make_fft2_ff(int nfft, int naverages, float sampling_freq, float fundamental_freq, const std::vector<float> &freqs,const std::vector<float> &window) { return afm_fft2_ff_sptr (new afm_fft2_ff(nfft,naverages,sampling_freq,fundamental_freq,freqs,window)); } afm_fft2_ff::afm_fft2_ff(int nfft, int naverages, float sampling_freq, float fundamental_freq, const std::vector<float> &freqs, const std::vector<float> &window) : gr_sync_decimator("fft2_ff", gr_make_io_signature(3, 3, sizeof(float)), gr_make_io_signature(1, 1, sizeof(float)), (int) ceil(naverages*sampling_freq/(fundamental_freq*(2+freqs.size() ))) ) { d_nfft = nfft; d_fft_input = (double *) malloc(sizeof(double)*nfft); d_fft_out = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * (nfft/2 +1)); d_plan = fftw_plan_dft_r2c_1d(nfft,d_fft_input, d_fft_out,FFTW_MEASURE); d_naverages = naverages; d_window = window; d_freqs = freqs; DPRINTF(("Freq vector size = %d\n", d_freqs.size())); d_sampling_freq = sampling_freq; d_fundamental_freq = fundamental_freq; d_bufferlen = (int) ceil(naverages*sampling_freq/fundamental_freq); d_buffer.reserve(d_bufferlen); d_buffer.clear(); d_runonce = false; set_output_multiple((2+freqs.size())); //X,Y,freqs unsigned int i, index; for (i=0;i<d_freqs.size();i++){ index = (int)round(d_freqs[i]*d_nfft/d_sampling_freq); DPRINTF(("Index for frequency%d = %d\n",i,index)); try { if (index > d_nfft/2) throw "Frequency must be less that 1/2 Sampling Frequency"; } catch( char * str ) { printf("Exception raised: %s\n",str); exit(1); } d_freqs_index.push_back(index); } try { if(window.size() != nfft) throw "Window size and nfft should be the same"; } catch( char * str) { printf("Exception raised: %s\n",str); exit(1); } if( d_bufferlen > nfft) printf("\nWarning: Buffer length = %d, FFT length = %d. Signal will be truncated",d_bufferlen,nfft); } afm_fft2_ff::~afm_fft2_ff() { fftw_destroy_plan(d_plan); fftw_free(d_fft_out); free(d_fft_input); } int afm_fft2_ff:: work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { /* chan[0] is signal * chan[1] X imaging signal * chan[2] Y imaging signal */ int i, j, noutput_samples = 0; const float * chan[3]; float ** out = (float **) &output_items[0]; for(i=0;i<3;i++) chan[i] = (const float *) input_items[i]; if (d_runonce) { d_upordown = (chan[2][0] > 0) ? AFM_UP : AFM_DOWN; d_leftorright = (chan[1][0] > 0) ? AFM_LEFT : AFM_RIGHT; d_runonce = true; } for(i=0;i< noutput_items/(2+d_freqs.size());i++) { //stuff the buffer for(j=0;j<d_bufferlen;j++) d_buffer.push_back(chan[0][i*d_bufferlen + j]); //X imaging voltage if(d_leftorright == AFM_LEFT) { if (chan[1][i*d_bufferlen] < 0) d_leftorright = AFM_RIGHT; } else { if (chan[1][i*d_bufferlen] > 0.02) d_leftorright = AFM_LEFT; } out[0][noutput_samples] = (d_leftorright == AFM_LEFT) ? 1.0 : -1.0; noutput_samples++; //Y imaging voltage if(d_upordown == AFM_UP) { if (chan[2][i*d_bufferlen] < 0) d_upordown = AFM_DOWN; } else { if (chan[2][i*d_bufferlen] > 0.05) d_upordown = AFM_UP; } out[0][noutput_samples] = (d_upordown == AFM_DOWN) ? 1.0 : -1.0; noutput_samples++; noutput_samples = compute_params(out,noutput_samples); d_buffer.clear(); } DPRINTF(("Outputs requested: %d, Output produced: %d, Input consumption(expected): %d, Input consumption(actual): %d\n",noutput_items,noutput_samples, (int) ceil(d_naverages*d_sampling_freq/(d_fundamental_freq*(2+d_freqs.size()))) * noutput_samples, noutput_items*d_bufferlen/(2+d_freqs.size()) )); return noutput_samples; } int afm_fft2_ff:: compute_params(float ** out,int noutput_samples) { unsigned int i,index; float temp; if (d_bufferlen < d_nfft) { for (i=0;i<d_bufferlen;i++) d_fft_input[i] = (double) (d_buffer[i]*d_window[i]); for (;i<d_nfft;i++) d_fft_input[i] = 0; //zero-pad } else { for (i=0;i<d_nfft;i++) d_fft_input[i] = (double) (d_buffer[i]*d_window[i]); //truncate after d_nfft } fftw_execute(d_plan); for(i=0;i<d_freqs.size();i++) { index = d_freqs_index[i]; temp = (float) sqrt(d_fft_out[index][0]*d_fft_out[index][0] + d_fft_out[index][1]*d_fft_out[index][1]); out[0][noutput_samples] = temp; noutput_samples++; } return noutput_samples; }
#ifndef INCLUDED_AFM_FFT2_FF_H #define INCLUDED_AFM_FFT2_FF_H #include <gr_sync_decimator.h> #include "afm_trig_type.h" #include <vector> #include <complex.h> #include <fftw3.h> #define SILENT #ifdef SILENT #define DPRINTF(X) #else #define DPRINTF(X) printf X #endif class afm_fft2_ff; typedef boost::shared_ptr<afm_fft2_ff> afm_fft2_ff_sptr; afm_fft2_ff_sptr afm_make_fft2_ff(int nfft, int naverages, float sampling_freq, float fundamental_freq, const std::vector<float> &freqs,const std::vector<float> &window); class afm_fft2_ff : public gr_sync_decimator { private: friend afm_fft2_ff_sptr afm_make_fft2_ff(int nfft, int naverages, float sampling_freq, float fundamental_freq, const std::vector<float> &freqs,const std::vector<float> &window); afm_fft2_ff(int nfft, int naverages, float sampling_freq, float fundamental_freq, const std::vector<float> &freqs,const std::vector<float> &window); std::vector<float> d_buffer; int d_nfft; int d_naverages; double * d_fft_input; std::vector<float> d_window; std::vector<float> d_freqs; std::vector<int> d_freqs_index; float d_sampling_freq; float d_fundamental_freq; int d_bufferlen; fftw_complex *d_fft_out; fftw_plan d_plan; afm_direction_t d_upordown; afm_direction_t d_leftorright; bool d_runonce; public: ~afm_fft2_ff(); int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); int compute_params(float ** out,int noutput_samples); }; #endif /* INCLUDED_AFM_FFT2_FF_H */
_______________________________________________ Discuss-gnuradio mailing list Discuss-gnuradio@gnu.org http://lists.gnu.org/mailman/listinfo/discuss-gnuradio