Main Idea is to store the input and output within the same class, some sort of "numeric storage"
#pragma once
#include < tiostream >
#include < vector >
#include < complex >
using namespace std;
/*
Global type signal interface ::: IOSignal.h *
input | signal_in |
----> | |_ _| | ------ > || PROCESS ||
| | | | |
| | | | |
| _| |_ |
| |_____| N T E R F A CE <------| return
| signal_out |
*/
struct IOSignal{
// domain for input/ output signal manipulation
// sampling frequency
double fs;
// for time domain
vector signal_in;
vector signal_out;
// for frequency domain
vector> spectrum_in;
vector> spectrum_out;
void inputRe(const vector& sIn) {
this->signal_in = sIn;
};
void outputRe(const vector& sOut)
{
this ->signal_out = sOut;
}
void type(){
vector ::iterator pos;
cout << "\n INPUT signal :" ;
for ( pos = signal_in.begin(); pos != signal_in.end(); pos++)
{
cout << *(pos) << " ";
}
cout << endl;
cout << "\n OUTPUT signal :" ;
for ( pos = signal_out.begin(); pos != signal_out.end(); pos++)
{
cout << *(pos) << " ";
}
cout << endl;
};
};
#pragma once
#include < sstream >
#include < cmath >
#include < complex >
#include < vector >
#include < iostream >
#include < fstream >
const double PI = 3.14159265358979323846;
/*
___ |
/\ \ | IOSignal
/::\ \ | | |
/:/\:\__\ | ||| | | |||
/:/ /:/ / |.. |||||||||||||||||||||||||.... -> || PROCESSING || --> output to IOsignal
/:/_/:/ / ||| | || |||| | ||
\:\/:/ / | | | || |
\::/__/ |
\:\ \
\:\__\
\/__/ PROCESSING MODULE
Global functions for auxilliary use
*/
// DSP General module for processing signal interface IOSignal
// GAIN THE SIGNAL :::
// time domain function
void gain( IOSignal& iosig, double fact)
{
// Input Vector
vector inVec = iosig.signal_in;
// Output Vector
vector outVec;
vector:: iterator p; // pointer u vektor inVec
for ( p = inVec.begin(); p!= inVec.end(); p++)
{
double value = *(p);
iosig.signal_out.push_back(value*fact);
}
}
// turn real double values to complex double values for DFT
vector> real2cpx( IOSignal& iosig)
{
vector> cpx;
if(iosig.signal_in.empty())
{
cout << "this signal is empty \n";
cpx ={0,0};
}
else{
vector x = iosig.signal_in;
int N = x.size();
for (size_t i = 0; i < N; i++)
{
cpx.push_back( {x[i], 0});
}
}
return cpx; // retunr complex vector
}
// compute DFT from signal interface and return it to freq_dom cpx vector
void DFT( IOSignal& iosig)
{
//DFT ::: inputs
// input vector
vector x = iosig.signal_in;
//int N = x.size(); //| GRESKA.. NE IDE DO VELICINE X.SIZE() NEGO DO FS !
int N = iosig.fs;
std::complex intSum; //| take memory for computation
iosig.spectrum_in.reserve(N); //| write to freq. domain N
vector> X = real2cpx(iosig); //| turn real signal to complex for DFT
// loop through each k of DFT
for (int k = 0; k < N; k++)
{
intSum = complex(0,0);
for (int n = 0; n < N; n++)
{
double realPart = cos( ((2*PI)/N)*k*n);
double imagPart = sin( ((2*PI)/N)*k*n);
std::complex w(realPart, -imagPart);
intSum += X[n]*w;
}
iosig.spectrum_in.push_back(intSum);
}
// transformation length
int L = floor(iosig.spectrum_in.size()/2);
double mag;
for (size_t i = 0; i < L ; i++)
{
// |a| = ( a^2 + b^2)^0.5
mag = sqrt(pow(iosig.spectrum_in[i].real() ,2) + pow(iosig.spectrum_in[i].imag(),2));
iosig.spectrum_out.push_back( 2*mag/(2*L));
}
}
/* ___ _ _ _
/ _ \_ __(_)_ __ | |_(_)_ __ __ _
/ /_)/ '__| | '_ \| __| | '_ \ / _` |
/ ___/| | | | | | | |_| | | | | (_| |
\/ |_| |_|_| |_|\__|_|_| |_|\__, | FUNCTIONS
|___/
*/
// write interface to file
void ioWriter( IOSignal& interface, string fileName)
{
ofstream os(fileName);
// if interface vectors not equal, give some warning
if(interface.signal_in.size() != interface.signal_out.size())
{
cout << "Vectors in IOSignal unequal... \n";
cout << "signal_in.size() taken for the end raw in the file ... \n";
}
// print both signals to interface/ signal_in size ...
for (int i = 0; i < interface.signal_in.size(); i++)
{
os << i << "\t"< cpx_dft; // complex DFT output
double abs_val; // place holder absolute value
ofstream os(fileName); // open file to stream data in
cout << iosig.spectrum_out.size();
for (size_t i = 0; i < iosig.spectrum_out.size() ; i++)
{
cpx_dft = iosig.spectrum_out[i]; // take single cpx value
abs_val = sqrt(pow(cpx_dft.real(),2) + pow(cpx_dft.imag(),2)); // calcuate magnitude of complex no.
os << i << "\t" << abs_val << endl;
}
os.close(); // close the file
cout <<" magnitude of DFT to *.dat exported " << endl; // say when finished
}
#include < iostream >
#include < vector >
using namespace std;
#include "signal_gen.h"
#include "IOSignal.h"
#include "processing_m.h"
//*****************************************************************|
//
// || signal input ||
// || || vector processing_m.h
// || INTERFACE ---------------------------->|| DSP ||
// || || |
// ||signal output<-------------------------------|
//
//
//*****************************************************************|
int main()
{
// INPUT
//
signal_gen sineSweep;
// fs= 8096;
// f0 = 1
// f1 = 10
// Amp = 5
// PhaseShift = 0
// max time = 1;
// Interfaces
//
// CH1:::
signal_gen myWave;
myWave.sine(8096,10,5,0,1);
IOSignal channel_01;
channel_01.signal_in = myWave.getSignal();
ioWriter(channel_01,"DFT_mag.dat");
// CH2:::
IOSignal channel02;
vector k = sineSweep.getSignal();
channel02.signal_in = k;
// CH3:::
IOSignal channel03;
channel03.inputRe(sineSweep.getSignal());
// gain channel03 x 2
gain(channel03, 2);
ioWriter(channel03,"ioFile.dat");
// random channel
signal_gen gaussian; // inicijaliziraj
gaussian.random_normal(0,0.3, 1000); // generiraj
IOSignal channel04; // stvori interface
channel04.inputRe(gaussian.getSignal()); // kopiraj generator u interface
gain(channel04,5); // obradi kanal u interfejsu i stavi u output vector
ioWriter(channel04,"io_random.dat");
cout << endl <<"... end of main"<
set title "DFT"
set xlabel 'Frequency (Hz) '
set ylabel 'Mag(n)'
set yrange [-8:8]
set xrange [0:50]
set grid
plot 'DFT_mag.dat' using 2:3 with line lt -1 lw 1 title 'output'
Lessons learned...
with: "procssing_m.h" and "IOSignal.h" can gain the signal before computing dft .. here two examples