Recitation 7: Neopixel Music Visualizati

Thanks to La Kaylee, I finally understood how processing communicates with Arduino programs. The data of the index and CRGB color of the LEDs are stored in an array of serialRead(serialRead.value[]=4 here) and sent by serialRead.send(), toward the program in Arduino(we copied it from IX lab page); then, with library fastLEDs, arduino control the Neopixel.

To visualize the music, I chose the lenth of lit LEDs to show frequency of sounds–higher tone reacted with more LEDs.

As is shown in the first version above, every second, every LED changed colors because of the default random() color setting, making the Neopixel a effect of flashing. Unfortunately, the flashing effect weakens the LEDs’ reaction to music changes. That is, changing color made the length change unobvious.

Therefore, in the second version, I default all colors into one, to that we can simply see the jumping LED lines.

/* This is a code example for Processing, to be used on Recitation 7
 You need to have installed the SerialRecord library.
 
 Interaction Lab
 IMA NYU Shanghai
 2022 Fall
 */
import processing.sound.*;

SoundFile sample;
Amplitude analysis;

import processing.serial.*;
import osteele.processing.SerialRecord.*;

Serial serialPort;
SerialRecord serialRecord;

int W;         //width of the tiles
int NUM = 60;  //amount of pixels
int[] r = new int[NUM]; //red of each tile
int[] g = new int[NUM]; //red of each tile
int[] b = new int[NUM]; //red of each tile

// declare an AudioIn object
//AudioIn microphone;
// declare an Frequency analysis object to detect the frequencies in a sound
FFT freqAnalysis;
// declare a variable for the amount of frequencies to analyze
// should be a multiple of 64 for best results
int frequencies = 1024;
// Define the frequencies wanted for our visualization.  Above that treshold frequencies are rarely atteigned and stay flat.
int freqWanted = 128;
// declare an array to store the frequency anlysis results in
float[] spectrum = new float[freqWanted];
// Declare a drawing variable for calculating the width of the
float circleWidth;


void setup() {
  size(600, 400);
  W = width/NUM;


  // You can use this syntax and change COM3 for your serial port
  printArray(Serial.list());
  serialPort = new Serial(this, "COM3", 9600);
  // in MacOS it looks like "/dev/cu.usbmodem1101"
  //or you can try to use this instead:

  String serialPortName = SerialUtils.findArduinoPort();
  //serialPort = new Serial(this, serialPortName, 9600);
  serialRecord = new SerialRecord(this, serialPort, 4);
  serialRecord.logToCanvas(false);
  rectMode(CENTER);

  sample = new SoundFile(this, "lanTingXu.mp3");

  // create the Amplitude analysis object
  analysis = new Amplitude(this);
  // analyze the playing sound file
  analysis.input(sample);

  //freq
  //size(512, 480);
  // Calculate the width of the circles depending on how the bands we want to display.
  circleWidth = width/float(freqWanted);
  // create the AudioIn object and select the mic as the input stream
  //microphone = new AudioIn(this, 0);
  // start the mic input without routing it to the speakers
  //microphone.start();
  // create the Frequency analysis object and tell it how many frequencies to analyze
  freqAnalysis = new FFT(this, frequencies);
  // use the microphone as the input for the analysis
  //freqAnalysis.input(microphone);
}

