Individual colors for a series of shapes

edited November 2017 in Library Questions

Hi everyone ! So I thought my problem was solved once we got over this question of colored rectangles. ( https://forum.processing.org/two/discussion/comment/109296#Comment_109296 )

But not at all. This time I don't want random colors, and making an array isn't enough... So my question is the same as before: how to draw each rectangle so that its color stays the same, independently from the following rectangles? I want the color to change according to the frequency. Here is the code:

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

Minim minim;
AudioPlayer song;
FFT fft;
float highestAmp = 0;
int frequency;
float amplitude;
int rectX;
float time;
color[] colors = new color[3];

void setup(){
  size(1500,500);
  background(255);


    // initialize Minim and catching the output
  minim = new Minim(this);
  song = minim.loadFile("altj.mp3",1024);
//better result with *8
fft = new FFT(song.left.size(), 44100);
song.play();

// define 3 colors
colors[0] = color(255,0,0);
colors[1] = color(255,255,0);
colors[2] = color(0,255,0);
 }


 void draw (){
   highestAmp=0;
   amplitude=0;
   frequency=0;
   fft.forward(song.left);
   background(255);

   // get frequency from 0Hz to 20000Hz
   for(int i = 0; i < 20000; i++){
     amplitude = fft.getFreq(i);
     if (amplitude > highestAmp) {
       highestAmp = amplitude;
       frequency = i;
     }
   }
   //make it move !
   for (int x = 0; x < time; x = x+5) {
     // color frequencies
    if (frequency < 70){
    fill(colors[0]);
    }else if (frequency < 250){
      fill(colors[1]);
    }else{
    fill(colors[2]);
    }
    rect(x,0,5, height); 
  }
time++;
 }

I learned about classes and tried to use them (still a noob, haha). It looks like this :

Slot mySlot;
float x;
color[] colors = new color[3];
import ddf.minim.*;
import ddf.minim.analysis.*;

Minim minim;
AudioPlayer song;
FFT fft;
float highestAmp = 0;
int frequency;
float amplitude;

void setup()  {
  size(1500,500);
  // initialize Minim and catching the output
  minim = new Minim(this);
  song = minim.loadFile("altj.mp3",1024);
//better result with *8
fft = new FFT(song.left.size(), 44100);
song.play();

  mySlot = new Slot ();  
  colors[0] = color(255,0,0);
  colors[1] = color(255,255,0);
  colors[2] = color(0,255,0);
}    

void draw()  {  
  highestAmp=0;
   amplitude=0;
   frequency=0;
   fft.forward(song.left);

   // get frequency from 0Hz to 20000Hz
   for(int i = 0; i < 20000; i++){
     amplitude = fft.getFreq(i);
     if (amplitude > highestAmp) {
       highestAmp = amplitude;
       frequency = i;
     }
   }

  mySlot.display();   
  mySlot.avance();  
  x = 0;
  if (frequency <70){
    fill(colors[0]);
    }else if (frequency < 250){
      fill(colors[1]);
    }else{
      fill(colors[2]);
    }
    rect(x,0,5, height);

}       

class Slot{

  //Data
  float x;
  float time;

  //Constructor
  Slot(){
    x = 0;
  }

  //Functionality
  void display() {
    rect(x,0,5,height);
  }

  void avance(){
    x = 0;
    for(int x = 0; x < time; x = x + 5){
      rect(x,0,5,height);
    }
    time++;
    if (x > width) {
      x = 0;
    }
  }
} 

But same problem: the "fill" color is inside the same draw function as the rectangle. I don't know how I can separate it from the above line of the shape, or make a series of shapes related to these conditions for colors... Any clue?

Answers

  • you only have one Slot, how can they all be different colours?

  • So... Make an array of slots?

  • yep. add a colour member to each.

  • ok let's try !

  • edited November 2017
    Slot[] slotx = new Slot[1001];
    float x;
    color[] colors = new color[3];
    import ddf.minim.*;
    import ddf.minim.analysis.*;
    
    Minim minim;
    AudioPlayer song;
    FFT fft;
    float highestAmp = 0;
    int frequency;
    float amplitude;
    
    void setup()  {
      size(1500,500);
      // initialize Minim and catching the output
      minim = new Minim(this);
      song = minim.loadFile("altj.mp3",1024);
    //better result with *8
    fft = new FFT(song.left.size(), 44100);
    song.play();
    
      colors[0] = color(255,0,0);
      colors[1] = color(255,255,0);
      colors[2] = color(0,255,0);
    
      for (int indexSlot = 0; indexSlot < 1001; indexSlot++){
      slotx[indexSlot] = new Slot[3];
      for (int f = 0; f<2; f++){
        fill(colors[f]);
        rect(slotx[indexSlot],0,5,height);
      }
      }
    }  
    
    void draw()  {  
      highestAmp=0;
       amplitude=0;
       frequency=0;
       fft.forward(song.left);
       background(255);
    
       // get frequency from 0Hz to 20000Hz
       for(int i = 0; i < 20000; i++){
         amplitude = fft.getFreq(i);
         if (amplitude > highestAmp) {
           highestAmp = amplitude;
           frequency = i;
         }
       }
       for(int f = 0; f< 1001; f++){
      Slot[indexSlot].display();   
      Slot[indexSlot].avance();  
      x = 0;
      if (frequency <70){
        fill(colors[0]);
        }else if (frequency < 250){
          fill(colors[1]);
        }else{
          fill(colors[2]);
        }
        rect(slotx[indexSlot],0,5, height);
    
    }       
    
    }
    
    class Slot{
    
      //Data
      float x;
      float time;
      //Constructor
      Slot(){
        x = 0;
      }
    
      //Functionality
      void display() {
        rect(x,0,5,height);
      }
    
      void avance(){
        x = 0;
        for(int x = 0; x < time; x = x + 5){
          rect(x,0,5,height);
        }
        time++;
        if (x > width) {
          x = 0;
        }
      }
    } 
    

    full of mistakes. I didn't really get how to use classes and convert them into variables, like this class-making-rectangles that I'm actually using as an "x" position for the final rectangle in "draw", something's wrong.

  • Answer ✓

    This is my attempt. Notice the new places for certain operations and object management (this goes along the lines of encapsulation...)

    Kf

    ArrayList<Slot> mySlot;
    float x;
    
    import ddf.minim.*;
    import ddf.minim.analysis.*;
    
    Minim minim;
    AudioPlayer song;
    FFT fft;
    float highestAmp = 0;
    int frequency;
    float amplitude;
    
    void setup() {
      size(1500, 500);
      // initialize Minim and catching the output
      minim = new Minim(this);
      song = minim.loadFile("test-sound.mp3", 1024);
      //better result with *8
      fft = new FFT(song.left.size(), 44100);
      song.play();
    
      mySlot=new ArrayList<Slot>();
    }    
    
    void draw() { 
      background(150);
      highestAmp=0;
      amplitude=0;
      frequency=0;
      fft.forward(song.left);
    
      // get frequency from 0Hz to 20000Hz
      for (int i = 0; i < 20000; i++) {
        amplitude = fft.getFreq(i);
        if (amplitude > highestAmp) {
          highestAmp = amplitude;
          frequency = i;
        }
      }
    
      Slot ss=new Slot();
      ss.updateX(mySlot.size());
      ss.updateColor(frequency);
    
    
      mySlot.add(ss);
    
      for (int i=0; i<mySlot.size(); i++) {
        mySlot.get(i).display();
      }
    }       
    
    class Slot {
    
      final int SLOTWIDTH=5;
      final color[] colors = {color(255, 0, 0),color(255, 255, 0),color(0, 255, 0)};
    
      //Data
      float x;
      float time;
      color c;
    
      //Constructor
      Slot() {
        x = 0;
      }
    
      void updateX(int valx) {
        x=valx*SLOTWIDTH;
      }
    
      void updateColor(float freq) {
        if (freq <70) {
          c=(colors[0]);
        } else if (freq < 250) {
          c=(colors[1]);
        } else {
          c=(colors[2]);
        }
      }
    
      //Functionality
      void display() {
        fill(c);
        rect(x, 0, 5, height);
      }
    } 
    
  • edited November 2017

    WHOOOO it works !!! and the code looks so pure... great !! So you put everything in the functionalities of the class Slot, almost nothing in the constructor, just x=0. You also use arguments, which I am not too familiar with... how come you don't have to declare the variables "valx" and "freq" ?

    When you write " mySlot.get(i).display(); " line 50, do you mean "display a new slot every new frequency"? What if I want it to be slower (I tried to change i++ to i = i +0.5 but get(i) doesn't work for float) ?

    I didn't know the keyword "final", btw. Thanks ! Though it seems I can remove it without changing the program. More important: I didn't know "add" !

    Thank you ! I'm learning a lot.

  • edited November 2017 Answer ✓

    @Billy, re:

    how come you don't have to declare the variables "valx" and "freq"

    You do -- see the type "int" in front of the argument in the first line of the function? You declared the argument variable there.

    void updateX ( int valx ) {

    See: http://www.cs.toronto.edu/~reid/web/javaparams.html

  • Oh ok ! thanks. I'm still trying to make it display them slower now.

Sign In or Register to comment.