waw to midi

Programme en C++ Qt6 basé directement sur la transformée de Fourier rapide. Retrouve les notes de musique (et leur code midi) à partir d'un fichier audio (fichier.wav)
Ce fichier source doit être stéréo échantillonné à 48kb/s, ce qui peut être facilement obtenu avec le soft avidemux (par exemple), éventuellement après extraction de la piste audio d'une vidéo .mp4.

1 Vue d'ensemble



Les notes obtenues peuvent être rejouées, les durées et le rythme sont pris en compte

2 Scan en cours (Transformée de fourier d'un échantillon de signal)

3 Aperçu en vidéo


A voir directement sur Youtube en 1080p pour voir les détails !!!

4 Le code source en C++ Qt6: fichier mainwindow.cpp

CODE SOURCE en C++
  1. /* top
  2.   Calcul de la transformée de Fourier rapide d'un signal audio au format PCM enregistré dans un fichier .wav
  3.   Format WAVE, RIFF, fmt échantilloné à 48000Hz
  4.  
  5.   Format : Wave
  6.   File size : 2.39 MiB
  7.   Duration : 13 s 54 ms
  8.   Overall bit rate mode : Constant
  9.   Overall bit rate : 1 536 kb/s
  10.  
  11.   Audio
  12.   Format : PCM
  13.   Format settings : Little / Signed
  14.   Codec ID : 1
  15.   Duration : 13 s 54 ms
  16.   Bit rate mode : Constant
  17.   Bit rate : 1 536 kb/s
  18.   Channel(s) : 2 channels
  19.   Sampling rate : 48.0 kHz
  20.   Bit depth : 16 bits
  21.   Stream size : 2.39 MiB (100%)
  22.  
  23.   Programme écrit par Silicium628
  24.   ce logiciel est libre et open source
  25. */
  26. /*
  27. ***** RAPPEL**** (source: https://helpx.adobe.com/fr/audition/using/digitizing-audio.html) **
  28. Taux d’échantillonnage Niveau de qualité Plage de fréquences
  29.  
  30. 11,025 Hz Faible qualité radio AM (multimédia bas de gamme) 0- 5 512 Hz
  31. 22,050 Hz Comparable à la qualité radio FM (multimédia haut de gamme) 0-11 025 Hz
  32. 32 000 Hz Meilleur que la qualité radio FM (taux de diffusion standard) 0-16 000 Hz
  33. 44 100 Hz CD 0-22 050 Hz
  34. 48 000 Hz DVD standard 0-24 000 Hz
  35. 96 000 Hz DVD Blu-ray 0-48 000 Hz
  36. *********************************************************************************************/
  37. /*
  38. Le présent logiciel est paramétré pour traiter les fichiers audio ECHANTILLONES à 48000Hz (qualité DVD)
  39. ET PAS 44.1 !!
  40. Je le rendrai compatible avec les autres taux, mais pour l'instant il faut enregistrer
  41. au préalable l'audio à traiter avec un taux de 48kHz
  42. (par exemple avec Audacity, c'est facile voir en bas à gauche de sa fenêtre).
  43. */
  44.  
  45.  
  46. #include "mainwindow.h"
  47. #include "ui_mainwindow.h"
  48. #include "math.h"
  49. #include "complexe.cpp"
  50.  
  51. #include <QMessageBox>
  52. #include <QFileDialog>
  53. #include <QFile>
  54. //#include <QImage>
  55.  
  56. #include <QtMultimedia/QMediaPlayer>
  57. #include <QAudioOutput>
  58.  
  59. #include <QMouseEvent>
  60. #include <QDateTime>
  61. #include <QScrollBar>
  62.  
  63.  
  64. /* FFT_wav */
  65.  
  66. QString version = "33.1";
  67.  
  68. /* todo:
  69. - clic trop haut en dehors du cadre -> note MI 52 au lieu de rien
  70.  
  71. */
  72.  
  73. int write_mode =0;
  74.  
  75. QString couleur_ecran = "#141414";
  76. QString couleur_ligne = "#878787";
  77. QString couleur_trace1 = "#0EA004";
  78. QString couleur_trace2 = "#00FFFF";
  79. QString couleur_curseur = "#FFFF00";
  80. QString couleur_texte = "#FFFF00"; // JAUNE
  81. QString couleur_encadrement = "#FF0000"; // ROUGE
  82.  
  83. QPen pen_ligne(QColor(couleur_ligne), 1, Qt::SolidLine);
  84. QPen pen_trace1(QColor(couleur_trace1), 1, Qt::SolidLine);
  85. QPen pen_trace2(QColor(couleur_trace2), 1, Qt::SolidLine);
  86. QPen pen_curseur(QColor(couleur_curseur), 1, Qt::SolidLine);
  87. QPen pen_reticule(QColor(couleur_ligne), 1, Qt::SolidLine);
  88. QPen pen_encadrement(QColor(couleur_encadrement), 1, Qt::SolidLine);
  89.  
  90. char temp_entete[100]; // signal entete lu dans le fichier .wav
  91. char temp_data[2000000]; // signal audio lu dans le fichier .wav (max 2MB)
  92. int pas_echantillonage = 24;
  93.  
  94. Complexe ech[2048]; // nb_ech echantillons
  95. Complexe tab_X[2048]; // nb_ech valeurs traitées
  96. Complexe tab_W[2048];
  97. bool tableau_w_plein = false;
  98.  
  99. uint8_t table_FREQ_midi[2000][1]; // [t][num_raie]
  100. uint8_t table_amplitudes[2000][1];// [t][num_raie]
  101.  
  102. double facteur_compression=1.0;
  103.  
  104. double frequence1=400; // Hz
  105. double frequence2=400; // Hz
  106. double frequence3=100; // Hz
  107.  
  108. uint nb_etapes=10; // 10
  109. uint nb_ech = pow (2, nb_etapes); // nombre d'échantillons = 2 puissance(nb_etapes) ->2^10 = 1024
  110.  
  111. float table_modules_FFT[1024]; // = 2^10
  112.  
  113. float x_clic_ecran, y_clic_ecran;
  114.  
  115. int nb_tics;
  116. long T_i=0;
  117. int n_player=1;
  118. double seuil;
  119. double gain =1.0;
  120. int num_note_depart;
  121. int num_note_jouee=0;
  122. int nb_acc=0;
  123. int num_note_max=0;
  124. double memo_scroll_x=0;
  125. QDateTime temps_0; // départ du jeu des notes
  126. bool hamming = true;
  127. bool bourrage_de_zeros = true;
  128. bool second_Frq = false;
  129. bool bz = true;
  130. bool modul = false;
  131.  
  132. // type de mesure noté Ta/Tb (4/4, 3/2 ...)
  133. int Ta = 4;
  134. int Tb = 4;
  135.  
  136. //QList<int> index_midi; // position x des notes midi sur le graphe FFT (à partir de midi=52)
  137. QList<QString> liste_couleurs;
  138. QList<ENR_FFT> liste_ENR_FFT; // liste de "notes" détectées (maximums de FFT)
  139. QList<NOTE> liste_NOTES;
  140. QList<QString> noms_notes;
  141. QList<QString> gamme_chromatique;
  142.  
  143.  
  144.  
  145. QFile file_wav; // fichier à analyser
  146. QFile file_dat; // datas du TAB_FRQ
  147.  
  148. QDir currentDir;
  149. QString base_Dir;
  150. QString default_Dir = "/home/";
  151. QString string_currentDir = default_Dir; // à priori; sera mis à jour lors de la lecture du fichier 'params.ini'
  152. QString string_currentFile;
  153. QString nom_fichier_in="";
  154.  
  155. QDataStream binStream1;
  156.  
  157. float duree; // calculée dans la fonction 'decode_entete'
  158. float data_size; // calculée dans la fonction 'decode_entete'
  159.  
  160. bool wav_ok = false;
  161. bool dossier_de_travail_ok = false;
  162. bool data_nts_ok = false;
  163. bool rapide = false;
  164. bool etendre = true;
  165. bool visu_notes = true;
  166. bool visu_freq = true;
  167. bool visu_ech_tps;
  168. bool visu_mesures;
  169. bool visu_duree_notes = true;
  170. bool lecture_en_cours = false;
  171.  
  172. uint32_t offset_t;
  173. float zoom_x =1.0;
  174.  
  175.  
  176. MainWindow::MainWindow(QWidget *parent) :
  177. QMainWindow(parent)
  178. {
  179. setupUi(this);
  180. setWindowTitle("Transformée de Fourier Rapide FFT - version " + version);
  181.  
  182. //this->setGeometry(0,0, 1900, 1000);
  183. setWindowState(Qt::WindowMaximized);
  184.  
  185. tabWidget_Global->setGeometry(0,0, 1920, 1280);
  186. tabWidget_Global->setCurrentIndex(0);
  187.  
  188. //-----------------------------------------------------
  189. // SCENE 1 - celle du haut ('Transformée de Fourier' ET 'partie échantillonée du signal')
  190.  
  191. scene1 = new QGraphicsScene(this);
  192. scene1->setBackgroundBrush(QColor(couleur_ecran));
  193. graphicsView1->setScene(scene1);
  194. graphicsView1->setGeometry(0, 0, 1900, 655); //( 0, 0, 1900, 700)
  195. graphicsView1->verticalScrollBar()->setValue(0);
  196.  
  197. calque_lignes_F_zero = new QGraphicsItemGroup();
  198. scene1->addItem(calque_lignes_F_zero);
  199.  
  200. calque_reticule1 = new QGraphicsItemGroup();
  201. scene1->addItem(calque_reticule1);
  202. afficher_titre_calque("Transformée de Fourier", 0, 0, calque_reticule1);
  203.  
  204. calque_trace_FFT = new QGraphicsItemGroup();
  205. scene1->addItem(calque_trace_FFT);
  206.  
  207. calque_trace_signal1 = new QGraphicsItemGroup();
  208. scene1->addItem(calque_trace_signal1);
  209.  
  210. calque_curseur = new QGraphicsItemGroup();
  211. scene1->addItem(calque_curseur);
  212.  
  213.  
  214. //-----------------------------------------------------
  215. // SCENE 2 - celle du bas ('Fichier Audio .wav')
  216.  
  217. scene2 = new QGraphicsScene(this);
  218. QBrush QB1("#222222");
  219. scene2->setBackgroundBrush(QB1); // couleur_ecran
  220.  
  221. graphicsView2->setScene(scene2);
  222. graphicsView2->setGeometry(0, 660, 1900, 200); // (0, 660, 1900, 200)
  223.  
  224. calque_trace_signal2 = new QGraphicsItemGroup();
  225. scene2->addItem(calque_trace_signal2);
  226.  
  227. calque_reticule2 = new QGraphicsItemGroup();
  228. scene2->addItem(calque_reticule2);
  229. afficher_titre_calque("Fichier Audio .wav", 0, -80, calque_reticule2);
  230.  
  231. calque_encadrement1 = new QGraphicsItemGroup();
  232. scene2->addItem(calque_encadrement1);
  233.  
  234. calque_encadrement2 = new QGraphicsItemGroup();
  235. scene2->addItem(calque_encadrement2);
  236.  
  237. //-----------------------------------------------------
  238. // SCENE 3 - LISTE verticale NOTES sur l'onglet NOTES
  239. scene3 = new QGraphicsScene(this);
  240. scene3->setBackgroundBrush(QColor(couleur_ecran));
  241. graphicsView3->setScene(scene3);
  242.  
  243. calque_gradu_TAB_FRQ = new QGraphicsItemGroup();
  244. scene3->addItem(calque_gradu_TAB_FRQ);
  245.  
  246. //-----------------------------------------------------
  247. // SCENE 4 - ANALYSE sur l'onglet NOTES
  248.  
  249. scene4 = new QGraphicsScene(this);
  250. scene4->setBackgroundBrush(QColor(couleur_ecran));
  251. graphicsView4->setScene(scene4);
  252. // graphicsView4->setEnabled(false); // pour empêcher le scrolling (pb: l'horizontal aussi !)
  253. // graphicsView4->setGeometry(10, 30, 1000, 690); // (10,30,1000,690)
  254.  
  255.  
  256. calque_grille_mesures = new QGraphicsItemGroup();
  257. scene4->addItem(calque_grille_mesures);
  258.  
  259. calque_TAB_FRQ = new QGraphicsItemGroup();
  260. scene4->addItem(calque_TAB_FRQ);
  261. afficher_titre_calque("Table Fréquences & notes", 200, 0, calque_TAB_FRQ);
  262.  
  263. calque_notes = new QGraphicsItemGroup();
  264. scene4->addItem(calque_notes);
  265.  
  266. calque_notes_jouee = new QGraphicsItemGroup();
  267. scene4->addItem(calque_notes_jouee);
  268.  
  269. calque_echelle_temporelle =new QGraphicsItemGroup();
  270. scene4->addItem(calque_echelle_temporelle);
  271.  
  272. //-----------------------------------------------------
  273.  
  274. Timer1 = new QTimer(this);
  275. connect(Timer1, SIGNAL(timeout()), this, SLOT(Tic1()));
  276.  
  277. Timer2 = new QTimer(this);
  278. connect(Timer2, SIGNAL(timeout()), this, SLOT(Tic2()));
  279.  
  280.  
  281. noms_notes<<"La"<<"Si"<<"Do"<<"Ré"<<"Mi" <<"Fa"<<"Sol"<<"--"<<"--"; // <- A B C D E F G
  282. gamme_chromatique<<"Do"<<"Do#"<<"Ré"<<"Mib"<<"Mi"<<"Fa"<<"Fa#"<<"Sol"<<"Sol#"<<"La"<<"Sib"<<"Si";
  283.  
  284. liste_couleurs <<"#EF2929"<<"#FF5C00"<<"#FCAF3E"<<"#FFE300"<<"#BFFF00"<<"#07F64F"
  285. <<"#16D298"<<"#16D2C4"<<"#00AEFF"<<"#1667D2"<<"#7C00FF"<<"#FF67EF"<<"#EEEEEC";
  286.  
  287. player1 = new QMediaPlayer;
  288. audioOutput1 = new QAudioOutput(this);
  289. player1->setAudioOutput(audioOutput1);
  290.  
  291. player2 = new QMediaPlayer;
  292. audioOutput2 = new QAudioOutput(this);
  293. player2->setAudioOutput(audioOutput2);
  294.  
  295. player3 = new QMediaPlayer;
  296. audioOutput3 = new QAudioOutput(this);
  297. player3->setAudioOutput(audioOutput3);
  298.  
  299. player4 = new QMediaPlayer;
  300. audioOutput4 = new QAudioOutput(this);
  301. player4->setAudioOutput(audioOutput4);
  302.  
  303. load_fichier_ini();
  304.  
  305. calcul_tableau_W();
  306. tracer_graduations_signal();
  307. tracer_graduations_FFT();
  308.  
  309. init_TW_1();
  310. init_TAB_FRQ();
  311. init_TAB_lst_notes();
  312. init_TW_type_M();
  313. init_Autres();
  314.  
  315. seuil = doubleSpinBox_seuil->value();
  316.  
  317. spinBox_offset->setValue(-2146); // 2146; +/- 22 pour un décalage de +/-1/4 de ton
  318. spinBox_echx->setValue(498);
  319. write_mode=0;
  320. on_Bt_mode_R_clicked();
  321.  
  322. visu_mesures = false;
  323. on_Bt_toggle_visu_mesures_clicked();
  324.  
  325. visu_ech_tps = true;
  326. on_Bt_toggle_visu_ech_tps_clicked();
  327.  
  328. visu_notes = false;
  329. on_Bt_toggle_visu_notes_clicked();
  330.  
  331. on_tableWidget_type_M_cellClicked(2, 0);
  332.  
  333. spinBox_zoom_2->setValue(2);
  334. Bt_jouer_tout->setStyleSheet("background-color: rgb(200, 200, 200);");
  335.  
  336. progressBar_1->setValue(0);
  337.  
  338. }
  339.  
  340.  
  341. void MainWindow::init_TAB_FRQ()
  342. {
  343. frame_notes->setGeometry(0,0,1920,720);
  344.  
  345. graphicsView3->setGeometry(0, 30, 100, 670);
  346.  
  347. graphicsView4->setGeometry(100, 30, 2000, 700);
  348. graphicsView4->setEnabled(false); // empêche le recadrage auto par le contenu, mais disable le scroll manuel !
  349.  
  350. rectangle1 = new QGraphicsRectItem(0, 0, 2000, 670);
  351.  
  352.  
  353. rectangle1->setPen(QColor(couleur_ligne));
  354. calque_TAB_FRQ->addToGroup(rectangle1);
  355. tracer_graduation_TAB_NOTES();
  356. tracer_grille_MESURES();
  357. }
  358.  
  359.  
  360. void MainWindow::init_TAB_lst_notes()
  361. {
  362. tableWidget_lst_notes->setGeometry(1000, 30, 450, 201);
  363. QStringList liste_entetes1;
  364. liste_entetes1<<"numéro"<<"midi"<<"note"<<"n° barre"<< "temps"<< "durée" << "type";
  365. tableWidget_lst_notes->setHorizontalHeaderLabels (liste_entetes1);
  366. tableWidget_lst_notes->setEditTriggers(QAbstractItemView::NoEditTriggers);
  367. }
  368.  
  369.  
  370.  
  371. void MainWindow::init_Autres()
  372. {
  373. frame_1->setGeometry(1250,865,410,131);
  374. frame_1->setVisible(false);
  375. frame_2->setGeometry(10,865,970,75);
  376. frame_3->setGeometry(1000,865,661,121);
  377. frame_5->setGeometry(0, 730, 1920, 260);
  378. frame_6->setGeometry(10, 950, 901, 40);
  379.  
  380. Bt_efface->setGeometry(915,950,60,21);
  381.  
  382. lineEdit_fichier_FREQ->setGeometry(1250, 0, 700, 26);
  383. Bt_efface_2->setGeometry(1165, 0, 81, 26);
  384. progressBar_1->setGeometry(98, 4, 101, 18); //(1085, 3, 78, 18);
  385. lineEdit_fichier->setGeometry(380, 40, 601, 26);
  386. groupBox_2->setGeometry(380, 70, 241, 161);
  387. groupBox_3->setGeometry(630, 70, 351, 161);
  388.  
  389. groupBox_4->setGeometry(5, 5, 5, 5); // (215, 40, 155, 191)
  390.  
  391. textEdit_ETAT->setGeometry(1480, 30, 400, 200);
  392.  
  393. Bt_prev->setGeometry(880, 702, 92, 26);
  394. Bt_next->setGeometry(980, 702, 92, 26);
  395. Bt_debut->setGeometry(780, 702, 92, 26);
  396. Bt_fin->setGeometry(1080, 702, 92, 26);
  397.  
  398. tracer_gradu_temporelle_signal_entree();
  399. tracer_graduations_signal();
  400. }
  401.  
  402.  
  403. void MainWindow::init_TW_type_M()
  404. {
  405. frame_4->setGeometry(210, 40, 120, 120);
  406.  
  407. tableWidget_type_M->setGeometry(5, 20, 40, 70);
  408. lineEdit_10->setGeometry(60,30,51,26);
  409. label_8->setGeometry(2,2,111,20);
  410.  
  411. QStringList liste_labels; // pour mettre directement dans la 1ere colonne (et pas en entêtes)
  412. liste_labels << "2/4" << "3/4" << "4/4";
  413. for(int n=0; n<3; n++) { tableWidget_type_M->setItem(0, n, new QTableWidgetItem (liste_labels[n])); }
  414. }
  415.  
  416.  
  417. void MainWindow::init_TW_1() // affi entete du fichier wav
  418. {
  419. tableWidget_1->setGeometry(700, 200, 600, 300);
  420. Bt_close_entete->setGeometry(1280, 200, 20, 20);
  421. tableWidget_1->setColumnCount(6);
  422. tableWidget_1->setColumnWidth(4, 120);
  423. tableWidget_1->setColumnWidth(5, 130);
  424.  
  425. tableWidget_1->setVisible(false);
  426. Bt_close_entete->setVisible(false);
  427.  
  428. QStringList liste_entetes;
  429. liste_entetes <<"FileTypeBlocID"
  430. <<"FileSize"
  431. <<"FileFormatID"
  432. <<"FormatBlocID"
  433. <<"BlocSize"
  434. <<"AudioFormat"
  435. <<"NbrCanaux"
  436. <<"Frequence"
  437. <<"ECH (BytePerSec)"
  438. <<"BytePerBloc"
  439. <<"BitsPerSample"
  440. <<"DataBlocID"
  441. <<"DataSize"
  442. <<"durée calculée";
  443.  
  444. tableWidget_1->setVerticalHeaderLabels(liste_entetes);
  445. }
  446.  
  447.  
  448. void MainWindow::load_fichier_ini()
  449. {
  450. QString line;
  451. int p1, p2, p3;
  452.  
  453. dossier_de_travail_ok = false; // à priori
  454. QFile file1(QDir::currentPath() + "/" + "params_FFT.ini"); // dans le dossier de l'exécutable (= QDir::currentPath() )
  455. if (file1.open(QIODevice::ReadOnly | QIODevice::Text))
  456. {
  457. QTextStream in(&file1);
  458. in.reset();
  459. while ( !in.atEnd() )
  460. {
  461. line = in.readLine();
  462. if (line.at(0) !='#')
  463. {
  464. if ((p1 = line.indexOf("<currentDir>")) != -1)
  465. {
  466. p2 = line.indexOf('>',p1);
  467. p3 = line.indexOf("</",p2);
  468. QString s1 = line.mid(p2+1, p3-p2-1);
  469. string_currentDir = s1;
  470. dossier_de_travail_ok = true;
  471. }
  472.  
  473. if ((p1 = line.indexOf("<currentFile>")) != -1)
  474. {
  475. p2 = line.indexOf('>',p1);
  476. p3 = line.indexOf("</",p2);
  477. QString s1 = line.mid(p2+1, p3-p2-1);
  478. string_currentFile = s1;
  479. }
  480. }
  481. }
  482. file1.close();
  483. }
  484. else
  485. {
  486. QString s1 = "fichier .ini non trouvé, je le crée (dans le dossier de l'executable)";
  487. QMessageBox msgBox; msgBox.setText(s1); msgBox.exec();
  488. base_Dir=QDir::currentPath() + "/";
  489. save_fichier_ini();
  490. dossier_de_travail_ok = false;
  491. }
  492.  
  493. lineEdit_current_dir->setText(string_currentDir);
  494. lineEdit_fichier->setText(string_currentDir);
  495. }
  496.  
  497.  
  498.  
  499. QString calcul_couleur(float x) // x = 0.0 à 1.0 ; return: rouge->jaune->vert
  500. {
  501. QString coul_str ="#000000";
  502. QString coul_R_str="#000000";
  503. QString coul_V_str="#000000";
  504.  
  505. int R, V; // rouge, vert
  506.  
  507. V= x * 255;
  508. R= 300 - (1.2 * V);
  509.  
  510. float coxh;
  511. // la formule suivante met le jaune en valeur (avec un cosinus hyperbolique)
  512. coxh = 3.2 - 1.5 * cosh(2.6*x - 1.5); // merci kmplot (testez la courbe f(x) = 3.2 −1.5 * cosh(2.6x − 1.5) )
  513.  
  514. R *= coxh/1.2;
  515. V *= coxh/1.2;
  516.  
  517. coul_R_str.setNum(R, 16); coul_R_str = "0" + coul_R_str; coul_R_str = coul_R_str.right(2);
  518. coul_V_str.setNum(V, 16); coul_V_str = "0" + coul_V_str; coul_V_str = coul_V_str.right(2);
  519. coul_str = coul_R_str + coul_V_str;
  520. coul_str = "#" + coul_str + "00";
  521. return coul_str; // de la forme "#AABB00" (rouge & vert en exa, (bleu à zéro, à traiter))
  522. }
  523.  
  524.  
  525.  
  526. int MainWindow::calcul_y_note(int mid) // en pixels sur la grille
  527. {
  528. int h1, y;
  529. h1 = mid-52;
  530. y =655 - (h1 * 16); // voir 'tracer_graduation_TAB_NOTES()' pour l'espacement vertical
  531. return y;
  532. }
  533.  
  534.  
  535.  
  536. int MainWindow::calcul_hauteur_note(int mid) // de 0 à 11
  537. {
  538. int h1;
  539. h1 = mid-52;
  540. h1 -=5;
  541. h1+=12;
  542. while(h1>=12) {h1-=12;}
  543. if (h1==12) {h1=0;}
  544. return h1; // h1 = 0..11
  545. }
  546.  
  547.  
  548. QString MainWindow::nom_note(int mid)
  549. {
  550. QString s1;
  551.  
  552. int h1 = calcul_hauteur_note(mid);
  553. h1-=3;
  554. if(h1<0){h1+=12;}
  555. if(h1>11){h1-=12;}
  556.  
  557. if((h1<0) || ( h1>= gamme_chromatique.length())) {return "-";}
  558. s1 = gamme_chromatique[h1];
  559. return s1;
  560. }
  561.  
  562.  
  563. float freq_mid(int midi_i) // calcule la fréquence (en Hertz) d'une note à partir de son numéro midi
  564. {
  565. // https://fr.wikipedia.org/wiki/MIDI_Tuning_Standard
  566. float F, A;
  567. A=((float)midi_i-69.0)/12.0;
  568. F= 440 * powf(2,A);
  569. return F;
  570. }
  571.  
  572.  
  573. double calcul_id_midi(double freq_i) // complément de la fonction précédente ( float freq_mid(int midi_i) )
  574. {
  575. double id;
  576. id = 69.0 + 12.0 * log2(freq_i / 440.0);
  577. return id;
  578. }
  579.  
  580.  
  581. int MainWindow::calcul_num_midi(double x) // en fonction de la position horizontale dans le tableau d'affichage de la FFT
  582. {
  583. // on va détecter la note la plus proche de la position donnée
  584. // rappel : x=92 +(m-52) * 40.9 (voir la fonction : 'tracer_graduations_FFT()')
  585.  
  586. double dx;
  587. double xm;
  588.  
  589. for (int m=52; m<94; m++)
  590. {
  591. xm= 92.0 +(m-52) * 40.9;
  592. dx = xm-x;
  593. if (dx<0){dx=-dx;}
  594. if (dx < (40.9/2) )
  595. {
  596. encadrement_note(m);
  597. return m;
  598. }
  599. }
  600. return 0;
  601. }
  602.  
  603.  
  604. void MainWindow::play_note(int midi) // sortie audio
  605. {
  606. QString s1, freq_txt;
  607.  
  608. calcul_hauteur_note(midi);
  609. s1.setNum(midi);
  610.  
  611. s1="notes/"+s1+".wav"; // fichiers audio comprenant une seule note chacun, voir dans le dossier "notes" sur le HDD
  612.  
  613. if (n_player == 1) {player1->setSource(QUrl::fromLocalFile(s1)); player1->play();}
  614. if (n_player == 2) {player2->setSource(QUrl::fromLocalFile(s1)); player2->play();}
  615. if (n_player == 3) {player3->setSource(QUrl::fromLocalFile(s1)); player3->play();}
  616. if (n_player == 4) {player4->setSource(QUrl::fromLocalFile(s1)); player4->play();}
  617. if (n_player == 5) {player5->setSource(QUrl::fromLocalFile(s1)); player5->play();}
  618. n_player++;
  619. if (n_player >= 5) {n_player = 1;}
  620. }
  621.  
  622.  
  623.  
  624.  
  625. void MainWindow::effacer_calque(QGraphicsScene *scene_i, QGraphicsItemGroup *calque_i)
  626. {
  627. foreach( QGraphicsItem *item, scene_i->items( calque_i->boundingRect() ) )
  628. {if( item->group() == calque_i ) { delete item; }}
  629. }
  630.  
  631.  
  632. MainWindow::~MainWindow()
  633. {
  634.  
  635. }
  636.  
  637.  
  638.  
  639. void MainWindow::Etiquette(int x, int y, QString s, QString coul_txt, QString coul_fond, QString coul_bord,QGraphicsItemGroup *calque_i )
  640. {
  641. // fond noir sous le texte
  642. rect1 = new QGraphicsRectItem(x, y+4, 40, 18);
  643. rect1->setPen(QColor(coul_bord)); // bordure
  644. rect1->setBrush(QColor(coul_fond)); // fond
  645. calque_i->addToGroup(rect1);
  646.  
  647. //texte
  648. GraphicsTextItem = new QGraphicsTextItem(s);
  649. GraphicsTextItem->setPos(x, y);
  650. GraphicsTextItem->setDefaultTextColor(coul_txt);
  651. calque_i->addToGroup(GraphicsTextItem);
  652. }
  653.  
  654.  
  655.  
  656. void MainWindow::tracer_graduations_FFT() // sur onglet
  657. {
  658. double x=0;
  659. QString s1;
  660. int y_bas =450; // 350
  661.  
  662. // cadre
  663. rectangle1 = new QGraphicsRectItem(0, 0, 1900, y_bas);
  664. QPen pen1("#12FF00");
  665. rectangle1->setPen(pen1);
  666.  
  667. calque_reticule1->addToGroup(rectangle1);
  668.  
  669. s1 = "midi :"; // numéro midi
  670. GraphicsTextItem = new QGraphicsTextItem(s1);
  671. GraphicsTextItem->setDefaultTextColor("#FFFFFF");
  672. GraphicsTextItem->setPos(30, 20);
  673. // if(x<1900)
  674. {
  675. calque_reticule1->addToGroup(GraphicsTextItem);
  676. }
  677.  
  678. // positions des notes midi
  679. x= 96;
  680. for(int m=52; m<=94; m++)
  681. {
  682. ligne1 = new QGraphicsLineItem(x, 70, x, y_bas);
  683. ligne1->setPen(pen_reticule);
  684. calque_reticule1->addToGroup(ligne1);
  685.  
  686. s1.setNum(m); // numéro midi
  687. GraphicsTextItem = new QGraphicsTextItem(s1);
  688. GraphicsTextItem->setDefaultTextColor("#D3D7CF");
  689. GraphicsTextItem->setPos(x-15, 20);
  690. if(x<1900) {calque_reticule1->addToGroup(GraphicsTextItem); }
  691.  
  692. int h1 = calcul_hauteur_note(m);
  693. h1-=3;
  694. if(h1<0){h1+=12;}
  695. if(h1>11){h1-=12;}
  696. if((h1<0) || ( h1>= gamme_chromatique.length())) {return;}
  697. s1 = " " + gamme_chromatique[h1]; // nom de la note
  698. GraphicsTextItem = new QGraphicsTextItem(s1);
  699. GraphicsTextItem->setDefaultTextColor(liste_couleurs[h1]);
  700. GraphicsTextItem->setPos(x-18, 40);
  701. if(x<1900) {calque_reticule1->addToGroup(GraphicsTextItem); }
  702.  
  703. x+=40.9; // espacement des graduation
  704. }
  705. }
  706.  
  707.  
  708.  
  709. float MainWindow::calcul_x_barre(int n_barre)
  710. {
  711. // calcul de l'abscisse (en pixel) d'une barre de mesure
  712.  
  713. float x0 = 100; // à voir !
  714. float pas_grille = doubleSpinBox_dt->value()/2.0 * zoom_x;
  715. float x = x0 + float(n_barre) * pas_grille;
  716. return x;
  717. }
  718.  
  719.  
  720.  
  721.  
  722. void MainWindow::tracer_grille_MESURES()
  723. {
  724. //grille temporelle (mesures et temps forts/faibles) sur le TAB NOTES (barres verticales)
  725. QString s1;
  726. QString bleu_clair = "#00AAFF";
  727. QString jaune = "#FFFF00";
  728. QString gris_clair = "#CCCCCC";
  729. QString gris_fonce = "#777777";
  730. QString gris_tres_fonce = "#444444";
  731. QString couleur_i;
  732. QPen pen_i;
  733. float x_i1;
  734.  
  735. int num_mesure;
  736.  
  737. effacer_calque(scene4, calque_grille_mesures);
  738.  
  739. if ( visu_mesures)
  740. {
  741. for(int n=0; n<=120*16; n++) //42
  742. {
  743. x_i1 = calcul_x_barre(n);
  744.  
  745. couleur_i = gris_tres_fonce; // à priori
  746. if ( n%(Ta/2) == 0) { couleur_i = gris_fonce; }
  747. if ( n%(4) == 0) { couleur_i = gris_clair; }
  748.  
  749. if ( n%(4*Ta) == 0) // 1er temps fort de la mmesure
  750. {
  751. // numérotation des mesures, en bas, chiffres jaunes
  752. num_mesure = n /Ta/4;
  753. s1.setNum(num_mesure);
  754. Etiquette(x_i1-10, 650, s1, "#FFFF00", "#000000", "#0000FF", calque_grille_mesures);
  755. }
  756. //if ( n%(4*m)== 0) {couleur_i = jaune;}
  757.  
  758. pen_i.setColor(couleur_i);
  759. ligne1 = new QGraphicsLineItem(x_i1, 0.0, x_i1, 650.0);
  760. ligne1->setPen(pen_i);
  761. calque_grille_mesures->addToGroup(ligne1);
  762.  
  763. if (n==0)
  764. {
  765. /* A REVOIR
  766.  
  767.   // représentation de la durée d'une NOIRE sous la forme d'un petit rectangle horizontal
  768.   // afin de bien visualiser le type de mesures à la clef : 2/4 .. 3/4 .. 4/4 .. etc
  769.   GraphicsTextItem = new QGraphicsTextItem("noire");
  770.   GraphicsTextItem->setDefaultTextColor("#AAAAAA");
  771.   GraphicsTextItem->setPos(x_i1+1.0, 595);
  772.   calque_grille_mesures->addToGroup(GraphicsTextItem);
  773.  
  774.   rect2 = new QGraphicsRectItem(x_i1+1.0, 620, (4.0 * pas_grille) -2, 5);
  775.  
  776.   QBrush br2; br2.setStyle(Qt::SolidPattern); br2.setColor("#222222");rect2->setBrush(br2);
  777.   pen_i.setColor("#FFFFFF");
  778.   rect2->setPen(pen_i);
  779.   calque_grille_mesures->addToGroup(rect2);
  780.   s1 += " <- n° mesure";
  781.   GraphicsTextItem = new QGraphicsTextItem(s1);
  782.   GraphicsTextItem->setDefaultTextColor("#FFFF00"); // jaune
  783.   GraphicsTextItem->setPos(x_i1-10.0, 650);
  784.   calque_grille_mesures->addToGroup(GraphicsTextItem);
  785.   */
  786. }
  787. }
  788. }
  789. }
  790.  
  791.  
  792. void MainWindow::afficher_titre_calque(QString titre, int x, int y, QGraphicsItemGroup *calque_i)
  793. {
  794. GraphicsTextItem = new QGraphicsTextItem(titre);
  795. GraphicsTextItem->setDefaultTextColor("#FFFFFF");
  796. GraphicsTextItem->setPos(x, y);
  797. calque_i->addToGroup(GraphicsTextItem);
  798. }
  799.  
  800.  
  801.  
  802. void MainWindow::tracer_graduation_TAB_NOTES() // midi ; en colonne à gauche + noms des notes
  803. {
  804. // positions des notes midi
  805. QString s1;
  806. int y= 640; //640
  807. for(int m=52; m<=92; m++)
  808. {
  809. //ligne1 = new QGraphicsLineItem(100, 0, 100, 350);
  810. //ligne1->setPen(pen_reticule);
  811. //calque_reticule1->addToGroup(ligne1);
  812.  
  813. s1.setNum(m); // numéro midi
  814. GraphicsTextItem = new QGraphicsTextItem(s1);
  815. GraphicsTextItem->setDefaultTextColor("#D3D7CF");
  816. GraphicsTextItem->setPos(0, y);
  817. if(y> -50) {calque_gradu_TAB_FRQ->addToGroup(GraphicsTextItem); }
  818.  
  819. int h1 = calcul_hauteur_note(m);
  820. h1-=3;
  821. if(h1<0){h1+=12;}
  822. if(h1>11){h1-=12;}
  823. if((h1<0) || ( h1>= gamme_chromatique.length())) {return;}
  824. s1 = " " + gamme_chromatique[h1]; // nom de la note
  825. GraphicsTextItem = new QGraphicsTextItem(s1);
  826. GraphicsTextItem->setDefaultTextColor(liste_couleurs[h1]);
  827. // GraphicsTextItem->setHtml("<div style='background-color:#666666;'>" + s1 + "</div>");
  828.  
  829. if (m==69) // La 440
  830. {
  831. rect3 = new QGraphicsRectItem(30, y+6, 40, 15);
  832. QBrush br2;
  833. QPen pen_i;
  834. pen_i.setColor("#AAAAAA");
  835. rect3->setPen(pen_i);
  836. calque_gradu_TAB_FRQ->addToGroup(rect3);
  837.  
  838. }
  839.  
  840. GraphicsTextItem->setPos(30, y);
  841. if(y > -50) {calque_gradu_TAB_FRQ->addToGroup(GraphicsTextItem); }
  842.  
  843. y-=16; // espacement des graduations
  844. }
  845. }
  846.  
  847.  
  848.  
  849. void MainWindow::tracer_graduations_signal() // sur le 1er onglet (Source.wav)
  850. {
  851. /*
  852.   midi57 = 110Hz
  853.   1/110Hz = 9ms -> delta x = 142-46 = 96px
  854.   echelle x = 96/9 = 10.6 px/ms
  855.   soit:
  856.   10ms -> 106px
  857. */
  858. double x;
  859. double nb_grad_max;
  860. double intervalle; // séparant les graduations
  861. QPen pen1;
  862. // int num_x;
  863. //QString sti;
  864. // uint decal = 3; // leger decallage vertical pour ne pas masquer la trace
  865.  
  866. /*
  867.   rectangle1 = new QGraphicsRectItem(5, 452, 1900, 200);
  868.   pen1.setColor("#0073FF");
  869.   rectangle1->setPen(pen1);
  870.   calque_reticule1->addToGroup(rectangle1);
  871.  
  872.   ligne1 = new QGraphicsLineItem(10, 475, 1900, 475); // ligne horizontale
  873.   pen1.setColor("#0073FF");
  874.   ligne1->setPen(pen1);
  875.   calque_reticule1->addToGroup(ligne1);
  876. */
  877. afficher_titre_calque("Partie échantillonée du signal", 0, 452, calque_reticule1);
  878.  
  879. // lignes verticales
  880.  
  881. intervalle = 106;
  882. nb_grad_max = 18;
  883.  
  884. for (int i=0; i<=nb_grad_max; i++)
  885. {
  886. x = intervalle * i;
  887.  
  888. ligne1 = new QGraphicsLineItem(x, 452, x, 780);
  889. ligne1->setPen(pen_reticule);
  890. /*
  891.   sti.setNum(num_x);
  892.   sti+=" ms";
  893.   GraphicsTextItem = new QGraphicsTextItem(sti);
  894.   GraphicsTextItem->setDefaultTextColor(couleur_texte);
  895.   GraphicsTextItem->setPos(x,550);
  896.   if(x<1900) {calque_reticule1->addToGroup(GraphicsTextItem); }// évite que l'écriture ne déborde du cadre a droite
  897. */
  898. }
  899.  
  900. /*
  901. // lignes horizontales
  902.   intervalle = 55;
  903.   nb_grad_max = 3;
  904.   for (i=0; i<=nb_grad_max; i++)
  905.   {
  906.   y = 300 - intervalle * i;
  907.  
  908.   ligne1 = new QGraphicsLineItem(0, y, 1350, y);
  909.   ligne1->setPen(pen_reticule);
  910.   calque_reticule1->addToGroup(ligne1);
  911.   }
  912.   texte_mid = new QGraphicsTextItem("Silicium628");
  913.   texte_mid->setDefaultTextColor(couleur_signature);
  914.   texte_mid->setPos(5,5);
  915.   calque_reticule1->addToGroup(texte_mid);
  916.  */
  917.  
  918. scene1->addItem(calque_reticule1);
  919. }
  920.  
  921.  
  922.  
  923. void MainWindow::tracer_gradu_temporelle_signal_entree()
  924. {
  925. // GRADUATION TEMPORELLE sur le signal d'entrée, en secondes
  926.  
  927. QString s1;
  928. int x=0;
  929. int dy = 75;
  930. float pas =8;
  931.  
  932. for(int n=0; n<1200; n++)
  933. {
  934.  
  935. if (n%10 == 0) { dy = 75; }
  936. else if (n%5 == 0) {dy = 20; }
  937. else {dy = 10;}
  938.  
  939. x = n *pas;
  940. ligne1 = new QGraphicsLineItem(x, -dy, x, dy);
  941. QPen P1("#AAAAAA");
  942. ligne1->setPen(P1);
  943. calque_reticule2->addToGroup(ligne1);
  944.  
  945. if (n%10 == 0)
  946. {
  947. s1.setNum(n/10);
  948. s1+="s";
  949. GraphicsTextItem = new QGraphicsTextItem(s1);
  950. GraphicsTextItem->setDefaultTextColor(couleur_texte);
  951. GraphicsTextItem->setPos(x,55);
  952. if(x<6000) {calque_reticule2->addToGroup(GraphicsTextItem); }//3000
  953. }
  954. }
  955. }
  956.  
  957.  
  958.  
  959. void MainWindow::tracer_signal_complet() // totalité du fichier wav (dans le cadre du bas du 1er onglet)
  960. {
  961. uint8_t octet_n;
  962. double R;
  963. double offset_y = 0.0;
  964. double echelle_y =2.0;
  965. double echelle =0.074;
  966.  
  967. int x, y, memo_x, memo_y;
  968. double min= 1000000.0;
  969. double max=-1000000.0;
  970.  
  971. int pas = 10 * pas_echantillonage; // 240;
  972. // le signal wav est échantilloné à l'origine à 96000 Bps (séréo 2*fois 48000 Bps)
  973. // en ne prenant qu'un octet sur 24 on obtient 4000 Bps stéréo, c.a.d 2000 Bps mono.
  974.  
  975. QString s1;
  976.  
  977. effacer_calque(scene2, calque_trace_signal2 );
  978. segment_trace = new QGraphicsLineItem(0, offset_y, 512, offset_y);
  979. QPen P1("#0000FF");
  980. segment_trace->setPen(P1); //couleur_ligne
  981. calque_trace_signal2->addToGroup(segment_trace);
  982.  
  983. x=0;
  984. y=offset_y;
  985. long n_max = 80000; // (2 000 000/25 = 80 000) voir le fonction 'garnis_temp_data()'
  986.  
  987. long n;
  988. long i=0;
  989. int j=0;
  990.  
  991. for(n=0; n<n_max; n+=10)
  992. {
  993. memo_x = x;
  994. memo_y = y;
  995. x = echelle * n;
  996.  
  997. octet_n = temp_data[i]; // canal 1
  998. R = octet_n - 128; // pour oter la composante continue propre au codage par des octets non signés
  999. R *= echelle_y;
  1000. y=offset_y + R;
  1001.  
  1002. // recherche du mini-maxi:
  1003. if (y < min) {min = y;}
  1004. if (y > max) {max = y;}
  1005.  
  1006. // if (x<3000)
  1007. {
  1008. segment_trace = new QGraphicsLineItem(memo_x ,memo_y, x, y);
  1009. QPen P1("#0055FF");
  1010. segment_trace->setPen(P1);
  1011. calque_trace_signal2->addToGroup(segment_trace);
  1012. }
  1013.  
  1014. i++; // pour sauter le canal B (le signal dans le fichier .wav est stéréo)
  1015. i+= pas;
  1016.  
  1017. j++;
  1018.  
  1019. }
  1020. //scene1->addItem(calque_trace_signal);
  1021. s1.setNum(min);
  1022. //lineEdit_4->setText(s1);
  1023. s1.setNum(max);
  1024. // lineEdit_5->setText(s1);
  1025. }
  1026.  
  1027.  
  1028.  
  1029. void MainWindow::encadrement_signal(int x, int dx)
  1030. {
  1031. ligne1 = new QGraphicsLineItem(x, -80, x, 80);
  1032. ligne1->setPen(pen_encadrement);
  1033. calque_encadrement2->addToGroup(ligne1);
  1034.  
  1035. ligne1 = new QGraphicsLineItem(x+dx, -80, x+dx, 80);
  1036. ligne1->setPen(pen_encadrement);
  1037. calque_encadrement2->addToGroup(ligne1);
  1038.  
  1039. ligne1 = new QGraphicsLineItem(x, -80, x+dx, -80);
  1040. ligne1->setPen(pen_encadrement);
  1041. calque_encadrement2->addToGroup(ligne1);
  1042.  
  1043. ligne1 = new QGraphicsLineItem(x, 80, x+dx, 80);
  1044. ligne1->setPen(pen_encadrement);
  1045. calque_encadrement2->addToGroup(ligne1);
  1046. }
  1047.  
  1048.  
  1049.  
  1050. void MainWindow::encadrement_note(int n_midi) // par un rectangle
  1051. {
  1052. double x, dx, y, dy;
  1053.  
  1054. x=92 - 13 + ((double)n_midi-52.0) * 40.9;
  1055. dx=35;
  1056. y=16;
  1057. dy=50;
  1058.  
  1059. rectangle1 = new QGraphicsRectItem(x, y, dx, dy);
  1060. rectangle1->setPen(pen_encadrement);
  1061. calque_trace_FFT->addToGroup(rectangle1);
  1062. }
  1063.  
  1064.  
  1065.  
  1066. void MainWindow::tracer_signal_a_convertir() //partie à analyser s=f(t) (signal incident, pas le FFT); dans le cadre du haut
  1067. {
  1068. double offset_y = 575.0;
  1069. double echelle =5.0;
  1070. uint8_t octet_n;
  1071. double R;
  1072. double x, y, memo_x, memo_y;
  1073. double min= 1000000.0;
  1074. double max=-1000000.0;
  1075. QString s1;
  1076.  
  1077. effacer_calque(scene1,calque_trace_signal1 );
  1078. segment_trace = new QGraphicsLineItem(0, offset_y, 512, offset_y);
  1079. segment_trace->setPen(QColor(couleur_ligne));
  1080. calque_trace_signal1->addToGroup(segment_trace);
  1081.  
  1082. long n;
  1083. long i=0;
  1084. x=0;
  1085. y=offset_y;
  1086. int pas = 64;
  1087. for(n=0; n<nb_ech/2; n++)
  1088. {
  1089. memo_x = x;
  1090. memo_y = y;
  1091. x = echelle * n;
  1092.  
  1093. octet_n = temp_data[i]; // canal 1
  1094. R = octet_n - 128; // pour oter la composante continue propre au codage par des octets non signés
  1095. // R /= 10.0;
  1096. y=offset_y + R;
  1097.  
  1098. if (y < min) {min = y;}
  1099. if (y > max) {max = y;}
  1100.  
  1101. if (x<1800)
  1102. {
  1103. segment_trace = new QGraphicsLineItem(memo_x ,memo_y, x, y);
  1104. segment_trace->setPen(pen_trace1);
  1105. calque_trace_signal1->addToGroup(segment_trace);
  1106. }
  1107.  
  1108. i++; // pour sauter le canal B (le signal dans le fichier .wav est stéréo)
  1109. i+= pas;
  1110. }
  1111. //scene1->addItem(calque_trace_signal);
  1112. s1.setNum(min);
  1113. //lineEdit_4->setText(s1);
  1114. s1.setNum(max);
  1115. // lineEdit_5->setText(s1);
  1116. }
  1117.  
  1118.  
  1119.  
  1120.  
  1121. void MainWindow::tracer_notes_FFT() // sur onglet NOTES
  1122. {
  1123. double offset_x= spinBox_offset->value(); // ref -2146 ; +/- 22 pour un décalage de +/-1/4 de ton
  1124. double echelle_x =spinBox_echx->value(); // 498
  1125. double offset_y = 350.0;
  1126.  
  1127. uint n;
  1128. double module_FFT;
  1129. double x, y;
  1130. double memo_x[5]={0,0,0,0,0};
  1131. double memo_y[5]={0,0,0,0,0};
  1132. double x0, y0; // fréquence centrale trouvée comme résultat (points d'inflexions de la courbe)
  1133.  
  1134. double z=1.6;
  1135. //int x1=0;
  1136. //int x2=0;
  1137. int num_raie=0;
  1138.  
  1139. QPen pen1("#12FF00");
  1140.  
  1141. if(!rapide)
  1142. {
  1143. effacer_calque(scene1,calque_trace_FFT );
  1144. effacer_calque(scene1,calque_lignes_F_zero );
  1145. }
  1146.  
  1147. x=0;
  1148. y = offset_y;
  1149. ENR_FFT enr_i;
  1150. for(n=0; n<nb_ech; n++)
  1151. {
  1152. //qDebug() << "n" << n;
  1153.  
  1154. memo_x[0] = x;
  1155. memo_y[0] = y;
  1156. // x = offset_x + echelle_x * n; // echelle linéaire -> pas top
  1157. x = offset_x + echelle_x * log2((double)(n+1)); // échelle logarithmique afin que les tons soient équi-espacés
  1158.  
  1159. // ci-dessous 'a' est la partie réelle du complexe, et 'b' la partie imaginaire
  1160. // on calcule le module :
  1161. module_FFT = z * sqrt( tab_X[n].a * tab_X[n].a + tab_X[n].b * tab_X[n].b ); // z * racine(a²+b²)
  1162.  
  1163. y = module_FFT*10.0; // amplitude
  1164. y = offset_y - y; // offset et inversion du sens d'affichage because à l'écran les y croissent de haut en bas
  1165.  
  1166.  
  1167. // décale la pile memo_x
  1168. // puis mise en mémoire (empile) le dernier point
  1169. memo_x[4] = memo_x[3]; memo_y[4] = memo_y[3];
  1170. memo_x[3] = memo_x[2]; memo_y[3] = memo_y[2];
  1171. memo_x[2] = memo_x[1]; memo_y[2] = memo_y[1];
  1172. memo_x[1] = memo_x[0]; memo_y[1] = memo_y[0];
  1173. memo_x[0] = x;
  1174. memo_y[0] = y;
  1175.  
  1176. if((x>20) && (x<1900))
  1177. {
  1178. //y *=1.0;
  1179. if (x > -100)
  1180. {
  1181. if (!rapide)
  1182. {
  1183. segment_trace = new QGraphicsLineItem(memo_x[1] ,memo_y[1], x, y);
  1184. segment_trace->setPen(pen_trace2);
  1185. calque_trace_FFT->addToGroup(segment_trace);
  1186. }
  1187.  
  1188. }
  1189.  
  1190. // DETECTION DES NOTES
  1191.  
  1192. //----------------------------------------------------------------------------------
  1193. // détection direct des points hauts (points d'inflexion de la courbe)
  1194. // on pourrait calculer la dérivée de la courbe, et détecter les valeurs pour lesquelles elle s'annule
  1195. // problème : peut ne pas détecter si le sommet est un pic (discontinuité)
  1196. //----------------------------------------------------------------------------------
  1197.  
  1198. // Autre méthode :
  1199. // détection de 2 doublets de points de part et d'autre, montants puis descendant
  1200. // le sommet se situe donc entre les 2 doublets
  1201.  
  1202. // la DETECTION s'effectue ICI
  1203.  
  1204. // ATTENTION : la ligne qui suit détermine la stratégie utilisée et son paramétrage influe grandement
  1205. // sur la qualité du résultat.
  1206. // on doit pouvoir l'améliorer mais attention : toujours expérimenter sur des données réelles (air de musique)
  1207. // avant de valider la moindre "améloration".
  1208.  
  1209. //if ( (memo_y[3] - memo_y[2]) >0.5 && (memo_y[1] - memo_y[2]) >0.5 )
  1210. if ( (memo_y[3] - memo_y[2]) > 1.1 && (memo_y[1] - memo_y[2]) > 1.1 )
  1211. {
  1212. x0 = memo_x[2]; // point d'inflexion probable
  1213. y0 = memo_y[2];
  1214.  
  1215. if( !rapide) // pas d'affichage en mode rapide
  1216. {
  1217. ligne1 = new QGraphicsLineItem(x0, 60, x0, 350);
  1218. ligne1->setPen(pen1); // BLEU
  1219. calque_lignes_F_zero->addToGroup(ligne1);
  1220. ligne1 = new QGraphicsLineItem(x0, T_i-1, x0, T_i+1);
  1221. ligne1->setPen(pen1);
  1222. }
  1223.  
  1224. int m0 = 0;
  1225. m0 = calcul_num_midi(x0);
  1226.  
  1227. enr_i.t=T_i;
  1228. enr_i.num=num_raie;
  1229. enr_i.midi=m0;
  1230. enr_i.amplitude=y0;
  1231.  
  1232. // tracer sur tableau fréquences
  1233. if(num_raie<10) // 6
  1234. {
  1235. liste_ENR_FFT << enr_i; // memorisation ; donc 5 notes max pour un temps (T_i) donné
  1236. // les notes ayant même T_i seront considérées comme simultanées (accord)
  1237. tracer_1enr_sur_TAB_NOTES(enr_i);
  1238. }
  1239. num_raie++;
  1240. }
  1241. }
  1242. }
  1243. T_i++;
  1244. // T_i est ici incrémenté à chaque appel de la fonction
  1245. // sachant que chaque appel de cette fonction analyse 1024 échantillons du signal.
  1246. // et que chaque échantillon représente une durée = 0.5ms du signal d'origine
  1247. // donc T_i est (virtuellement) incrémenté toutes les 1024*0.5ms = 512ms;
  1248. // pourquoi 'virtuellement' ? parce que chaque échantillon "REPRESENTE" une durée de 0.5 ms
  1249. // mais ne "DURE PAS" 0.5ms; L'analyse s'effectue à très haute vitesse sur un signal pré-échantilloné.
  1250. // de quel chapeau sort ce 0.5ms? Voir la fontion 'void MainWindow::remplir_tableau_echantillons_signal()'
  1251.  
  1252. num_raie=0;
  1253. //affi_notes();
  1254.  
  1255. }
  1256.  
  1257.  
  1258. void MainWindow::tracer_echelle_temps_TAB_NOTES() // en secondes sur l'onglet NOTES
  1259. {
  1260. QString s1;
  1261. float x, x0, dx;
  1262. int offset_x = 80;
  1263. int y0 = 620;
  1264. float nbs;
  1265.  
  1266. effacer_calque(scene4, calque_echelle_temporelle);
  1267.  
  1268. if (visu_ech_tps == true) {y0 = 0;} // grandes lignes
  1269. for(int n=0; n<=120; n++)
  1270. {
  1271. x0 = 10.0 * doubleSpinBox_T0->value();
  1272. dx = 1000.0 * pas_echantillonage/256.0; // =93.75
  1273.  
  1274. x = x0 + dx * zoom_x * (float)n;
  1275.  
  1276. ligne1 = new QGraphicsLineItem(offset_x + x, y0-5, offset_x + x, 650);
  1277. QPen pen1;
  1278. pen1.setColor("#00FF00"); //
  1279. ligne1->setPen(pen1);
  1280. calque_echelle_temporelle->addToGroup(ligne1);
  1281.  
  1282. nbs = (float) n;
  1283. s1.setNum(nbs, 10, 0); // base 10, 0 décimale
  1284. s1 += "s";
  1285.  
  1286. Etiquette(offset_x + x, 630, s1, "#FFFFFF", "#000000", "#00FF00", calque_echelle_temporelle);
  1287. }
  1288. }
  1289.  
  1290.  
  1291.  
  1292. void MainWindow::tracer_1enr_sur_TAB_NOTES(ENR_FFT enr_i) // c.a.d. ayant la durée élémentaire T_i = 256 ms
  1293. {
  1294. int T_i;
  1295. //uint8_t num_raie;
  1296. uint8_t m0;
  1297. double yH, yL;
  1298. double y0, y2, dy, dy2;
  1299. double offset_y = 350.0;
  1300. QString couleur1;
  1301.  
  1302. T_i = zoom_x * enr_i.t;
  1303.  
  1304. m0 = enr_i.midi;
  1305. y0 = enr_i.amplitude;
  1306.  
  1307. if (checkBox_flitrer->isChecked() && (m0 != spinBox_filtre->value())) {return;}
  1308.  
  1309. int v; // v comme 'vertical'
  1310.  
  1311. v= 655 - (16 * (m0-52) );
  1312. y2 = -y0 + offset_y;
  1313.  
  1314. dy = y2/30.0; // 40
  1315. //dy = y2/10;
  1316.  
  1317. //dy=dy*dy; // pour un meilleur affichage ; A VOIR !!!!
  1318. //dy /=5.0;
  1319.  
  1320. dy *= gain;
  1321.  
  1322. if ( dy > 200) { dy = 200;} // bridage amplitude max
  1323.  
  1324. if(v > 655) {return;}
  1325.  
  1326. if (dy > seuil)
  1327. {
  1328. dy2 = dy;
  1329. if (checkBox_norm->isChecked()) {dy2=5; } // bride la hauteur des tirets
  1330. float x = 80.0 + T_i;
  1331. yH = v+dy2/2;
  1332. yL = v-dy2/2;
  1333. // rabotage pour éviter le scrolling de l'affichage:
  1334. if(yH > 655) {yH = 655;}
  1335. if(yL <0) {yH = 0;}
  1336.  
  1337. //ligne1 = new QGraphicsLineItem(x, yL, x, yH);
  1338.  
  1339. rectangle1 = new QGraphicsRectItem(x, v-dy2/2, zoom_x-2, dy2);
  1340. int h1 = calcul_hauteur_note(m0);
  1341. h1-=3;
  1342. if(h1<0){h1+=12;}
  1343. if(h1>11){h1-=12;}
  1344. couleur1 = liste_couleurs[h1];
  1345. if (checkBox_norm->isChecked()) // utilise une couleur en fonction de l'amplitude du signal
  1346. {
  1347. float dy3 = dy/ 20;
  1348. if (dy3 > 0.8) {dy3 = 0.8;}
  1349. couleur1 = calcul_couleur(dy3);
  1350. }
  1351.  
  1352. QPen pen1;
  1353. pen1.setColor(couleur1);
  1354.  
  1355. rectangle1->setPen(pen1);
  1356. rectangle1->setBrush(QColor(couleur1));
  1357.  
  1358. QBrush br1;
  1359. br1.setStyle(Qt::SolidPattern);
  1360. br1.setColor(couleur1);
  1361. rectangle1->setBrush(br1);
  1362.  
  1363. calque_TAB_FRQ->addToGroup(rectangle1);
  1364.  
  1365. graphicsView1->verticalScrollBar()->setValue(0);
  1366. }
  1367. }
  1368.  
  1369.  
  1370.  
  1371. void MainWindow::retracer_TAB_FRQ()
  1372. {
  1373. ENR_FFT enr_i;
  1374. uint16_t n_max = liste_ENR_FFT.length();
  1375. if (n_max == 0) return;
  1376. //effacer_calque(scene1,calque_trace_FFT );
  1377. tracer_graduation_TAB_NOTES();
  1378.  
  1379. calque_TAB_FRQ->setPos(0, 0);
  1380. for(uint16_t n=0; n<n_max-1; n++)
  1381. {
  1382. enr_i = liste_ENR_FFT[n];
  1383. tracer_1enr_sur_TAB_NOTES(enr_i);
  1384. }
  1385.  
  1386. float pas_grille = doubleSpinBox_dt->value()/2.0 * zoom_x;
  1387. double offset_x = 10 * doubleSpinBox_x0->value() + spinBox_d_barres->value() * pas_grille;
  1388. calque_TAB_FRQ->setPos(offset_x, 0);
  1389. }
  1390.  
  1391.  
  1392.  
  1393. void RAZ_tableau_echantillons()
  1394. {
  1395. uint n;
  1396. for(n=0; n < nb_ech; n++)
  1397. {
  1398. ech[n].a = 0; // partie reelle
  1399. ech[n].b = 0; // partie imaginaire
  1400. }
  1401. }
  1402.  
  1403.  
  1404.  
  1405.  
  1406. void MainWindow::remplir_tableau_echantillons_sinus()
  1407. {
  1408. // création du signal à analyser
  1409. uint n, n_max;
  1410. double R;
  1411. double frq_echantillonnage=48000; // Hz
  1412. double Te; // période d'échantillonage
  1413.  
  1414. Te = 1.0 / frq_echantillonnage;
  1415. Te *=15.0;
  1416.  
  1417. if (bz==true) {n_max = nb_ech /4; } else {n_max = nb_ech; }
  1418.  
  1419. for(n=0; n < n_max; n++) // nb d'échantillons
  1420. {
  1421. R= cos(2.0 * M_PI * frequence1 * n * Te );
  1422.  
  1423. if (modul) {R *= 1 + 0.8 * cos(2 * M_PI * frequence3 * n * Te);} // modulation d'amplitude
  1424.  
  1425. if (second_Frq) {R+=cos(2 * M_PI * frequence2 * n * Te); }
  1426. if (hamming) { R = R * (1- cos (2* M_PI * n / n_max ));}
  1427.  
  1428. R/=10;
  1429. ech[n].a = R; // partie reelle
  1430. ech[n].b = 0; // partie imaginaire
  1431. }
  1432. }
  1433.  
  1434.  
  1435.  
  1436. uint bit_reversal(uint num, uint nb_bits)
  1437. {
  1438. uint r = 0, i, s;
  1439. if ( num > (1<< nb_bits)) { return 0; }
  1440.  
  1441. for (i=0; i<nb_bits; i++)
  1442. {
  1443. s = (num & (1 << i));
  1444. if(s) { r |= (1 << ((nb_bits - 1) - i)); }
  1445. }
  1446. return r;
  1447. }
  1448.  
  1449.  
  1450.  
  1451. void MainWindow::bit_reverse_tableau_X()
  1452. {
  1453.  
  1454. // recopie les échantillons en les classant dans l'ordre 'bit reverse'
  1455. uint n,r;
  1456.  
  1457. for(n=0; n < nb_ech; n++) // nb d'échantillons
  1458. {
  1459. r=bit_reversal(n,nb_etapes);
  1460. tab_X[n] = ech[r];
  1461. }
  1462. }
  1463.  
  1464.  
  1465.  
  1466. void MainWindow::calcul_tableau_W()
  1467. {
  1468. if (tableau_w_plein == true) {return;}
  1469. // calcul et memorisation dans un tableau des twiddle factors (facteurs de rotation)
  1470. uint n;
  1471. double x;
  1472.  
  1473. for(n=0; n<(nb_ech/2-1); n++)
  1474. {
  1475. x=2.0*M_PI * n / nb_ech;
  1476.  
  1477. tab_W[n].a = cos(x); // partie reelle
  1478. tab_W[n].b = -sin(x); // partie imaginaire
  1479. }
  1480. tableau_w_plein = true;
  1481. }
  1482.  
  1483.  
  1484.  
  1485. void MainWindow::calcul_FFT()
  1486. {
  1487. Complexe produit; // voir la classe "Complexe" : complexe.h et complexe.ccp
  1488.  
  1489. uint etape, e1, e2, li, w, ci;
  1490. uint li_max=nb_ech;
  1491.  
  1492. e2=1;
  1493.  
  1494. for (etape=1; etape<=nb_etapes; etape++)
  1495. {
  1496. e1=e2; //(e1 évite d'effectuer des divisions e2/2 plus bas)
  1497. e2=e2+e2; // plus rapide que *=2
  1498.  
  1499. for (li=0; li<li_max; li+=1)
  1500. {
  1501. ci=li & (e2-1); // ET bit à bit
  1502. if (ci>(e1-1))
  1503. {
  1504. w=li_max/e2*(li & (e1 -1)); // ET bit à bit calcul du numéro du facteur de rotation W
  1505.  
  1506. produit = tab_W[w] * tab_X[li]; // le twiddle factor est lu en memoire; le produit est une mutiplication de nb complexes. Voir "complexe.cpp"
  1507.  
  1508. tab_X[li]=tab_X[li-e1] - produit; // concerne la ligne basse du croisillon; soustraction complexe; Voir "complexe.cpp"
  1509. tab_X[li-e1]=tab_X[li-e1] + produit; // concerne la ligne haute du croisillon; addition complexe; Voir "complexe.cpp"
  1510. }
  1511. }
  1512. }
  1513. }
  1514.  
  1515.  
  1516.  
  1517. void MainWindow::on_spinBox_frq_valueChanged(int arg1) // SELECTEUR DE FREQUENCE 1
  1518. {
  1519. effacer_calque(scene1,calque_trace_FFT );
  1520. frequence1 = arg1;
  1521. RAZ_tableau_echantillons();
  1522. remplir_tableau_echantillons_sinus();
  1523. tracer_signal_a_convertir();
  1524. calcul_tableau_W();
  1525. bit_reverse_tableau_X();
  1526. calcul_FFT(); // pour 1 cluster
  1527. // tracer_graduations();
  1528. tracer_notes_FFT();
  1529. }
  1530.  
  1531.  
  1532. void MainWindow::on_spinBox_frq_2_valueChanged(int arg1) // SELECTEUR DE FREQUENCE 2
  1533. {
  1534. effacer_calque(scene1,calque_trace_FFT );
  1535. frequence2 = arg1;
  1536. RAZ_tableau_echantillons();
  1537. remplir_tableau_echantillons_sinus();
  1538. tracer_signal_a_convertir();
  1539. calcul_tableau_W();
  1540. bit_reverse_tableau_X();
  1541. calcul_FFT();
  1542. // tracer_graduations();
  1543. tracer_notes_FFT();
  1544. }
  1545.  
  1546.  
  1547. void MainWindow::on_spinBox_frq_3_valueChanged(int arg1)
  1548. {
  1549. effacer_calque(scene1,calque_trace_FFT );
  1550. frequence3 = arg1;
  1551. RAZ_tableau_echantillons();
  1552. remplir_tableau_echantillons_sinus();
  1553. tracer_signal_a_convertir();
  1554. calcul_tableau_W();
  1555. bit_reverse_tableau_X();
  1556. calcul_FFT();
  1557. // tracer_graduations();
  1558. tracer_notes_FFT();
  1559. }
  1560.  
  1561.  
  1562. void MainWindow::on_checkBox1_toggled(bool checked) // HAMMING
  1563. {
  1564. effacer_calque(scene1,calque_trace_FFT );
  1565. if (checked) {hamming = true;} else {hamming = false;}
  1566. RAZ_tableau_echantillons();
  1567. remplir_tableau_echantillons_sinus();
  1568. tracer_signal_a_convertir();
  1569. calcul_tableau_W();
  1570. bit_reverse_tableau_X();
  1571. calcul_FFT();
  1572. // tracer_graduations();
  1573. tracer_notes_FFT();
  1574.  
  1575. }
  1576.  
  1577.  
  1578. void MainWindow::on_checkBox2_toggled(bool checked) // SECONDE FREQUENCE
  1579. {
  1580. effacer_calque(scene1,calque_trace_FFT );
  1581. if (checked) {second_Frq = true;} else {second_Frq = false;}
  1582. RAZ_tableau_echantillons();
  1583. remplir_tableau_echantillons_sinus();
  1584. tracer_signal_a_convertir();
  1585. calcul_tableau_W();
  1586. bit_reverse_tableau_X();
  1587. calcul_FFT();
  1588. // tracer_graduations();
  1589. tracer_notes_FFT();
  1590. }
  1591.  
  1592.  
  1593. void MainWindow::on_checkBox3_toggled(bool checked)
  1594. {
  1595. effacer_calque(scene1,calque_trace_FFT );
  1596. if (checked) {bz = true;} else {bz = false;}
  1597. RAZ_tableau_echantillons();
  1598. remplir_tableau_echantillons_sinus();
  1599. tracer_signal_a_convertir();
  1600. calcul_tableau_W();
  1601. bit_reverse_tableau_X();
  1602. calcul_FFT();
  1603. // tracer_graduations();
  1604. tracer_notes_FFT();
  1605. }
  1606.  
  1607.  
  1608. void MainWindow::on_checkBox4_clicked(bool checked)
  1609. {
  1610. effacer_calque(scene1,calque_trace_FFT );
  1611. if (checked) {modul = true;} else {modul = false;}
  1612. RAZ_tableau_echantillons();
  1613. remplir_tableau_echantillons_sinus();
  1614. tracer_signal_a_convertir();
  1615. calcul_tableau_W();
  1616. bit_reverse_tableau_X();
  1617. calcul_FFT();
  1618. // tracer_graduations();
  1619. tracer_notes_FFT();
  1620. }
  1621.  
  1622.  
  1623. void MainWindow::Tic1()
  1624. {
  1625.  
  1626. nb_tics++;
  1627. if(nb_tics > 4000)
  1628. {
  1629. Timer1->stop();
  1630. nb_tics=0;
  1631. }
  1632. else
  1633. {
  1634. spinBox_4->setValue( spinBox_4->value() +1);
  1635. Timer1->setInterval(2); // à voir
  1636. }
  1637. }
  1638.  
  1639.  
  1640. void MainWindow::Tic2()
  1641. {
  1642. int d_barre;
  1643. float dt, vts;
  1644. int itrv;
  1645.  
  1646. vts = doubleSpinBox_vitesse->value();
  1647. d_barre = joue_1_note_de_la_liste(); // nb de barres temporelles séparant la note avec celle qui suit
  1648.  
  1649. dt = 20.0 * (float)d_barre;
  1650. dt *= (100.0 / vts);
  1651. itrv = (int) dt;
  1652.  
  1653. Timer2->setInterval(itrv);
  1654. }
  1655.  
  1656.  
  1657. void clear_temp_data()
  1658. {
  1659. for(int i=0; i<2000000; i++)
  1660. {
  1661. temp_data[i]=0;
  1662. }
  1663.  
  1664. }
  1665.  
  1666.  
  1667. void MainWindow::on_Bt_load_wav_clicked()
  1668. {
  1669. open_fichier_wav(); // associe le binStream1 au fichier wav
  1670. decode_entete();
  1671.  
  1672. MainWindow::setCursor(Qt::WaitCursor);
  1673. liste_ENR_FFT.clear();
  1674. effacer_calque(scene1,calque_trace_signal1 );
  1675.  
  1676. effacer_calque(scene1, calque_trace_FFT);
  1677. clear_temp_data();
  1678. garnis_temp_data(0); // donne accès à la totalité (2MB) du fichier wav (dans le 'temp_data')
  1679. tracer_signal_complet();
  1680. MainWindow::setCursor(Qt::ArrowCursor);
  1681. tracer_gradu_temporelle_signal_entree();
  1682.  
  1683. frame_3->setVisible(true);
  1684. Bt_scan_auto->setVisible(true);
  1685. checkBox_rapide->setVisible(true);
  1686. }
  1687.  
  1688.  
  1689.  
  1690. /*
  1691.   char RIFF[4]; (4 bytes)
  1692.   unsigned long ChunkSize; (4 bytes)
  1693.   char WAVE[4]; (4 bytes)
  1694.   char fmt[4]; (4 bytes)
  1695.   unsigned long Subchunk1Size; (4 bytes)
  1696.   unsigned short AudioFormat; (2 octets)
  1697.   unsigned short NumOfChan; (2 octets)
  1698.   unsigned long SamplesPerSec; (4 bytes)
  1699.   unsigned long bytesPerSec; (4 bytes)
  1700.   unsigned short blockAlign; (2 octets)
  1701.   unsigned short bitsPerSample; (2 octets)
  1702.   char Subchunk2ID[4]; (4 bytes)
  1703.   unsigned long Subchunk2Size; (4 bytes)
  1704.  
  1705.   TOTAL 44 octets
  1706. */
  1707.  
  1708.  
  1709. QString separ_milliers(uint n) // séparation des miliers par des espaces
  1710. {
  1711. QString s1, s1a, s1b, s1c;
  1712. s1.setNum(n);
  1713. int L= s1.length(); s1a = s1.right(3); s1b = s1.mid(L-6, 3); s1c = s1.mid(L-9, 3);
  1714. return (s1c+" "+s1b+" "+s1a);
  1715. }
  1716.  
  1717.  
  1718.  
  1719. void MainWindow::save_fichier_ini()
  1720. {
  1721. QFile file1(QDir::currentPath() + "/" + "params_FFT.ini"); // dans le dossier de l'exécutable
  1722. if (file1.open(QIODevice::WriteOnly | QIODevice::Text))
  1723. {
  1724. //int p1= string_currentFile.lastIndexOf('/');
  1725. //string_currentDir = string_currentFile.left(p1);
  1726.  
  1727. QTextStream out(&file1);
  1728.  
  1729. out << "# Ce fichier est crée automatiquement par le programme";
  1730. out << '\n';
  1731. out << "#";
  1732. out << '\n';
  1733. out << "# chemins:";
  1734. out << '\n';
  1735. out << "<currentDir>" << string_currentDir << "</currentDir>";
  1736. out << '\n';
  1737. out << "<currentFile>" << string_currentFile << "</currentFile>";
  1738. }
  1739. file1.close();
  1740. }
  1741.  
  1742.  
  1743.  
  1744. void MainWindow::open_fichier_wav()
  1745. {
  1746. // Le fichier .wav comprend un signal audio stéréo échantilloné à 48 000 octets/seconde pour chaque canal
  1747. // ce qui fait 96000 octets/s pour l'ensemble du signal stéréo
  1748.  
  1749. string_currentFile = QFileDialog::getOpenFileName(this, tr("Ouvrir Fichier wav..."), string_currentDir,
  1750. tr("Fichiers wav (*.wav);;All Files (*)"));
  1751. if (string_currentFile != "")
  1752. {
  1753. save_fichier_ini();
  1754. }
  1755. lineEdit_1->setText(string_currentFile);
  1756.  
  1757. int p1= string_currentFile.lastIndexOf('/');
  1758. string_currentDir = string_currentFile.left(p1);
  1759. lineEdit_current_dir->setText(string_currentDir);
  1760.  
  1761. save_fichier_ini();
  1762.  
  1763. file_wav.setFileName(string_currentFile);
  1764. if (!file_wav.open(QIODevice::ReadOnly))
  1765. {
  1766. wav_ok = false;
  1767. Bt_scan_auto->setStyleSheet("background-color: rgb(200, 200, 200);");
  1768. return ;
  1769. }
  1770. else
  1771. {
  1772. binStream1.setDevice(&file_wav); // accès à la totalité du fichier wav
  1773. wav_ok = true;
  1774. Bt_scan_auto->setStyleSheet("background-color: rgb(0, 255, 0);"); // vert
  1775.  
  1776. }
  1777. // le fichier reste ouvert pour toute la session
  1778. }
  1779.  
  1780.  
  1781.  
  1782.  
  1783. void MainWindow::decode_entete()
  1784. {
  1785. // ============ [Bloc de déclaration d'un fichier au format WAVE] ============
  1786.  
  1787. if (! wav_ok) {return;}
  1788. QString s3, s4, s5, fileSize1;
  1789. uint8_t x, nb_canaux;
  1790. float tot1, tot2, tot3, tot4;
  1791.  
  1792.  
  1793. binStream1.device()->seek(0); // retour de la lecture au début du fichier
  1794. binStream1.readRawData (temp_entete, 100); // lecture entete du fichier
  1795. //FileTypeBlocID
  1796. x=(uint8_t)temp_entete[0]; if ((x>64) && (x<127)) { s3 = char(x); }
  1797. x=(uint8_t)temp_entete[1]; if ((x>64) && (x<127)) { s3 += char(x); }
  1798. x=(uint8_t)temp_entete[2]; if ((x>64) && (x<127)) { s3 += char(x); }
  1799. x=(uint8_t)temp_entete[3]; if ((x>64) && (x<127)) { s3 += char(x); }
  1800. tableWidget_1->setItem(0, 0, new QTableWidgetItem (s3) ); //FileTypeBlocID
  1801.  
  1802. // FileSize
  1803. x=(uint8_t)temp_entete[4]; s3.setNum(x); tableWidget_1->setItem(1, 0, new QTableWidgetItem (s3) );
  1804. x=(uint8_t)temp_entete[5]; s3.setNum(x); tableWidget_1->setItem(1, 1, new QTableWidgetItem (s3) );
  1805. x=(uint8_t)temp_entete[6]; s3.setNum(x); tableWidget_1->setItem(1, 2, new QTableWidgetItem (s3) );
  1806. x=(uint8_t)temp_entete[7]; s3.setNum(x); tableWidget_1->setItem(1, 3, new QTableWidgetItem (s3) );
  1807.  
  1808. tot1 = temp_entete[4] + (2<<7) * temp_entete[5] + (2<<15) * temp_entete[6] + (2<23)* temp_entete[7];
  1809. fileSize1 = separ_milliers(tot1);
  1810. tableWidget_1->setItem(1, 4, new QTableWidgetItem ("= " + fileSize1) );
  1811.  
  1812. // FileFormatID
  1813. x=(uint8_t)temp_entete[8]; if ((x>64) && (x<127)) { s3 = char(x); }
  1814. x=(uint8_t)temp_entete[9]; if ((x>64) && (x<127)) { s3 += char(x); }
  1815. x=(uint8_t)temp_entete[10]; if ((x>64) && (x<127)) { s3 += char(x); }
  1816. x=(uint8_t)temp_entete[11]; if ((x>64) && (x<127)) { s3 += char(x); }
  1817. tableWidget_1->setItem(2, 0, new QTableWidgetItem (s3) );
  1818.  
  1819. // ============ [Bloc décrivant le format audio] ==============
  1820.  
  1821. // FormatBlocID
  1822. x=(uint8_t)temp_entete[12]; if ((x>64) && (x<127)) { s3 = char(x); }
  1823. x=(uint8_t)temp_entete[13]; if ((x>64) && (x<127)) { s3 += char(x); }
  1824. x=(uint8_t)temp_entete[14]; if ((x>64) && (x<127)) { s3 += char(x); }
  1825. x=(uint8_t)temp_entete[15]; if ((x>64) && (x<127)) { s3 += char(x); }
  1826. tableWidget_1->setItem(3, 0, new QTableWidgetItem (s3) );
  1827.  
  1828. //BlocSize
  1829. x=(uint8_t)temp_entete[16]; s3.setNum(x); tableWidget_1->setItem(4, 0, new QTableWidgetItem (s3) );
  1830. x=(uint8_t)temp_entete[17]; s3.setNum(x); tableWidget_1->setItem(4, 1, new QTableWidgetItem (s3) );
  1831. x=(uint8_t)temp_entete[18]; s3.setNum(x); tableWidget_1->setItem(4, 2, new QTableWidgetItem (s3) );
  1832. x=(uint8_t)temp_entete[19]; s3.setNum(x); tableWidget_1->setItem(4, 3, new QTableWidgetItem (s3) );
  1833.  
  1834. tot2 = (uint8_t)temp_entete[16] + (2<<7) * (uint8_t)temp_entete[17] + (2<<15) * (uint8_t)temp_entete[18] + (2<23)* (uint8_t)temp_entete[19];
  1835. tableWidget_1->setItem(4, 4, new QTableWidgetItem ("= " + separ_milliers(tot2)) );
  1836.  
  1837. //AudioFormat
  1838. x=(uint8_t)temp_entete[20]; s3.setNum(x); tableWidget_1->setItem(5, 0, new QTableWidgetItem (s3) );
  1839. x=(uint8_t)temp_entete[21]; s3.setNum(x); tableWidget_1->setItem(5, 1, new QTableWidgetItem (s3) );
  1840.  
  1841. if ((uint8_t)temp_entete[20]==1){tableWidget_1->setItem(5, 4, new QTableWidgetItem ("PCM") );}
  1842.  
  1843. //NbrCanaux
  1844. nb_canaux=(uint8_t)temp_entete[22]; s3.setNum(nb_canaux); tableWidget_1->setItem(6, 0, new QTableWidgetItem (s3) );
  1845. x=(uint8_t)temp_entete[23]; s3.setNum(x); tableWidget_1->setItem(6, 1, new QTableWidgetItem (s3) );
  1846.  
  1847. //Fréquence d'échantillonage en Hz
  1848. x=(uint8_t)temp_entete[24]; s3.setNum(x); tableWidget_1->setItem(7, 0, new QTableWidgetItem (s3) );
  1849. x=(uint8_t)temp_entete[25]; s3.setNum(x); tableWidget_1->setItem(7, 1, new QTableWidgetItem (s3) );
  1850. x=(uint8_t)temp_entete[26]; s3.setNum(x); tableWidget_1->setItem(7, 2, new QTableWidgetItem (s3) );
  1851. x=(uint8_t)temp_entete[27]; s3.setNum(x); tableWidget_1->setItem(7, 3, new QTableWidgetItem (s3) );
  1852.  
  1853. tot3 = (uint8_t)temp_entete[24] + (2<<7) * (uint8_t)temp_entete[25] + (2<<15) * (uint8_t)temp_entete[26] + (2<23)* (uint8_t)temp_entete[27];
  1854. tableWidget_1->setItem(7, 4, new QTableWidgetItem ("= " + separ_milliers(tot3)) );
  1855.  
  1856. //BytePerSec
  1857. x=temp_entete[28]; s3.setNum(x); tableWidget_1->setItem(8, 0, new QTableWidgetItem (s3) );
  1858. x=temp_entete[29]; s3.setNum(x); tableWidget_1->setItem(8, 1, new QTableWidgetItem (s3) );
  1859. x=temp_entete[30]; s3.setNum(x); tableWidget_1->setItem(8, 2, new QTableWidgetItem (s3) );
  1860. x=temp_entete[31]; s3.setNum(x); tableWidget_1->setItem(8, 3, new QTableWidgetItem (s3) );
  1861.  
  1862. tot4 = (uint8_t)temp_entete[28] + (2<<7) * (uint8_t)temp_entete[29] + (2<<15) * (uint8_t)temp_entete[30] + (2<23)* (uint8_t)temp_entete[31];
  1863. s3.setNum(tot4);
  1864. tableWidget_1->setItem(8, 4, new QTableWidgetItem (s3));
  1865. //tableWidget_1->setItem(8, 4, new QTableWidgetItem ("= " + separ_milliers(tot4)) );
  1866.  
  1867. //BytePerBloc
  1868. x=(uint8_t)temp_entete[32]; s3.setNum(x); tableWidget_1->setItem(9, 0, new QTableWidgetItem (s3) );
  1869. x=(uint8_t)temp_entete[33]; s3.setNum(x); tableWidget_1->setItem(9, 1, new QTableWidgetItem (s3) );
  1870.  
  1871. //BitsPerSample
  1872. x=(uint8_t)temp_entete[34]; s3.setNum(x); tableWidget_1->setItem(10, 0, new QTableWidgetItem (s3) );
  1873. x=(uint8_t)temp_entete[35]; s3.setNum(x); tableWidget_1->setItem(10, 1, new QTableWidgetItem (s3) );
  1874.  
  1875. x=(uint8_t)temp_entete[36]; if ((x>64) && (x<127)) { s3 = char(x); }
  1876. x=(uint8_t)temp_entete[37]; if ((x>64) && (x<127)) { s3 += char(x); }
  1877. x=(uint8_t)temp_entete[38]; if ((x>64) && (x<127)) { s3 += char(x); }
  1878. x=(uint8_t)temp_entete[39]; if ((x>64) && (x<127)) { s3 += char(x); }
  1879. tableWidget_1->setItem(11, 0, new QTableWidgetItem (s3) );
  1880.  
  1881. // DataSize
  1882. x=(uint8_t)temp_entete[40]; s3.setNum(x); tableWidget_1->setItem(12, 0, new QTableWidgetItem (s3) );
  1883. x=(uint8_t)temp_entete[41]; s3.setNum(x); tableWidget_1->setItem(12, 1, new QTableWidgetItem (s3) );
  1884. x=(uint8_t)temp_entete[42]; s3.setNum(x); tableWidget_1->setItem(12, 2, new QTableWidgetItem (s3) );
  1885. x=(uint8_t)temp_entete[43]; s3.setNum(x); tableWidget_1->setItem(12, 3, new QTableWidgetItem (s3) );
  1886.  
  1887. int tot5a = 1 * (uint8_t) temp_entete[40]; //because le temp_entête de type 'char' code avec entiers signés
  1888. int tot5b = (1<<8) * (uint8_t)temp_entete[41]; // remarque: (1<<8) = 2^8 = 256 // ne pas écrire (2<<8) !!
  1889. int tot5c = (1<<16) * (uint8_t)temp_entete[42];
  1890. int tot5d = (1<<24) * (uint8_t)temp_entete[43];
  1891.  
  1892. data_size = tot5a + tot5b + tot5c + tot5d;
  1893.  
  1894. // 21248 + 458752 = 480000
  1895. // pour le .wav LA 440 (48000, durée 10s) ->14x(2^16) + 166 * (2^8) = 960000
  1896. // 960 000 kb (stéréo) / 96 000 kb/s (stéréo)= 10s
  1897.  
  1898. tableWidget_1->setItem(12, 4, new QTableWidgetItem ("= " + separ_milliers(data_size)) ); // DataSize
  1899.  
  1900. // durée calculée
  1901. duree = data_size / tot4;
  1902. s3.setNum(duree, 'f', 3);// double n, char format = 'g', int precision = 6
  1903. tableWidget_1->setItem(13, 4, new QTableWidgetItem (s3 + " s") );
  1904.  
  1905. s4.setNum(tot4);
  1906. s4 = "ech : " + s3;
  1907. s4 += " Bps / 2 voies (stéréo) = ";
  1908.  
  1909. s5.setNum(tot4/2000);
  1910. s5 +=" kBps";
  1911.  
  1912. tableWidget_1->setItem(8, 5, new QTableWidgetItem (s5) );
  1913. lineEdit_6->setText("File size = " + fileSize1 + " bytes ; " + s4 + s5 + " ; durée calculée = " +s3 + "s");
  1914.  
  1915. if ((nb_canaux == 2) && (tot4 != 96000))
  1916. {
  1917. QMessageBox msgBox;
  1918. QString s1;
  1919. s1 = "Attention: Le taux d'échentillonage n'est pas 48 kb/s";
  1920. msgBox.setText(s1);
  1921. msgBox.exec();
  1922. }
  1923. if (nb_canaux != 2)
  1924. {
  1925. QMessageBox msgBox;
  1926. QString s1;
  1927. s1 = "Attention: Signal mono (doit être STEREO !)";
  1928. msgBox.setText(s1);
  1929. msgBox.exec();
  1930. }
  1931. }
  1932.  
  1933.  
  1934.  
  1935.  
  1936.  
  1937. // voir la page : https://fr.wikipedia.org/wiki/Waveform_Audio_File_Format
  1938. void MainWindow::garnis_temp_data(qint32 offset_i)
  1939. {
  1940. if (! wav_ok) {return;}
  1941.  
  1942. binStream1.device()->seek(0); // retour de la lecture au début du fichier
  1943. binStream1.skipRawData(44+offset_i); // saut bien plus loin dans le fichier
  1944. binStream1.readRawData (temp_data, 2000000); //lecture des données audio
  1945.  
  1946. //file_wav.close();
  1947. }
  1948.  
  1949.  
  1950. void MainWindow::calcul_compression()
  1951. {
  1952. double R;
  1953. double R_max=0;
  1954.  
  1955. for(uint n =0; n<nb_ech/4; n++)
  1956. {
  1957. R=ech[n].a;
  1958. if (R>R_max) {R_max=R;}
  1959. }
  1960. }
  1961.  
  1962.  
  1963. void MainWindow::remplir_tableau_echantillons_signal() // lecture du signal à analyser dans le 'temp_data' -> ech[n]
  1964. {
  1965.  
  1966. /*
  1967. Le fichier .wav doit avoir les caractéristiques suivantes :
  1968. - RIFF PCM WAVE fmt
  1969. - stéréo deux voies
  1970. - 96000 octets/s c'est à dire acqui avec 48000 octets/s x 2 voies
  1971. La FTT sera effectuée en 10 passes, sur un nb_ech = 2^10 = 1024 échantillons
  1972. */
  1973.  
  1974. uint n, n_max, i, offset_x;
  1975. double R;
  1976.  
  1977. offset_x = 40; // ou plus, si lecture plus loin dans le temps, à voir
  1978.  
  1979. uint8_t octet_n; // octet_B;
  1980. /*
  1981.   pour un codage 8 bits/sample = 2 * 1 octet/sample (stéréo)
  1982.   [Octet du Sample1 Canal1 ] (octet_A, octet_B)
  1983.   [Octet du Sample1 Canal2 ]
  1984.   ...
  1985. */
  1986. i=0;
  1987. n=0;
  1988. // on ne prend pas en compte tous les échantillons dispo dans le .wav (inutile ici)
  1989. // mais 1 sur 40 (la fréquence de la note la plus aigue (midi94) est = 932Hz)
  1990. // et seul le fondamental est pertinant pour reconnaitre la note, les harmoniques (timbre) sont ignorées
  1991. // il faut donc échantilloner à 932*2 = 1864 Hz au minimum
  1992. // Le fichier .wav d'origine est échantilloné à 48kHz
  1993. // 48000 / 1864 = 25.75
  1994. // On va prendre 1 échantillon sur 24 , ce qui donne un échantillonage à 48000/24 = 2000Hz
  1995. // attention : tout changement de cette valeur (pas = 24) change l'échelle de représentation de la FFT
  1996. // et fout le bocson dans tout le programme !!!
  1997. // chaque échantillon représente donc une durée = 1/2000 seconde = 0.5ms = 500us
  1998. // voir la suite des explications vers la fin de la fonction 'void MainWindow::tracer_notes_FFT()'
  1999.  
  2000. n_max = nb_ech /2; // = 1024/2 = 512
  2001. // 512*0.5ms = 256 ms
  2002.  
  2003. while (n < n_max)
  2004. {
  2005. octet_n = temp_data[offset_x + i]; // canal A
  2006. i++; // pour sauter (et ignorer) le canal B (le signal dans le fichier .wav est stéréo)
  2007. i+= pas_echantillonage;
  2008.  
  2009. // x= 256 * octet_A + octet_B;
  2010. R = octet_n - 128; // pour oter la composante continue propre au codage par des octets non signés
  2011. R /= 10.0;
  2012. R *= doubleSpinBox_1->value();
  2013.  
  2014. if (hamming) { R = R * (1- cos (2* M_PI * n / nb_ech/2 ));}
  2015.  
  2016. if (bourrage_de_zeros)
  2017. {
  2018. if (n<=nb_ech/4) // /4 -> signal
  2019. {
  2020. ech[n].a = R; // partie reelle
  2021. ech[n].b = 0; // partie imaginaire
  2022. }
  2023. else // -> Bourage de zéros
  2024. {
  2025. ech[n].a = 0; // partie reelle
  2026. ech[n].b = 0; // partie imaginaire
  2027. }
  2028. }
  2029. else
  2030. {
  2031. ech[n].a = R; // partie reelle
  2032. ech[n].b = 0; // partie imaginaire
  2033. }
  2034.  
  2035.  
  2036.  
  2037. n++; // n atteindra la valeur max = 512 ech représentant une durée totale de 256 ms
  2038. }
  2039.  
  2040. //calcul_compression();
  2041.  
  2042. }
  2043.  
  2044. /*
  2045. void MainWindow::on_toolButton_2_clicked() // recup signal
  2046. {
  2047.   RAZ_tableau_echantillons();
  2048.   remplir_tableau_echantillons_signal();
  2049.   tracer_signal_a_convertir();
  2050. }
  2051. */
  2052.  
  2053. void MainWindow::calcul_ofsset()
  2054. {
  2055. if(!wav_ok) return;
  2056. offset_t = spinBox_1->value() + 10 * spinBox_2->value() + 100 * spinBox_3->value() + 1000 * spinBox_4->value()
  2057. + 10000 * spinBox_5->value() + 100000 * spinBox_6->value();
  2058. QString s1;
  2059. s1 = separ_milliers(offset_t) ;
  2060. lineEdit_3->setText(s1);
  2061. effacer_calque(scene2, calque_encadrement2);
  2062. encadrement_signal(offset_t/1200, 25);
  2063. }
  2064.  
  2065.  
  2066. void MainWindow::traitement_signal()
  2067. {
  2068. if (! wav_ok) {return;}
  2069.  
  2070. garnis_temp_data(offset_t);
  2071. remplir_tableau_echantillons_signal();
  2072.  
  2073. calcul_tableau_W();
  2074. //RAZ_tableau_echantillons();
  2075.  
  2076. if(!rapide) { tracer_signal_a_convertir();}
  2077. bit_reverse_tableau_X();
  2078.  
  2079. calcul_FFT(); // 1 FFT s'effectue sur 1 cluster de 1024 échantillons.
  2080. //Le résultat représente un spectre élémentaire correspondant au cluster, c.a.d à une durée = 1024 x 0.5ms = 512 ms
  2081. // ce résultat est retourné dans le tableau 'Complexe tab_X[2048]'
  2082.  
  2083. //if (radioButton_notes->isChecked()) { tracer_notes_FFT(); }
  2084. //else { tracer_modules_FFT(); }
  2085.  
  2086. tracer_notes_FFT();
  2087. }
  2088.  
  2089.  
  2090.  
  2091. void MainWindow::analyse_tout()
  2092. {
  2093.  
  2094. progressBar_1->setVisible(true);
  2095. /*
  2096.   if (wav_ok == false)
  2097.   {
  2098.   QMessageBox msgBox;
  2099.   msgBox.setText("file 'wav' not open");
  2100.   int ret = msgBox.exec();
  2101.   return;
  2102.   }
  2103. */
  2104. /*
  2105.   if (data_nts_ok == false)
  2106.   {
  2107.   QMessageBox msgBox;
  2108.   msgBox.setText("file 'nts' not open");
  2109.   int ret = msgBox.exec();
  2110.   return;
  2111.   }
  2112. */
  2113.  
  2114. QString s1;
  2115. offset_t=0;
  2116. T_i=0;
  2117.  
  2118. uint16_t i_max = data_size / 1024; // = environ 6000
  2119.  
  2120. //i_max=7000; // < ----- bridé pour la phase de tests <---- ******************************
  2121.  
  2122. // data_size est affiché par le visualisateur d'entête
  2123. // et aussi dans le LineEdit en bas de l'onglet FFT
  2124. // data_size = de l'ordre de 7MB, ce qui nous donne un i_max d'environ 6900
  2125.  
  2126. effacer_calque(scene4, calque_TAB_FRQ);
  2127. liste_ENR_FFT.clear();
  2128. //clear_temp_data();
  2129. //garnis_temp_data(0);
  2130.  
  2131. // effacer_calque(scene4, calque_gradu_TAB_FRQ);
  2132. // effacer_calque(scene4, calque_notes);
  2133. // effacer_calque(scene4, calque_notes_jouee);
  2134. // effacer_calque(scene4, calque_grille_mesures);
  2135. // effacer_calque(scene4, calque_echelle_temporelle);
  2136.  
  2137. for(uint16_t i=0 ; i<i_max ; i++) // cette boucle sera donc parcourue environ 6000 fois...
  2138. {
  2139. qDebug() << "i=" << i;
  2140.  
  2141. if ((i % 200) == 0)
  2142. {
  2143. uint16_t pc = 100 * i / i_max;
  2144. pc+=2;
  2145. progressBar_1->setValue(pc);
  2146. // la ligne suivante permet l'affichage de la progression
  2147. QCoreApplication::processEvents(QEventLoop::AllEvents, 1);
  2148. }
  2149. //s1.setNum(i); lineEdit_compteur->setText(s1);
  2150.  
  2151. traitement_signal(); // traitement d'un cluster de 1024 échantillons
  2152. offset_t += 1024; // on passera au cluster de 1024 échantillons suivant c.a.d à un temps + 0.5ms
  2153.  
  2154. }
  2155. progressBar_1->setVisible(false);
  2156.  
  2157. tracer_echelle_temps_TAB_NOTES();
  2158. }
  2159.  
  2160.  
  2161.  
  2162.  
  2163. void MainWindow::on_spinBox_1_valueChanged(int arg1)
  2164. {
  2165. if (arg1==10) { spinBox_1->setValue(0); spinBox_2->stepUp();}
  2166. calcul_ofsset();
  2167. traitement_signal();
  2168. }
  2169.  
  2170.  
  2171. void MainWindow::on_spinBox_2_valueChanged(int arg1)
  2172. {
  2173. if (arg1==-1) {spinBox_2->setValue(9); spinBox_3->stepDown();}
  2174. if (arg1==10) { spinBox_2->setValue(0); spinBox_3->stepUp();}
  2175. calcul_ofsset();
  2176. traitement_signal();
  2177. }
  2178.  
  2179.  
  2180. void MainWindow::on_spinBox_3_valueChanged(int arg1)
  2181. {
  2182. if (arg1==-1) {spinBox_3->setValue(9); spinBox_4->stepDown();}
  2183. if (arg1==10) { spinBox_3->setValue(0); spinBox_4->stepUp();}
  2184. calcul_ofsset();
  2185. traitement_signal();
  2186. }
  2187.  
  2188.  
  2189. void MainWindow::on_spinBox_4_valueChanged(int arg1)
  2190. {
  2191. if (arg1==-1) {spinBox_4->setValue(9); spinBox_5->stepDown();}
  2192. if (arg1==10) { spinBox_4->setValue(0); spinBox_5->stepUp();}
  2193. calcul_ofsset();
  2194. traitement_signal();
  2195. }
  2196.  
  2197.  
  2198. void MainWindow::on_spinBox_5_valueChanged(int arg1)
  2199. {
  2200. if (arg1==-1) {spinBox_5->setValue(9); spinBox_6->stepDown();}
  2201. if (arg1==10) { spinBox_5->setValue(0); spinBox_6->stepUp();}
  2202. calcul_ofsset();
  2203. traitement_signal();
  2204. }
  2205.  
  2206.  
  2207. void MainWindow::on_spinBox_6_valueChanged()
  2208. {
  2209. //if (arg1==-1) {spinBox_6->setValue(9);} //spinBox_6->stepDown();}
  2210. calcul_ofsset();
  2211. traitement_signal();
  2212. }
  2213.  
  2214.  
  2215. void MainWindow::on_doubleSpinBox_1_valueChanged()
  2216. {
  2217. calcul_ofsset();
  2218. traitement_signal();
  2219. }
  2220.  
  2221.  
  2222. void MainWindow::on_pushButton_8_clicked()
  2223. {
  2224. QMessageBox msgBox;
  2225. QString s1;
  2226. s1 = "Le fichier audio à analyser doit être au format unsigned 8 bits PCM";
  2227. s1 += " (généré par exemple avec Audacity)";
  2228. s1 += "\n";
  2229. s1 += "Attention: ce n'est pas le format PCM par défaut, il faut aller dans les sous-menus :";
  2230. s1 += "\n";
  2231. s1 += "Fichier/Exporter/Exporter en WAV / encodage : Unsigned 8-bit PCM";
  2232. s1 += "\n";
  2233. s1 += "Ce n'est pas 'top WiFi', mais largement suffisant pour en faire la FFT et retrouver les notes.";
  2234. s1 += "\n";
  2235. s1 += "Ce qui est le but ici.";
  2236. s1 += "\n";
  2237. s1 += "D'autre part il est vivement conseillé de compresser la dynamique de l'audio (ce qui est simple avec Audacity)";
  2238. s1 += "\n";
  2239. s1 += "ce qui facilite grandement la détection des notes.";
  2240.  
  2241. msgBox.setText(s1);
  2242. msgBox.exec();
  2243. }
  2244.  
  2245.  
  2246. void MainWindow::on_Bt_RAZ_clicked()
  2247. {
  2248. spinBox_1->setValue(0);
  2249. spinBox_2->setValue(0);
  2250. spinBox_3->setValue(0);
  2251. spinBox_4->setValue(0);
  2252. spinBox_5->setValue(0);
  2253. spinBox_6->setValue(0);
  2254. offset_t=0;
  2255. }
  2256.  
  2257.  
  2258. void MainWindow::on_spinBox_7_valueChanged(int arg1)
  2259. {
  2260. // ligne verticale
  2261. effacer_calque(scene1,calque_curseur);
  2262. int x = arg1;
  2263. ligne1 = new QGraphicsLineItem(x, 10, x, 500);
  2264. ligne1->setPen(pen_curseur);
  2265. calque_curseur->addToGroup(ligne1);
  2266.  
  2267. }
  2268.  
  2269.  
  2270.  
  2271.  
  2272. void MainWindow::on_pushButton_2_clicked()
  2273. {
  2274. Timer1->stop();
  2275. nb_tics=0;
  2276. }
  2277.  
  2278.  
  2279. void MainWindow::on_Btn_52_clicked()
  2280. {
  2281. //spinBox_n_midi->setValue(52);
  2282.  
  2283. file_wav.setFileName(nom_fichier_in);
  2284. if (!file_wav.open(QIODevice::ReadOnly))
  2285. {
  2286. wav_ok = false;
  2287. return ;
  2288. }
  2289.  
  2290. wav_ok = true;
  2291.  
  2292. on_Bt_RAZ_clicked();
  2293.  
  2294. binStream1.setDevice(&file_wav);
  2295. calcul_ofsset();
  2296. traitement_signal();
  2297. }
  2298.  
  2299.  
  2300. void MainWindow::on_Btn_94_clicked()
  2301. {
  2302.  
  2303. file_wav.setFileName(nom_fichier_in);
  2304. if (!file_wav.open(QIODevice::ReadOnly))
  2305. {
  2306. wav_ok = false;
  2307. return ;
  2308. }
  2309.  
  2310. wav_ok = true;
  2311.  
  2312. on_Bt_RAZ_clicked();
  2313.  
  2314. binStream1.setDevice(&file_wav);
  2315. calcul_ofsset();
  2316. traitement_signal();
  2317. }
  2318.  
  2319.  
  2320. void MainWindow::on_Bt_efface_clicked()
  2321. {
  2322. QMessageBox msgBox;
  2323. msgBox.setText("Erase Frequences");
  2324. msgBox.setInformativeText("Effacer toutes les FFT ?");
  2325. msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
  2326. msgBox.setDefaultButton(QMessageBox::Cancel);
  2327. int ret = msgBox.exec();
  2328.  
  2329. if (ret == QMessageBox::Ok )
  2330. {
  2331. effacer_calque(scene1,calque_trace_signal1 );
  2332. effacer_calque(scene1,calque_trace_FFT );
  2333. effacer_calque(scene1,calque_lignes_F_zero );
  2334. effacer_calque(scene1,calque_encadrement1 );
  2335. effacer_calque(scene2,calque_encadrement2 );
  2336.  
  2337. effacer_calque(scene4,calque_TAB_FRQ );
  2338. on_Bt_RAZ_clicked();
  2339. T_i=0;
  2340. }
  2341.  
  2342. }
  2343.  
  2344.  
  2345.  
  2346. void MainWindow::on_pushButton_3_clicked()
  2347. {
  2348.  
  2349. tableWidget_1->setVisible(true);
  2350. Bt_close_entete->setVisible(true);
  2351. }
  2352.  
  2353.  
  2354. void MainWindow::on_Bt_close_entete_clicked()
  2355. {
  2356. tableWidget_1->setVisible(false);
  2357. Bt_close_entete->setVisible(false);
  2358. }
  2359.  
  2360.  
  2361. void MainWindow::on_Bt_close_frame1_clicked()
  2362. {
  2363. frame_1->setVisible(false);
  2364. frame_3->setVisible(true);
  2365. }
  2366.  
  2367.  
  2368. void MainWindow::on_pushButton_4_clicked()
  2369. {
  2370. frame_3->setVisible(false);
  2371. frame_1->setVisible(true);
  2372. }
  2373.  
  2374.  
  2375.  
  2376. void MainWindow::on_pushButton_6_clicked()
  2377. {
  2378. frame_notes->setVisible(false);
  2379. }
  2380.  
  2381.  
  2382.  
  2383. void MainWindow::on_pushButton_5_clicked()
  2384. {
  2385. spinBox_offset->setValue(-2146); // 2154 ; ref -2210 ; +/- 22 pour un décalage de +/-1/4 de ton
  2386. spinBox_echx->setValue(498); // 498
  2387. }
  2388.  
  2389.  
  2390.  
  2391. void MainWindow::save_fichier_FRQ()
  2392. {
  2393. // enregisterment incrémentiel sur le disque (nom de fichier = 1..2...3...)
  2394. ENR_FFT enr_i;
  2395. QString s1;
  2396.  
  2397. long n_max = liste_ENR_FFT.length();
  2398. if (n_max == 0)
  2399. {
  2400. QMessageBox msgBox; msgBox.setText("liste vide !"); msgBox.exec();
  2401. return;
  2402. }
  2403.  
  2404.  
  2405. int numero=0;
  2406. QString s2;
  2407.  
  2408. Timer1->stop();
  2409.  
  2410. bool existe =1;
  2411. while(existe)
  2412. {
  2413. numero++;
  2414. s2.setNum(numero);
  2415. existe = QFile::exists(string_currentDir + "/" + "TAB_FREQ_" + s2 + ".tfrq");
  2416. }
  2417. s2.setNum(numero);
  2418.  
  2419. QFile file1(string_currentDir + "/" + "TAB_FREQ_" + s2 + ".tfrq");
  2420. if (file1.open(QIODevice::WriteOnly | QIODevice::Text))
  2421. {
  2422. QByteArray byteArray1;
  2423. QDataStream stream1(&byteArray1, QIODevice::WriteOnly);
  2424. stream1.setDevice(&file1);
  2425. stream1.setVersion(QDataStream::Qt_6_8);
  2426.  
  2427. // entête 64 octets------------------
  2428. uint8_t d_barre = spinBox_d_barres->value(); // 1 octet
  2429. double dx = doubleSpinBox_dt->value(); // 8 octets
  2430. double x0 = doubleSpinBox_x0->value(); // 8 octets
  2431. stream1 << d_barre << dx << x0; //1+8+8 = 17 octets au début du fichier
  2432. for (int i=0; i<(64-17); i++) {stream1 << 'x';} // complète à 64 octets
  2433. // ----------------------------------
  2434.  
  2435. for(int n=0; n<n_max; n++)
  2436. {
  2437. enr_i = liste_ENR_FFT[n];
  2438. stream1 << enr_i.amplitude << enr_i.midi << enr_i.num << enr_i.t; // sérialisation des data
  2439. }
  2440. }
  2441. file1.close();
  2442.  
  2443. QMessageBox msgBox;
  2444. s1="Fichier enregistré: " + string_currentDir + "/" + "TAB_FREQ_" + s2 + ".tfrq"; msgBox.setText(s1); msgBox.exec();
  2445. }
  2446.  
  2447.  
  2448. void MainWindow::choix_dossier_de_travail()
  2449. {
  2450.  
  2451. QString actuel = string_currentDir;
  2452. string_currentDir = QFileDialog::getExistingDirectory
  2453. (this, tr("Open Directory"), actuel, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
  2454.  
  2455. if (string_currentDir != "")
  2456. {
  2457. dossier_de_travail_ok = true;
  2458. save_fichier_ini();
  2459. lineEdit_current_dir->setText(string_currentDir);
  2460. }
  2461. else { dossier_de_travail_ok = false; } // -> si on clique sur le bouton 'cancel'
  2462.  
  2463. }
  2464.  
  2465.  
  2466. void MainWindow::on_Bt_choix_current_dir_clicked()
  2467. {
  2468. choix_dossier_de_travail();
  2469. }
  2470.  
  2471.  
  2472. void MainWindow::load_fichier_FRQ()
  2473. {
  2474.  
  2475. QString filename1;
  2476. QString s1;
  2477.  
  2478. if(dossier_de_travail_ok == false)
  2479. {
  2480. choix_dossier_de_travail();
  2481. if (dossier_de_travail_ok == false)
  2482. {
  2483. QMessageBox msgBox;
  2484. s1="Le dossier de travail n'est pas spécifié";
  2485. msgBox.setText(s1); msgBox.exec();
  2486. return ;
  2487. }
  2488. }
  2489.  
  2490. filename1 = QFileDialog::getOpenFileName(this,
  2491. tr("Ouvrir Fichier tfrq"), string_currentDir + "/", tr("Fichiers tfrq (*.tfrq)"));
  2492.  
  2493. lineEdit_fichier_FREQ->setText(filename1);
  2494.  
  2495. file_dat.setFileName(filename1);
  2496. if (!file_dat.open(QIODevice::ReadOnly))
  2497. {
  2498. data_nts_ok = false;
  2499. return ;
  2500. }
  2501. else
  2502. {
  2503. binStream1.setDevice(&file_dat); // accès à la totalité du fichier dat
  2504. binStream1.setVersion(QDataStream::Qt_6_8);
  2505. data_nts_ok = true;
  2506. liste_ENR_FFT.clear();
  2507. }
  2508.  
  2509. //int z = sizeof(ENR_FFT); // ATTENTION ! ne PAS utiliser cette valeur qui tient en compte l'alignement en RAM
  2510. long n_max = file_dat.bytesAvailable() / 14; // 14 bits par enr; voir la def de 'ENR_FFT' dans le .h
  2511.  
  2512. // lecture entête -----------------
  2513.  
  2514. uint8_t d_barre; // 1 octet
  2515. double dt;
  2516. double x0;
  2517. binStream1 >> d_barre >> dt >> x0; // 1+8+8 = 17 octets au début du fichiers
  2518. uint8_t xx;
  2519. for (int i=0; i<(64-17); i++) {binStream1 >> xx;} // lit en tout à 64 octets libre pour l'avenir
  2520. //---------------------------------
  2521.  
  2522. doubleSpinBox_dt->setValue(dt);
  2523. doubleSpinBox_x0->setValue(x0);
  2524.  
  2525. ENR_FFT enr_i;
  2526. for(int n=0; n<n_max; n++)
  2527. {
  2528. binStream1 >> enr_i.amplitude >> enr_i.midi >> enr_i.num >> enr_i.t;
  2529. liste_ENR_FFT << enr_i;
  2530. }
  2531. file_dat.close();
  2532. retracer_TAB_FRQ();
  2533. spinBox_d_barres->setValue(d_barre);
  2534. }
  2535.  
  2536.  
  2537. void MainWindow::save_fichier_NOTES()
  2538. {
  2539. // enregisterment incrémentiel sur le disque (nom de fichier = 1..2...3...)
  2540. NOTE note_i;
  2541. QString s1;
  2542.  
  2543. double x = 80;
  2544. double dx = doubleSpinBox_dt->value();
  2545.  
  2546. uint16_t n_max = liste_NOTES.length();
  2547. if (n_max == 0)
  2548. {
  2549. QMessageBox msgBox; msgBox.setText("liste vide !"); msgBox.exec();
  2550. return;
  2551. }
  2552.  
  2553. int numero=0;
  2554. QString s2;
  2555.  
  2556. Timer1->stop();
  2557.  
  2558. bool existe =1;
  2559. while(existe)
  2560. {
  2561. numero++;
  2562. s2.setNum(numero);
  2563. existe = QFile::exists(string_currentDir + "/" + "NOTES_" + s2 + ".nts");
  2564. }
  2565. s2.setNum(numero);
  2566.  
  2567. QFile file1(string_currentDir + "/" + "NOTES_" + s2 + ".nts");
  2568. if (file1.open(QIODevice::WriteOnly | QIODevice::Text))
  2569. {
  2570. QByteArray byteArray1;
  2571. QDataStream stream1(&byteArray1, QIODevice::WriteOnly);
  2572. stream1.setDevice(&file1);
  2573. stream1.setVersion(QDataStream::Qt_6_8);
  2574.  
  2575. // entête 64 octets --------------
  2576. double vts = doubleSpinBox_vitesse->value(); // 8 octets
  2577. stream1 << x << dx << vts; //8+8+8 = 24 octets au début du fichier
  2578. for (int i=0; i<(64-24); i++) {stream1 << 'x';} // complète à 64 octets
  2579. //--------------------------------
  2580.  
  2581. for(uint16_t n=0; n<n_max; n++)
  2582. {
  2583. note_i = liste_NOTES[n];
  2584. // sérialisation des data
  2585. stream1 << note_i.numero << note_i.midi << note_i.n_barre << note_i.n_temps << note_i.duree;
  2586. }
  2587. }
  2588. file1.close();
  2589.  
  2590. QMessageBox msgBox;
  2591. s1="Fichier enregistré: " + string_currentDir + "/" + "NOTES_" + s2 + ".nts"; msgBox.setText(s1); msgBox.exec();
  2592. }
  2593.  
  2594.  
  2595.  
  2596. void MainWindow::load_fichier_NOTES()
  2597. {
  2598. QString filename1;
  2599. QString s1;
  2600.  
  2601. if(dossier_de_travail_ok == false)
  2602. {
  2603. choix_dossier_de_travail();
  2604. if (dossier_de_travail_ok == false)
  2605. {
  2606. QMessageBox msgBox;
  2607. s1="Le dossier de travail n'est pas spécifié";
  2608. msgBox.setText(s1); msgBox.exec();
  2609. return ;
  2610. }
  2611. }
  2612.  
  2613. filename1 = QFileDialog::getOpenFileName(this,
  2614. tr("Ouvrir Fichier nts"), string_currentDir+"/", tr("Fichiers nts (*.nts)"));
  2615.  
  2616. lineEdit_fichier->setText(filename1);
  2617.  
  2618. file_dat.setFileName(filename1);
  2619. if (!file_dat.open(QIODevice::ReadOnly))
  2620. {
  2621. data_nts_ok = false;
  2622. return ;
  2623. }
  2624. else
  2625. {
  2626. binStream1.setDevice(&file_dat); // accès à la totalité du fichier dat
  2627. binStream1.setVersion(QDataStream::Qt_6_8);
  2628. data_nts_ok = true;
  2629. }
  2630.  
  2631. //int z = sizeof(NOTE); // ATTENTION ! ne PAS utiliser cette valeur qui tient en compte l'alignement en RAM
  2632. uint16_t n_max = file_dat.bytesAvailable() / 7; // 7 bits par enr; voir la def de 'NOTE' dans le .h
  2633.  
  2634. double x;
  2635. double dx;
  2636. double vts;
  2637.  
  2638. // lecture entête -----------------
  2639. binStream1 >> x >> dx >> vts; // 8+8+8=24 octets au début du fichiers
  2640.  
  2641. uint8_t xx;
  2642. for (int i=0; i<(64-24); i++) {binStream1 >> xx;} // lit en tout à 64 octets
  2643. //---------------------------------
  2644.  
  2645. doubleSpinBox_dt->setValue(dx);
  2646. doubleSpinBox_vitesse->setValue(vts);
  2647.  
  2648. NOTE note_i;
  2649. for(int n=0; n<n_max; n++)
  2650. {
  2651. binStream1 >> note_i.numero >> note_i.midi >> note_i.n_barre >> note_i.n_temps >> note_i.duree;
  2652. liste_NOTES << note_i;
  2653. }
  2654.  
  2655. file_dat.close();
  2656.  
  2657. Bt_jouer_tout->setStyleSheet("background-color: rgb(0, 255, 0);"); // vert
  2658.  
  2659. }
  2660.  
  2661.  
  2662. void decalle_notes(int d)
  2663. {
  2664. int nb;
  2665. uint16_t i_max = liste_NOTES.length();
  2666. for( int i =0; i<i_max; i++)
  2667. {
  2668. nb = liste_NOTES[i].n_barre;
  2669. nb += d;
  2670. liste_NOTES[i].n_barre = nb;
  2671. }
  2672.  
  2673. }
  2674.  
  2675.  
  2676. void MainWindow::on_Bt_save_clicked()
  2677. {
  2678. save_fichier_FRQ();
  2679. }
  2680.  
  2681.  
  2682. void MainWindow::on_Bt_load_FREQ_clicked()
  2683. {
  2684. load_fichier_FRQ();
  2685. tracer_echelle_temps_TAB_NOTES();
  2686. }
  2687.  
  2688. void MainWindow::on_checkBox_rapide_stateChanged(int arg1)
  2689. {
  2690. rapide=arg1;
  2691. init_TAB_FRQ();
  2692. }
  2693.  
  2694.  
  2695.  
  2696. void MainWindow::on_doubleSpinBox_seuil_valueChanged(double arg1)
  2697. {
  2698. seuil = arg1;
  2699. effacer_calque(scene4, calque_TAB_FRQ);
  2700. retracer_TAB_FRQ();
  2701. }
  2702.  
  2703.  
  2704. void MainWindow::on_checkBox_norm_clicked()
  2705. {
  2706. if (checkBox_norm->isChecked())
  2707. {
  2708. textEdit_ETAT->setText("Mode Normalisé : \n Les couleurs représentent l'amplitude du signal");
  2709. }
  2710. else
  2711. {
  2712. textEdit_ETAT->setText(
  2713. "Mode Fréquences : \n"
  2714. "Les couleurs représentent la valeur (fréquence) de la note (Do, RE, MI...) \n"
  2715. "La taille de chaque tiret représente (abusivement sur l'axe fréquenciel) l'amplitude du signal \n"
  2716. "cette taille ne signifie donc pas un étalement en fréquence du signal, c'est juste une astuce de représentation."
  2717. );
  2718. }
  2719. effacer_calque(scene4, calque_TAB_FRQ);
  2720. retracer_TAB_FRQ();
  2721. }
  2722.  
  2723.  
  2724.  
  2725. void MainWindow::surbrille_note(uint16_t n)
  2726. {
  2727. double x_note;
  2728.  
  2729. NOTE note_i;
  2730. uint16_t n_max = liste_NOTES.length();
  2731. if ( n>= n_max) {return;}
  2732.  
  2733. note_i = liste_NOTES[n];
  2734. x_note = calcul_x_barre(note_i.n_barre);
  2735.  
  2736. if (checkBox_scrolling->isEnabled())
  2737. {
  2738. double scroll_x = graphicsView4->horizontalScrollBar()->value();
  2739. double diff_x = (2.0*x_note - scroll_x);
  2740. if (diff_x > (memo_scroll_x + 1800))
  2741. {
  2742. graphicsView4->horizontalScrollBar()->setValue(diff_x - 2000);
  2743. memo_scroll_x = diff_x;
  2744. }
  2745. }
  2746.  
  2747. int y;
  2748.  
  2749. int midi_i;
  2750. QString blanc = "#FFFFFF";
  2751.  
  2752. midi_i = note_i.midi;
  2753. y = calcul_y_note(midi_i) ;
  2754.  
  2755. //if (effacer) {effacer_calque(scene4, calque_notes_jouee);}
  2756.  
  2757. QPen pen1;
  2758. pen1.setColor(blanc);
  2759. pen1.setWidth(2);
  2760. ellipse1 = new QGraphicsEllipseItem(x_note-15, y-15, 30, 30) ;
  2761. ellipse1->setPen(pen1);
  2762. //ellipse1->setBrush(blanc);
  2763.  
  2764. calque_notes_jouee->addToGroup(ellipse1);
  2765.  
  2766.  
  2767. }
  2768.  
  2769.  
  2770. void MainWindow::complete_case(int row, int column, QString s1, QString c1, QString c2, bool bold1, QTableWidget *QTI)
  2771. {
  2772. QTableWidgetItem *Item1 = new QTableWidgetItem();
  2773. Item1->QTableWidgetItem::setForeground(QColor(c1));
  2774. Item1->QTableWidgetItem::setBackground(QColor(c2));
  2775.  
  2776. QFont font1;
  2777. font1.setBold(bold1);
  2778. Item1->setFont(font1);
  2779. Item1->setTextAlignment(Qt::AlignCenter);
  2780.  
  2781. Item1->setText(s1);
  2782. QTI->setItem(row,column,Item1);
  2783. }
  2784.  
  2785.  
  2786. void MainWindow::affiche_liste_notes() // en TEXTE dans le petit tableau
  2787. {
  2788. NOTE note_i;
  2789. QString s1;
  2790.  
  2791. tableWidget_lst_notes->clear();
  2792. tableWidget_lst_notes->setRowCount(0);
  2793. init_TAB_lst_notes();
  2794.  
  2795. uint16_t n_max = liste_NOTES.length();
  2796. if (n_max == 0) {return;}
  2797.  
  2798. for(int n=0; n<n_max; n++) //n_max
  2799. {
  2800. note_i=liste_NOTES[n];
  2801.  
  2802. int numero = note_i.numero;
  2803. int midi = note_i.midi;
  2804. int n_barre =note_i.n_barre;
  2805. int n_temps =note_i.n_temps;
  2806. int duree = note_i.duree;
  2807.  
  2808. int num_ligne = tableWidget_lst_notes->rowCount();
  2809. tableWidget_lst_notes->setRowCount(num_ligne+1); // ajout une ligne au tableau
  2810.  
  2811. s1.setNum(numero);
  2812. complete_case(n, 0, s1, "#000000", "#FFFFFF", false, tableWidget_lst_notes);
  2813.  
  2814. s1.setNum(midi);
  2815. int h1 = calcul_hauteur_note(midi); h1-=3; if(h1<0){h1+=12;} if(h1>11){h1-=12;}
  2816. if ((h1<0) || (h1>(liste_couleurs.length()-1))) {h1 = 0;}
  2817.  
  2818. QString couleur1 = liste_couleurs[h1];
  2819. complete_case(n, 1, s1, "#000000", couleur1, true, tableWidget_lst_notes);
  2820.  
  2821. s1 = nom_note(midi);
  2822. complete_case(n, 2, s1, "#000000", "#FFFFFF", false, tableWidget_lst_notes);
  2823.  
  2824. s1.setNum(n_barre);
  2825. complete_case(n, 3, s1, "#000000", "#FFFFFF", false, tableWidget_lst_notes);
  2826.  
  2827. s1.setNum(n_temps); // ok
  2828. complete_case(n, 4, s1, "#000000", "#FFFFFF", true, tableWidget_lst_notes);
  2829.  
  2830. s1.setNum(duree); //ok
  2831. complete_case(n, 5, s1, "#000000", "#FFFFFF", true, tableWidget_lst_notes);
  2832.  
  2833. if (duree == 16) {s1 = "R";} // Ronde
  2834. if (duree == 12) {s1 = "B.";}
  2835. if (duree == 8) {s1 = "B";} // blanche
  2836. if (duree == 4) {s1 = "N";} // noire
  2837. if (duree == 2) {s1 = "c";} // croche
  2838. if (duree == 1) {s1 = "db_c";} // double croche
  2839. if (duree == 0) {s1 = "-";}
  2840. //if (midi == 100) {s1 = "--";}
  2841.  
  2842. complete_case(n, 6, s1, "#000000", "#FFFFFF", true, tableWidget_lst_notes);
  2843. }
  2844.  
  2845. }
  2846.  
  2847.  
  2848. void MainWindow::calcule_durees_notes()
  2849. {
  2850. int db;
  2851. uint16_t i_max = liste_NOTES.length();
  2852. if (i_max == 0) {return;}
  2853.  
  2854. int n_barre_1;
  2855. int n_barre_2;
  2856.  
  2857. for(int n=0; n<i_max-1; n++) // 'i_max-1' because plus bas on indexe liste_NOTES[n+1] !!!
  2858. {
  2859. n_barre_1 = liste_NOTES[n].n_barre;
  2860. n_barre_2 = liste_NOTES[n+1].n_barre;
  2861. db = n_barre_2 - n_barre_1;
  2862.  
  2863. if (db<0) {db=0;}
  2864. if (db>48){db=48;}
  2865. liste_NOTES[n].duree = db;
  2866. }
  2867. }
  2868.  
  2869.  
  2870.  
  2871. void MainWindow::trace_liste_notes() //dessine des cercles)colorés (couleur midi) sur la grille
  2872. {
  2873. QString s1;
  2874. int db, midi_i;
  2875. float x, dx, dbx, y; //, dy;
  2876. int numero;
  2877. uint16_t n_max = liste_NOTES.length();
  2878. int n_barre_1;
  2879. //int n_barre_2;
  2880. for(int n=0; n<n_max; n++)
  2881. {
  2882. n_barre_1 = liste_NOTES[n].n_barre;
  2883.  
  2884. db = liste_NOTES[n].duree;
  2885. dx = doubleSpinBox_dt->value();
  2886. dbx = (float)db * dx * zoom_x / 2.0 ;
  2887.  
  2888. //if (visu_duree_notes == false) {dbx = 20;} // dessinera 1 note toute ronde
  2889.  
  2890. // x = x0 + (float)n_barre_1 * doubleSpinBox_dt->value()/2.0 * zoom_x;
  2891.  
  2892. x = calcul_x_barre(n_barre_1);
  2893.  
  2894. midi_i = liste_NOTES[n].midi;
  2895.  
  2896. if ((midi_i >=52) && (midi_i <=92) )
  2897. {
  2898. y = calcul_y_note(midi_i);
  2899.  
  2900. int h1 = calcul_hauteur_note(midi_i); h1-=3; if(h1<0){h1+=12;} if(h1>11){h1-=12;}
  2901. QString couleur1 = liste_couleurs[h1];
  2902. QString blanc = "#FFFFFF";
  2903.  
  2904. // rectangle (queue de la note représentant sa durée)
  2905. rect1 = new QGraphicsRectItem(x, y-2, dbx, 4);
  2906. QBrush br1;
  2907. br1.setStyle(Qt::SolidPattern);
  2908. br1.setColor(couleur1);
  2909. rect1->setBrush(br1);
  2910. //rect1->setPen(pen_i);
  2911. calque_notes->addToGroup(rect1);
  2912.  
  2913. ellipse1 = new QGraphicsEllipseItem(x-10, y-10, 20, 20);
  2914. ellipse1->setPen(QColor(blanc));
  2915. ellipse1->setBrush(QColor(couleur1));
  2916. calque_notes->addToGroup(ellipse1);
  2917.  
  2918.  
  2919. // inscrit le numéro de la note au centre de la note
  2920. numero = liste_NOTES[n].numero;
  2921. s1.setNum(numero);
  2922. GraphicsTextItem = new QGraphicsTextItem(s1);
  2923. GraphicsTextItem->setFont(QFont("Arial", 8));
  2924. GraphicsTextItem->setDefaultTextColor("#000000");
  2925. int x2 = x-12; if(numero<10){x2+=4;}
  2926. GraphicsTextItem->setPos(x2, y-10);
  2927. calque_notes->addToGroup(GraphicsTextItem);
  2928. }
  2929. /*
  2930.   if (midi_i == 100) // barre de mesure
  2931.   {
  2932.   ellipse1 = new QGraphicsEllipseItem(x-5, 20, 10, 10);
  2933.  
  2934.   QColor vert = "#00FF00";
  2935.   ellipse1->setBrush(vert);
  2936.   calque_notes->addToGroup(ellipse1);
  2937.   }
  2938. */
  2939. }
  2940. }
  2941.  
  2942.  
  2943. void MainWindow::numerotation_liste_notes()
  2944. {
  2945. uint16_t i_max = liste_NOTES.length();
  2946.  
  2947. for(uint16_t n=0; n<i_max; n++)
  2948. {
  2949. liste_NOTES[n].numero = n;
  2950. }
  2951. }
  2952.  
  2953.  
  2954. void MainWindow::suppression_notes_invalides()
  2955. {
  2956. int midi;
  2957. int nb = 0;
  2958.  
  2959. uint16_t n_max = liste_NOTES.length();
  2960. if (n_max == 0) {return;}
  2961.  
  2962. bool boucler=true;
  2963. do
  2964. {
  2965. nb=0;
  2966. for(uint16_t n=0; n<n_max; n++)
  2967. {
  2968. midi = liste_NOTES[n].midi;
  2969. if ((midi <52) || (midi>92))
  2970. {
  2971. supprime_note(n);
  2972. if (n_max == 0) {return;}
  2973. n_max --;
  2974. nb++;
  2975. }
  2976. }
  2977. if (nb==0) {boucler=false;}
  2978. }
  2979. while (boucler == true);
  2980.  
  2981. }
  2982.  
  2983.  
  2984. void MainWindow::suppression_mesures()
  2985. {
  2986. //int midi;
  2987. uint16_t n_max = liste_NOTES.length();
  2988. int nb = 0;
  2989.  
  2990. bool boucler=true;
  2991. do
  2992. {
  2993. nb=0;
  2994. for(int n=0; n<n_max; n++)
  2995. {
  2996. //midi = liste_NOTES[n].midi;
  2997. /*
  2998.   if (midi == 100) // midi=100 codera pour les barres de mesures
  2999.   {
  3000.   supprime_note(n);
  3001.   n_max --;
  3002.   nb++;
  3003.   }
  3004. */
  3005. }
  3006. if (nb==0) {boucler=false;}
  3007. }
  3008. while (boucler == true);
  3009.  
  3010. }
  3011.  
  3012.  
  3013.  
  3014. void MainWindow::tri_liste_notes_par_num_barre()
  3015. {
  3016.  
  3017. // tri par bulles
  3018.  
  3019. int ba1, ba2; // barres
  3020. NOTE note_i;
  3021. uint16_t i_max = liste_NOTES.length();
  3022. if (i_max==0){return;}
  3023.  
  3024. for(int p=0; p<i_max; p++)
  3025. {
  3026. for(int n=0; n<i_max-1; n++)
  3027. {
  3028. ba1=liste_NOTES[n].n_barre;
  3029. ba2=liste_NOTES[n+1].n_barre;
  3030. if(ba1 > ba2)
  3031. {
  3032. //permutter les notes
  3033. note_i = liste_NOTES[n];
  3034. liste_NOTES[n] = liste_NOTES[n+1];
  3035. liste_NOTES[n+1] = note_i;
  3036. }
  3037. }
  3038. }
  3039. }
  3040.  
  3041.  
  3042.  
  3043. void MainWindow::ajout_note(int midi, int B, int T)
  3044. {
  3045. NOTE note_i;
  3046. note_i.midi = midi;
  3047. note_i.n_barre = B; // valeur discrete, entière : numéro de la barre de la grille temporelle
  3048. note_i.n_temps = T; // numero au sein de la mesure
  3049. liste_NOTES << note_i;
  3050. }
  3051.  
  3052.  
  3053.  
  3054.  
  3055. void MainWindow::supprime_note(uint16_t n)
  3056. {
  3057. int L = liste_NOTES.length();
  3058. if (L==0) {return;}
  3059.  
  3060. if ((n>0) && (n<L))
  3061. {
  3062. liste_NOTES.remove(n);
  3063. effacer_calque(scene4,calque_notes);
  3064. tri_liste_notes_par_num_barre(); //les notes seront triées par temps croissant
  3065.  
  3066. numerotation_liste_notes(); //les notes seront numérotées par temps croissant
  3067.  
  3068. trace_liste_notes();
  3069. }
  3070. }
  3071.  
  3072.  
  3073.  
  3074. int MainWindow::test_if_note_in_liste(uint16_t n_barre, int midi)
  3075. {
  3076. // retourne la position dans la liste, sinon zéro;
  3077. uint16_t barre_i;
  3078. int midi_i;
  3079. int i_max = liste_NOTES.length();
  3080. for(int n=0; n<i_max; n++)
  3081. {
  3082. barre_i = liste_NOTES[n].n_barre;
  3083. midi_i = liste_NOTES[n].midi;
  3084.  
  3085. if ((barre_i == n_barre) && (midi_i == midi))
  3086. {
  3087. return n;
  3088. }
  3089. }
  3090. return -1;
  3091. }
  3092.  
  3093.  
  3094. void MainWindow::affi_txt_en_couleur(int midi_i, QLineEdit *lineEdit_i)
  3095. {
  3096. int h1 = calcul_hauteur_note(midi_i); h1-=3; if(h1<0){h1+=12;} if(h1>11){h1-=12;}
  3097. if ((h1<0) || (h1>(liste_couleurs.length()-1))) {h1 = 0;}
  3098. QString c1 = liste_couleurs[h1];
  3099. QString c2 = "#000000";
  3100. lineEdit_i->setStyleSheet("color: " + c1 + "; background-color: " + c2 + "; font: 700 14pt 'Ubuntu';");
  3101. QString s1;
  3102. lineEdit_7b->setText(nom_note(midi_i));
  3103. }
  3104.  
  3105.  
  3106.  
  3107. void MainWindow::encadre_midi(int n_midi)
  3108. {
  3109. effacer_calque(scene3, calque_gradu_TAB_FRQ);
  3110. tracer_graduation_TAB_NOTES();
  3111. double x, dx, y, dy;
  3112.  
  3113. int dm = n_midi -52;
  3114. y = 645 - (dm * 16);
  3115.  
  3116. dy=16;
  3117. x=0;
  3118. dx=85;
  3119.  
  3120. rectangle1 = new QGraphicsRectItem(x, y, dx, dy);
  3121. QPen pen1;
  3122. pen1.setColor("#FFFFFF");
  3123. pen1.setWidth(2);
  3124. rectangle1->setPen(pen1);
  3125. calque_gradu_TAB_FRQ->addToGroup(rectangle1);
  3126. }
  3127.  
  3128.  
  3129. void MainWindow::mousePressEvent(QMouseEvent *event)
  3130. {
  3131. if (tabWidget_Global->currentIndex() != 1) {return;}
  3132.  
  3133. QString s1;
  3134. float x0, y0; // position cliquée, libre
  3135.  
  3136. int n_barre=0; // numero de la barre verticale de la grille temporelle (depuis le départ)
  3137. int n_temps=0; // numero de la barre verticale de la grille temporelle (au sein de la mesure)
  3138. int n2;
  3139.  
  3140. float x_barre=0;
  3141. float x_min, x_max;
  3142. float y_min, y_max;
  3143.  
  3144. int midi=0; // midi
  3145.  
  3146. float scroll_x = graphicsView4->horizontalScrollBar()->value();
  3147. float scroll_y = graphicsView4->verticalScrollBar()->value();
  3148.  
  3149. graphicsView4->verticalScrollBar()->setValue(0);
  3150.  
  3151. s1.setNum(scroll_x); lineEdit_8->setText(s1);
  3152. s1.setNum(scroll_y); lineEdit_9->setText(s1);
  3153.  
  3154. x_min = graphicsView4->x();
  3155. x_max = x_min + graphicsView4->width();
  3156.  
  3157. y_min = graphicsView4->y();
  3158. y_max = y_min + graphicsView4->height() + 16; // +16 sinon rate le mi grave (midi 52)
  3159.  
  3160. x_clic_ecran = event->position().x();
  3161. y_clic_ecran = event->position().y();
  3162.  
  3163. x0 = x_clic_ecran-102 + scroll_x; // position cliquée
  3164. y0 = y_clic_ecran-78 + scroll_y;
  3165.  
  3166. // pour test (petite croix)
  3167. if (0)
  3168. {
  3169. QPen pen1; pen1.setColor("#FFFF00");
  3170. ligne1 = new QGraphicsLineItem(x0-10, y0-10, x0+10, y0+10);
  3171. ligne1->setPen(pen1);
  3172. calque_notes->addToGroup(ligne1);
  3173. ligne1 = new QGraphicsLineItem(x0-10, y0+10, x0+10, y0-10);
  3174. ligne1->setPen(pen1);
  3175. calque_notes->addToGroup(ligne1);
  3176. }
  3177. // ----------------------
  3178.  
  3179. if (x_clic_ecran > x_min && x_clic_ecran < x_max && y_clic_ecran > y_min && y_clic_ecran < y_max)
  3180. {
  3181. s1.setNum(x0); lineEdit_4->setText(s1);
  3182. s1.setNum(y0); lineEdit_5->setText(s1); // =481 foire !
  3183.  
  3184. // recherche (verticale) de la note midi la plus proche du point cliqué
  3185. int dm =0;
  3186. for(int n=0; n<=40; n++)
  3187. {
  3188. int d1= (655-y0) - 16*n; // 681
  3189. d1=abs(d1);
  3190.  
  3191. if(d1<=8) // 8 sachant que l'espacement de niveaux est = 16
  3192. {
  3193. dm = n;
  3194. }
  3195. }
  3196.  
  3197. // calcul de la valeur midi de la note
  3198. midi = 52 + dm;
  3199. encadre_midi(midi);
  3200.  
  3201. // calcul de l'abscisse discret
  3202. // voir le tracé des barres de mesure 'tracer_grille_MESURES()'
  3203.  
  3204. float pas_grille = doubleSpinBox_dt->value()/2.0 * zoom_x; // pas de la grille
  3205. float offset_grille = 0; //75;
  3206.  
  3207. x_barre = offset_grille; //0
  3208.  
  3209. bool trouve = false; // à priori
  3210. int n =-1;
  3211. while ((n<800) && (trouve == false))
  3212. {
  3213. float dx2 = x0 - x_barre;
  3214. if (dx2<0) {dx2 = -dx2;}
  3215.  
  3216. if (dx2 < pas_grille/2.0)
  3217. {
  3218. trouve = true;
  3219. n_barre = n; // numero de la barre verticale de la grille temporelle
  3220. n_temps = n%32;
  3221. if (n_temps == 0) {n_temps = 32;}
  3222. }
  3223. x_barre = calcul_x_barre(n+1);
  3224. n++;
  3225. }
  3226.  
  3227. if (trouve == false) {return ;}
  3228. if (n==0) {return ;}
  3229.  
  3230. s1.setNum(midi);
  3231. lineEdit_7->setText(s1);
  3232. lineEdit_7b->setText(nom_note(midi));
  3233.  
  3234. float F = freq_mid(midi);
  3235. s1.setNum(F);
  3236. s1.replace('.',','); // ce qui permet un copier collé direct dans 'Adacity'
  3237. lineEdit_7d->setText(s1);
  3238.  
  3239. affi_txt_en_couleur(midi, lineEdit_7b);
  3240.  
  3241. n2 = test_if_note_in_liste(n_barre, midi); // si note in liste, -> n2 = num de la note
  3242. if (n2 != -1) { QString s1; s1.setNum(n2); lineEdit_7c->setText(s1); }
  3243.  
  3244. play_note(midi);
  3245. }
  3246.  
  3247. int h1 = calcul_hauteur_note(midi);
  3248. h1-=3;
  3249. if(h1<0){h1+=12;}
  3250. if(h1>11){h1-=12;}
  3251.  
  3252. //QColor couleur1 = liste_couleurs[h1];
  3253. /*
  3254. // détection de la couleur du point cliqué
  3255.   QPixmap pixmap1 = graphicsView4->grab();
  3256.   QRgb rgbValue = pixmap1.toImage().pixel(x0, y0);
  3257.   QColor couleur1 = QColor::fromRgb(rgbValue);
  3258. */
  3259. if (write_mode == 1)
  3260. {
  3261. n2 = test_if_note_in_liste(n_barre, midi);
  3262. if (n2 == -1) // si la note ne figure pas déjà dans la liste...
  3263. {
  3264. // enregistre la note dans la liste (à la fin)
  3265. ajout_note(midi, n_barre, n_temps);
  3266. }
  3267. else { supprime_note(n2); }
  3268.  
  3269. effacer_calque(scene4,calque_notes);
  3270. tri_liste_notes_par_num_barre(); // les notes seront triées par num_barre croissant
  3271. numerotation_liste_notes(); // les notes seront numérotées par num_barre croissant
  3272. calcule_durees_notes();
  3273. affiche_liste_notes();
  3274. trace_liste_notes();
  3275. }
  3276. }
  3277.  
  3278.  
  3279.  
  3280. int MainWindow::joue_1_note_de_la_liste()
  3281. {
  3282. NOTE note_i1, note_i2;
  3283. int midi_i;
  3284. int barre1, barre2; // barres de la grille temporelle
  3285. int d_barre;
  3286. QString s1;
  3287.  
  3288. QDateTime tpi;
  3289. tpi = QDateTime::currentDateTime();
  3290. qint64 tp_relatif = temps_0.msecsTo(tpi); // en ms
  3291. s1.setNum(tp_relatif);
  3292.  
  3293. uint16_t num_max = liste_NOTES.length();
  3294. if (num_max == 0) {return 0;}
  3295. if (num_max < 3) {return 0;}
  3296.  
  3297.  
  3298. if (num_note_jouee > (num_max -2)) {return 0;}
  3299. note_i1 = liste_NOTES[num_note_jouee];
  3300. note_i2 = liste_NOTES[num_note_jouee+1];
  3301.  
  3302. barre1 = note_i1.n_barre;
  3303. barre2 = note_i2.n_barre;
  3304.  
  3305. if (barre1 == barre2) // detection d'un accord (notes simultanées)
  3306. {
  3307. surbrille_note(num_note_jouee);
  3308. surbrille_note(num_note_jouee+1);
  3309. nb_acc++;
  3310. }
  3311. else
  3312. {
  3313. if (nb_acc == 0) {effacer_calque(scene4, calque_notes_jouee);}
  3314. surbrille_note(num_note_jouee);
  3315. nb_acc--; if (nb_acc<0) {nb_acc=0;}
  3316. }
  3317.  
  3318. d_barre = barre2 - barre1;
  3319. if (d_barre < 0){d_barre = -d_barre;}
  3320.  
  3321. midi_i=note_i1.midi;
  3322.  
  3323. s1.setNum(num_note_jouee); lineEdit_7c->setText(s1);
  3324. lineEdit_7->setText("");
  3325. lineEdit_7b->setText("");
  3326.  
  3327.  
  3328. s1.setNum(midi_i) ;
  3329.  
  3330. if ( ! (checkBox_basses->isChecked() && midi_i > spinBox_filtre_2->value() ))
  3331. {
  3332. play_note(midi_i);
  3333. encadre_midi(midi_i);
  3334. }
  3335.  
  3336. num_note_jouee++;
  3337. if(num_note_jouee >= num_note_max)
  3338. {
  3339. Timer2->stop();
  3340. num_note_jouee=0;
  3341. }
  3342.  
  3343. return d_barre; // permet de retrouver l'espacement temporel entre la note et celle qui suit.
  3344. }
  3345.  
  3346.  
  3347. void MainWindow::on_Bt_toggle_visu_notes_clicked() // toggle visu notes
  3348. {
  3349. if(visu_notes == 0)
  3350. {
  3351. visu_notes = 1;
  3352. Bt_toggle_visu_notes->setStyleSheet("background-color: rgb(0, 255, 0);"); // vert
  3353. tri_liste_notes_par_num_barre(); //les notes seront triées par temps croissant
  3354. numerotation_liste_notes(); //les notes seront numérotées par temps croissant
  3355. affiche_liste_notes();
  3356. trace_liste_notes();
  3357. }
  3358. else
  3359. {
  3360. Bt_toggle_visu_notes->setStyleSheet("background-color: rgb(200, 200, 200);");
  3361. visu_notes = 0;
  3362. effacer_calque(scene4,calque_notes);
  3363. }
  3364. }
  3365.  
  3366.  
  3367. void MainWindow::on_Bt_save_notes_clicked()
  3368. {
  3369. calcule_durees_notes();
  3370. save_fichier_NOTES();
  3371. }
  3372.  
  3373.  
  3374. void MainWindow::on_Bt_load_notes_clicked()
  3375. {
  3376. uint16_t n_max = liste_NOTES.length();
  3377. if (n_max != 0) // pour éviter d'enregistrer un fichier vide lors du 1er chargement des notes
  3378. {
  3379. QMessageBox msgBox;
  3380. msgBox.setText("Confirmation de chargement");
  3381. msgBox.setInformativeText("Un enregistrement des notes va être effectué au préalable. Si clic sur Cancel, opération annulée");
  3382. msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
  3383. msgBox.setDefaultButton(QMessageBox::Ok);
  3384. int ret = msgBox.exec();
  3385.  
  3386. if (ret == QMessageBox::Cancel ) { return; }
  3387.  
  3388. on_Bt_save_notes_clicked();
  3389. }
  3390.  
  3391. liste_NOTES.clear();
  3392. effacer_calque(scene4,calque_notes);
  3393. load_fichier_NOTES();
  3394.  
  3395. suppression_notes_invalides();
  3396.  
  3397. affiche_liste_notes(); // en texte
  3398. trace_liste_notes(); // ellipses
  3399. }
  3400.  
  3401.  
  3402. void MainWindow::on_Bt_joue_passage_clicked()
  3403. {
  3404. if (liste_NOTES.length() == 0) {return;}
  3405.  
  3406. if (Timer2->isActive())
  3407. {
  3408. Timer2->stop();
  3409. return;
  3410. }
  3411.  
  3412. Timer2->start(500);
  3413.  
  3414. int note_de_depart = spinBox_10->value();
  3415. int nb_notes_a_jouer = spinBox_11->value()-1;
  3416.  
  3417. num_note_jouee = note_de_depart;
  3418. num_note_max = note_de_depart + nb_notes_a_jouer;
  3419. if (num_note_max > liste_NOTES.length()-1) { num_note_max = liste_NOTES.length()-1;}
  3420.  
  3421. NOTE note_i = liste_NOTES[note_de_depart];
  3422. double x_note = 80 + note_i.n_barre * doubleSpinBox_dt->value()/2.0 * zoom_x;
  3423. graphicsView4->horizontalScrollBar()->setValue(x_note - 100);
  3424.  
  3425. Timer2->start(500);
  3426. }
  3427.  
  3428.  
  3429. void MainWindow::on_Bt_joue_wav_clicked()
  3430. {
  3431. QStringList arguments;
  3432. arguments << string_currentFile;
  3433. QString program = "audacity"; //"audacious"
  3434. QProcess *myProcess = new QProcess();
  3435. myProcess->start(program, arguments);
  3436. }
  3437.  
  3438.  
  3439.  
  3440. void MainWindow::on_Bt_joue_wav_2_clicked()
  3441. {
  3442. on_Bt_joue_wav_clicked();
  3443. }
  3444.  
  3445.  
  3446. void MainWindow::on_Btn_RAZ_notes_clicked()
  3447. {
  3448. QMessageBox msgBox;
  3449. msgBox.setText("Erase notes");
  3450. msgBox.setInformativeText("Effacer toutes les notes ?");
  3451. msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
  3452. msgBox.setDefaultButton(QMessageBox::Cancel);
  3453. int ret = msgBox.exec();
  3454.  
  3455. if (ret == QMessageBox::Ok )
  3456. {
  3457. liste_NOTES.clear();
  3458. effacer_calque(scene4,calque_notes);
  3459. Bt_jouer_tout->setStyleSheet("background-color: rgb(200, 200, 200);");
  3460. affiche_liste_notes();
  3461. }
  3462. }
  3463.  
  3464.  
  3465. void MainWindow::on_Bt_stop_clicked()
  3466. {
  3467. num_note_depart = 0;
  3468. num_note_jouee=0;
  3469. Timer2->stop();
  3470. Bt_jouer_tout->setText("Jouer tout");
  3471. }
  3472.  
  3473.  
  3474. void MainWindow::on_spinBox_8_textChanged()
  3475. {
  3476. effacer_calque(scene4, calque_echelle_temporelle);
  3477. tracer_echelle_temps_TAB_NOTES();
  3478. }
  3479.  
  3480.  
  3481.  
  3482.  
  3483. void MainWindow::on_doubleSpinBox_dt_valueChanged()
  3484. {
  3485. effacer_calque(scene4, calque_grille_mesures);
  3486. tracer_grille_MESURES();
  3487. effacer_calque(scene4, calque_notes);
  3488. affiche_liste_notes();
  3489. trace_liste_notes();
  3490. effacer_calque(scene4, calque_echelle_temporelle);
  3491. tracer_echelle_temps_TAB_NOTES();
  3492. }
  3493.  
  3494.  
  3495.  
  3496. void MainWindow::on_Bt_mode_R_clicked()
  3497. {
  3498. write_mode=0;
  3499. MainWindow::setCursor(Qt::ArrowCursor);
  3500. Bt_mode_R->setStyleSheet("background-color: rgb(0, 255, 0);"); // vert
  3501. Bt_mode_W->setStyleSheet("background-color: rgb(200, 200, 200);");
  3502. }
  3503.  
  3504.  
  3505. void MainWindow::on_Bt_mode_W_clicked()
  3506. {
  3507. write_mode=1;
  3508. //MainWindow::setCursor(Qt::SplitHCursor);
  3509. Bt_mode_W->setStyleSheet("background-color: rgb(255, 0, 0);"); // rouge
  3510. Bt_mode_R->setStyleSheet("background-color: rgb(200, 200, 200);");
  3511. }
  3512.  
  3513.  
  3514. void MainWindow::on_Bt_scan_auto_clicked()
  3515. {
  3516. if (! wav_ok) {return;}
  3517.  
  3518. if (rapide)
  3519. {
  3520. tabWidget_Global->setCurrentIndex(1);
  3521.  
  3522. on_Bt_RAZ_clicked();
  3523.  
  3524. MainWindow::setCursor(Qt::WaitCursor);
  3525. effacer_calque(scene4, calque_TAB_FRQ );
  3526. analyse_tout();
  3527. MainWindow::setCursor(Qt::ArrowCursor);
  3528. }
  3529. else {Timer1->start(10);}
  3530.  
  3531. }
  3532.  
  3533.  
  3534.  
  3535. void MainWindow::on_Bt_jouer_tout_clicked()
  3536. {
  3537. if (liste_NOTES.length() == 0) {return;}
  3538.  
  3539. if (lecture_en_cours == false)
  3540. {
  3541. Bt_jouer_tout->setText("[]");
  3542. lecture_en_cours = true;
  3543. graphicsView4->horizontalScrollBar()->setValue(0);
  3544. memo_scroll_x = 0;
  3545.  
  3546. //Timer2->stop();
  3547. //num_note_depart = 0;
  3548. // num_note_jouee=0;
  3549. num_note_max = liste_NOTES.length()-1;
  3550. if (num_note_max < 1) {return;}
  3551. Timer2->start(1);
  3552. temps_0 = QDateTime::currentDateTime();
  3553. }
  3554. else
  3555. {
  3556. lecture_en_cours = false;
  3557. Timer2->stop();
  3558. Bt_jouer_tout->setText(">");
  3559. }
  3560.  
  3561. }
  3562.  
  3563.  
  3564. void MainWindow::on_Btn_SUPP_notes_invalides_clicked()
  3565. {
  3566. suppression_notes_invalides();
  3567. }
  3568.  
  3569.  
  3570.  
  3571. void MainWindow::on_Bt_toggle_visu_freq_clicked()
  3572. {
  3573. if(visu_freq == 0)
  3574. {
  3575. visu_freq = 1;
  3576. Bt_toggle_visu_freq->setStyleSheet("background-color: rgb(0, 255, 0);"); // vert
  3577. calque_TAB_FRQ->setVisible(true);
  3578. }
  3579. else
  3580. {
  3581. visu_freq = 0;
  3582. Bt_toggle_visu_freq->setStyleSheet("background-color: rgb(200, 200, 200);");
  3583. calque_TAB_FRQ->setVisible(false);
  3584. }
  3585. }
  3586.  
  3587.  
  3588. void MainWindow::on_Bt_efface_2_clicked() // sur tab FREQ-NOTES
  3589. {
  3590. on_Bt_efface_clicked(); // (celui de l'autre tab FFT)
  3591. }
  3592.  
  3593.  
  3594. void MainWindow::on_Bt_toggle_visu_ech_tps_clicked()
  3595. {
  3596. if(visu_ech_tps == 0)
  3597. {
  3598. visu_ech_tps = 1;
  3599. Bt_toggle_visu_ech_tps->setStyleSheet("background-color: rgb(0, 255, 0);"); // vert
  3600. tracer_echelle_temps_TAB_NOTES();
  3601. }
  3602. else
  3603. {
  3604. visu_ech_tps = 0;
  3605. Bt_toggle_visu_ech_tps->setStyleSheet("background-color: rgb(200, 200, 200);");
  3606. //effacer_calque(scene4,calque_echelle_temporelle);
  3607. tracer_echelle_temps_TAB_NOTES();
  3608. }
  3609. }
  3610.  
  3611.  
  3612. void MainWindow::on_Bt_toggle_visu_mesures_clicked()
  3613. {
  3614. if(visu_mesures == 0)
  3615. {
  3616. visu_mesures = 1;
  3617. Bt_toggle_visu_mesures->setStyleSheet("background-color: rgb(0, 255, 0);"); // vert
  3618. tracer_grille_MESURES();
  3619. }
  3620. else
  3621. {
  3622. visu_mesures = 0;
  3623. Bt_toggle_visu_mesures->setStyleSheet("background-color: rgb(200, 200, 200);");
  3624. tracer_grille_MESURES();
  3625. }
  3626. }
  3627.  
  3628.  
  3629.  
  3630. void MainWindow::on_doubleSpinBox_t0_valueChanged()
  3631. {
  3632. effacer_calque(scene4, calque_grille_mesures);
  3633. tracer_grille_MESURES();
  3634. effacer_calque(scene4, calque_notes);
  3635. affiche_liste_notes();
  3636. trace_liste_notes();
  3637. effacer_calque(scene4, calque_echelle_temporelle);
  3638. tracer_echelle_temps_TAB_NOTES();
  3639. }
  3640.  
  3641.  
  3642.  
  3643. void MainWindow::maj_TAB_NOTES()
  3644. {
  3645. effacer_calque(scene4, calque_grille_mesures);
  3646. effacer_calque(scene4, calque_notes);
  3647. effacer_calque(scene4, calque_echelle_temporelle);
  3648. effacer_calque(scene4, calque_TAB_FRQ);
  3649.  
  3650. retracer_TAB_FRQ();
  3651. tracer_grille_MESURES();
  3652. trace_liste_notes();
  3653. tracer_echelle_temps_TAB_NOTES();
  3654. }
  3655.  
  3656.  
  3657.  
  3658. void MainWindow::on_spinBox_zoom_2_valueChanged(int arg1)
  3659. {
  3660. zoom_x = arg1;
  3661. MainWindow::setCursor(Qt::WaitCursor);
  3662. maj_TAB_NOTES();
  3663. MainWindow::setCursor(Qt::ArrowCursor);
  3664. }
  3665.  
  3666.  
  3667.  
  3668. void MainWindow::on_pushButton_9_clicked()
  3669. {
  3670. QMessageBox msgBox;
  3671. QString s1;
  3672. s1 = "n° barre (de fraction 1/16 de mesure) est comptée depuis le début.";
  3673. s1 += "\n";
  3674. s1 += "'temps'= numéro de barre au sein de chaque mesure.";
  3675. s1 += "\n";
  3676. s1 += "'durée' est exprimée en nb de barres.";
  3677. s1 += "\n";
  3678. s1 += "'type' = 'B' = blanche, 'N' = noire, 'C' = croche etc...";
  3679. s1 += "\n";
  3680.  
  3681. msgBox.setText(s1);
  3682. msgBox.exec();
  3683. }
  3684.  
  3685.  
  3686. void MainWindow::on_spinBox_offset_valueChanged()
  3687. {
  3688. //do_FFT_freq_midi();
  3689. }
  3690.  
  3691.  
  3692.  
  3693. void MainWindow::on_doubleSpinBox_x0_valueChanged(double arg1)
  3694. {
  3695. //double offset_x = 10 * doubleSpinBox_dx->value();
  3696. float pas_grille = doubleSpinBox_dt->value()/2.0 * zoom_x;
  3697. double offset_x = 10 * arg1 + spinBox_d_barres->value() * pas_grille;
  3698. calque_TAB_FRQ->setPos(offset_x, 0);
  3699. }
  3700.  
  3701.  
  3702. void MainWindow::on_spinBox_d_barres_valueChanged()
  3703. {
  3704. float pas_grille = doubleSpinBox_dt->value()/2.0 * zoom_x;
  3705. double offset_x = 10 * doubleSpinBox_x0->value() + spinBox_d_barres->value() * pas_grille;
  3706. calque_TAB_FRQ->setPos(offset_x, 0);
  3707. }
  3708.  
  3709.  
  3710. void MainWindow::on_Bt_decale_notes_L_clicked()
  3711. {
  3712. decalle_notes(-1);
  3713. effacer_calque(scene4,calque_notes);
  3714. affiche_liste_notes(); // en texte
  3715. trace_liste_notes(); // ellipses
  3716. }
  3717.  
  3718.  
  3719. void MainWindow::on_Bt_decale_notes_R_clicked()
  3720. {
  3721. decalle_notes(1);
  3722. effacer_calque(scene4,calque_notes);
  3723. affiche_liste_notes(); // en texte
  3724. trace_liste_notes(); // ellipses
  3725. }
  3726.  
  3727.  
  3728.  
  3729. void MainWindow::on_tableWidget_type_M_cellClicked(int row, int column)
  3730. {
  3731. switch (row)
  3732. {
  3733. case 0: {lineEdit_10->setText("2/4"); Ta=2; Tb=4;} break;
  3734. case 1: {lineEdit_10->setText("3/4"); Ta=3; Tb=4;} break;
  3735. case 2: {lineEdit_10->setText("4/4"); Ta=4; Tb=4;} break;
  3736. default: break;
  3737. }
  3738. tracer_grille_MESURES();
  3739. }
  3740.  
  3741.  
  3742.  
  3743.  
  3744. void MainWindow::on_Bt_stop_2_clicked()
  3745. {
  3746. on_Bt_stop_clicked();
  3747. }
  3748.  
  3749.  
  3750. void MainWindow::on_checkBox_flitrer_clicked()
  3751. {
  3752. if (checkBox_flitrer->isChecked())
  3753. {
  3754. textEdit_ETAT->setText("Mode Filtré : \n Ne sont représentés que les signaux dont l'amplitude est supérieure au seuil choisi");
  3755. }
  3756. else
  3757. {
  3758. textEdit_ETAT->setText("Mode non-filtré : \n Tous les signaux issus de la FFT sont représentés");
  3759. }
  3760.  
  3761.  
  3762. MainWindow::setCursor(Qt::WaitCursor);
  3763. maj_TAB_NOTES();
  3764. MainWindow::setCursor(Qt::ArrowCursor);
  3765. }
  3766.  
  3767. /*
  3768. void MainWindow::on_spinBox_filtre_valueChanged()
  3769. {
  3770.   if (checkBox_flitrer->isChecked())
  3771.   {
  3772.   MainWindow::setCursor(Qt::WaitCursor);
  3773.   maj_TAB_NOTES();
  3774.   MainWindow::setCursor(Qt::ArrowCursor);
  3775.   }
  3776. }
  3777. */
  3778. /*
  3779. void MainWindow::on_doubleSpinBox_gain_valueChanged()
  3780. {
  3781.   MainWindow::setCursor(Qt::WaitCursor);
  3782.   effacer_calque(scene4, calque_TAB_FRQ);
  3783.   retracer_TAB_FRQ();
  3784.   MainWindow::setCursor(Qt::ArrowCursor);
  3785. }
  3786. */
  3787.  
  3788. void MainWindow::on_Bt_open_DIR_clicked()
  3789. {
  3790. QString s1, path1;
  3791.  
  3792. path1 = string_currentDir;
  3793.  
  3794. QProcess process1;
  3795. process1.setProgram("caja");
  3796. process1.setArguments({path1});
  3797. process1.startDetached();
  3798. }
  3799.  
  3800.  
  3801.  
  3802. void MainWindow::on_Bt_goto_clicked()
  3803. {
  3804.  
  3805. QString s1;
  3806. int n = lineEdit_7c->text().toInt();
  3807. if ((n<0) || (n>=liste_NOTES.length())) {return;}
  3808.  
  3809. spinBox_10->setValue(n);
  3810. NOTE note_i = liste_NOTES[n];
  3811.  
  3812. double x_note = 80 + note_i.n_barre * doubleSpinBox_dt->value()/2.0 * zoom_x;
  3813.  
  3814. num_note_jouee = n;
  3815. surbrille_note(n);
  3816.  
  3817. int midi = note_i.midi;
  3818. s1.setNum(midi);
  3819.  
  3820. lineEdit_7->setText(s1);
  3821. affi_txt_en_couleur(midi, lineEdit_7b); // nom de la note
  3822.  
  3823. graphicsView4->horizontalScrollBar()->setValue(x_note - 100);
  3824.  
  3825. }
  3826.  
  3827.  
  3828. void MainWindow::on_doubleSpinBox_T0_valueChanged(double arg1)
  3829. {
  3830. tracer_echelle_temps_TAB_NOTES();
  3831. }
  3832.  
  3833.  
  3834. void MainWindow::on_Bt_test1_clicked()
  3835. {
  3836. QString s1;
  3837. float valeur;
  3838.  
  3839. for (int n = 0; n <= 255; n+=1)
  3840. {
  3841. valeur = (float )n / 255;
  3842. s1 = calcul_couleur(valeur);
  3843.  
  3844. qDebug() << "n" << n;
  3845. qDebug() << "valeur" << valeur;
  3846. qDebug() << "s1" << s1;
  3847. qDebug() << "______________";
  3848.  
  3849. rectangle1 = new QGraphicsRectItem(n, 200, 2, 5);
  3850. QPen pen1;
  3851. pen1.setColor(s1);
  3852. pen1.setWidth(2);
  3853. rectangle1->setPen(pen1);
  3854. calque_grille_mesures->addToGroup(rectangle1);
  3855.  
  3856.  
  3857. }
  3858.  
  3859. }
  3860.  
  3861.  
  3862.  
  3863. void MainWindow::on_Bt_div2_clicked()
  3864. {
  3865. gain /=2;
  3866. MainWindow::setCursor(Qt::WaitCursor);
  3867. effacer_calque(scene4, calque_TAB_FRQ);
  3868. retracer_TAB_FRQ();
  3869. MainWindow::setCursor(Qt::ArrowCursor);
  3870. }
  3871.  
  3872.  
  3873. void MainWindow::on_pushButton_clicked()
  3874. {
  3875. gain *=2;
  3876. MainWindow::setCursor(Qt::WaitCursor);
  3877. effacer_calque(scene4, calque_TAB_FRQ);
  3878. retracer_TAB_FRQ();
  3879. MainWindow::setCursor(Qt::ArrowCursor);
  3880. }
  3881.  
  3882.  
  3883. void MainWindow::on_Bt_next_clicked()
  3884. {
  3885. double scroll_x = graphicsView4->horizontalScrollBar()->value();
  3886. graphicsView4->horizontalScrollBar()->setValue(scroll_x + 1000);
  3887.  
  3888. }
  3889.  
  3890.  
  3891. void MainWindow::on_Bt_prev_clicked()
  3892. {
  3893. double scroll_x = graphicsView4->horizontalScrollBar()->value();
  3894. graphicsView4->horizontalScrollBar()->setValue(scroll_x - 1000);
  3895. }
  3896.  
  3897.  
  3898. void MainWindow::on_Bt_debut_clicked()
  3899. {
  3900. graphicsView4->horizontalScrollBar()->setValue(0);
  3901. }
  3902.  
  3903.  
  3904. void MainWindow::on_Bt_fin_clicked()
  3905. {
  3906. graphicsView4->horizontalScrollBar()->setValue(10000);
  3907. }
  3908.  
  3909.  

5 fichier mainwindow.h

CODE SOURCE en C++
  1.  
  2. #ifndef MAINWINDOW_H
  3. #define MAINWINDOW_H
  4.  
  5. #include <QMainWindow>
  6. #include "ui_mainwindow.h"
  7.  
  8. #include <QGraphicsView>
  9. #include <QGraphicsSceneMouseEvent>
  10. #include <QGraphicsTextItem>
  11. #include <QGraphicsLineItem>
  12. #include <QGraphicsRectItem>
  13. #include <QGraphicsItemGroup>
  14. //#include <QImage>
  15. #include <QProcess>
  16. #include <QtMultimedia/QMediaPlayer>
  17. #include <QAudioOutput>
  18. #include <QTimer>
  19.  
  20. #include "complexe.h"
  21.  
  22.  
  23. struct ENR_FFT
  24. {
  25. double amplitude; // 8 octets
  26. uint32_t t; // 4 octets
  27. uint8_t num; // 1 octet
  28. uint8_t midi; //1 octet
  29. // total 4+1+1+8 = 14 octets
  30. };
  31.  
  32.  
  33. // à propos des notes : PRINCIPE
  34. // les notes ont une fréquence qui n'est pas directement enregistrée ici mais est représenté par le numéro MIDI.
  35. // elles ont un emplacement qui est enregistré et qui permet de connaitre l'instant de son jeu, connaissant la grille.
  36. // pour la grille temporelle, voir 'tracer_grille_MESURES()'
  37. // la variable 'duree' pourrait être calculée en fonction des précédentes, mais le fait de l'avoir ici
  38. // permet de visualiser une toute partie de la partition, voir une note unique, en dehors du contexte
  39. struct NOTE
  40. {
  41. uint16_t numero; // 2 octets
  42. uint8_t midi; // 1 octet
  43. uint16_t n_barre; // 2 octets ; numéro de la barre temporelle sur laquelle est posée la note
  44. uint8_t n_temps; // 1 octet ; numéro du temps (temps fort, temps faible) au sein de la mesure
  45. uint8_t duree; // 1 octet ; en nb d'intervalles de barres
  46. // total 7 octets
  47. };
  48.  
  49.  
  50.  
  51. /* FFT */
  52.  
  53. class MainWindow : public QMainWindow, public Ui::MainWindow
  54. {
  55. Q_OBJECT
  56.  
  57. public:
  58. explicit MainWindow(QWidget *parent = 0);
  59. ~MainWindow();
  60.  
  61. protected:
  62.  
  63. void mousePressEvent(QMouseEvent *event);
  64.  
  65.  
  66. private slots:
  67. void Tic1();
  68. void Tic2();
  69. void save_fichier_ini();
  70. void load_fichier_ini();
  71. void choix_dossier_de_travail();
  72. void open_fichier_wav();
  73.  
  74. void on_Bt_load_wav_clicked();
  75. void load_fichier_FRQ();
  76. void save_fichier_FRQ();
  77. void load_fichier_NOTES();
  78. void save_fichier_NOTES();
  79.  
  80. void decode_entete();
  81. void garnis_temp_data(qint32 offset);
  82.  
  83. void init_TW_1();
  84. void init_TAB_FRQ();
  85. void init_TAB_lst_notes();
  86. void init_TW_type_M();
  87. void init_Autres();
  88.  
  89. void Etiquette(int x, int y, QString s, QString coul_txt, QString coul_fond, QString coul_cadre , QGraphicsItemGroup *calque_i);
  90.  
  91. void afficher_titre_calque(QString titre, int x, int y, QGraphicsItemGroup *calque_i);
  92. void tracer_graduations_signal();
  93. void tracer_graduations_FFT();
  94. void tracer_signal_complet();
  95. void tracer_gradu_temporelle_signal_entree();
  96. void tracer_signal_a_convertir();
  97. void tracer_graduation_TAB_NOTES();
  98. void tracer_echelle_temps_TAB_NOTES();
  99. float calcul_x_barre(int n_barre);
  100. void tracer_grille_MESURES();
  101. void tracer_1enr_sur_TAB_NOTES(ENR_FFT enr_i);
  102. void retracer_TAB_FRQ();
  103. void maj_TAB_NOTES();
  104.  
  105. void encadrement_signal(int x, int dx);
  106. void encadrement_note(int n_midi);
  107. void encadre_midi(int n_midi);
  108. int calcul_num_midi(double x);
  109. void tracer_notes_FFT();
  110.  
  111. void complete_case(int row, int column, QString s1, QString c1, QString c2, bool bold1, QTableWidget *QTI);
  112. void affiche_liste_notes();
  113. void trace_liste_notes();
  114. int test_if_note_in_liste(uint16_t n_barre, int midi);
  115. void affi_txt_en_couleur(int midi_i, QLineEdit *lineEdit_i);
  116.  
  117. void ajout_note(int midi, int B, int T);
  118. void supprime_note(uint16_t n);
  119.  
  120. void remplir_tableau_echantillons_sinus();
  121. void remplir_tableau_echantillons_signal();
  122. void calcul_compression();
  123. void bit_reverse_tableau_X();
  124.  
  125. int calcul_y_note(int mid); // en pixels sur la grille
  126. int calcul_hauteur_note(int mid);
  127. void calcule_durees_notes();
  128. void calcul_tableau_W();
  129. void calcul_FFT();
  130. void calcul_ofsset();
  131. void traitement_signal();
  132. void analyse_tout();
  133. QString nom_note(int mid);
  134.  
  135. void numerotation_liste_notes();
  136. void tri_liste_notes_par_num_barre();
  137. void suppression_notes_invalides();
  138. void suppression_mesures();
  139.  
  140. void play_note(int midi);// sortie audio
  141. int joue_1_note_de_la_liste();
  142. void surbrille_note(uint16_t n);
  143.  
  144. void effacer_calque(QGraphicsScene *scene_i, QGraphicsItemGroup *calque_i);
  145.  
  146. void on_spinBox_frq_valueChanged(int arg1);
  147. void on_checkBox1_toggled(bool checked);
  148. void on_checkBox2_toggled(bool checked);
  149. void on_spinBox_frq_2_valueChanged(int arg1);
  150. void on_checkBox3_toggled(bool checked);
  151. void on_checkBox4_clicked(bool checked);
  152. void on_spinBox_frq_3_valueChanged(int arg1);
  153.  
  154. // void on_toolButton_2_clicked();
  155. void on_spinBox_1_valueChanged(int arg1);
  156. void on_spinBox_2_valueChanged(int arg1);
  157. void on_spinBox_3_valueChanged(int arg1);
  158. void on_spinBox_4_valueChanged(int arg1);
  159. void on_spinBox_5_valueChanged(int arg1);
  160.  
  161. //void on_spinBox_6_valueChanged(int arg1);
  162. void on_spinBox_6_valueChanged();
  163.  
  164. void on_spinBox_7_valueChanged(int arg1);
  165. void on_pushButton_8_clicked();
  166. void on_doubleSpinBox_1_valueChanged();
  167. void on_Bt_RAZ_clicked();
  168. void on_Bt_scan_auto_clicked();
  169. void on_pushButton_2_clicked();
  170. void on_Btn_52_clicked();
  171. void on_Btn_94_clicked();
  172. //void on_spinBox_n_midi_valueChanged(int arg1);
  173. void on_pushButton_3_clicked();
  174. void on_Bt_close_entete_clicked();
  175. void on_Bt_close_frame1_clicked();
  176. void on_pushButton_4_clicked();
  177. void on_Bt_save_clicked();
  178. void on_pushButton_6_clicked();
  179. void on_Bt_efface_clicked();
  180. void on_pushButton_5_clicked();
  181. void on_checkBox_rapide_stateChanged(int arg1);
  182. void on_doubleSpinBox_seuil_valueChanged(double arg1);
  183. void on_checkBox_norm_clicked();
  184.  
  185. void on_Bt_jouer_tout_clicked();
  186. void on_Bt_toggle_visu_notes_clicked();
  187. void on_Bt_save_notes_clicked();
  188. void on_Bt_load_notes_clicked();
  189. void on_Bt_joue_passage_clicked();
  190. void on_Bt_joue_wav_clicked();
  191. void on_Btn_RAZ_notes_clicked();
  192. void on_Bt_stop_clicked();
  193. void on_Bt_stop_2_clicked();
  194.  
  195. void on_Bt_mode_R_clicked();
  196. void on_Bt_mode_W_clicked();
  197. void on_Btn_SUPP_notes_invalides_clicked();
  198. void on_Bt_toggle_visu_freq_clicked();
  199. void on_Bt_efface_2_clicked();
  200. void on_Bt_toggle_visu_ech_tps_clicked();
  201. void on_Bt_toggle_visu_mesures_clicked();
  202. void on_Bt_joue_wav_2_clicked();
  203. void on_Bt_choix_current_dir_clicked();
  204. void on_pushButton_9_clicked();
  205.  
  206. void on_spinBox_8_textChanged();
  207. void on_doubleSpinBox_dt_valueChanged();
  208. void on_doubleSpinBox_t0_valueChanged();
  209. void on_spinBox_offset_valueChanged();
  210. void on_spinBox_zoom_2_valueChanged(int arg1);
  211. void on_spinBox_d_barres_valueChanged();
  212.  
  213. void on_Bt_load_FREQ_clicked();
  214.  
  215. void on_Bt_decale_notes_L_clicked();
  216. void on_Bt_decale_notes_R_clicked();
  217.  
  218. void on_tableWidget_type_M_cellClicked(int row, int column);
  219.  
  220. void on_checkBox_flitrer_clicked();
  221. //void on_spinBox_filtre_valueChanged();
  222. //void on_doubleSpinBox_gain_valueChanged();
  223. void on_Bt_open_DIR_clicked();
  224. void on_Bt_goto_clicked();
  225.  
  226. void on_doubleSpinBox_x0_valueChanged(double arg1);
  227. void on_doubleSpinBox_T0_valueChanged(double arg1);
  228.  
  229. void on_Bt_test1_clicked();
  230.  
  231. void on_Bt_div2_clicked();
  232.  
  233. void on_pushButton_clicked();
  234.  
  235. void on_Bt_next_clicked();
  236.  
  237. void on_Bt_prev_clicked();
  238.  
  239. void on_Bt_debut_clicked();
  240.  
  241. void on_Bt_fin_clicked();
  242.  
  243. private:
  244.  
  245. QPoint Zoom_point2_;
  246.  
  247. // QImage image1;
  248.  
  249. QGraphicsScene *scene1; // sur l'onglet FFT - Trace FFT
  250. QGraphicsItemGroup *calque_reticule1;
  251. QGraphicsItemGroup *calque_trace_signal1;
  252. QGraphicsItemGroup *calque_trace_FFT;
  253. QGraphicsItemGroup *calque_curseur;
  254. QGraphicsItemGroup *calque_encadrement1;
  255. QGraphicsItemGroup *calque_lignes_F_zero;
  256.  
  257. QGraphicsScene *scene2; // sur l'onglet FFT - Signal d'entrée
  258. QGraphicsItemGroup *calque_reticule2;
  259. QGraphicsItemGroup *calque_encadrement2;
  260. QGraphicsItemGroup *calque_trace_signal2;
  261.  
  262. QGraphicsScene *scene3;
  263. QGraphicsItemGroup *calque_gradu_TAB_FRQ;
  264.  
  265. QGraphicsScene *scene4; // sur l'onglet NOTES
  266. QGraphicsItemGroup *calque_TAB_FRQ;
  267.  
  268. QGraphicsItemGroup *calque_grille_mesures;
  269. QGraphicsItemGroup *calque_echelle_temporelle;
  270. QGraphicsItemGroup *calque_notes;
  271. QGraphicsItemGroup *calque_notes_jouee;
  272.  
  273. QGraphicsLineItem *ligne1;
  274. QGraphicsLineItem *segment_trace;
  275. QGraphicsLineItem *segment_trace2;
  276. QGraphicsRectItem *rectangle1;
  277. QGraphicsEllipseItem *ellipse1;
  278. QGraphicsRectItem *rect1;
  279. QGraphicsRectItem *rect2;
  280. QGraphicsRectItem *rect3;
  281.  
  282. QGraphicsTextItem *GraphicsTextItem;
  283.  
  284. QMediaPlayer *player1;
  285. QMediaPlayer *player2;
  286. QMediaPlayer *player3;
  287. QMediaPlayer *player4;
  288. QMediaPlayer *player5;
  289.  
  290. QAudioOutput *audioOutput1;
  291. QAudioOutput *audioOutput2;
  292. QAudioOutput *audioOutput3;
  293. QAudioOutput *audioOutput4;
  294. QAudioOutput *audioOutput5;
  295.  
  296. QTimer *Timer1; // pour analyse auto à faible vitesse
  297. QTimer *Timer2; // pour rejouer les notes détectées
  298.  
  299. };
  300.  
  301.  
  302.  
  303. #endif // MAINWINDOW_H
  304.  

6 fichier complexe.cpp

CODE SOURCE en C++
  1.  
  2. #include "complexe.h"
  3. //
  4.  
  5. void Complexe::multi_lambda(float lambda)
  6. {
  7. a *= lambda;
  8. b *= lambda;
  9. }
  10.  
  11.  
  12. Complexe Complexe::operator+ (Complexe c)
  13. {
  14. Complexe r;
  15. r.a=this->a+c.a;
  16. r.b=this->b+c.b;
  17. return r;
  18. }
  19.  
  20.  
  21. Complexe Complexe::operator- (Complexe c)
  22. {
  23. Complexe r;
  24. r.a=this->a-c.a;
  25. r.b=this->b-c.b;
  26. return r;
  27. }
  28.  
  29.  
  30. Complexe Complexe::operator* (Complexe c)
  31. {
  32. Complexe r;
  33. r.a=this->a * c.a - this->b * c.b;
  34. r.b=this->a * c.b + this->b * c.a;
  35. return r;
  36. }
  37.  
  38.  
  39.  
  40. /* rappel: fonction en pascal
  41. function produit_cplx(c1,c2:complexe):complexe;
  42.  begin
  43.   produit_cplx[1]:=c1[1]*c2[1]-c1[2]*c2[2];
  44.   produit_cplx[2]:=c1[1]*c2[2]+c1[2]*c2[1];
  45.  end;
  46. */
  47.  
  48.  

7 fichier complexe.h

CODE SOURCE en C++
  1.  
  2. #ifndef COMPLEXE_H
  3. #define COMPLEXE_H
  4. // Nombres complexes de la forme a+ib
  5.  
  6. //
  7. class Complexe
  8. {
  9.  
  10. public:
  11.  
  12. float a; // partie reelle
  13. float b; // partie imaginaire
  14. void multi_lambda(float lambda);
  15. Complexe operator+ (Complexe c);
  16. Complexe operator- (Complexe c);
  17. Complexe operator* (Complexe c); //equivaut a une rotation dans le plan (produit des modules, somme des arguments)
  18.  
  19. };
  20.  
  21.  
  22.  
  23.  
  24. #endif
  25.  

8 Autre programme : 'Guitare'


Ce nouveau programme constitue la suite logique du programme 'wav to midi'.
Il peut traiter la liste de notes générée par 'wav to midi'.
On part donc d'un fichier audio et on arrive à une sorte de suite de tablatures représentées sur la manche de la guitare avec position de chaque doigt de la main. Le tout ré-jouable avec respect du tempo.

Il fera l'objet d'un prochain article sur ce site. Je vous donne juste un aperçu en vidéo en attendant.
A suivre...

9 Documents

Tous les fichiers sources :
Important : Le dossier 'notes' contenant les échantillons audios des notes midi (midi 52 à 94) doit être placé dans le dossier de l’exécutable. (Ce dossier de l’exécutable (= Répertoire de compilation) étant choisi lors de la configuration du projet sous Qt Creator). Ces notes servent à rejouer la musique à partir des codes midi fournis par la transformée de Fourier.

10 -

Liens...

56