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 vectorsignal_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 vectorinVec = 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 || // || || vectorprocessing_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