void draw() {
  background(0);
  backGround();
  for (int i=0; i<NUM; i ++) {
    fill(r[i], g[i], b[i]);
    rect(i * W + W/2, height/2, 10, 10);
  }

  //if (mousePressed == true) {
  //  int n = floor(constrain(mouseX/W, 0, NUM-1));

  //  r[n] = floor(random(255));
  //  g[n] = floor(random(255));
  //  b[n] = floor(random(255));

  //  serialRecord.values[0] = n;     // which pixel we change (0-59)
  //  serialRecord.values[1] = r[n];  // how much red (0-255)
  //  serialRecord.values[2] = g[n];  // how much green (0-255)
  //  serialRecord.values[3] = b[n];  // how much blue (0-255)
  //  serialRecord.send();            // send it!
  //}

  noStroke();
  fill(255, 0, 150);

  // analyze the audio for its volume level
  float volume = analysis.analyze();
  float freq=analysis.analyze();

  // volume is a number between 0.0 and 1.0//but actually the max is 0.5
  // map the volume value to a useful scale
  float diameter = map(volume, 0, 1, 0, width);
  int voln=int(map(volume, 0, 0.5, 0, 30));
  float y=height/2;
  // draw a circle based on the microphone amplitude (volume)
  circle(width/2, y, diameter);

  //freq
  // analyze the frequency spectrum and store it in the array
  freqAnalysis.analyze(spectrum);
  printArray(spectrum);
  //background(0);
  fill(200, 0, 100, 150);
  noStroke();

  // draw circles based on the values stored in the spectrum array
  // adjust the scale variable as needed
  //float scale = 600;
  //for (int i=0; i<freqWanted; i++) {
  //  circle(i*circleWidth, height/2, spectrum[i]*scale);
  //}
  //
  //lenth-volumn//light frequent
  if (sample.isPlaying()) {
    for (int i=0; i<voln; i++) {
      //int n = floor(constrain(mouseX/W, 0, NUM-1));
      int n=i;
      //r[n] = floor(random(255));
      //g[n] = floor(random(255));
      //b[n] = floor(random(255));
      r[n] = 140;
      g[n] = 190;
      b[n] = 200;

      serialRecord.values[0] = n;     // which pixel we change (0-59)
      serialRecord.values[1] = r[n];  // how much red (0-255)
      serialRecord.values[2] = g[n];  // how much green (0-255)
      serialRecord.values[3] = b[n];  // how much blue (0-255)
      serialRecord.send();            // send it!
    }
    for (int i=voln; i<60; i++) {
      //int n = floor(constrain(mouseX/W, 0, NUM-1));
      int n=i;
      r[n] = 0;
      g[n] = 0;
      b[n] = 0;

      serialRecord.values[0] = n;     // which pixel we change (0-59)
      serialRecord.values[1] = r[n];  // how much red (0-255)
      serialRecord.values[2] = g[n];  // how much green (0-255)
      serialRecord.values[3] = b[n];  // how much blue (0-255)
      serialRecord.send();            // send it!
    }
    //int n = floor(constrain(mouseX/W, 0, NUM-1));

    //r[n] = floor(random(255));
    //g[n] = floor(random(255));
    //b[n] = floor(random(255));

    //serialRecord.values[0] = n;     // which pixel we change (0-59)
    //serialRecord.values[1] = r[n];  // how much red (0-255)
    //serialRecord.values[2] = g[n];  // how much green (0-255)
    //serialRecord.values[3] = b[n];  // how much blue (0-255)
    //serialRecord.send();            // send it!
  } else {
    for (int i=0; i<30; i++) { //int n = floor(constrain(mouseX/W, 0, NUM-1)); int n=i; r[n] = 200; g[n] = 140; b[n] = 190; serialRecord.values[0] = n; // which pixel we change (0-59) serialRecord.values[1] = r[n]; // how much red (0-255) serialRecord.values[2] = g[n]; // how much green (0-255) serialRecord.values[3] = b[n]; // how much blue (0-255) serialRecord.send(); // send it! if (n>6) {
        n=n-1;
        r[n] = 0;
        g[n] = 0;
        b[n] = 0;
        serialRecord.values[0] = n;     // which pixel we change (0-59)
        serialRecord.values[1] = r[n];  // how much red (0-255)
        serialRecord.values[2] = g[n];  // how much green (0-255)
        serialRecord.values[3] = b[n];  // how much blue (0-255)
        serialRecord.send();
      }
      serialRecord.values[0] = n;     // which pixel we change (0-59)
      serialRecord.values[1] = r[n];  // how much red (0-255)
      serialRecord.values[2] = g[n];  // how much green (0-255)
      serialRecord.values[3] = b[n];  // how much blue (0-255)
      serialRecord.send();
    }
  }
}
void backGround() {
  long t = millis();
  if (t < 1500) { background(155); } else if ((t>=1500) && t<3000) {
    background(255);
  } else {
    background(55);
  }
}
void mousePressed() {
  sample.play();
}

One aspect can be develop is about delay. As we can see on the taptop screen in my two versions, the graphic changing was not smooth. I guessed it’s probably  because too many LED changed status and took times and made delays. This was comfirmed when I helped another students to shut up the LED last seconds.

Leave a Reply

Your email address will not be published. Required fields are marked *