Arduino controlled soundfile in Processing

So, me and my group are trying to control a soundfile in Processing through a potentiometer and sensor data from an Arduino UNO. We’re controlling it’s attributes (specifically pitch) through the beads library. However, we’ve come to a standstill at the serial communication between the two sketches. Below is our current Processing code and below that, our Arduino code. Hopefully someone can help us out! :slight_smile:

import beads.*;
import processing.serial.*;

Serial myPort;

int [] serialInArray = new int[2]; // if only pot-value is sent, this array is unessecary
int serialCount = 0;
boolean firstContact = false;

AudioContext   ac;
Gain           g;

float plantData;
float prevPlantData;
float potData;

void setup()
{
  size(500, 500);

  myPort = new Serial (this, "COM4", 115200);
  myPort.bufferUntil('\n');

  ac = new AudioContext();
  g = new Gain(ac, 1, 0.5);

  ac.out.addInput(g);
  ac.start();
}

void draw()
{
  if (potData != 0) {
    ambientSound();
  }
}

int[] guitarPitches = {0, 5, 10, 15, 19, 24}; // hlf steps from low e, for each open string
int ctr = 0;

void ambientSound() //if statement with any plant changes
{
  int pitchIdx = guitarPitches[ctr];
  ctr = (ctr + 1) % guitarPitches.length;
  float pitchRatio = pow(2, pitchIdx/12.0);
  String sourceFile = dataPath("ambient_single_note001.wav");
  try {
    SamplePlayer sp = new SamplePlayer(ac, new Sample(sourceFile));
    sp.setRate(new Glide(ac, pitchRatio));
    sp.setKillOnEnd(true);
    g.addInput(sp);
    sp.start();
  }
  catch (Exception e) {
    println("Exception loading sample: " + sourceFile);
    e.printStackTrace();
  }
}

void serialEvent (Serial myPort) {
  plantData = int (myPort.readStringUntil('\n'));

  int inByte = myPort.read();
  if (firstContact == false) {
    if (inByte == 'A') {
      myPort.clear();
      firstContact = true;
      myPort.write('A');
    }
  } else {
    serialInArray[serialCount] = inByte;
    serialCount++;

    if (serialCount > 2) {
      plantData = serialInArray[0];
      potData = serialInArray[1];
      println(plantData + "\t" + potData + "\t");
      myPort.write('A');

      serialCount = 0;
    }
  }
}

Arduino IDE

int plantVal; // a value to store data from the plant
int plantMidi; // a value for the MIDI data

int potVal; // a value to store data from the potentiometer
int potPre; // a value to store the previously used value
int potMidi; // a value for the MIDI data

int inByte = 0;

void setup() {
  Serial.begin(115200); // set the baudrate to the same as will be used in the Hairless Midi software
  establishContact();
}

void loop() {
  //setup communication
  if (Serial.available() > 0) {
    inByte = Serial.read();
    Serial.write(plantMidi);
    Serial.write(potMidi);
  }

  // setup for the plant readings
  plantVal = analogRead(A5); // read the data from pin?
  plantMidi = map(plantVal, 330, 350, 0, 127); // map the reading from the plant to data usable in MIDI

  // setup for the potentiometer
  potVal = analogRead(A2); // read the data from pin2?
  if (potVal != potPre) {
    potMidi = map(potVal, 501, 1023, 0, 127); // map the reading from the potentiometer
    potPre = potVal; // update the previous value of the potentiometer
  }

  delay(100); //short delay to help prevent unstableness

  Serial.print("Plant value: ");
  Serial.println(plantVal);
  Serial.print("Potentiometer value: ");
  Serial.println(potVal);
  Serial.println();
  Serial.print("Midi plantvalue: ");
  Serial.println(plantMidi);
  Serial.print("Midi potvalue: ");
  Serial.println(potMidi);
  Serial.println();
}

void establishContact() {
  while (Serial.available() <= 0) {
    Serial.print('A');
    delay(300);
  }
}

Hi, I tried running your sketches, had to comment out all the audio parts that I don’t have the libraries. Couldn’t get the start to work with the 'A’s going back and forth. It can be difficult to get that kind of logic to work in all circumstances. In the Ard code you are using serial for 2 purposes: Serial.write(plantMidi); - characters transmitted to Processing, Serial.print("Plant value: "); - information messages. Both these outputs will go to the Processing sketch. This is usually not good unless you’ve specially designed the Processing code to select out what it wants and discard the information messages.

You could try this to work out what’s going on. At each point in the logic of serialEvent(), after each {, insert a statement like print(“a”); (then b,c etc. obviously). From the pattern of what’s printed out you’ll see what’s happening.

Another option would be to try a working example I made. I’m reasonably sure it will work first time. If you like it you could merge parts of your sketches into it.

Okay, so we got processing to recieve the right values now, however, we’re at a standstill on how to control the pitch with these revieved values. I don’t know if you’re able to help, since this is pretty much just beads at this point, but let’s give it a shot :smiley:

Arduino code:

int potVal; 
int plantVal;

void setup() {
  Serial.begin(115200);
}

void loop() {
  potVal = (analogRead(A2));
  Serial.write(potVal);

  plantVal = (analogRead(A5));
  Serial.write(plantVal);
  
  delay(100);
}

Processing code:

import beads.*;
import processing.serial.*;

Serial myPort;

int potVal;
int plantVal;

int[] guitarPitches = {0, 5, 10, 15, 19, 24}; // hlf steps from low e, for each open string
int ctr = 0;

AudioContext ac;
Gain         g;

void setup() {
  //fullScreen();
  size(500, 500);
  myPort = new Serial(this, Serial.list()[0], 115200);


  ac = new AudioContext();
  g = new Gain(ac, 1, 0.5);

  ac.out.addInput(g);
  ac.start();
}

void draw() {
  if (potVal != 0) {
    ambientSound();
  }
  if (myPort.available() > 0) {
    potVal = myPort.read();
    plantVal = myPort.read();
    println("Potentiometer value: ");
    println(potVal);
    println("Plant value: ");
    println(plantVal);
    println("_____________________________");
    println();
  }
}

void ambientSound() //if statement with any plant changes
{
  int pitchIdx = guitarPitches[ctr];
  ctr = (ctr + 1) % guitarPitches.length;
  float pitchRatio = pow(2, pitchIdx/12.0);
  String sourceFile = dataPath("ambient_single_note001.wav");
  try {
    SamplePlayer sp = new SamplePlayer(ac, new Sample(sourceFile));
    sp.setRate(new Glide(ac, pitchRatio));
    sp.setKillOnEnd(true);
    g.addInput(sp);
    sp.start();
  }
  catch (Exception e) {
    println("Exception loading sample: " + sourceFile);
    e.printStackTrace();
  }
}

I’m not seeing where you update anything in the ambientSound() method. You are just calling the function in the draw() loop. You need to either pass your potVal or plantVal to the ambientSound() method or call it in some way in your method to get the update from the Arduino.

Have you created a working adjustable pitch playback example without the Arduino library?

Also, your posts keep getting ignored or flagged, I’m assuming it’s the offensive user name. Maybe look into that. We all try to be as respectful as possible on the forum.

Good luck with your project.

1 Like