For this week I am talking about the YouTuber Answer in Progress, and her video “the science behind lofi music”. Lofi hip hop music has become popular in the late 2010s and early 2020s as background music for studying and gaming amongst Millennials and Gen Z. Answer in Progress sought to write an AI that could randomly produce lofi music. She gave the program a bunch of different drum and instrumental audio files and background noise, told it what frequencies and RPMs to play at that most lofi music plays at, and has the AI learn what notes should come after what other notes. Then her code should be able to produce a lofi song on its own. There are a few errors, including one song that just plays the same note over and over again, so the program does not produce a very sonically pleasing songs. It lacks an ear for what makes some notes and chords more pleasing than others that humans have, but its pretty impressive for randomly generated music with no human help.
Author: Technopat
Project 5: Wallpaper
var size = 40; //variable that determines the size of the indvidiual flowers
var ypos = size;
var xpos = size;
var oDist = size * 1.4 //distance between two origins for the rings
var storedY; //variable to store previous ypos
function setup() {
createCanvas(600, 600);
background(231,227,210);
}
function draw() {
for(ypos = size; ypos <= height; ypos +=(2*size)+oDist) { //loop that increases the ypos and repeats the x loops
for(var xpos = size; xpos <= width + size; xpos += 2*size){ //loop to draw the line of flowers
storedY = ypos; //stores ypos
fill(0);
push();
translate(xpos,ypos);
flower(0,0);
pop();
}
ypos += oDist + (7*size/24);
for(var xpos = oDist/2; xpos <= width + size; xpos += oDist){ //loop to draw the line of rings
push();
fill(230,192,71);
translate(xpos,ypos);
criss(0,0);
pop();
}
ypos = storedY; //sets ypos back to what it was when the loop began so the loop iteration works properly and fills the screen
}
noLoop();
}
function criss(x,y){ //function that draws the ring shaps by drawing rotated flowers
push();
rotate(radians(45));
flower(x,y);
pop();
}
function flower(a,b){ //function that draws the flower by drawing a petal and then rotating 90 degrees and repeating
petal(a,b);
push();
rotate(radians(90));
petal(a,b);
pop();
push();
rotate(radians(180));
petal(a,b);
pop();
push();
rotate(radians(270));
petal(a,b);
pop();
}
function petal(x,y) { //function that draws an idvidual petal composed of two triangles and a square
noStroke();
var side = size/(1+sqrt(3)); //variable that determins the length of the side of the square and equilateral triangle
var triHigh = side*(sqrt(3)/2); //variable that determins the height of the triangle based on the length of the side
triangle(x,y,x-(side/2),y+triHigh,x+(side/2),y+triHigh);
square(x-(side/2),y+triHigh,side);
triangle(x,y+size,x-(side/2),y+size-triHigh,x+(side/2),y+size-triHigh);
}
I loved this project. I had a really great time breaking down the steps of drawing into individual functions to make the process easier. Additionally, it was very satisfying to get the loops working properly because I had to iterate on that a few times. The patterns would either be too far apart or on top of one another.
Looking Outwards 5
For 3D computer art, I looked at the artist known as Chaotic Atmospheres from Switzerland. They have made digital art since 2012. As their name implies, Chaotic Atmospheres makes atmospheres and landscapes but alters them in a surrealist way. Specifically, for their project “Shapes in Nature”, their environments will often be large in scale, have exaggerated features of the environment being depicted, and some large geometric shape in the middle that is reflective. The reason I find their work so impressive is their attention to detail. They make both art from scratch and art made from imported textures, both of which are laborious tasks, either writing code to create the images or writing code to take the textures and create realistic environments out of them. Additionally, creating the reflection must be difficult, whether it be algorithmic like ray tracing or hard-coded into the work.
Project 4: String Art
//Patrick Fisher Section B
var dx1;
var dy1;
var dx2;
var dy2;
var numLines = 50;
function setup() {
createCanvas(400, 300);
background(50);
fill(10);
rectMode(CENTER);
rect(200,150,250,250)
dx1 = (275-25)/numLines;
dy1 = (275-25)/numLines;
dx2 = (25-275)/numLines;
dy2 = (25-275)/numLines;
}
function draw() {
var x1 = 75;
var y1 = 25;
var x2 = 275;
var y2 = 275;
stroke(255,0,0,200);
for (var i = 0; i <= numLines; i += 1) { //crates x design that goes from upper left to bottom right
line(x1, y1, x2, y2);
x1 += dx1;
y1 += dy1;
x2 += dx2;
y2 += dy2;
}
x1 = 375;
y1 = 25;
x2 = 75;
y2 = 275;
for ( i = 0; i <= numLines; i += 1) { //creates x design that goes from lower left to upper right
line(x1, y1, x2, y2);
x1 += -dx1;
y1 += dy1;
x2 += -dx2;
y2 += dy2;
}
dx1 = (325-25)/numLines;
dy1 = (75-25)/numLines;
dx2 = (25-275)/numLines;
dy2 = (25-0)/numLines;
x1 = 75;
y1 = 25;
x2 = 325;
y2 = 75;
stroke(0,0,255,200);
for ( i = 0; i <= numLines; i += 1) { //creates the blue pattern at the top
line(x1, y1, x2, y2);
x1 += dx1;
y1 += dy1;
x2 += dx2;
y2 += dy2;
}
x1 = 325;
y1 = 75;
x2 = 75;
y2 = 25;
for ( i = 0; i <= numLines; i += 1) { //creates the second half of the top blue pattern
line(x1, y1, x2, y2);
x1 += -dx1;
y1 += -dy1;
x2 += -dx2;
y2 += -dy2;
}
x1 = 325;
y1 = 175;
x2 = 75;
y2 = 250;
stroke(0,0,255,200);
for ( i = 0; i <= numLines; i += 1) { //creates the botom blue pattern
line(x1, y1, x2, y2);
x1 += -dx1;
y1 += dy1;
x2 += -dx2;
y2 += dy2;
}
x1 = 75;
y1 = 250;
x2 = 325;
y2 = 175;
stroke(0,0,255,200);
for ( i = 0; i <= numLines; i += 1) { //creates the top half of the bottom blue pattern
line(x1, y1, x2, y2);
x1 += dx1;
y1 += -dy1;
x2 += dx2;
y2 += -dy2;
}
noLoop();
}
I really struggled with this project, both creatively and technically. I had to take the sample code and finger with it mostly randomly to create anything that I was remotely satisfied with it.
Looking Outward 4
The video “Sound Machines” on the YouTube channel MediaArtTube demonstrates a machine that uses light recognition to play sound. The machine has three sensors and takes in visual information from vinyl record sized discs with patters engraved. The three discs have different types of patterns which the sensors read. The first reads color, with the disk having red, yellow, and blue lines on a white disc, depending on where the sensor is located up or down the radius changes the sequence of colors, therefore changing the sound. The second disc reads either black or white, with 3 patterns made using a black disc hollowed out. When the sensor detects black is plays a noise. The final disk is split into thirds, where white becomes more and more grey. The sensor reads the grey scale and increases the volume the grayer the image gets.
Project 3: Dynamic Drawing
function setup() {
createCanvas(600, 450);
}
function draw() {
var positionY = constrain(mouseY, 80, 400); //relative Y position for everything that is constrained so the sun doesnt shoot off into the sky etc
background(139,214,241);
fill(21,8,29, mouseY - 80); //transitions background to night sky by decreasing transparency with mouseY position
rect(0,0,600,300);
var rainbowAlpha = map(constrain(mouseY,80,400), 80, 250, 255, 0); //variable to control transparency of the rainbow as it goes down
noStroke();
fill(255,0,0,rainbowAlpha); //the rainbow: red
ellipse(300, positionY + 100, 700, 200);
fill(254,98,48,rainbowAlpha); //orange
ellipse(300, positionY + 120, 700, 200);
fill(255,246,2,rainbowAlpha); //yellow
ellipse(300, positionY + 140, 700, 200);
fill(1,179,2,rainbowAlpha); //green
ellipse(300, positionY + 160, 700, 200);
fill(4,1,119,rainbowAlpha); //blue
ellipse(300, positionY + 180, 700, 200);
fill(35,3,114,rainbowAlpha); //violet
ellipse(300, positionY + 200, 700, 200,);
fill(139,214,241); //"clear" ellipse that is the same color as the day background
ellipse(300, positionY + 220, 700, 200,);
fill(21,8,29, mouseY - 80); //"clear" ellipse that tranistions to night sky same why the regular background does
ellipse(300, positionY + 220, 700, 200);
fill(255,246,2); //sun
circle(150, positionY - 50, 50);
fill(241,222,150); //moon
circle(390, positionY - 325, 30);
fill(233,233,255,mouseY - 250); //stars
circle(40,96,10);
circle(250,15,10);
circle(330,62,10);
circle(470,340,10);
circle(580,70,10);
circle(346,54,10);
circle(200,30,10);
circle(475,120,10);
circle(175,60,10);
circle(275,115,10);
circle(430,50,10);
circle(20,20,10);
circle(100,40,10);
circle(270,50,10);
circle(80,130,10);
circle(500,25,10);
circle(400,100,10);
circle(150,85,10);
circle(500,55,10);
var positionX = constrain(mouseX,35,565);
fill(141,196,39); //green "field"
rect(0,300,600, 150);
var oppositeX = map(positionX, 0, 600, 600, 0);
fill(103,62,16); //left dog
ellipse(positionX, 350,30,15); //body
circle(positionX + 15, 345,15); //head
ellipse(positionX-10,355, 5,8); //leg
ellipse(positionX + 10, 355, 5, 8); //leg
ellipse(positionX-15,350,15,5); //tail
triangle(positionX+9,340,positionX+12,335,positionX+16,340); //ear
triangle(positionX+14,340,positionX+17,335,positionX+20,340); //ear
fill(0);
circle(positionX+16,343,2); //eyes
circle(positionX+19,343,2);
fill(103,62,16); //right dog
ellipse(oppositeX, 390,30,15); //body
circle(oppositeX - 15, 385,15); //head
ellipse(oppositeX + 10,395, 5,8); //leg
ellipse(oppositeX - 10, 395, 5, 8); //leg
ellipse(oppositeX + 15,390,15,5); //tail
triangle(oppositeX - 9,380,oppositeX - 12,375,oppositeX - 16,380); //ear
triangle(oppositeX - 14,380,oppositeX - 17,375,oppositeX - 20,380); //ear
fill(0);
circle(oppositeX - 16,383,2); //eyes
circle(oppositeX - 19,383,2);
}
I had difficulty with this project. I had a hard time coming up with something to draw. Once I had an idea I really enjoyed coming up with ways as to how I could incorporate dynamic elements into it. One thing, in particular, I am proud of is figuring out that the map function can work backwards, with the higher value being the start point and the lower value being the stop point, which allows you to invert the value of a variable in a sense.
Looking Outwards 3
I looked at Torolf Saurmann’s Moebius Ring. I chose this piece because I find its intricacy really beautiful. The strange spiral the ring inverts itself on is facilitating to look at and the mesh design it has increases that enjoyment. Because of the mesh design, the ring is somewhat see through. This further complicates of the spiral inverts itself and requires the viewer to focus to understand it. I find it really fun and enjoy the design. The algorithm that generated this work was likely very versatile and I think that comes from the mesh design. Not only does the mesh save material, it also puts the entire project into component parts that were likely much easier to code into larger designs. The Ring is also able to stand up on its own and I wonder if that is a coincidence or something the algorithm makes sure can happen. Saurmann as an artist really likes round and circular shapes, which one can see in his other work. In this piece he doubles down on that by basing his design on a Mobius Strip, a circle that inverts and doubles back on itself. This piece does that multiple times, to the point where its hard to tell where one inversion stops another the next begins.
Torolf Saurmann
LookingOutwards-02 Dave Bollinger
I really loved Dave Bollinger’s collection of glass like geometric pieces. The pieces look like abstract stained glass, with really natural looking curves and divisions that look like it was shattered. I really like this randomness as it is satisfying how different each work looks while still being part of the same collection, and demonstrates a robust algorithm for randomization with many possible ways the “shards” could have been created. Also, the use of color is really amazing, the way some of the colors fade out looks the same way worn stained glass fades over time. It feels as if the sun is behind the patterns shining through. I admire this use of color because it shows dedication to recreating the effect of real glass and it must have been a complex effect to code. Most of these pieces focus on one color but a few of them have many colors which demonstrates that the algorithm must have been versatile in the way it filled in the shards.
Project 2: Variable Faces
//Patrick Fisher, section B
var eyeSize = 20;
var faceWidth = 100;
var faceHeight = 150;
var eyeColor = 2;
var mouthType = 1;
var noseType = 1;
var browLength = (1.15 * eyeSize);
var r = 0; //color value for eyebrows
var m = 1; //coefficent for for size of mouth and nose
var skinColor = 1;
function setup() {
createCanvas(480, 640);
}
function draw() {
var midX = width / 2; //intermediate varriable for half the canvas length
background(180);
if(skinColor == 1){ //chooses a variety of skin colors from paper white to dark brown
strokeWeight(1);
fill(255);
ellipse(midX, height / 2, faceWidth, faceHeight);
} else if(skinColor == 2){
strokeWeight(1);
fill(254, 219, 117);
ellipse(midX, height / 2, faceWidth, faceHeight);
} else if(skinColor == 3){
strokeWeight(1);
fill(241, 194, 125);
ellipse(midX, height / 2, faceWidth, faceHeight);
} else if(skinColor == 4){
strokeWeight(1);
fill(224, 172, 105);
ellipse(midX, height / 2, faceWidth, faceHeight);
} else if(skinColor == 5){
strokeWeight(1);
fill(198, 134, 66);
ellipse(midX, height / 2, faceWidth, faceHeight);
} else if(skinColor == 6){
strokeWeight(1);
fill(140, 85, 36);
ellipse(midX, height / 2, faceWidth, faceHeight);
} else if(skinColor == 7){
strokeWeight(1);
fill(54, 30, 2);
ellipse(midX, height / 2, faceWidth, faceHeight);
}
var eyeLX = midX - faceWidth * 0.25; //variable for x position of left eye
var eyeRX = midX + faceWidth * 0.25; //wariable for x position of left eye
var eyeBrowL = (eyeLX - (.65 * eyeSize)); //variable for left eyebrow x position based off of left eye position
var eyeBrowR = (eyeRX - (.5 * eyeSize)); //wariable for right eyebrow x position based off of the right eye position
strokeWeight(1);
fill(r);
rect(eyeBrowL, ((height / 2) - eyeSize), browLength, (0.25 * eyeSize)); //left eyebrow
strokeWeight(1);
fill(r);
rect(eyeBrowR, ((height / 2) - eyeSize), browLength, (0.25 * eyeSize)); //right eyebrow
strokeWeight(1);
fill(255);
ellipse(eyeLX, height / 2, eyeSize, eyeSize); //creates left eye
strokeWeight(1);
fill(255);
ellipse(eyeRX, height / 2, eyeSize, eyeSize); //creates right eye
if(eyeColor == 1){ //makes brown irises
strokeWeight(1);
fill(100,63,33);
ellipse(eyeLX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
strokeWeight(1);
fill(100,63,33);
ellipse(eyeRX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
} else if(eyeColor == 2){ //makes green irises
strokeWeight(1);
fill(0,125,75);
ellipse(eyeLX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
strokeWeight(1);
fill(0,125,75);
ellipse(eyeRX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
} else if(eyeColor == 3){ //makes blue irises
strokeWeight(1);
fill(35,164,242);
ellipse(eyeLX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
strokeWeight(1);
fill(35,164,242);
ellipse(eyeRX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
} else if(eyeColor == 4){ //makes heterochromia, brown right blue left
strokeWeight(1);
fill(100,63,33);
ellipse(eyeLX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
strokeWeight(1);
fill(35,164,242);
ellipse(eyeRX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
} else if(eyeColor == 5){ //makes heterochromia, blue right brown left
strokeWeight(1);
fill(35,164,242);
ellipse(eyeLX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
strokeWeight(1);
fill(100,63,33);
ellipse(eyeRX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
} else if(eyeColor == 6){ //makes heterochromia, blue right green left
strokeWeight(1);
fill(0,125,75);
ellipse(eyeLX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
strokeWeight(1);
fill(35,164,242);
ellipse(eyeRX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
} else if(eyeColor == 7){ //makes heterochromia, green right blue left
strokeWeight(1);
fill(35,164,242);
ellipse(eyeLX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
strokeWeight(1);
fill(0,125,75);
ellipse(eyeRX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
} else if(eyeColor == 8){ //makes heterochromia, brown right green left
strokeWeight(1);
fill(0,125,75);
ellipse(eyeLX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
strokeWeight(1);
fill(100,63,33);
ellipse(eyeRX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
} else if(eyeColor == 9){ //makes heterochromia, green right brown left
strokeWeight(1);
fill(100,63,33);
ellipse(eyeLX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
strokeWeight(1);
fill(0,125,75);
ellipse(eyeRX, height / 2, eyeSize * (2/3), eyeSize * (2/3));
}
//variables for positioning and drawing the mouth
var mouthWidth = (faceWidth * (1/3));
var mouthHeight = (faceHeight * .25);
//intermediate variables for the x,y coordiantes for the tirangle nose type
var tx1 = midX;
var ty1 = ((height / 2) - (faceHeight / 16));
var tx2 = (midX - (faceWidth / 8));
var ty2 = ((height / 2) + (faceHeight / 6))
var tx3 = (midX + (faceWidth / 8));
var ty3 = ((height / 2) + (faceHeight / 6));
if(mouthType == 1){
strokeWeight(1);
fill(0);
arc(midX , ((height / 2) + (faceHeight * .25)), mouthWidth, mouthHeight, m * TWO_PI, m * PI); //creates a smiling mouth
} else if(mouthType == 2){ //creates a frowning mouth
strokeWeight(1);
fill(0);
arc(midX , ((height / 2) + (faceHeight * .375)), mouthWidth, mouthHeight, m * PI, m * TWO_PI,);
} else if(mouthType == 3) { //creates a neutral line mouth
strokeWeight(3);
line(m * (midX - (mouthWidth / 2)), ((height / 2) + (faceHeight * .25)), m * (midX + (mouthWidth / 2)), ((height / 2) + (faceHeight * .25)));
}
if(noseType == 1){ //creates a half circle nose
strokeWeight(1);
fill(255);
arc(((width * (51/100))), (height * (51/100)), (faceWidth / 4), (faceHeight / 6), m * HALF_PI, m * PI + HALF_PI);
}
else if(noseType == 2){ //creates a triangle nose
strokeWeight(1);
fill(255);
triangle(tx1, ty1, m * tx2, ty2, m * tx3, ty3);
}
else if(noseType == 3){ //creates a line nose
strokeWeight(3);
line(midX, m * ((height / 2) + (faceHeight / 8)),midX, ((height / 2) - (faceHeight / 8)));
}
}
function mousePressed() {
// when the user clicks, these variables are reassigned
// to random values within specified ranges. For example,
// 'faceWidth' gets a random value between 75 and 150.
faceWidth = random(75, 150);
faceHeight = random(100, 200);
eyeSize = random(10, 30);
browLength = random((eyeSize * .95), (eyeSize * 1.35));
eyeColor = floor(random(1,10)); //chooses one of the eye color combinations
mouthType = floor(random(1,4)); //choose the mouth type
noseType = floor(random(1,4)); //chooses the nose type
r = random(255); //changes eyebrow color
m = (random(.95,1.05));
skinColor = floor(random(1,8)); //changes the skin color
}
I had a lot of fun with this project. It was interesting trying to come up with more and more ways to make the face different. One of my early troubles was a problem with my eye colors. I was using “if(eyeColor == x)…” and eyeColor = “random(1,10)” but most clicks would end with no irises at all. I then realized the problem was that random() gives a floating point number and I was asking for a specific integer, so the odds of getting one were super low, so I changed the line to “floor(random(1,10))” which thankfully fixed it.
Project 1: Self Portrait
function setup() {
createCanvas(400, 600);
background(0,186,247);
}
function draw() {
fill(70,44,26);
arc(200, 150, 200, 200, PI, TWO_PI,);
fill(70,44,26);
arc(200, 125, 200, 200, PI, TWO_PI,);
fill(233,168,139);
ellipse(200,150,175,175);
stroke(70,44,26);
fill(70,44,26);
rect(125,60,150,30);
fill(70,44,26);
rect(225,120,22.5,5);
fill(70,44,26);
rect(152,120,22.5,5);
fill(255,255,255);
ellipse(165,140,17.5,17.5);
fill(255,255,255);
ellipse(235,140,17.5,17.5);
fill(35,163,102);
ellipse(235,140,10,10);
fill(35,163,102);
ellipse(165,140,10,10);
fill(0);
ellipse(165,140,5,5);
fill(0);
ellipse(235,140,5,5);
fill(239,139,129);
arc(200, 200, 40, 40, TWO_PI, PI);
fill(0);
arc(200, 202.5, 30, 30, TWO_PI, PI);
fill(241,215,212);
arc(200, 202.5, 10, 10, TWO_PI, PI);
fill(241,215,212);
arc(210, 202.5, 10, 10, TWO_PI, PI);
fill(241,215,212);
arc(190, 202.5, 10, 10, TWO_PI, PI);
fill(255,175,145);
arc(200, 175, 15, 30, PI, TWO_PI,);
fill(0);
arc(197.5, 175, 4, 4, PI, TWO_PI,);
fill(0);
arc(202.5, 175, 4, 4, PI, TWO_PI,);
fill(46,56,66)
arc(200, 637.5, 200, 800, PI, TWO_PI,);
}
I found this self-portrait very challenging, particularly creating hair that looked even remotely human, but I had a lot of fun trying to draw myself.