signl_gen.h
Generating different signals, like sine, cosine or sine sweep
#pragma once
#include < cmath >
#include < sstream >
#include < vector >
#include < iostream >
#include < fstream >
/* signal_gen
__ ___ __ __ _ _ _ ___ _ _
(_ | /__ |\ | /\ | /__ |_ |\ | |_ |_) /\ | / \ |_)
__) _|_ \_| | \| /--\ |_ \_| |_ | \| |_ | \ /--\ | \_/ | \
Returns real type double values only
t[i] , n[i] |
t[i+1], n[i+1] .... | | | | | |
| ||| || | || |
... etc. | ||||| |||||| ||| |
|---------------------------> t[i]
||||| | |
|| |
| |
Jan Gusic, v 14.Apr. 2020
*/
class signal_gen
{
private:
vector real_signal; //| vector < n[i], n[i+1] .... n[N]>
double fs = 0; //| sampling frequency
double Ts; //| sampling time
double N = 0; //| samples generated inside of vector
const double PI = 3.14159265358979323846;
//| flag shows the signal type generated
//| 0 - no signal created ( default )
int FLAG = 0; //| 1 sine wave fixed freq
//| 2 cos wave fixed freq
//| 3 sweep sine linear frequency change
public:
signal_gen(double, double); //| each signal has base of sampling frequency
//| number of points in a buffer
~signal_gen();
signal_gen();
void type() const; //| type object information
std::string readSignal() const; //| return string with signal values ...
vector getSignal() const; //| return double values from objects vector( export vector as copy)
// GENERATOR MATH FUNCTIONS
void sinus(double, double, double, double,double); //| constant freq & amp. sine wave
void cosinus(double, double, double, double,double); //| constant freq & amp. sine wave
void sweep_linear(double,double,double,double,double,double); //| sweept sinewave, varying in frequency
void random_normal(double, double, int); //| Gaussian random signal
void sweep_log(); //| logarithimic frequency change
//AUX global function:::
// DO NOT UNCOMMENT, at the end of a class see
// void signal_write( signal_gen& signal, string fileName)
};
signal_gen::signal_gen()
{
static int i =0;
i++;
cout << i;
}
signal_gen::~signal_gen()
{ cout << "--" << endl;
}
void signal_gen::type() const //| PERHAPS redo TO return STRING ...
{
switch (FLAG)
{
case 0 : cout << "|| IDLE object" << endl; break;
case 1 : cout << "|| SINE(x), f = const. " << endl; break;
case 2 : cout << "|| COSINE(x), f = const. " << endl; break;
case 3 : cout << "|| sin(2_PI_f*t), linear f f1> " << endl; break;
default:
break;
}
cout <<" |--Sampling frequency [fs]: "<< this-> fs << " s-1"<< endl;
cout <<" |--Signal length [N ]: "<< this-> N << " - " << endl;
cout <<" |--Sampling Time [ts]: "<< 1/fs << " sec"<< endl;
cout <<"====================================================|" << endl;
}
std::string signal_gen::readSignal() const
{
std::stringstream s;
for(auto sample: real_signal)
{
s << sample << endl;
}
return s.str();
}
vector signal_gen:: getSignal() const
{
vector vec;
if( real_signal.empty()==0 )
{ cout <<"xxxx";
vec = this-> real_signal;
}
else
{
cerr << "\n signal_gen::cannot return anything from an empty object" << endl;
}
return vec;
}
void signal_gen::sinus(double Fs, double f, double Amp ,double phi, double t_max)
{
// A = sine wave amplitude
// fs = sample rate (Hz)
// f = sine wave frequency (Hz)
real_signal.clear(); // clear vector
this->FLAG = 1; // change signal flag
this->fs = Fs; // sampling frequency
this-> N = t_max*Fs;
phi *= PI/180.0;
for (size_t i = 0; i < N; i++)
{
double arg = (2*PI * f/Fs)*i;
phi =+ arg;
double output = Amp* sin(phi);
real_signal.push_back(output);
}
// logic behind
// sin( phi + 2pif/fs )
// phi+ phi + 2pif/fs
// phi+ phi + phi + 2pif/ ....
}
void signal_gen::cosinus(double Fs, double f, double Amp ,double phi, double t_max)
{
phi+=90.0; // 90 degrees shift
signal_gen::sinus( Fs, f, Amp, phi, t_max);
}
void signal_gen::sweep_linear(double Fs, double f0, double f1,double Amp, double phi, double T_sweep)
{
// A = sine wave amplitude
// fs = sample rate (Hz)
// f0 = initial frequency (Hz)
// f1 = final frequency (Hz)
// T_sweep = duration of sweep (s)
real_signal.clear(); //|clear vector
this->FLAG = 3; //|change signal flag to 3;
this->fs = Fs; //|sampling frequency
this-> N = T_sweep*Fs; //|max number of samples
phi *= PI/180.0; //|convert pahse PI from degrees to radians
//| phase accumulator
double f = f0; //| initial frequency
double delta = 2 * M_PI * f / Fs; //| phase increment per sample
double f_delta = (f1 - f0) / (Fs * T_sweep); //| instantaneous frequency increment per sample
for (size_t i = 0; i < N; i++)
{
double output = Amp * sin(phi); //| output sample value for current sample
phi += delta; //| increment phase accumulator
f += f_delta; //| increment instantaneous frequency
delta = 2 * M_PI * f / Fs; //| re-calculate phase increment
real_signal.push_back(output);
}
}
void signal_gen:: random_normal(double mu, double stddev, int L)
{
this->FLAG =4;
const double mean = mu;
const double std = stddev;
std::default_random_engine random_engine;
std::normal_distribution DIST(mean,std);
for (size_t i = 0; i < L; i++)
{
double r_var = DIST(random_engine);
real_signal.push_back(r_var);
}
}
// PRINTER FUNCTION ::: signal_write(system, "DATA.dat");
void signal_write( signal_gen& signal, string fileName)
{
ofstream os(fileName);
os<< signal.readSignal();
os.close();
cout <<"*.dat exported " << endl;
}
main.cpp
let as use the class above...
#include< iostream >
using namespace std;
#include "signal_gen.h"
int main()
{
// make vector of signals
// vector < signal_gen > signalPack;
signal_gen signal_sinus;
signal_sinus.sinus(8096,1,1,0,1);
signal_sinus.type();
signal_gen sineSweep;
sineSweep.sweep_linear(10000,20,100, 1,0,1);
sineSweep.type();
// export generated double values ... from object
vector k = sineSweep.getSignal();
// to the global function
// filename
// object name |
// | |
// signal_write(signal_sinus,"sinus.dat");
// signal_write(sineSweep,"sinus_sweep.dat");
signal_gen ch1;
ch1.sweep_linear(21e3, 10,440, 1,0,1);
signal_write(ch1,"sweep_2.dat");
cout << endl <<"last in main"<<endl;
return 0;
}