xxxxxxxxxx
263
//for arduino serial connection
let serial, reverb, slider, osc;
let lightVal = 0;
let latestData = "waiting for data";
let octave = 2.5;
let pitch = 1;
let reverbVal = 0.7;
//random chant
let ballYellow, ballBlue; // i need two color ellipses
let musicalCircles = []; //empty array for my instrument
let playingYellow = false; // start oscillator 1 audio off
let playingBlue = false; // start oscillator 2 audio off
let oscYellow, oscBlue; // i need two oscillators
function serverConnected() {
print("Connected to Server");
}
function gotList(thelist) {
print("List of Serial Ports:");
for (let i = 0; i < thelist.length; i++) {
print(i + " " + thelist[i]);
}
}
function gotOpen() {
print("Serial Port is Open");
}
function gotClose(){
print("Serial Port is Closed - connect Arduino to control sound with light");
latestData = "Serial Port is Closed - connect Arduino to control sound with light";
}
function gotError(theerror) {
print(theerror);
}
// end boilerplate serial server connection
function gotData() {
latestData = "Open Connection";
let data = serial.readStringUntil('\n');
console.log(data);
if (data !== null) {
let values = data.split(',');
lightVal = parseInt(values[0]);
}
}
// define a custom ball with parameters with position, color, size, speed and name
// i want to plug in arduino to increase and decrease speed with light sensor.
class Ball {
constructor(x, y, col, diameter, name) {
this.x = x;
this.y = y;
this.col = col;
this.diameter = diameter;
this.radius = diameter / 2;
this.speedX = random(0.5, 3) * (random() > 0.5 ? 1 : -1);
this.speedY = random(0.5, 3) * (random() > 0.5 ? 1 : -1);
this.name = name; // Add a name property
}
move(lightVal) {
let speedFactor;
// Check if lightVal is undefined or NaN, and set a default value of 1
if (lightVal === undefined || isNaN(lightVal)) {
speedFactor = 1;
} else {
speedFactor = lightVal;
this.x += this.speedX * speedFactor;
this.y += this.speedY * speedFactor;
// Bounce off the edges of the screen
if (this.x < 0 || this.x > width) {
this.speedX *= -1;
}
if (this.y < 0 || this.y > height) {
this.speedY *= -1;
}
}
}
display(diameterFactor) {
fill(this.col);
noStroke();
let bouncingDiameter = this.diameter * diameterFactor;
ellipse(this.x, this.y, bouncingDiameter, bouncingDiameter);
}
}
// my custom musical instrument soundboard, parameters are position, size and tone.
class MusicalCircle {
constructor(x, y, diameter, frequency) {
this.x = x;
this.y = y;
this.diameter = diameter;
this.radius = diameter / 2;
this.frequency = frequency;
}
display(colorType) {
noFill();
stroke(0);
let alpha = 50;
if (colorType === "yellow") {
fill(255, 255, 0, alpha); // Yellow color when playing
} else if (colorType === "blue") {
fill(0, 0, 255, alpha); // Blue color when playing
}
ellipse(this.x, this.y, this.diameter, this.diameter);
}
contains(ball) {
let d = dist(ball.x, ball.y, this.x, this.y); //distance between center of circle and ball
return d < this.radius; // checks if the distance < the radius of circle
}
}
function setup() {
createCanvas(600, 600);
reverb = new p5.Reverb();
slider = createSlider(0.1, 7.0, octave,0.1);
slider.position(10, height + 10);
slider.style('width', '80px');
slider2 = createSlider(0.1, 10.0, reverbVal,0.1);
slider2.position(10, height + 40);
slider2.style('width', '80px');
serial = new p5.SerialPort();
serial.list();
serial.open('/dev/tty.usbmodem14101');
serial.on('connected', serverConnected);
serial.on('list', gotList);
serial.on('data', gotData);
serial.on('error', gotError);
serial.on('open', gotOpen);
serial.on('close', gotClose);
// create two new balls, 1 yellow, 1 blue
ballYellow = new Ball(
random(width),
random(height),
color(255, 255, 0, 128),
50,
"ballYellow"
);
ballBlue = new Ball(
random(width),
random(height),
color(0, 0, 255, 128),
200,
"ballBlue"
);
// create two oscillators, 1 for the yellow ball, and one for the blue ball
oscYellow = new p5.Oscillator();
oscYellow.setType("sine");
oscYellow.amp(0); // Start with zero amplitude
oscYellow.start();
oscYellow.disconnect();
oscBlue = new p5.Oscillator();
oscBlue.setType("sine");
oscBlue.amp(0); // Start with zero amplitude
oscBlue.start();
oscBlue.disconnect();
// create the soundboard, assign frequencies, position in the center, define the size by number of frequencies provided and increment by 100px. center circle is 0+1*100 or 100px.
let frequencies = [396, 417, 528, 639, 741, 852]; // 11th century chant tones, Benedictine monk Guido d’Arezzo Solfeggio frequencies.
for (let i = 0; i < frequencies.length; i++) {
musicalCircles.push(
new MusicalCircle(width / 2, height / 2, (i + 1) * 100, frequencies[i])
);
}
}
// YOU NEED ARDUINO CONNECTION TO CONTROL SPEED.
function draw() {
background(255);
//ball diameter
let bouncingFactor = map(octave, 0.1, 7, 0.5, 3.0);
//display connection
text(latestData, 10, 10);
if (!serial.isConnected()) {
// If open, move and display the balls based on lightVal
ballYellow.move(1);
ballBlue.move(1);
ballYellow.display(bouncingFactor);
ballBlue.display(bouncingFactor);
} else {
ballYellow.move(lightVal);
ballBlue.move(lightVal);
ballYellow.display(bouncingFactor);
ballBlue.display(bouncingFactor);
}
//pitch slider
octave = slider.value();
textSize(16);
text(`Pitch: ${octave}`, 10, height - 10);
fill(0, 0, 255);
ellipse(width / 2, height / 2, octave, octave);
//reverb activation
reverbVal = slider2.value();
textSize(16);
text(`Reverb: ${reverbVal}`, 10, height - 40);
fill(0, 0, 255);
ellipse(width / 2, height / 2, reverbVal, reverbVal);
// draw the musicalCircle soundboard
for (let i = 0; i < musicalCircles.length; i++) {
// Check if the yellow ball is within a circle; if it is contained fill the circle yello and play a note. when it leaves the circle clear the colorType parameter and stop sound.
if (musicalCircles[i].contains(ballYellow)) {
if (!playingYellow) {
playNote(oscYellow, musicalCircles[i].frequency / (pitch * octave));
playingYellow = true;
}
musicalCircles[i].display("yellow");
} else {
stopNote(oscYellow);
playingYellow = false;
musicalCircles[i].display();
}
// Check if the blue ball is within a circle; if it is contained fill the circle blue and play a note, BUT cut the frequency in half so the tone is deeper aka lower 1 octave. when it leaves the circle clear the colorType parameter and stop sound.
if (musicalCircles[i].contains(ballBlue)) {
if (!playingBlue) {
playNote(oscBlue, musicalCircles[i].frequency / ((2*pitch) * octave));
playingBlue = true;
}
musicalCircles[i].display("blue");
} else {
stopNote(oscBlue);
playingBlue = false;
musicalCircles[i].display();
}
}
}
// play a note
function playNote(oscillator, frequency) {
oscillator.freq(frequency);
oscillator.amp(0.1); // Amplitude
reverb.drywet(reverbVal); // Thanks Professor!
oscillator.connect(reverb);
}
function stopNote(oscillator) {
oscillator.amp(0); // Amplitude
}