Signal Generator

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; 
                    }
            

GnuPlot

Plotting the results

                set title "Input signal of constant frequency" 
                set xlabel 'sample[n] * ts'
                set ylabel 'Amplitude' 
                set grid
                plot 'sinus_sweep.dat' using 1 with line lt -1 lw 1 title 'SINE sweep',\
                'sinus.dat' using 1 with line lt -1 lw 2 title 'SINE const'  

            
function generator output