pulse_shape.h
Go to the documentation of this file.
#ifndef PULSE_SHAPE_H
#define PULSE_SHAPE_H
#include <itpp/base/vec.h>
#include <itpp/base/matfunc.h>
#include <itpp/base/math/trig_hyp.h>
#include <itpp/signal/filter.h>
#include <itpp/signal/resampling.h>
namespace itpp
{
template<class T1, class T2, class T3>
class Pulse_Shape
{
public:
Pulse_Shape();
Pulse_Shape(const Vec<T2> &impulse_response, int upsampling_factor);
virtual ~Pulse_Shape() {}
void set_pulse_shape(const Vec<T2> &impulse_response, int upsampling_factor);
Vec<T2> get_pulse_shape(void) const;
int get_upsampling_factor() const;
int get_pulse_length() const;
int get_filter_length() const;
void shape_symbols(const Vec<T1> &input, Vec<T3> &output);
Vec<T3> shape_symbols(const Vec<T1> &input);
void shape_samples(const Vec<T1> &input, Vec<T3> &output);
Vec<T3> shape_samples(const Vec<T1> &input);
void clear(void);
protected:
Vec<T2> impulse_response;
MA_Filter<T1, T2, T3> shaping_filter;
int pulse_length;
int upsampling_factor;
bool setup_done;
};
template<class T1>
class Raised_Cosine : public Pulse_Shape<T1, double, T1>
{
public:
Raised_Cosine() {}
Raised_Cosine(double roll_off, int filter_length = 6, int upsampling_factor = 8);
virtual ~Raised_Cosine() {}
void set_pulse_shape(double roll_off_factor, int filter_length = 6, int upsampling_factor = 8);
double get_roll_off(void) const;
protected:
double roll_off_factor;
};
template<class T1>
class Root_Raised_Cosine : public Pulse_Shape<T1, double, T1>
{
public:
Root_Raised_Cosine() {}
Root_Raised_Cosine(double roll_off_factor, int filter_length = 6, int upsampling_factor = 8);
virtual ~Root_Raised_Cosine() {}
void set_pulse_shape(double roll_off_factor, int filter_length = 6, int upsampling_factor = 8);
double get_roll_off(void) const;
protected:
double roll_off_factor;
};
//-------------------------------------------------------------------------
// Implementation of templated code starts here
//-------------------------------------------------------------------------
//---------------------------- Pulse_Shape --------------------------------
template<class T1, class T2, class T3>
Pulse_Shape<T1, T2, T3>::Pulse_Shape()
{
setup_done = false;
pulse_length = 0;
upsampling_factor = 0;
}
template<class T1, class T2, class T3>
Pulse_Shape<T1, T2, T3>::Pulse_Shape(const Vec<T2> &impulse_response, int upsampling_factor)
{
set_pulse_shape(impulse_response, upsampling_factor);
}
template<class T1, class T2, class T3>
void Pulse_Shape<T1, T2, T3>::set_pulse_shape(const Vec<T2> &impulse_response_in, int upsampling_factor_in)
{
it_error_if(impulse_response_in.size() == 0, "Pulse_Shape: impulse response is zero length");
it_error_if(upsampling_factor_in < 1, "Pulse_Shape: incorrect upsampling factor");
pulse_length = (impulse_response_in.size() - 1) / upsampling_factor_in;
upsampling_factor = upsampling_factor_in;
impulse_response = impulse_response_in;
shaping_filter.set_coeffs(impulse_response);
shaping_filter.clear();
setup_done = true;
}
template<class T1, class T2, class T3>
Vec<T2> Pulse_Shape<T1, T2, T3>::get_pulse_shape(void) const
{
return impulse_response;
}
template<class T1, class T2, class T3>
int Pulse_Shape<T1, T2, T3>::get_upsampling_factor(void) const
{
return upsampling_factor;
}
template<class T1, class T2, class T3>
int Pulse_Shape<T1, T2, T3>::get_pulse_length(void) const
{
return pulse_length;
}
template<class T1, class T2, class T3>
int Pulse_Shape<T1, T2, T3>::get_filter_length(void) const
{
return impulse_response.size();
}
template<class T1, class T2, class T3>
void Pulse_Shape<T1, T2, T3>::shape_symbols(const Vec<T1>& input, Vec<T3> &output)
{
it_assert(setup_done, "Pulse_Shape must be set up before using");
it_error_if(pulse_length == 0, "Pulse_Shape: impulse response is zero length");
it_error_if(input.size() == 0, "Pulse_Shape: input is zero length");
if (upsampling_factor > 1)
output = shaping_filter(upsample(input, upsampling_factor));
else
output = input;
}
template<class T1, class T2, class T3>
Vec<T3> Pulse_Shape<T1, T2, T3>::shape_symbols(const Vec<T1>& input)
{
it_assert(setup_done, "Pulse_Shape must be set up before using");
Vec<T3> temp;
shape_symbols(input, temp);
return temp;
}
template<class T1, class T2, class T3>
void Pulse_Shape<T1, T2, T3>::shape_samples(const Vec<T1>& input, Vec<T3> &output)
{
it_assert(setup_done, "Pulse_Shape must be set up before using");
it_error_if(pulse_length == 0, "Pulse_Shape: impulse response is zero length");
it_error_if(input.size() == 0, "Pulse_Shape: input is zero length");
if (upsampling_factor > 1)
output = shaping_filter(input);
else
output = input;
}
template<class T1, class T2, class T3>
Vec<T3> Pulse_Shape<T1, T2, T3>::shape_samples(const Vec<T1>& input)
{
it_assert(setup_done, "Pulse_Shape must be set up before using");
Vec<T3> temp;
shape_samples(input, temp);
return temp;
}
template<class T1, class T2, class T3>
void Pulse_Shape<T1, T2, T3>::clear(void)
{
it_assert(setup_done, "Pulse_Shape must be set up before using");
shaping_filter.clear();
}
//-------------------- Raised_Cosine -----------------------------------
template<class T1>
Raised_Cosine<T1>::Raised_Cosine(double roll_off_factor, int filter_length, int upsampling_factor)
{
set_pulse_shape(roll_off_factor, filter_length, upsampling_factor);
}
template<class T1>
void Raised_Cosine<T1>::set_pulse_shape(double roll_off_factor_in, int filter_length, int upsampling_factor_in)
{
it_error_if(roll_off_factor_in < 0 || roll_off_factor_in > 1, "Raised_Cosine: roll-off out of range");
roll_off_factor = roll_off_factor_in;
it_assert(is_even(filter_length), "Raised_Cosine: Filter length not even");
int i;
double t, den;
this->upsampling_factor = upsampling_factor_in;
this->pulse_length = filter_length;
this->impulse_response.set_size(filter_length * upsampling_factor_in + 1,
false);
for (i = 0; i < this->impulse_response.size(); i++) {
// delayed to be casual
t = (double)(i - filter_length * upsampling_factor_in / 2)
/ upsampling_factor_in;
den = 1 - sqr(2 * roll_off_factor * t);
if (den == 0) {
// exception according to "The Care and feeding of digital,
// pulse-shaping filters" by Ken Gentile,
// the limit of raised cosine impulse responce function,
// as (alpha * t / tau) approaches (+- 0.5) is given as:
this->impulse_response(i) = sinc(t) * pi / 4;
}
else {
this->impulse_response(i) = std::cos(roll_off_factor * pi * t)
* sinc(t) / den;
}
}
// BUGFIX: Commented out to achieve similar results to Matlab
// rcosfil function. Now the concatenation of two root-raised
// cosine filters gives tha same results as a one raised cosine
// shaping function.
// this->impulse_response /= std::sqrt(double(this->upsampling_factor));
this->shaping_filter.set_coeffs(this->impulse_response);
this->shaping_filter.clear();
this->setup_done = true;
}
template<class T1>
double Raised_Cosine<T1>::get_roll_off(void) const
{
it_assert(this->setup_done, "Pulse_Shape must be set up before using");
return roll_off_factor;
}
//-------------------- Root_Raised_Cosine -----------------------------------
template<class T1>
Root_Raised_Cosine<T1>::Root_Raised_Cosine(double roll_off_factor, int filter_length, int upsampling_factor)
{
set_pulse_shape(roll_off_factor, filter_length, upsampling_factor);
}
template<class T1>
void Root_Raised_Cosine<T1>::set_pulse_shape(double roll_off_factor_in, int filter_length, int upsampling_factor_in)
{
it_error_if(roll_off_factor_in <= 0 || roll_off_factor_in > 1,
"Root_Raised_Cosine: roll-off out of range");
roll_off_factor = roll_off_factor_in;
it_assert(is_even(filter_length),
"Root_Raised_Cosine: Filter length not even");
int i;
double t, num, den, tmp_arg;
this->upsampling_factor = upsampling_factor_in;
this->pulse_length = filter_length;
this->impulse_response.set_size(filter_length * upsampling_factor_in + 1,
false);
for (i = 0; i < this->impulse_response.size(); i++) {
// delayed to be casual
t = (double)(i - filter_length * upsampling_factor_in / 2)
/ upsampling_factor_in;
den = 1 - sqr(4 * roll_off_factor * t);
if (t == 0) {
this->impulse_response(i) = 1 + (4 * roll_off_factor / pi)
- roll_off_factor;
}
else if (den == 0) {
tmp_arg = pi / (4 * roll_off_factor);
this->impulse_response(i) = roll_off_factor / std::sqrt(2.0)
* ((1 + 2 / pi) * std::sin(tmp_arg) + (1 - 2 / pi) * std::cos(tmp_arg));
}
else {
num = std::sin(pi * (1 - roll_off_factor) * t)
+ std::cos(pi * (1 + roll_off_factor) * t) * 4 * roll_off_factor * t;
this->impulse_response(i) = num / (pi * t * den);
}
}
this->impulse_response /= std::sqrt(double(upsampling_factor_in));
this->shaping_filter.set_coeffs(this->impulse_response);
this->shaping_filter.clear();
this->setup_done = true;
}
template<class T1>
double Root_Raised_Cosine<T1>::get_roll_off(void) const
{
it_assert(this->setup_done, "Pulse_Shape must be set up before using");
return roll_off_factor;
}
// ----------------------------------------------------------------------
// Instantiations
// ----------------------------------------------------------------------
ITPP_EXPORT_TEMPLATE template class ITPP_EXPORT Pulse_Shape<double, double, double>;
ITPP_EXPORT_TEMPLATE template class ITPP_EXPORT Pulse_Shape < std::complex<double>, double,
std::complex<double> >;
ITPP_EXPORT_TEMPLATE template class ITPP_EXPORT Pulse_Shape < std::complex<double>, std::complex<double>,
std::complex<double> >;
ITPP_EXPORT_TEMPLATE template class ITPP_EXPORT Root_Raised_Cosine<double>;
ITPP_EXPORT_TEMPLATE template class ITPP_EXPORT Root_Raised_Cosine<std::complex<double> >;
ITPP_EXPORT_TEMPLATE template class ITPP_EXPORT Raised_Cosine<double>;
ITPP_EXPORT_TEMPLATE template class ITPP_EXPORT Raised_Cosine<std::complex<double> >;
} // namespace itpp
#endif // #ifndef PULSE_SHAPE_H
itpp::Array
General array class.
Definition array.h:105
itpp::Array::size
int size() const
Returns the number of data elements in the array object.
Definition array.h:155
itpp::Array::set_size
void set_size(int n, bool copy=false)
Resizing an Array<T>.
Definition array.h:257
itpp::Pulse_Shape
General FIR Pulse Shape.
Definition pulse_shape.h:74
itpp::Pulse_Shape::shape_samples
Vec< T3 > shape_samples(const Vec< T1 > &input)
Shape the input symbols already upsampled.
Definition pulse_shape.h:341
itpp::Pulse_Shape::get_pulse_shape
Vec< T2 > get_pulse_shape(void) const
Get the pulse shape.
Definition pulse_shape.h:282
itpp::Pulse_Shape::set_pulse_shape
void set_pulse_shape(const Vec< T2 > &impulse_response, int upsampling_factor)
Set the general impulse response of the FIR filter.
Definition pulse_shape.h:267
itpp::Pulse_Shape::upsampling_factor
int upsampling_factor
Samples per input symbol.
Definition pulse_shape.h:120
itpp::Pulse_Shape::shape_samples
void shape_samples(const Vec< T1 > &input, Vec< T3 > &output)
Shape the input samples already upsampled.
Definition pulse_shape.h:328
itpp::Pulse_Shape::Pulse_Shape
Pulse_Shape()
Constructor.
Definition pulse_shape.h:252
itpp::Pulse_Shape::get_filter_length
int get_filter_length() const
Get the length of the internal FIR filter.
Definition pulse_shape.h:300
itpp::Pulse_Shape::get_upsampling_factor
int get_upsampling_factor() const
Get the over sampling factor.
Definition pulse_shape.h:288
itpp::Pulse_Shape::shape_symbols
void shape_symbols(const Vec< T1 > &input, Vec< T3 > &output)
Shape the input symbols performing upsampling.
Definition pulse_shape.h:306
itpp::Pulse_Shape::shaping_filter
MA_Filter< T1, T2, T3 > shaping_filter
The pulse shaping filter.
Definition pulse_shape.h:116
itpp::Pulse_Shape::get_pulse_length
int get_pulse_length() const
Get the length of the pulse in number of symbols.
Definition pulse_shape.h:294
itpp::Pulse_Shape::~Pulse_Shape
virtual ~Pulse_Shape()
Destructor.
Definition pulse_shape.h:81
itpp::Pulse_Shape::Pulse_Shape
Pulse_Shape(const Vec< T2 > &impulse_response, int upsampling_factor)
Constructor.
Definition pulse_shape.h:261
itpp::Pulse_Shape::pulse_length
int pulse_length
Length in symbols.
Definition pulse_shape.h:118
itpp::Pulse_Shape::impulse_response
Vec< T2 > impulse_response
The impulse resounse of the pulse shaping filter.
Definition pulse_shape.h:114
itpp::Pulse_Shape::shape_symbols
Vec< T3 > shape_symbols(const Vec< T1 > &input)
Shape the input symbols performing upsampling.
Definition pulse_shape.h:319
itpp::Pulse_Shape::setup_done
bool setup_done
Ensures that setup is called before any other member function.
Definition pulse_shape.h:122
itpp::Pulse_Shape::clear
void clear(void)
Clear internal states.
Definition pulse_shape.h:350
itpp::Raised_Cosine
Raised Cosine (RC) Pulse Shaper.
Definition pulse_shape.h:163
itpp::Raised_Cosine::Raised_Cosine
Raised_Cosine()
Constructor.
Definition pulse_shape.h:166
itpp::Raised_Cosine::roll_off_factor
double roll_off_factor
The roll off factor (i.e. alpha)
Definition pulse_shape.h:178
itpp::Raised_Cosine::get_roll_off
double get_roll_off(void) const
Get the roll-off factor.
Definition pulse_shape.h:408
itpp::Raised_Cosine::~Raised_Cosine
virtual ~Raised_Cosine()
Destructor.
Definition pulse_shape.h:170
itpp::Raised_Cosine::set_pulse_shape
void set_pulse_shape(double roll_off_factor, int filter_length=6, int upsampling_factor=8)
Set pulse shape (roll_off_factor between 0 and 1, filter_length even)
Definition pulse_shape.h:365
itpp::Root_Raised_Cosine
(Square) Root Raised Cosine (RRC) Pulse Shaper
Definition pulse_shape.h:227
itpp::Root_Raised_Cosine::~Root_Raised_Cosine
virtual ~Root_Raised_Cosine()
Destructor.
Definition pulse_shape.h:234
itpp::Root_Raised_Cosine::set_pulse_shape
void set_pulse_shape(double roll_off_factor, int filter_length=6, int upsampling_factor=8)
Set pulse_shape, roll_off_factor between 0 and 1, filter_length even.
Definition pulse_shape.h:423
itpp::Root_Raised_Cosine::roll_off_factor
double roll_off_factor
The roll off factor (i.e. alpha)
Definition pulse_shape.h:242
itpp::Root_Raised_Cosine::get_roll_off
double get_roll_off(void) const
Get the Roll-off factor.
Definition pulse_shape.h:467
itpp::Root_Raised_Cosine::Root_Raised_Cosine
Root_Raised_Cosine()
Constructor.
Definition pulse_shape.h:230
filter.h
Definitions of Filter classes and functions.
it_error_if
#define it_error_if(t, s)
Abort if t is true.
Definition itassert.h:117
it_assert
#define it_assert(t, s)
Abort if t is not true.
Definition itassert.h:94
itpp::is_even
bool is_even(int x)
Return true if x is an even integer.
Definition misc.h:122
itpp::sqr
vec sqr(const cvec &data)
Absolute square of elements.
Definition elem_math.cpp:36
itpp::sinc
double sinc(double x)
Sinc function: sinc(x) = sin(pi*x)/pi*x.
Definition trig_hyp.h:42
matfunc.h
Various functions on vectors and matrices - header file.
itpp
itpp namespace
Definition itmex.h:37
itpp::pi
const double pi
Constant Pi.
Definition misc.h:103
resampling.h
Resampling functions - header file.
trig_hyp.h
Trigonometric and hyperbolic functions - header file.
vec.h
Templated Vector Class Definitions.

Generated on Mon Jun 10 2024 11:49:22 for IT++ by Doxygen 1.9.8