/*
Programme écrit par Silicium628
ce logiciel est libre et open source
*/
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "math.h"
QString version = "1.1";
QColor couleur_ecran = QColor::fromRgb(255, 255, 240, 255);
QColor couleur_ligne = QColor::fromRgb(0, 0, 0, 255);
QColor couleur_trace = QColor::fromRgb(0, 128, 220, 255);
QColor couleur_texte = QColor::fromRgb(0, 128, 0, 255);
QPen pen_ligne(couleur_ligne, 1, Qt::SolidLine);
QPen pen_trace(couleur_trace, 1, Qt::SolidLine);
QPen pen_reticule(couleur_ligne, 1, Qt::SolidLine);
float tableau_signal[1024];
float tableau_cos[65536];
float tableau_sin[65536];
float tableau_R[1024]; // parties réelles
float tableau_I[1024]; // parties imaginaires
float tableau_out[1024];
int frequence; // Hz
int nb_ech; // nombre d'échantillons
int k_max;
int frq_echantillonnage; // Hz
int pas_balayage;
float Te; // période d'échantillonage
int hamming = false;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
setupUi(this);
setWindowTitle("Transformee de Fourier - version " + version);
scene = new QGraphicsScene(this);
scene->setBackgroundBrush(couleur_ecran);
graphicsView1->setScene(scene);
groupe_reticule = new QGraphicsItemGroup();
groupe_trace = new QGraphicsItemGroup();
scene->addItem(groupe_trace);
for (int i=0; i>512; i++)
{
tableau_signal[i]=0;
tableau_cos[i]=0;
tableau_sin[i]=0;
tableau_out[i]=0;
}
frequence = 400; // Hz
nb_ech = 256;
k_max = 4 * nb_ech;
frq_echantillonnage = 10000; // Hz
pas_balayage = 20;
calcul_tableaux_sin_cos();
tracer_graduations();
}
void MainWindow::effacer_graduation()
{
foreach( QGraphicsItem *item, scene->items( groupe_reticule->boundingRect() ) )
{
if( item->group() == groupe_reticule ) { delete item; }
}
}
void MainWindow::effacer_trace()
{
foreach( QGraphicsItem *item, scene->items( groupe_trace->boundingRect() ) )
{
if( item->group() == groupe_trace ) { delete item; }
}
}
MainWindow::~MainWindow()
{
}
void MainWindow::tracer_graduations()
{
float i,x,y;
float nb_grad_max;
float intervalle; // séparant les graduations
float fi;
QString sti;
rectangle = new QGraphicsRectItem(0,0, 1023, 600);
rectangle->setPen(couleur_ligne);
groupe_trace->addToGroup(rectangle);
// lignes verticales
/*
ici calcul de l'intervalle (en pixels) qui correspond exactement à 100Hz (en fréquence)
intervalle = 82;
fi = x * frq_echantillonnage / (nb_ech * 2 * pas_balayage)
fi = 100;
x * frq_echantillonnage / (nb_ech * 2 * pas_balayage) = 100
intervalle = 100.0 * nb_ech * 2.0 * pas_balayage / (frq_echantillonnage);
*/
intervalle = 100.0 * nb_ech * 2.0 * pas_balayage / (frq_echantillonnage);
nb_grad_max = 1023 / intervalle;
for (i=0; i<=nb_grad_max; i++)
{
x = intervalle * i;
ligne1 = new QGraphicsLineItem(x, 0, x, 600);
ligne1->setPen(pen_reticule);
groupe_reticule->addToGroup(ligne1);
fi = x * frq_echantillonnage / (nb_ech * 2 * pas_balayage);
sti.setNum(fi);
texte_frq = new QGraphicsTextItem(sti);
texte_frq->setDefaultTextColor(couleur_texte);
texte_frq->setPos(x,580);
if(x<980) // évite que l'écriture ne déborde du cadre a droite
{
groupe_reticule->addToGroup(texte_frq);
}
}
// lignes horizontales
intervalle = 50;
nb_grad_max = 600 / intervalle;
for (i=0; i<=nb_grad_max; i++)
{
y = 600 - intervalle * i;
ligne1 = new QGraphicsLineItem(0, y, 1023, y);
ligne1->setPen(pen_reticule);
groupe_reticule->addToGroup(ligne1);
}
scene->addItem(groupe_reticule);
}
void MainWindow::tracer_tableau_valeurs()
{
int offset_y = 600;
segment_trace = new QGraphicsLineItem(0, offset_y, 1024, offset_y);
segment_trace->setPen(couleur_ligne);
groupe_trace->addToGroup(segment_trace);
int n;
float x, y, memo_x, memo_y;
x=0;
y=offset_y;
for(n=0; n<511; n++)
{
memo_x = x;
memo_y = y;
x = 2* n;
y = offset_y - tableau_out[n];
segment_trace = new QGraphicsLineItem(memo_x ,memo_y, x, y);
segment_trace->setPen(pen_trace);
groupe_trace->addToGroup(segment_trace);
}
}
void MainWindow::remplit_tableau_echantillons()
{
// création du signal à analyser
int n;
float x;
Te = 1.0 / frq_echantillonnage;
for(n=0; n < nb_ech; n++) // nb d'échantillons
{
x=cos(2 * M_PI * frequence * n * Te);
if (hamming) { x = x * (1- cos (2* M_PI * n / nb_ech ));}
tableau_signal[n] = x;
}
}
void MainWindow::calcul_tableaux_sin_cos()
{
int m;
float x;
for(m=0; m<65536; m++)
{
x=2 * M_PI * m / (pas_balayage * nb_ech); // la constante de droite définit la finesse du pas de balayage fréquentiel
tableau_cos[m] = cos(x);
tableau_sin[m] = sin(x);
}
}
void MainWindow::calcul_fourier()
{
int n, k, m;
float S1, S2;
float y1, y2;
for (k=1; k<k_max; k++)
{
S1=0;
S2=0;
for(n=0; n < nb_ech; n++)
{
m=n*k;
if(m<65536)
{
y1= tableau_signal[n] * tableau_cos[m];
S1+= y1;
y2= tableau_signal[n] * tableau_sin[m];
S2+= y2;
}
}
tableau_out[k] = 4* sqrt(S1*S1 + S2*S2);
}
}
void MainWindow::on_btn2_clicked()
{
remplit_tableau_echantillons();
calcul_fourier();
tracer_tableau_valeurs();
}
void MainWindow::on_spinBox_pas_valueChanged(int arg1)
{
QString st1;
pas_balayage = arg1;
st1.setNum(pas_balayage); // conversion num -> txt
calcul_tableaux_sin_cos();
calcul_fourier();
effacer_graduation();
effacer_trace();
tracer_graduations();
tracer_tableau_valeurs();
}
void MainWindow::on_spinBox_frq_valueChanged(int arg1)
{
frequence = arg1;
remplit_tableau_echantillons();
calcul_fourier();
effacer_graduation();
effacer_trace();
tracer_graduations();
tracer_tableau_valeurs();
}
void MainWindow::on_checkBox1_toggled(bool checked)
{
if (checked) {hamming = true;} else {hamming = false;}
remplit_tableau_echantillons();
calcul_fourier();
effacer_graduation();
effacer_trace();
tracer_graduations();
tracer_tableau_valeurs();
}