La Transformée de Fourier

C'est une extension des séries de Fourier, mais pouvant s'appliquer à des fonctions non périodiques. Elle permet d'obtenir le spectre (fréquentiel) d'une fonction (qui peut être périodique mais pas nécessairement). Comme je l'ai déjà écrit à propos des séries de Fourier, les transformées de Fourier constituent le domaine de l'analyse harmonique qui est une branche des mathématiques très importante pour les physiciens et les électroniciens, au même titre que les équations aux dérivées partielles. (Voyez comme j'aime parler de ce que je vous présenterai plus tard dès que j'expose une chose...) Je veux aller à l'essentiel : comprendre de quoi il s'agit, d'une manière théorique puis pratique par le calcul des transformées de Fourier sur ordinateur. C'est ainsi que je vous donne un programme graphique en C++ et Qt4 que j'ai écrit sous Linux Mint avec QT Creator, directement calqué sur les équations, qui calcule et trace des TF.

1 La partie théorique

Sur ma page:

Transformée de Fourier - Etude analytique

figurent les belles équations dont découle directement le programme ci-dessous.

2 Le programme en C++ et Qt4

CODE SOURCE C++ Qt4
  1. /*
  2.   Programme écrit par Silicium628
  3.   ce logiciel est libre et open source
  4.  
  5.   */
  6.  
  7. #include "mainwindow.h"
  8. #include "ui_mainwindow.h"
  9. #include "math.h"
  10.  
  11. QString version = "1.1";
  12.  
  13. QColor couleur_ecran = QColor::fromRgb(255, 255, 240, 255);
  14. QColor couleur_ligne = QColor::fromRgb(0, 0, 0, 255);
  15. QColor couleur_trace = QColor::fromRgb(0, 128, 220, 255);
  16. QColor couleur_texte = QColor::fromRgb(0, 128, 0, 255);
  17.  
  18. QPen pen_ligne(couleur_ligne, 1, Qt::SolidLine);
  19. QPen pen_trace(couleur_trace, 1, Qt::SolidLine);
  20. QPen pen_reticule(couleur_ligne, 1, Qt::SolidLine);
  21.  
  22. float tableau_signal[1024];
  23.  
  24. float tableau_cos[65536];
  25. float tableau_sin[65536];
  26.  
  27. float tableau_R[1024]; // parties réelles
  28. float tableau_I[1024]; // parties imaginaires
  29.  
  30. float tableau_out[1024];
  31.  
  32. int frequence; // Hz
  33. int nb_ech; // nombre d'échantillons
  34. int k_max;
  35. int frq_echantillonnage; // Hz
  36. int pas_balayage;
  37. float Te; // période d'échantillonage
  38. int hamming = false;
  39.  
  40.  
  41.  
  42. MainWindow::MainWindow(QWidget *parent) :
  43. QMainWindow(parent)
  44.  
  45. {
  46. setupUi(this);
  47. setWindowTitle("Transformee de Fourier - version " + version);
  48.  
  49.  
  50. scene = new QGraphicsScene(this);
  51. scene->setBackgroundBrush(couleur_ecran);
  52. graphicsView1->setScene(scene);
  53.  
  54. groupe_reticule = new QGraphicsItemGroup();
  55. groupe_trace = new QGraphicsItemGroup();
  56. scene->addItem(groupe_trace);
  57.  
  58. for (int i=0; i>512; i++)
  59. {
  60. tableau_signal[i]=0;
  61.  
  62. tableau_cos[i]=0;
  63. tableau_sin[i]=0;
  64. tableau_out[i]=0;
  65. }
  66.  
  67. frequence = 400; // Hz
  68. nb_ech = 256;
  69. k_max = 4 * nb_ech;
  70. frq_echantillonnage = 10000; // Hz
  71. pas_balayage = 20;
  72.  
  73. calcul_tableaux_sin_cos();
  74. tracer_graduations();
  75. }
  76.  
  77.  
  78.  
  79. void MainWindow::effacer_graduation()
  80. {
  81. foreach( QGraphicsItem *item, scene->items( groupe_reticule->boundingRect() ) )
  82. {
  83. if( item->group() == groupe_reticule ) { delete item; }
  84. }
  85. }
  86.  
  87.  
  88. void MainWindow::effacer_trace()
  89. {
  90. foreach( QGraphicsItem *item, scene->items( groupe_trace->boundingRect() ) )
  91. {
  92. if( item->group() == groupe_trace ) { delete item; }
  93. }
  94. }
  95.  
  96.  
  97. MainWindow::~MainWindow()
  98. {
  99.  
  100. }
  101.  
  102. void MainWindow::tracer_graduations()
  103. {
  104. float i,x,y;
  105. float nb_grad_max;
  106. float intervalle; // séparant les graduations
  107. float fi;
  108. QString sti;
  109.  
  110. rectangle = new QGraphicsRectItem(0,0, 1023, 600);
  111. rectangle->setPen(couleur_ligne);
  112. groupe_trace->addToGroup(rectangle);
  113.  
  114. // lignes verticales
  115.  
  116. /*
  117.  ici calcul de l'intervalle (en pixels) qui correspond exactement à 100Hz (en fréquence)
  118.   intervalle = 82;
  119.   fi = x * frq_echantillonnage / (nb_ech * 2 * pas_balayage)
  120.   fi = 100;
  121.   x * frq_echantillonnage / (nb_ech * 2 * pas_balayage) = 100
  122.   intervalle = 100.0 * nb_ech * 2.0 * pas_balayage / (frq_echantillonnage);
  123. */
  124.  
  125. intervalle = 100.0 * nb_ech * 2.0 * pas_balayage / (frq_echantillonnage);
  126. nb_grad_max = 1023 / intervalle;
  127.  
  128. for (i=0; i<=nb_grad_max; i++)
  129. {
  130.  
  131. x = intervalle * i;
  132.  
  133. ligne1 = new QGraphicsLineItem(x, 0, x, 600);
  134. ligne1->setPen(pen_reticule);
  135. groupe_reticule->addToGroup(ligne1);
  136.  
  137. fi = x * frq_echantillonnage / (nb_ech * 2 * pas_balayage);
  138.  
  139. sti.setNum(fi);
  140. texte_frq = new QGraphicsTextItem(sti);
  141. texte_frq->setDefaultTextColor(couleur_texte);
  142. texte_frq->setPos(x,580);
  143. if(x<980) // évite que l'écriture ne déborde du cadre a droite
  144. {
  145. groupe_reticule->addToGroup(texte_frq);
  146. }
  147. }
  148.  
  149. // lignes horizontales
  150. intervalle = 50;
  151. nb_grad_max = 600 / intervalle;
  152.  
  153.  
  154. for (i=0; i<=nb_grad_max; i++)
  155. {
  156. y = 600 - intervalle * i;
  157.  
  158. ligne1 = new QGraphicsLineItem(0, y, 1023, y);
  159. ligne1->setPen(pen_reticule);
  160. groupe_reticule->addToGroup(ligne1);
  161. }
  162.  
  163. scene->addItem(groupe_reticule);
  164. }
  165.  
  166.  
  167.  
  168. void MainWindow::tracer_tableau_valeurs()
  169. {
  170. int offset_y = 600;
  171.  
  172. segment_trace = new QGraphicsLineItem(0, offset_y, 1024, offset_y);
  173. segment_trace->setPen(couleur_ligne);
  174. groupe_trace->addToGroup(segment_trace);
  175.  
  176. int n;
  177. float x, y, memo_x, memo_y;
  178. x=0;
  179. y=offset_y;
  180. for(n=0; n<511; n++)
  181. {
  182. memo_x = x;
  183. memo_y = y;
  184. x = 2* n;
  185. y = offset_y - tableau_out[n];
  186.  
  187. segment_trace = new QGraphicsLineItem(memo_x ,memo_y, x, y);
  188. segment_trace->setPen(pen_trace);
  189. groupe_trace->addToGroup(segment_trace);
  190. }
  191. }
  192.  
  193.  
  194.  
  195. void MainWindow::remplit_tableau_echantillons()
  196. {
  197. // création du signal à analyser
  198. int n;
  199. float x;
  200.  
  201. Te = 1.0 / frq_echantillonnage;
  202.  
  203. for(n=0; n < nb_ech; n++) // nb d'échantillons
  204. {
  205. x=cos(2 * M_PI * frequence * n * Te);
  206. if (hamming) { x = x * (1- cos (2* M_PI * n / nb_ech ));}
  207. tableau_signal[n] = x;
  208. }
  209. }
  210.  
  211.  
  212.  
  213. void MainWindow::calcul_tableaux_sin_cos()
  214. {
  215.  
  216. int m;
  217. float x;
  218.  
  219. for(m=0; m<65536; m++)
  220. {
  221. x=2 * M_PI * m / (pas_balayage * nb_ech); // la constante de droite définit la finesse du pas de balayage fréquentiel
  222. tableau_cos[m] = cos(x);
  223. tableau_sin[m] = sin(x);
  224. }
  225. }
  226.  
  227. void MainWindow::calcul_fourier()
  228. {
  229. int n, k, m;
  230. float S1, S2;
  231. float y1, y2;
  232.  
  233. for (k=1; k<k_max; k++)
  234. {
  235. S1=0;
  236. S2=0;
  237. for(n=0; n < nb_ech; n++)
  238. {
  239. m=n*k;
  240. if(m<65536)
  241. {
  242. y1= tableau_signal[n] * tableau_cos[m];
  243. S1+= y1;
  244.  
  245. y2= tableau_signal[n] * tableau_sin[m];
  246. S2+= y2;
  247. }
  248. }
  249. tableau_out[k] = 4* sqrt(S1*S1 + S2*S2);
  250. }
  251. }
  252.  
  253.  
  254.  
  255. void MainWindow::on_btn2_clicked()
  256. {
  257. remplit_tableau_echantillons();
  258. calcul_fourier();
  259. tracer_tableau_valeurs();
  260. }
  261.  
  262.  
  263. void MainWindow::on_spinBox_pas_valueChanged(int arg1)
  264. {
  265. QString st1;
  266. pas_balayage = arg1;
  267.  
  268. st1.setNum(pas_balayage); // conversion num -> txt
  269.  
  270. calcul_tableaux_sin_cos();
  271. calcul_fourier();
  272. effacer_graduation();
  273. effacer_trace();
  274. tracer_graduations();
  275. tracer_tableau_valeurs();
  276. }
  277.  
  278.  
  279. void MainWindow::on_spinBox_frq_valueChanged(int arg1)
  280. {
  281. frequence = arg1;
  282. remplit_tableau_echantillons();
  283.  
  284. calcul_fourier();
  285. effacer_graduation();
  286. effacer_trace();
  287. tracer_graduations();
  288. tracer_tableau_valeurs();
  289. }
  290.  
  291. void MainWindow::on_checkBox1_toggled(bool checked)
  292. {
  293. if (checked) {hamming = true;} else {hamming = false;}
  294. remplit_tableau_echantillons();
  295.  
  296. calcul_fourier();
  297. effacer_graduation();
  298. effacer_trace();
  299. tracer_graduations();
  300. tracer_tableau_valeurs();
  301.  
  302. }
  303.  

3 Copie d'écran du programme:

4 Documents

5 -

Liens...

15186