// Gerard Paresys // 28 06 2012 // Le dossier data doit comporter: // lesmaries_mme.wav // lesmaries_mme_Pitch_listing.txt // lesmaries_mme_Intensity_listing.txt // lesmaries_mme.TextGrid.xml (format Praat TextGrid) // Helvetica-50.vlw // Touche S Sauve l'ecran (format png) // Annuler Commentaire sur les 3 lignes qui commencent par: // NomFichier // pour ouvrir n'importe quel fichier // Exige la library toxiclibs de Karsten Schmidt: // http://hg.postspectacular.com/toxiclibs/downloads/toxiclibs-complete-0020.zip /** * Touche Espace Pause
* Touche Fleche <- Zoom Out
* Touche Fleche -> Zoom In
* Touche P Phonème
* Touche Y Syllabe
* Touche M Mot
* Clic souris dans la fenêtre d'abord

* Ouvre et joue le fichier Audio lesmaries_mme.wav
* Ouvre le fichier texte lesmaries_mme_Pitch_listing.txt généré par Praat
* Ouvre le fichier texte lesmaries_mme_Intensity_listing.txt généré par Praat
* Dessine les courbes Pitch et Intensity synchronisées avec l'Audio
* La courbe Pitch n'est pas dessinée quand pitch est "undefined"
* Chronomètre...
*
*/ // * Taper: P Phonème - Y Syllabe - M Mot - H Phonétique - O Orthographique
// * Affiche au choix 5 segmentations différentes du texte faites par Olivier Baude:
import ddf.minim.*; // pour AudioPlayer // import toxi.math.conversion.*; import toxi.geom.*; // pour VerletPhysics2D vp // import toxi.math.*; // import toxi.geom.mesh2d.*; // import toxi.util.datatypes.*; // import toxi.util.events.*; // import toxi.geom.mesh.subdiv.*; // import toxi.geom.mesh.*; // import toxi.math.waves.*; // import toxi.util.*; // import toxi.math.noise.*; // import toxi.physics2d.constraints.*; import toxi.physics2d.behaviors.*; // pour GravityBehavior import toxi.physics2d.*; // pour VerletPhysics2D vp; // import processing.opengl.*; PFont maFonte; String NomFichierAudio = "lesmaries_mme.mp3"; String NomFichierPitch = "lesmaries_mme_Pitch_listing.txt"; String NomFichierIntensity = "lesmaries_mme_Intensity_listing.txt"; String NomFichierXML = "lesmaries_mme.TextGrid.xml"; float FacteurX = 32; int Couche = 2; // Mot int CoucheHaut = 0; // Mot int CoucheBas = 1; // Mot int PitchMini = 75 ; // 75 Hz int PitchMaxi = 500; // 500 Hz int QuantiteParticule = 10; // Augmenter pour diminuer Quantite int EpaisseurCourbe = 8; // Pitch & Intensity int Trainee = 50; // Augmenter pour diminuer Trainee float PitchActuel = PitchMini; boolean Alea = true; String[] LignesPitch; String[] LignesIntensity; int IndexPitch = 0; int IndexIntensity = 0; float xAvantPitch, xApresPitch, yAvantPitch, yApresPitch; float xAvantIntensity, xApresIntensity, yAvantIntensity, yApresIntensity; int LigneText, x; AudioPlayer player; Minim minim; float temps, DureeFichier; boolean Probleme = false, Fin = false; boolean ToucheEspace = false, Pause = false, Trace = false; float[] LignePitch, LigneIntensity; float TempsPause, TempsDebutPause = 0; XMLElement xml1, kid1, kid2; XMLElement[] kid1Data, kidkid1Data; int NombreDeChild1, NombreDeChild2; int IndexXML = 0, IndexXMLCouche4 = 0, IndexXMLHaut = 0, IndexXMLBas = 0; float xmin, xmax; String s1, s2, Content1, Content2; VerletPhysics2D vp; Vec2D center; float angle, angleIncr; PFont myFont; // String letters = "go~dR go~dR@vij l@ pei d@ me gRa~ paRa~ go~dR@vij la fRa~s"; String Chaine ="AA"; // int counter = 0; // int TailleString; boolean NouvelleParticule = false; void setup() { // size(800, 600, OPENGL); // "The size() function must be the first line in setup()" size(800, 600); // "The size() function must be the first line in setup()" // maFonte = loadFont("Helvetica-50.vlw"); maFonte = loadFont("Verdana-48.vlw"); myFont = createFont("Impact", 48); textFont(myFont); angleIncr=0; center = new Vec2D(width/2, height/2); vp = new VerletPhysics2D(); vp.addBehavior(new GravityBehavior(new Vec2D(0, 0.001))); // TailleString = letters.length(); // println(TailleString); // smooth(); background(127); stroke(160); textAlign(LEFT, TOP); textFont(maFonte, 16); fill(0, 0, 0); // Texte noir // NomFichierPitch = selectInput("select a Pitch File"); if (loadStrings(NomFichierPitch) == null) { println("Le fichier " + NomFichierPitch + " n'existe pas"); Probleme = true; } else { LignesPitch = loadStrings(NomFichierPitch); println("Ouverture de: " + NomFichierPitch +" " + LignesPitch.length + " lignes" ); text(NomFichierPitch, 10, 5); } // NomFichierIntensity = selectInput("select an Intensity File"); if (loadStrings(NomFichierIntensity) == null) { println("Le fichier " + NomFichierIntensity + " n'existe pas"); Probleme = true; } else { LignesIntensity = loadStrings(NomFichierIntensity); println("Ouverture de: " + NomFichierIntensity +" " + LignesIntensity.length + " lignes" ); text(NomFichierIntensity, 10, 25); } // NomFichierAudio = selectInput("select an Audio File (wav, aiff, mp3..."); if (loadStrings(NomFichierAudio) == null) { println("Le fichier " + NomFichierAudio + " n'existe pas"); Probleme = true; } else { println("Ouverture de: " + NomFichierAudio); text(NomFichierAudio, 10, 45); minim = new Minim(this); player = minim.loadFile(NomFichierAudio, 2048); } // NomFichierXML = selectInput("select an XML File (format Praat textGrid)"); if (loadStrings(NomFichierXML) == null) { println("Le fichier " + NomFichierXML + " n'existe pas"); Probleme = true; } else { xml1 = new XMLElement(this, NomFichierXML); NombreDeChild1 = xml1.getChildCount(); kid1Data = xml1.getChildren(); s1 = kid1Data[0].getName(); // println(s1 + " : " + NombreDeChild1 + " child(s)"); kidkid1Data = kid1Data[0].getChildren(); s2 = kidkid1Data[1].getName(); println("Ouverture de: " + NomFichierXML); text(NomFichierXML, 10, 65); // AfficheCouche(Couche); } if (! Probleme) { player.play(); LignePitch = float(split(LignesPitch[LignesPitch.length - 1 ], " ")); DureeFichier = LignePitch[0]; println("Duree " + NomFichierPitch + " = " + DureeFichier + " sec"); LigneIntensity = float(split(LignesIntensity[LignesIntensity.length - 1 ], " ")); DureeFichier = LigneIntensity[0]; println("Duree " + NomFichierIntensity + " = " + DureeFichier + " sec"); EffaceEcran(); TempsPause = millis(); } else exit(); frameRate(30); } void draw() { temps = millis() - TempsPause; if ((! Pause) && (! Fin)) AfficheTemps(temps); temps = temps / 1000; // La courbe Pitch jaune if (IndexPitch < LignesPitch.length) { LignePitch = float(split(LignesPitch[IndexPitch], " ")); if (Float.isNaN(LignePitch[0])) { IndexPitch = IndexPitch + 1; } if (IndexPitch < 0) { //Astuce IndexPitch est > 0 LigneText = (IndexPitch * 14) + 20; fill(0, 0, 255); text(LignePitch[0], 50, LigneText); fill(255, 0, 0); text(LignePitch[1], 100, LigneText); } // println("temps = " + temps + " LignePitch[0] = " + LignePitch[0]); if ((temps > LignePitch[0]) && ! Pause) { xApresPitch = FacteurX * (width) * LignePitch[0] / DureeFichier; if (((xAvantPitch % width) > (xApresPitch % width)) && (IndexPitch < LignesPitch.length - 10) ) EffaceEcran(); if (Float.isNaN(LignePitch[1])) { PitchActuel = PitchMini; IndexPitch = IndexPitch + 1; Trace = false; xAvantPitch = xApresPitch; // println("NaN IndexPitch = " + IndexPitch); } else { PitchActuel = LignePitch[1]; yApresPitch = YPitch(PitchActuel) ; if (Trace) { // stroke(255); // Ligne blanche stroke(255, 255, 0); // Ligne jaune strokeWeight(EpaisseurCourbe); line(xAvantPitch % width, yAvantPitch, xApresPitch % width, yApresPitch); } xAvantPitch = xApresPitch; yAvantPitch = yApresPitch; Trace = true; IndexPitch = IndexPitch + 1; } } } else Fin = true; // La courbe Intensity rouge if (IndexIntensity < LignesIntensity.length) { LigneIntensity = float(split(LignesIntensity[IndexIntensity], " ")); if (Float.isNaN(LigneIntensity[0])) { IndexIntensity = IndexIntensity + 1; } if (IndexIntensity < 0) { //Astuce IndexIntensity est > 0 LigneText = (IndexIntensity * 14) + 20; fill(0, 0, 255); text(LigneIntensity[0], 50, LigneText); fill(255, 0, 0); text(LigneIntensity[1], 100, LigneText); } // println("temps = " + temps + " LigneIntensity[0] = " + LigneIntensity[0]); if ((temps > LigneIntensity[0]) && ! Pause) { xApresIntensity = FacteurX * (width) * LigneIntensity[0] / DureeFichier; if (((xAvantIntensity % width) > (xApresIntensity % width)) && (IndexIntensity < LignesIntensity.length - 10)) { EffaceEcran(); } if (Float.isNaN(LigneIntensity[1])) { IndexIntensity = IndexIntensity + 1; // Trace = false; xAvantIntensity = xApresIntensity; // println("NaN IndexIntensity = " + IndexIntensity); } else { yApresIntensity = YIntensity(LigneIntensity[1]) ; //if (Trace) { stroke(255, 100, 100); // Ligne rouge strokeWeight(EpaisseurCourbe); line(xAvantIntensity % width, yAvantIntensity, xApresIntensity % width, yApresIntensity); //} xAvantIntensity = xApresIntensity; yAvantIntensity = yApresIntensity; Trace = true; //IndexIntensity = IndexIntensity + 1; IndexIntensity = IndexIntensity + 5; } } } else Fin = true; // Texte courbe pitch en haut NombreDeChild2 = kidkid1Data[CoucheHaut].getChildCount(); if (IndexXMLHaut < NombreDeChild2) { kid1 = kidkid1Data[CoucheHaut].getChild(IndexXMLHaut); // n = kid1.getInt("n"); xmin = kid1.getFloat("xmin"); xmax = kid1.getFloat("xmax"); Content1 = kid1.getContent(); // println("Child(" + IndexXMLHaut + "): n = " + n + " xmin = " + xmin + " xmax = " + xmax + " " + Content1); if (Content1 == null) IndexXMLHaut = IndexXMLHaut + 1; else if (Content1.equals("_") == true) IndexXMLHaut = IndexXMLHaut + 1;//Elimination des caracteres _ qui separe les segments else { // if ((temps > xmin) && ! Pause) { // if ((temps > xmax) && ! Pause) { if ((temps > (xmin + xmax) / 2) && ! Pause) { fill(0, 0, 0); // Texte noir fill(255); // Texte blanc // textFont(maFonte, LignePitch[1] / 10); textFont(maFonte, PitchActuel / 5); // Plantage avec Font autre que Helvetica si Size = NaN // yApresPitch = YPitch(LignePitch[1]) ; // text(Content1, xApresPitch % width, yApresPitch - 20); text(Content1, xApresPitch % width, YPitch(PitchActuel) - 20); NouvelleParticule = true; IndexXMLHaut = IndexXMLHaut + 1; } } } // Texte courbe Intensity en bas NombreDeChild2 = kidkid1Data[CoucheBas].getChildCount(); if (IndexXMLBas < NombreDeChild2) { kid1 = kidkid1Data[CoucheBas].getChild(IndexXMLBas); // n = kid1.getInt("n"); xmin = kid1.getFloat("xmin"); xmax = kid1.getFloat("xmax"); Content1 = kid1.getContent(); // println("Child(" + IndexXMLBas + "): n = " + n + " xmin = " + xmin + " xmax = " + xmax + " " + Content1); if (Content1 == null) IndexXMLBas = IndexXMLBas + 1; else if (Content1.equals("_") == true) IndexXMLBas = IndexXMLBas + 1;//Elimination des caracteres _ qui separe les segments else { // if ((temps > xmin) && ! Pause) { // if ((temps > xmax) && ! Pause) { if ((temps > (xmin + xmax) / 2) && ! Pause) { fill(255, 0, 0); // Texte rouge // textFont(maFonte, (LigneIntensity[1] - 20) / 2); textFont(maFonte, (LigneIntensity[1] - 40) / 1); //yApresIntensity = YIntensity(LigneIntensity[1]) ; //text(Content1, xApresIntensity % width, yApresIntensity - 20); text(Content1, xApresIntensity % width, YIntensity(LigneIntensity[1]) - 20); NouvelleParticule = true; // letters = Content1; // Chaine = Content1; // vp.addParticle(new Particle(0, 0)); //envoi d'une "Particle" // println("Content1 = " + Content1); // println("Child(" + IndexXMLBas + "): n=" + n + " xmin=" + xmin + " xmax = " + xmax + " " + Content1 + " temps = " + temps); IndexXMLBas = IndexXMLBas + 1; } } } // Texte Particle NombreDeChild2 = kidkid1Data[Couche].getChildCount(); if (IndexXML < NombreDeChild2) { kid1 = kidkid1Data[Couche].getChild(IndexXML); // n = kid1.getInt("n"); xmin = kid1.getFloat("xmin"); xmax = kid1.getFloat("xmax"); Content1 = kid1.getContent(); // println("Child(" + IndexXML + "): n = " + n + " xmin = " + xmin + " xmax = " + xmax + " " + Content1); if (Content1 == null) IndexXML = IndexXML + 1; else if (Content1.equals("_") == true) IndexXML = IndexXML + 1;//Elimination des caracteres _ qui separe les segments else { // if ((temps > xmin) && ! Pause) { // if ((temps > xmax) && ! Pause) { if ((temps > (xmin + xmax) / 2) && ! Pause) { NouvelleParticule = true; IndexXML = IndexXML + 1; } } } // Le texte "Orthographique" en blanc en bas NombreDeChild2 = kidkid1Data[4].getChildCount(); // 4 = Couche orthographique if (IndexXMLCouche4 < NombreDeChild2) { // if (false) { kid2 = kidkid1Data[4].getChild(IndexXMLCouche4); // 4 = Couche orthographique // n = kid2.getInt("n"); xmin = kid2.getFloat("xmin"); xmax = kid2.getFloat("xmax"); Content2 = kid2.getContent(); // println("Child(" + IndexXML + "): n = " + n + " xmin = " + xmin + " xmax = " + xmax + " " + Content1); if (Content2 == null) IndexXMLCouche4 = IndexXMLCouche4 + 1; else if (Content2.equals("_") == true) IndexXMLCouche4 = IndexXMLCouche4 + 1;//Elimination des caracteres _ qui separe les segments else { if ((temps > xmin) && ! Pause) { // if ((temps > xmax) && ! Pause) { // if ((temps > (xmin + xmax) / 2) && ! Pause) { noStroke(); // pas de contour fill(0); // Rect noir rect(0, YIntensity(40) + 20, width, 90); fill(255); // Texte blanc textFont(maFonte, 20); text(Content2, 10, YIntensity(40) + 21, width-20, 60 ); // println("Child(" + IndexXMLCouche4 + "): n=" + n + " xmin=" + xmin + " xmax = " + xmax + " " + Content2 + " temps = " + temps); IndexXMLCouche4 = IndexXMLCouche4 + 1; } } } if (frameCount % QuantiteParticule == 0) { if (NouvelleParticule = true) { Chaine = Content1; vp.addParticle(new Particle(0, 0)); //envoi d'une "Particle" NouvelleParticule = false; } } fill(0, Trainee); noStroke(); // rect(0, 0, width, height-200); rect(0, 0, width, YIntensity(40) + 20); pushMatrix(); translate(center.x, center.y); rotate(radians(angle)); angle = (angle+angleIncr)%360; // if (frameCount % 2 == 0) // ------------------------- int nbParticles = vp.particles.size(); // println(nbParticles); for (int i = nbParticles-1; i >=0;--i) // for (int i = 0; i >0; --i) // if (nbParticles > 0) { // int i = 0; Particle particle = (Particle) vp.particles.get(i); if (particle.dead()) { vp.removeParticle(particle); } else { particle.display(); } } popMatrix(); vp.update(); //println(nbParticles + " " + angleIncr + " " + frameRate); // lights(); } float YPitch(float w) { // return ((PitchMaxi - w) / 2) + 100; return ((PitchMaxi - w) / 2) ; } float YIntensity(float w) { if (w < 40) w= 40; // return ((100 - w) * 3) + 312; return ((100 - w) * 3) + 420; } void AfficheTemps(float T) { T = T / 1000; noStroke(); textAlign(LEFT, BASELINE); fill(0); rect(width - 75, height - 13, 100, 15); fill(255); textFont(maFonte, 12); text(T + " sec", width - 72, height - 2); } void AfficheCouche(int Couche) { NombreDeChild2 = kidkid1Data[Couche].getChildCount(); // println(" " + s2 +" : NombreDeChild2 = " + NombreDeChild2 + " child(s)" ); // println(); // background(255); // textFont(maFonte, 24); textFont(maFonte, 16); fill(255, 0, 0, 100); for (int i = 0; i < NombreDeChild2; i++) { XMLElement kid1 = kidkid1Data[Couche].getChild(i); int n = kid1.getInt("n"); float xmin = kid1.getFloat("xmin"); float xmax = kid1.getFloat("xmax"); String Content1 = kid1.getContent(); // println("Child(" + i + "): n = " + n + " xmin = " + xmin + " xmax = " + xmax + " " + Content1); if (Content1 == null) { } else if (Content1.equals("_") == true) //Elimination des caracteres _ qui separe les segments { } else { if (Alea) { text(Content1, random(1, 790), random(1, 590)); } else { text(Content1, 5, i * 16); } } } } void EffaceEcranAvant() { // rbackground(255); // Fond blanc noStroke(); // pas de contour fill(200); // Blanc // rect(0, YPitch(PitchMaxi), width, YIntensity(40) - YPitch(PitchMaxi)); // AfficheCouche(Couche); textFont(maFonte, 12); stroke(0, 0, 0); // Ligne noire textAlign(LEFT, BASELINE); fill(0, 0, 0); // Texte noir line(0, YPitch(PitchMini), width, YPitch(PitchMini)); text(PitchMini + "Hz", width - 40, YPitch(PitchMini) - 16); line(0, YPitch(PitchMaxi), width, YPitch(PitchMaxi)); text(PitchMaxi + "Hz", width - 40, YPitch(PitchMaxi) - 1); text("Pause : Espace", width - 170, height - 2); fill(255, 0, 0); // Texte rouge stroke(255, 0, 0); // Ligne rouge text("100dB", width - 40, YPitch(PitchMini) -2); text("40dB", width - 40, YIntensity(40) - 15); line(0, YIntensity(40), width, YIntensity(40)); // line(0, YIntensity(40), width, YIntensity(100)); xAvantPitch = 0; yAvantPitch = YPitch(PitchMini) ; xAvantIntensity = 0; yAvantIntensity = YIntensity(40) ; } void EffaceEcran() { // background(255); // Fond blanc // AfficheCouche(Couche); textFont(maFonte, 12); textAlign(LEFT, BASELINE); // text("A: Particle Pause: Espace", width - 270, height - 2); text("Pause: Espace", width - 170, height - 2); xAvantPitch = 0; yAvantPitch = YPitch(PitchMini) ; xAvantIntensity = 0; yAvantIntensity = YIntensity(40) ; } void Debut() { ToucheEspace = false; Repos(); TempsPause = millis(); IndexPitch = 0; IndexIntensity = 0; IndexXML = 0; IndexXMLHaut = 0; IndexXMLBas = 0; IndexXMLCouche4 = 0; EffaceEcran(); PlayerAudioDebut(); } void PlayerAudioDebut() { player.close(); player = minim.loadFile(NomFichierAudio, 2048); player.play(); } void Repos() { Pause = ToucheEspace; if (Pause) { player.pause(); TempsDebutPause = millis(); } else { player.play(); TempsPause = TempsPause + millis() - TempsDebutPause; } } void keyPressed() { // println("key = " + key); if (key == ' ') { // barre d'espace ToucheEspace = ! ToucheEspace; Repos(); } else if ( key == 'p' || key == 'P' ) { Couche = 0; // P Phonème Debut(); } else if (key == 'y' || key == 'Y') { Couche = 1; // Y Syllabe Debut(); } else if (key == 'm' || key == 'M') { Couche = 2; // M Mot Debut(); } else if (key == 'h' || key == 'H') { Couche = 3; // H Phonétique Debut(); } else if (key == 'o' || key == 'O') { Couche = 4; // O Orthographique Debut(); } else if (key == 'a' || key == 'A') { //vp.addParticle(new Particle(0, 0)); //envoi d'une "Particle" // particle.display(); // Alea = !Alea; // EffaceEcran(); } else if (key == 's' || key == 'S') saveFrame(timestamp()+"_##.png"); else if (keyPressed && (key == CODED)) { // If it's a coded key if (keyCode == LEFT) { // Left arrow FacteurX = FacteurX / 2; Debut(); } else if (keyCode == RIGHT) { // Right arrow FacteurX = FacteurX * 2; Debut(); } } // println("key = " + key + " Erreur taper Espace"); } String timestamp() { Calendar now = Calendar.getInstance(); println("Frame saved"); // return String.format("%1$ty%1$tm%1$td_%1$tH%1$tM%1$tS", now); return String.format("%1$ty%1$tm%1$td_%1$tH%1$tM%1$tS", now); } void stop() { // always close Minim audio classes when you are done with them player.close(); minim.stop(); super.stop(); }