# Who knows well Geomerative?!

**URL:** <https://discourse.processing.org/t/who-knows-well-geomerative/10453>\
**Category:** Libraries\
**Created:** [April 19, 2019, 8:56am UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453 "2019-04-19T08:56:29Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [May 22, 2019, 8:39pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/21 "2019-05-22T20:39:22Z")

</div>

It compiles, but then it gets this runtime error

---

<div class="post-metadata">

**Author:** ![lolonulu](https://avatars.discourse-cdn.com/v4/letter/l/ad7895/32.png) [@lolonulu](https://discourse.processing.org/u/lolonulu)\
**Post date:** [May 22, 2019, 8:40pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/22 "2019-05-22T20:40:43Z")

</div>

yes, another issue!!

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [May 22, 2019, 8:45pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/23 "2019-05-22T20:45:13Z")

</div>

Write an email to the people of the geomerative website

---

<div class="post-metadata">

**Author:** ![lolonulu](https://avatars.discourse-cdn.com/v4/letter/l/ad7895/32.png) [@lolonulu](https://discourse.processing.org/u/lolonulu)\
**Post date:** [May 22, 2019, 8:46pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/24 "2019-05-22T20:46:21Z")

</div>

you think it’s linked to the library itself?

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [May 22, 2019, 8:52pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/25 "2019-05-22T20:52:32Z")

</div>

No, but they are good and will like it

---

<div class="post-metadata">

**Author:** ![lolonulu](https://avatars.discourse-cdn.com/v4/letter/l/ad7895/32.png) [@lolonulu](https://discourse.processing.org/u/lolonulu)\
**Post date:** [May 22, 2019, 8:54pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/26 "2019-05-22T20:54:03Z")

</div>

okay, I will try! Thanks a lot…

---

<div class="post-metadata">

**Author:** ![lolonulu](https://avatars.discourse-cdn.com/v4/letter/l/ad7895/32.png) [@lolonulu](https://discourse.processing.org/u/lolonulu)\
**Post date:** [May 24, 2019, 8:41am UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/27 "2019-05-24T08:41:03Z")

</div>

Dear @Chrisir, I’ve fixed the map() error, wrote to Ricard Maxer who developped the Geomerative Library and to another developper, but no answer until now…

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [May 24, 2019, 5:01pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/28 "2019-05-24T17:01:57Z")

</div>

Can you post your new code without the map() error please?

---

<div class="post-metadata">

**Author:** ![lolonulu](https://avatars.discourse-cdn.com/v4/letter/l/ad7895/32.png) [@lolonulu](https://discourse.processing.org/u/lolonulu)\
**Post date:** [May 24, 2019, 5:16pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/29 "2019-05-24T17:16:44Z")

</div>

Hi @Chrisir,  
with pleasure but I’ve made changes since to test if with two occurences of the class Characters() it would change the result. It appears that Geomerative select the last String as a reference…  
Thanks a lot for your patience and help.  
L

```auto
import processing.pdf.*;
import geomerative.*;
import ddf.minim.analysis.*;
import ddf.minim.*;

String soundNameFR = "FR_01";
Minim minim;
AudioPlayer soundsFR;
FFT fftFR;
float bandHeightFR;

int x, y;
String []mess={"On me dit de te haïr et je m'y efforce", 
  "Je t'imagine cruel, violent, implacable", 
  "mais à te voir je n'ai bientôt plus de force", 
  "et de te blesser je suis bien incapable"}; 

String []message={"Tous mes camarades combattent avec rage", 
  "Et pleurent la nuit au souvenir des supplices", 
  "Infligés à leurs frères qui sont du même âge", 
  "et rêvent comme eux de toucher une peau lisse"};

color textColor=0;
RFont f;

float fontSize=60;
int splitGlyph = 120;
RPoint[][] pointsP;
float r = random(5, 20);
WordAttractor attractorW;
// We create 3 new lists parallel to pointsP
// List of attractors, one per glyph
WordAttractor [][] listWordAttractors;
// List of all the distances between all the attractors and the pointsP
float [][] listDistMap;
// List of vectors to replace the pointsP coordinates
PVector [][] listPV;

RShape [] gShape = new RShape[message.length]; 
characterSpec [] characters= new characterSpec[message.length];

RShape [] dShape = new RShape[mess.length]; 
characterSpec [] chars= new characterSpec[mess.length];

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {
  size(1920, 1920);
  RG.init(this);
  f = new RFont("SFNSText.ttf", int( fontSize), LEFT);

  //println(message.length);
  minim=new Minim(this);
  soundsFR=minim.loadFile("FR_01.wav", 512);
  soundsFR.play();
  fftFR= new FFT(soundsFR.bufferSize(), soundsFR.sampleRate());

  for (int i=0; i<mess.length; i++) {
    chars[i]= new characterSpec( dShape[i], mess[i]);
    println("i"+":"+i);
  }

  for (int i=0; i<message.length; i++) {
  characters[i]= new characterSpec( gShape[i], message[i]);
  //println("i"+":"+i);
  }
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void draw() {

  background(0);
  smooth();
  soundFFTAnalyse();
  translate(200, 400);

  // println("i"+":"+i);
  //translate(50, 50);
  /*if (i%4==0) {
   translate(0, -10);
   }
   if (i<=3) {
   translate(i*20, 0);
   } else if (i>3 && i<=6) {
   translate(-280, 0);
   translate(i*45, 0);
   } else if (i==7) {
   translate(-150, 0);
   } else if (i>=8 && i<=10 ) {
   translate(-200, 0);
   translate(i*25, 0);
   } else if (i>10 && i <=13) {  
   translate(-35, 0);
   translate(i*-1, 0);
   }
   if (i<=8 && i%4==0) {
   translate(0, 40);
   } else if (i>8 && i%3==0) {
   translate(50, 0);
   }
   if (i==11) {
   translate(50, 40);
   }
   if (i==12 ) {
   translate(-40, 0);
   }*/
  for (int j=0; j<mess.length; j++) {
    chars[j].update();
    chars[j].display();
    translate(0, j+1*50);
  }
  for (int i=0; i<message.length; i++) {
  translate(0, i+1*50);
  characters[i].update();
  characters[i].display();
  }
  translate(0, 50);
}

void soundFFTAnalyse() {
  AudioPlayer fr = soundsFR;
  fftFR.forward(fr.mix);
  for (int i=0; i<fftFR.specSize(); i++) {
    float bandDBFR = 8*log(fftFR.getBand(i)/fftFR.timeSize());
    bandDBFR=constrain(bandDBFR, -1000, 1000);
    bandHeightFR = map(bandDBFR*4, 0, -220, 0, height);

    noStroke();
    fill(255, 0, 0);
    //ellipse(fr.position()/10, bandHeightFR/20, 5, 5);
  }
}

class characterSpec {
  String m;
  int tChildCount;
  RShape bShape;
  RShape letterShapes;

  characterSpec(RShape _letterShapes, String _m) {

    letterShapes=_letterShapes;
    //bShape=_bShape;
    m=_m;
    for (int i=0; i<m.length(); i++) {
      pointsP= new RPoint [m.length()][splitGlyph];

      listWordAttractors= new WordAttractor [m.length()][splitGlyph];
      listDistMap = new float [m.length()][splitGlyph];
      for (int n=0; n<m.length(); n++) {
        for (int j=0; j<splitGlyph; j++) {
          listDistMap[n][j]=100000;
        }
      }
      listPV = new PVector[m.length()][splitGlyph];
      //for (int l=0; l<m.length(); l++) {

      println("m.length()"+":"+m.length());
      if (m.length()>0) {
       
        bShape= new RShape();
        bShape= f.toShape(m);
        RShape[]letterShapes = bShape.children;
        letterShapes = bShape.children;
        tChildCount = bShape.children.length;
         int child=bShape.children.length;
        child=max(0, bShape.children.length);
        child=tChildCount;
        //println("bShape.children.length"+":"+bShape.children.length);
      }
    }
  }

  void update() {

    for (int k=0; k<tChildCount; k++) {  

      //println(tChildCount);
      // println("tChildCount"+":"+tChildCount);
      float posX = map(soundsFR.position(), 200, soundsFR.length(), 200, width-200);
      float posY = bandHeightFR/10-350;

      float d= dist(posX, 0, bShape.children[k].getCenter().x, 0);
      float sx=map(d, 0, 100, 1, 1.25);

      if (d<100) {
        bShape.children[k].scale(sx, bShape.children[k].getCenter());
      }
      for (int j=0; j<splitGlyph; j++) {      

        float frac =(1.0/splitGlyph);
        pointsP[k][j]=bShape.children[k].getPoint(j*frac);
        float dist1 = dist(posX-200, posY+100, pointsP[k][j].x, pointsP[k][j].y);
        if (dist1 < listDistMap[k][j]) {

          // On remplace toutes les distances possibles entre la souris et les points par la distance minimale
          listDistMap[k][j]=dist1;
          listPV[k][j]=new PVector(posX-200, posY+100);
          listWordAttractors[k][j]=new WordAttractor(listPV[k][j].x, listPV[k][j].y, pointsP[k][j]);
        }
        listWordAttractors[k][j].points = pointsP[k][j];
        listWordAttractors[k][j].attract(); 

        if (m==",") {
          pushMatrix();
          pointsP[k][j].x+=10*k;

          pointsP[k][j].x-=120;
          pointsP[k][j].x+=10*k;
          popMatrix();
        }
      }
    }
  }

  void display() {
    for (int k=0; k< tChildCount; k++) {
      for (int j=0; j<splitGlyph; j++) {
        pushMatrix();
        translate(pointsP[k][j].x, pointsP[k][j].y);
        beginShape();
        stroke(255);
        noFill();
        strokeWeight(0.5);
        float angle = TWO_PI/18;
        rotate(angle*j/4+noise(pointsP[k][j].x)/20);
        bezier(-3*(noise(5)), 3, -6*(noise(2)), 3, -4*noise(10), -3, 3, -3);
        endShape();
        popMatrix();
      }
    }
  }
}

class WordAttractor {

  float force_radious =150;
  float maxForce = 10;
  RPoint position;
  RPoint points;
  float pX;
  float pY;

  WordAttractor(float x, float y, RPoint p) {
    points =p;
    position = new RPoint(x, y);
  }

  void attract() {

    float d= points.dist(position);
    if (d < force_radious) {   
      RPoint desired = new RPoint(points);
      desired.sub(position);
      desired.normalize();
      desired.scale(map(d, 0, force_radious, maxForce, 0));
      points.add(desired);
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [May 24, 2019, 5:22pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/30 "2019-05-24T17:22:20Z")

</div>

I don’t have time atm

---

<div class="post-metadata">

**Author:** ![lolonulu](https://avatars.discourse-cdn.com/v4/letter/l/ad7895/32.png) [@lolonulu](https://discourse.processing.org/u/lolonulu)\
**Post date:** [May 24, 2019, 5:38pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/31 "2019-05-24T17:38:40Z")

</div>

No problem whenever you are free to test. I tried and it works with the 3 first stanzas but there is certainly a smarter and more elegant way than this one…  
Thks!

---

<div class="post-metadata">

**Author:** ![lolonulu](https://avatars.discourse-cdn.com/v4/letter/l/ad7895/32.png) [@lolonulu](https://discourse.processing.org/u/lolonulu)\
**Post date:** [June 1, 2019, 6:18pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/32 "2019-06-01T18:18:02Z")

</div>

Dear @Chrisir,

I’ve made some small progresses since last week: now no error with sound, and I’ve declared proper 2d arrays for the text:

```auto
for (int i=0; i<message.length; i++) {
    for (int j=0; j<message[i].length; j++) {
      characters[i][j]= new characterSpec( gShape[i][j], message[i][j]);
    }
  }

```

Now I’ve added a class dedicated to the sound. The sound plays fine, but when it plays, each sound file affects the whole text and not as I wish one sound deform the corresponding sentence, why?! I hope you will be able to help me with this new problem! Thanks in advance. Best, L

```auto
import processing.pdf.*;
import geomerative.*;
import ddf.minim.analysis.*;
import ddf.minim.*;

//TEXT
int indexPhraseSetFR;
int indexPhraseFR;
int x, y, i, j;
String [][]message={
  {"On me dit de te haïr et je m'y efforce", 
    "Je t'imagine cruel, violent, implacable", 
    "mais à te voir je n'ai bientôt plus de force", 
  "et de te blesser je suis bien incapable"}, 

  {"Tous mes camarades combattent avec rage", 
    "Et pleurent la nuit au souvenir des supplices", 
    "Infligés à leurs frères qui sont du même âge", 
  "et rêvent comme eux de toucher une peau lisse"}, 

  {"Et de pouvoir enfin caresser des obus", 
    "Autres que ceux produits par le pouvoir obtus", 
  "Je rêve de quitter ces boyaux infernaux"}, 

  {"De laisser ces furieux des deux bords du Rhin", 
    "Et de pouvoir embrasser ta chute de rein", 
  "Et porter notre amour sur les fonts baptismaux"}
};

color textColor=0;
RFont f;
float fontSize=60;
int splitGlyph = 120;
RPoint[][] pointsP;
float r = random(5, 20);
WordAttractor attractorW;
// We create 3 new lists parallel to pointsP
// List of attractors, one per glyph
WordAttractor [][] listWordAttractors;
// List of all the distances between all the attractors and the pointsP
float [][] listDistMap;
// List of vectors to replace the pointsP coordinates
PVector [][] listPV;

RShape [][] gShape = new RShape[message.length][message.length]; 
characterSpec [][] characters= new characterSpec[message.length][message.length];

//SOUND
SoundManager sm;
int startTime;
int loop=0;
Minim minim;
AudioPlayer background;
FFT fftFR;
float bandHeightFR;
boolean isTransitioning = false;
boolean messageOn = false;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {
  size(1920, 1920);
  RG.init(this);
  f = new RFont("SFNSText.ttf", int( fontSize), LEFT);

  for (int i=0; i<message.length; i++) {
    for (int j=0; j<message[i].length; j++) {
      characters[i][j]= new characterSpec( gShape[i][j], message[i][j]);
    }
  }

  //SOUND
  sm= new SoundManager(this);
  indexPhraseFR = 0;
  indexPhraseSetFR = -1;
  minim= new Minim(this);
  background = minim.loadFile("WAR.wav");
  // TIME
  startTime=millis();
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void draw() {

  background(0);
  smooth();
  sm.update();
 
  translate(300, 400);

  for (int i=0; i<message.length; i++) {
    for (int j=0; j<message[i].length; j++) {
      //indexPhraseFR = j;
      //indexPhraseSetFR = i;
       // println("i"+":"+i);
      //println("j"+":"+j);
      translate(0, 50);
      if (i==0 && j<=3) {
        translate(j*20, 0);
      }
      if (i==1 && j<=2) {
        translate(j*-20, 0);
      } else if (i==1 && j==3) {
        translate(j*-50, 0);
      }
      if (i==2 && j<=2) {
        translate(j*20, 0);
      }
      if (i==3 && j<=2) {
        translate(j*-20, 0);
      } 
      characters[i][j].update();
      characters[i][j].display();
    }
    translate(0, j+1*50);
  }
  messageOn=true;
}

void initAttractorFR(int i, int j) { 
  attractorW= new WordAttractor(x, y, pointsP[i][j]); 
}

void nextPhraseSetFR() { 
  messageOn=true;
}
void nextPhrase() {
  //println(phraseSet[indexPhraseSet][indexPhrase]);
}

class characterSpec {
  String m;
  int tChildCount;
  RShape bShape;
  RShape letterShapes;

  characterSpec(RShape _letterShapes, String _m) {

    letterShapes=_letterShapes;
    //bShape=_bShape;
    m=_m;
    for (int i=0; i<m.length(); i++) {
      pointsP= new RPoint [m.length()][splitGlyph];

      listWordAttractors= new WordAttractor [m.length()][splitGlyph];
      listDistMap = new float [m.length()][splitGlyph];
      for (int n=0; n<m.length(); n++) {
        for (int j=0; j<splitGlyph; j++) {
          listDistMap[n][j]=100000;
        }
      }
      listPV = new PVector[m.length()][splitGlyph];
      //for (int l=0; l<m.length(); l++) {

      //println("m.length()"+":"+m.length());
      if (m.length()>0) {

        bShape= new RShape();
        bShape= f.toShape(m);
        RShape[]letterShapes = bShape.children;
        letterShapes = bShape.children;
        tChildCount = bShape.children.length;
        int child=bShape.children.length;
        child=max(0, bShape.children.length);
        child=tChildCount;
        //println("bShape.children.length"+":"+bShape.children.length);
      }
    }
  }

  void update() {

    for (int k=0; k<tChildCount; k++) {  

      float d= dist(attractorPosXFR, 0, bShape.children[k].getCenter().x, 0);
      float sx=map(d, 0, 100, 1, 1.45);

      if (d<100) {
        bShape.children[k].scale(sx, bShape.children[k].getCenter());
      }
      for (int j=0; j<splitGlyph; j++) {      

        float frac =(1.0/splitGlyph);
        pointsP[k][j]=bShape.children[k].getPoint(j*frac);
        float dist1 = dist(attractorPosXFR -200, attractorPosYFR +100, pointsP[k][j].x, pointsP[k][j].y);
        if (dist1 < listDistMap[k][j]) {

          // On remplace toutes les distances possibles entre la souris et les points par la distance minimale
          listDistMap[k][j]=dist1;
          listPV[k][j]=new PVector(attractorPosXFR -200, attractorPosYFR +100);
          listWordAttractors[k][j]=new WordAttractor(listPV[k][j].x, listPV[k][j].y, pointsP[k][j]);
        }
        listWordAttractors[k][j].points = pointsP[k][j];
        listWordAttractors[k][j].attract(); 
        pushMatrix();
        if (m==",") {

          pointsP[k][j].x+=10*k;
        }
        pointsP[k][j].x-=120;
        pointsP[k][j].x+=10*k;
        popMatrix();
      }
    }
  }

  void display() {
    for (int k=0; k< tChildCount; k++) {
      for (int j=0; j<splitGlyph; j++) {

        //RPoint attractorPositFR = new RPoint(attractorPosXFR, attractorPosYFR);
        //float dist = pointsP[k][j].dist(attractorPositFR);
        pushMatrix();
        translate(pointsP[k][j].x, pointsP[k][j].y);
        beginShape();
        stroke(255);
        noFill();
        strokeWeight(0.5);
        float angle = TWO_PI/18;
        rotate(angle*j/4+noise(pointsP[k][j].x)/20);
        bezier(-3*(noise(5)), 3, -6*(noise(2)), 3, -4*noise(10), -3, 3, -3);
        endShape();
        popMatrix();

        if (k==indexPhraseFR) {
          pushMatrix();
          translate(pointsP[k][j].x, pointsP[k][j].y);
          RPoint attractorPosFR = new RPoint(attractorPosXFR, attractorPosYFR);
          attractorPosFR = new RPoint(attractorPosXFR, attractorPosYFR);
          float d = pointsP[k][j].dist(attractorPosFR);
          if (d<100) {
            d = map(d, 50, 0, 1, 0);
            noFill();
            stroke(255, 200);
          }
          float angle_01 = TWO_PI*10;
          //rotate (j/angle*frameCount/10);
          rotate (j/angle_01*2);
          bezier(-2*(noise(10)), 10, 10*(noise(10)), -5, 2*noise(5), -10, 10, attractorPosFR.x/20);//
          popMatrix();
        }
      }
    }
  }
}

import ddf.minim.analysis.*;
import ddf.minim.*;

// variable 'public'
String []soundNamesFR = {"FR_01", "FR_02", "FR_03", "FR_04", "FR_05", "FR_06", "FR_07", "FR_08", "FR_09", "FR_10", "FR_11", "FR_12", "FR_13", "FR_14"};
float attractorPosXFR, attractorPosYFR;

class SoundManager {
  //SOUND
  Minim minim;
  AudioPlayer[]soundsFR;
  FFT fftFR;
  float transitionTime = 0;
  int startTransitionTime;
  int transitionDuration = 1500;

  SoundManager(PApplet app) {

    minim = new Minim(app);
    soundsFR = new AudioPlayer[soundNamesFR.length];
    for (int i =0; i<soundNamesFR.length; i++) {
      soundsFR[i] = minim.loadFile(soundNamesFR[i]+".wav", 512);
    }
  }

  void update() {

    if (isTransitioning) {
      if (millis() >= startTransitionTime+transitionDuration) {
        // transition end
        // si c'est pas fini on passe au suivant
        if (indexPhraseSetFR < soundsFR.length) {
          isTransitioning=false;
          transitionTime=0; 
          nextPhraseSetFR();
          playSound();

          // si on a lu tous les groupes on recommence à zero
        } else if (indexPhraseSetFR == soundsFR.length && millis() >= startTransitionTime+transitionDuration) {         
          // reset from the beginning 
          isTransitioning=false;
          transitionTime=0;    
          indexPhraseSetFR=0;
          indexPhraseFR=0;
          nextPhraseSetFR();
          background.shiftGain(-20, -80, 1000);
          background.rewind();
          background.pause();
          startTime = millis();
          playSound();
          background.play();
          background.shiftGain(-80, -20, 1000);
        }
      } else if (millis() <= startTransitionTime+transitionDuration) {       
        // we are transiting 
        transitionTime = map(millis(), startTransitionTime, startTransitionTime+transitionDuration, 0., 1.);
      }
    } else {
      if ( indexPhraseSetFR==-1) { 
        // Initialise all
        indexPhraseSetFR=0;
        indexPhraseFR=0;
        playSound();
        nextPhraseSetFR();
        background.play();
        background.shiftGain(-80, -20, 1000);
      } else if ( !soundsFR[indexPhraseFR].isPlaying()) {  
       
        // sound file is finished read next one
        indexPhraseFR++;
        //println("soundsFR.length"+":"+ soundsFR.length);
        println("indexPhraseFR"+":"+ indexPhraseFR);

        println("indexPhraseSetFR"+":"+indexPhraseSetFR);
        if ( isTransitioning==false && indexPhraseFR >= soundsFR.length) {
          // If phrases'index is greater than the stanza's index then go on to the next stanza
          indexPhraseFR=0;// 1rst sentence
          indexPhraseSetFR++;// increase stanza's index
          isTransitioning = true;
          startTransitionTime = millis();
        } else {
          //go to the next phrase   
          nextPhrase();
        }
        if (millis() >= startTransitionTime+transitionDuration) {
          playSound();
        }
      } else { 
        // we're reading the sound file
        // analyse of the sound
        soundFFTAnalyse();
        wordAttractorToSound();
      }
    }
  }
  

  void pauseSound() {
    AudioPlayer fr = soundsFR[indexPhraseFR];
    fr.rewind();
    fr.pause();
    fftFR = new FFT(fr.bufferSize(), fr.sampleRate());
  }

  void playSound() {
    AudioPlayer fr = soundsFR[indexPhraseFR];
    fr.rewind(); 
    fr.play();
    fftFR = new FFT(fr.bufferSize(), fr.sampleRate());
    attractorPosXFR = 0;
    attractorPosYFR =0;
    bandHeightFR = 0;
  }

  void soundFFTAnalyse() {
    AudioPlayer fr = soundsFR[indexPhraseFR];
    fftFR.forward(fr.mix);
    for (int i =0; i< fftFR.specSize(); i++) {
      float bandDBFR = 10*log(fftFR.getBand(i)/fftFR.timeSize());
      bandDBFR = constrain(bandDBFR, -1000, 1000);
      bandHeightFR = map(bandDBFR*4, 0, -220, 0, height);
    }
  }

  void wordAttractorToSound() {

    AudioPlayer fr = soundsFR[indexPhraseFR]; 
    initAttractorFR(indexPhraseFR,indexPhraseFR);
    attractorPosXFR = map(fr.position(), 0, fr.length(), 100-width/5, width-100+width/7);
    attractorPosYFR = bandHeightFR/8-350;
    attractorW.moveTo(attractorPosXFR, attractorPosYFR); 
    attractorW.attract();
    //wAttractorFR.display();
  }
}

class WordAttractor {

  float force_radious =150;
  float maxForce = 10;
  RPoint position;
  RPoint points;
  float pX;
  float pY;

  WordAttractor(float x, float y, RPoint p) {
    points =p;
    position = new RPoint(x, y);
  }

  void attract() {
   
      float d= points.dist(position);
      if (d < force_radious) {   
        RPoint desired = new RPoint(points);
        desired.sub(position);
        desired.normalize();
        desired.scale(map(d, 0, force_radious, maxForce, 0));
        points.add(desired);
    }
  }
  void moveTo(float x, float y) {
    position.x=x;
    position.y=y;
  }
}

```

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [June 1, 2019, 6:28pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/33 "2019-06-01T18:28:20Z")

</div>

Hi!

I am afraid I don’t have time…

---

<div class="post-metadata">

**Author:** ![lolonulu](https://avatars.discourse-cdn.com/v4/letter/l/ad7895/32.png) [@lolonulu](https://discourse.processing.org/u/lolonulu)\
**Post date:** [June 1, 2019, 6:32pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/34 "2019-06-01T18:32:24Z")

</div>

Hi!  
Well if you find a bit of time in the coming days just to help me to find my way, how to debug, I’m doing my best and it’s the last touch to this project! Thanks a lot in advance.  
Best,  
L

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [June 2, 2019, 1:06pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/35 "2019-06-02T13:06:07Z")

</div>

you got mail…

---

<div class="post-metadata">

**Author:** ![lolonulu](https://avatars.discourse-cdn.com/v4/letter/l/ad7895/32.png) [@lolonulu](https://discourse.processing.org/u/lolonulu)\
**Post date:** [June 2, 2019, 1:08pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/36 "2019-06-02T13:08:05Z")

</div>

Here it is : [l.mareschal@free.fr](mailto:l.mareschal@free.fr)  
thanks @Chrisir

---

<div class="post-metadata">

**Author:** ![lolonulu](https://avatars.discourse-cdn.com/v4/letter/l/ad7895/32.png) [@lolonulu](https://discourse.processing.org/u/lolonulu)\
**Post date:** [June 2, 2019, 1:50pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/37 "2019-06-02T13:50:31Z")

</div>

?! I misunderstood ?! I haven’t received anything yet…

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [June 2, 2019, 2:02pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/38 "2019-06-02T14:02:23Z")

</div>

_just a short reply:_

**Remark**

I like it that you work with _tabs_

**Remark**

This should be in the soundmanager class [I guess, or do you play two sounds at the same time? Then forget my remark] and not before setup() (in fact you already have it in the class but it’s duplicate before setup()):

```auto
Minim minim;
AudioPlayer background;
FFT fftFR;

```

also this (which is in setup() but should be in the class instead):

background = minim.loadFile(“WAR.wav”);

**Your question**

> each sound file affects the whole text and not as I wish one sound deform the corresponding sentence, why

`WordAttractor attractorW, attractorPosXFR` etc. are modified by `wordAttractorToSound()` (`class SoundManager`)

but the problem is imho that all sentences do use these variables attractorW, attractorPosXFR etc.

so no wonder all sentences are affected / changed

To solve this problem: umhh…

_Do you want to play 1 soundfile that affects sentence 1 and then when it (1) has ended soundfile 2 starts and 2 affects sentence 2 ?_

when I look at your draw() I see

```auto
  translate(300, 400);

  for (int i=0; i<message.length; i++) {
    for (int j=0; j<message[i].length; j++) {

```

which means you put out all the letters at once (which is ok) and modify them all (which is not ok).

So you could have one variable storing which sentence is currently modified (1,2,3…)

```auto
if(sentenceNumberCurrentlyModified == i) {
      characters[i][j].update();
}

characters[i][j].display();

```

now initially sentenceNumberCurrentlyModified is 0, every time when you start a new sound in `update()` in `class SoundManager` say `sentenceNumberCurrentlyModified ++;`

Chrisir

---

<div class="post-metadata">

**Author:** ![lolonulu](https://avatars.discourse-cdn.com/v4/letter/l/ad7895/32.png) [@lolonulu](https://discourse.processing.org/u/lolonulu)\
**Post date:** [June 2, 2019, 2:11pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/39 "2019-06-02T14:11:20Z")

</div>

Thank you so much dear @Chrisir to take of your time to help me on sunday!

> _Do you want to play 1 soundfile that affects sentence 1 and then when it (1) has ended soundfile 2 starts and 2 affects sentence 2 ?_

Yes exactly.

> So you could have one variable storing which sentence is currently modified (1,2,3…)

ok I will try this… I will let you know if it works ;)) Thank you so much for this great pedagogical approach it helps me to understand my mistakes…

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [June 2, 2019, 2:19pm UTC](https://discourse.processing.org/t/who-knows-well-geomerative/10453/40 "2019-06-02T14:19:45Z")

</div>

Didn’t have time to do it… sorry…

[Previous page](https://discourse.processing.org/t/who-knows-well-geomerative/10453.md?page=1)

[Next page](https://discourse.processing.org/t/who-knows-well-geomerative/10453.md?page=3)
