Tuesday, July 1, 2014

Re: [Discuss-gnuradio] Simple block with constant rate

/* -*- c++ -*- */
/*
* Copyright 2014 <+YOU OR YOUR COMPANY+>.
*
* This 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.
*
* This software 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 software; 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 <gnuradio/io_signature.h>
#include "delay_cola_fff_impl.h"


Sample::Sample(float value,float next_value,float delay){
this->value=value;
this->next_value=next_value;
this->delay=delay;
this->current_delay=delay;
};


namespace gr {
namespace howto {
delay_cola_fff::sptr
delay_cola_fff::make()
{
return gnuradio::get_initial_sptr
(new delay_cola_fff_impl());
}

/*
* The private constructor
*/
delay_cola_fff_impl::delay_cola_fff_impl()
: gr::block("delay_cola_fff",
gr::io_signature::make(2,2, sizeof(float)),
gr::io_signature::make(1,1, sizeof(float)))
{
inicio=true;
sample_rate=5115000;
//sample_rate=32000;
}

/*
* Our virtual destructor.
*/
delay_cola_fff_impl::~delay_cola_fff_impl()
{
}

void
delay_cola_fff_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
{
ninput_items_required[0] = 1;
ninput_items_required[1] = 1;
}

int
delay_cola_fff_impl::general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const float *in_signal = (const float *) input_items[0];
const float *in_delay = (const float *) input_items[1];
float *out = (float*)output_items[0];

Sample *m;
float samples_deleted=0;

for(int i=0;i<noutput_items;++i){
//If it is the first sample
if(inicio==true){
q.push(new Sample(in_signal[i],-1,in_delay[i]));
//Send the sample
out[i]=in_signal[i];
inicio=false;
//Actually delay=input delay
delay=in_delay[i];
}
//If it is not the first sample
else{
/**** Update the end of the queue ***********/
//Last sample of the queue
m=q.back();
//Now next_value of the last sample in queue
//is the new sample value
m->next_value=in_signal[i];

/**** New sample in the queue ***************/
//If the current delay of the block control > signal delay
//-> Signal must be delayed in_delay[i]-delay samples
if(delay<in_delay[i]){
m=new Sample(in_signal[i],-1,in_delay[i]-delay);
delay=in_delay[i];
}
//If the current delay of the block control < signal delay
//-> Signal must be advanced in_delay[i]-delay samples
else if(delay>in_delay[i]){
//Nevative value of delay -> advancement
m=new Sample(in_signal[i],-1,in_delay[i]-delay);
delay=in_delay[i];
}
//No delay or advancement
else{
m=new Sample(in_signal[i],-1,0);
}
//Insert sample in queue
q.push(m);

/**** Update the front of the queue *********/
m=q.front();
//If there are not more samples to send (virtual samples)
//between current sample (first queue element) and next sample
if(m->current_delay==0){
//Delete the first sample
q.pop();
//Send the next sample
m=q.front();
out[i]=m->value;
}
//If there are more samples to send
else{
//Advancement
if(m->current_delay<0){
//Delete the samples for "forward" signal
for(int u=-(m->current_delay);u>0;--u){
q.pop();
m->current_delay=m->current_delay+1;
++samples_deleted;
}
}
//Delay
else{
//Linear interpolation.
//First point in the line:
//(0,m->next_value)
//Final point in the line:
//(m->delay/sample_rate,m->value)
//Position of virtual sample:
//(m->current_delay/rate,new_value)

//Slope
float slope = ( (m->value)-(m->next_value) ) / (m->delay/sample_rate);
//Y - Y_0 = m (X - X_0)
float new_value=( slope*((m->current_delay)/sample_rate)+m->next_value ); //y=pendiente*(x-x0)+y0;
//Envia el valor interpolado
out[i]=new_value;
m->current_delay=m->current_delay-1;
}
}
}
}


// Do <+signal processing+>
// Tell runtime system how many input items we consumed on
// each input stream.
consume_each (noutput_items-samples_deleted);

// Tell runtime system how many output items we produced.
return noutput_items-samples_deleted;
}
} /* namespace howto */
} /* namespace gr */


/* -*- c++ -*- */
/*
* Copyright 2014 <+YOU OR YOUR COMPANY+>.
*
* This 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.
*
* This software 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 software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/

#ifndef INCLUDED_HOWTO_DELAY_COLA_FFF_IMPL_H
#define INCLUDED_HOWTO_DELAY_COLA_FFF_IMPL_H

#include <howto/delay_cola_fff.h>
#include <queue>

class Sample{
public:
float value; //Sample value.
float next_value; //Next sample value.

float current_delay; //Current delay between this sample and the next.
float delay; //Delay between this sample and the next.

Sample(float value,float next_delay,float delay);
};

namespace gr {
namespace howto {
class delay_cola_fff_impl : public delay_cola_fff
{
private:
// Nothing to declare in this block.

public:

delay_cola_fff_impl();
~delay_cola_fff_impl();
std::queue<Sample*> q; //Queue with the samples
bool inicio; //If it is the first sample = true
int sample_rate;
float delay;


// Where all the action really happens
void forecast (int noutput_items, gr_vector_int &ninput_items_required);

int general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};
} // namespace howto
} // namespace gr

#endif /* INCLUDED_HOWTO_DELAY_COLA_FFF_IMPL_H */

Hi there,

I have modified my block. Now it works well for 10-15 seconds and then dies.
 
My block have two inputs:
- Signal
- Control delay: number of samples to delay
And one output:
- New signal
 
In the image example:
** Current delay = 0
 
---> Delay = 1
current_delay < delay ->delay of 1 sample
I insert a virtual sample (linear interpolation)
I sent the next sample (2)
current_delay = 1
 
---> Delay = 1
current_delay = delay -> nothing
I send the next sample (3)
current_delay = 1
 
 
 
---> Delay = 1
current_delay = delay -> nothing
I send the next sample (4)
current_delay = 1
 
 
---> Delay = 2
current_delay < delay -> delay of 1 sample (delay-current_delay)
I insert a virtual sample
I send the next sample (5)
current_delay = 2
 
 
---> Delay = 1
current_delay > delay ->ADVANCE 1 sample
I delete a sample (6)
I send the next sample (7)
current_delay = 1
 
Attach the code.
 
*** The value of control block is about 400000
 
 
Thank you ;)
 

No comments:

Post a Comment