diff --git a/README.md b/README.md
index 19ba88c75..f8deafa56 100644
--- a/README.md
+++ b/README.md
@@ -1,89 +1,142 @@
# Music Visualiser Project
-Name:
+Name: Yasmin Ismail
-Student Number:
-
-## Instructions
-- Fork this repository and use it a starter project for your assignment
-- Create a new package named your student number and put all your code in this package.
-- You should start by creating a subclass of ie.tudublin.Visual
-- There is an example visualiser called MyVisual in the example package
-- Check out the WaveForm and AudioBandsVisual for examples of how to call the Processing functions from other classes that are not subclasses of PApplet
+Student Number: C22485282
# Description of the assignment
+I have created five classes which each displays different visuals. The Worm class visualizes a worm-like shape that responds to audio input. The Rotating Blocks class renders 3D rotating blocks, modulates colors and movements that responds to audio input, creating visual effects. The Balls class generate bouncing balls thats responds to audio input, dynamic patterns with colorful ellipses. The Gradient Shape renders three gradient circles, colors changing based on the audio input. The Snow class has snowfall simulation where snow falls. The snow begins at the top and drifts down. It responds to audio input.
+
+Youtube video of Music Visualiser Project:
+
+
+[](https://www.youtube.com/watch?v=PFwGrX_GDFs)
+
+
+
+Song chosen for the Music Visualiser Project:
+
+[](https://www.youtube.com/watch?v=THFFP1EM3EU)
+
+
# Instructions
+Compile and run.
+Press 0-4 to change between backgrounds.
+
# How it works
-# What I am most proud of in the assignment
+I have chosen a song that inspires me and reflects my style and interests. The Mario Kart Luigi Circuit. It has a clear structure, rhythm, and mood as the visual elements react well to the audio in real-time. The video will show this. It conveys a sense of mood, tempo, and narrative. I have used colour, shape, motion, and composition to create a visually compelling and dynamic representation of the song.
+
+The classes of the visuals import from the "**c22485282**" package into their own Java programs to reuse the functionality demonstrated in these classes to render a visual effect.
+I've implemented several visual effects.
-# Markdown Tutorial
+MyVisual.java class is defined within the c22485282 package. Classes from ie.tudublin package are imported. MyVisual is a subclass that extends Visual which is an abstract class that's within the ie.tudublin package. This will serve as a foundation for audio visualization in Processing. This subclass was there when I forked the MusicVisuals repository, i have implemented more values in it. It contains several fields; wf, abv, worm, rotatingBlocks, balls, gradientShape. They are instances of different classes used for different visual effects and audio processing sketch.
+
+It contains methods; settings(), setup(), keyPressed(), draw().
+
+All of the classes below is part of the c22385282 package. The background colour was black and it felt plain, so I changed the background colour.
+
+Starting first with the Worm class. This renders a worm-like shape based on audio input. The Constructor Worm(MyVisual mv) initializes a Worm object with a reference to a MyVisual instance (mv).
+The render() method renders the worm visualization. It calls calcWorm() method and renderWorm() method thus rendering the worm visually. The calcWorm() method dynamically adjusts the worm's visual based on audio amplitude, it contains the functions sine and cosine to calculate the movement of segments. The amplitude of each segment is modulated by audio signal. The result of this leads to it responding to audio in a fluid wave-like motion.
+
+renderWorm() method draws the visual representation using ellipses. This provides a colourful and dynamic visual effect. It sets stroke properties. It iterates over yvalues to draw ellipses at each location. The position of the ellipses x, y is calculated based on the current xspacing and yvalues. The colours are determined by hue values. The result of this leads to it responding to audio in a fluid wave-like motion.
+
+The RotatingBlocks class creates 3D blocks that rotate. Each block’s color and position changes based on the audio input. The blocks rotate around a central axis and color shifts over time in response to the audio.
+The Constructor RotatingBlocks(MyVisual mv) initializes the mv reference with a MyVisual instance passed to the constructor. Creates array to store block colours and box poistions. initializeBlockColors() method fills the blockColors array with random hue values ranging from 0 to 360.
+
+For the initializeBoxPositions() method, the positions of boxes are arranged in a circle using polar coordinates and stores them in the boxPositions array. render() Method coordinates the rendering process by setting up stroke properties. It handles audio input for colour modulation. It positions and rotates each box, and updates for a dynamic visual effect.
+
+In the Balls class, bouncing balls are generated that respond to audio input.
+
+Balls(MyVisual mv) is a constructor that initializes a new instance of Balls that provides a MyVisual instance. This sets up parameters for balls such as amplitude, period, and positioning.
+The render() Method coordinates the rendering process for the balls. mv.hint(mv.DISABLE_DEPTH_TEST) ensures 2D rendering by disabling depth testing. calcBalls() method called to calculate ball heights based on audio input. renderBalls() called to draw the balls based on calculated heights. mv.hint(mv.ENABLE_DEPTH_TEST) depth testing re-enables after rendering.
-This is *emphasis*
+The calcBalls() method that calculates the height of each ball based on audio input. theta += 0.02 increments the angle for oscillation. There is a nested loop that iterates over yvalues array, calculates ballHeight based on audio input, also sine, cosine functions. The yvalues is updated with calculated ballHeight for each ball.
-This is a bulleted list
+The GradientShape class renders three gradient circles. The colors change based on the audio input. It utilizes the Processing library PApplet. The Constructor GradientShape(MyVisual mv) initializes the mv reference with a MyVisual instance passed to the constructor. Sets the canvas dimensions, which is the height and width and calculates the size of the gradient circles which is the dim.
-- Item
-- Item
+The render() method draws the gradient circles.The mv.background(0) sets the background color to black. The audio amplitude value from the MyVisual instance's audio buffer is retrieved from audioAmplitude = mv.getAudioBuffer().get(0). This fetches the amplitude value at index 0. A for loop is used to draw the gradient circles. It increments x by dim, the size of each circle to position the circles evenly spaced.
-This is a numbered list
+The drawGradient() Method is used within the render() method to draw a single gradient circle at a specified position x, y with a given amplitude. It Calculates initial Hue, h. Maps the audio amplitude to a hue value between 0 and 360 degrees. This is the initial color hue of the gradient. A nested loop to draw circles. Each iteration the saturation and brightness values are calculated. Fill color set using HSB color mode.
-1. Item
-1. Item
-This is a [hyperlink](http://bryanduggan.org)
+The Snow class simulates falling snow that responds to the audio input. The snow begins at the top and drifts down. Their size and speed influenced by the audio input. I have rendered the Snow class on all classes but balls and Gradient as it’s not as appealing.
+The Constructor Snow(MyVisual mv) initializes the mv reference with a MyVisual instance passed to the constructor. Initializes the snowflakes ArrayList too.
-# Headings
-## Headings
-#### Headings
-##### Headings
+The render() method calls addSnowflakes() to add new snowflakes. It will Iterates over snowflakes. update() updating their position. display() displays them, snowflakes removed if its offscreen.
-This is code:
+Specific number of snowflakes are added to the top of the screen with random positions and sizes in the addSnowflakes(). The class Snowflake contains individual snowflake with its own position, size and falling speed. Initializes the snowflake with specified parameters.
+Methods update() display() and isOffscreen() updates the position of the snowflake, renders the snowflake as a white ellipse, checks if the snowflake has fallen completely off the screen.
+
+
+In the MyVisual class, these visuals are switched using keyboard input, the keyPressed() method, allowing for real-time interaction with different visualizations. The draw() method causes the rendering of the chosen visual effect based on the current mode.
+
+
+
+
+
+# What I am most proud of in the assignment
+Doing this project has taught me a lot. I am most proud of what I managed to do, learning so much and how fun it was. Learning a concept to me that I had no knowledge of. Being able to create visuals responding to audio input using Processing is such a cool and fun concept, challenging but fun! Each process of the project, implementing various visual effects like rotating blocks, animated shapes, has taught me something new about Java. It was so fun, joyful and rewarding when the code worked as there were some difficulties implementing certain code, but I managed. It was challenging but as challenging as it was, it kept me engaged because the rewarding feeling of accomplishing it was worthwhile.
+
+# Markdown Tutorial
+
+
+
+This is some code from my project:
+
+Worm.java render()
```Java
-public void render()
-{
- ui.noFill();
- ui.stroke(255);
- ui.rect(x, y, width, height);
- ui.textAlign(PApplet.CENTER, PApplet.CENTER);
- ui.text(text, x + width * 0.5f, y + height * 0.5f);
-}
-```
+public void render() {
+ // mv.hint(mv.DISABLE_DEPTH_TEST);
+
+ // Calculate worm heights based on audio input
+ calcWorm();
-So is this without specifying the language:
+ // Render the worm visualization
+ renderWorm();
+ // mv.hint(mv.ENABLE_DEPTH_TEST);
+ }
```
-public void render()
-{
- ui.noFill();
- ui.stroke(255);
- ui.rect(x, y, width, height);
- ui.textAlign(PApplet.CENTER, PApplet.CENTER);
- ui.text(text, x + width * 0.5f, y + height * 0.5f);
-}
-```
+GradientShape.java
+```Java
+private void drawGradient(float x, float y, float amplitude) {
+ int radius = dim / 2;
-This is an image using a relative URL:
+ // Calculate the initial hue based on amplitude
+ float h = PApplet.map(amplitude, -1, 1, 0, 360);
-
+ // Draw each circle with a smoothly changing hue
+ for (int r = radius; r > 0; --r) {
+ // Adjust saturation and brightness for a more vivid color
+ float saturation = PApplet.map(r, 0, radius, 90, 100);
+ float brightness = PApplet.map(r, 0, radius, 90, 100);
-This is an image using an absolute URL:
+ // Set fill color using HSB color mode
+ mv.fill(h, saturation, brightness);
+ mv.ellipse(x, y, r, r);
-
+ // Gradually change the hue for the next circle
+ h = (h + 1) % 360;
-This is a youtube video:
+ } // End for
+```
+
+RotatingBlocks.java constructor
+```Java
+public RotatingBlocks(MyVisual mv) {
+ this.mv = mv; // Initialize the MyVisual reference
+ blockColors = new float[num]; // Initializes array to store block colors
+ boxPositions = new PVector[num]; // Initializes array to store box positions
+ initializeBlockColors(); // Call method to initialize block colors
+ initializeBoxPositions(); // Call method to initialize box positions
+ } // End RotatingShape(M)
+
+```
-[](https://www.youtube.com/watch?v=J2kHSSFA4NU)
-This is a table:
-| Heading 1 | Heading 2 |
-|-----------|-----------|
-|Some stuff | Some more stuff in this column |
-|Some stuff | Some more stuff in this column |
-|Some stuff | Some more stuff in this column |
-|Some stuff | Some more stuff in this column |
diff --git a/java/.project b/java/.project
index 0d5afed93..cc1c2184f 100644
--- a/java/.project
+++ b/java/.project
@@ -16,12 +16,12 @@
- 1616413840733
+ 1714506623165
30
org.eclipse.core.resources.regexFilterMatcher
- node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
diff --git a/java/music/MCLuigiCircuit.mp3 b/java/music/MCLuigiCircuit.mp3
new file mode 100644
index 000000000..80950f5e3
Binary files /dev/null and b/java/music/MCLuigiCircuit.mp3 differ
diff --git a/java/music/MCLuigiCircuit.wav b/java/music/MCLuigiCircuit.wav
new file mode 100644
index 000000000..e3b75164a
Binary files /dev/null and b/java/music/MCLuigiCircuit.wav differ
diff --git a/java/music/tagmp3_MCLuigiCircuit.mp3 b/java/music/tagmp3_MCLuigiCircuit.mp3
new file mode 100644
index 000000000..83f34d553
Binary files /dev/null and b/java/music/tagmp3_MCLuigiCircuit.mp3 differ
diff --git a/java/src/c123456/BryansVisual.java b/java/src/c123456/BryansVisual.java
deleted file mode 100644
index e69de29bb..000000000
diff --git a/java/src/example/AudioBandsVisual.java b/java/src/c22485282/AudioBandsVisual.java
similarity index 93%
rename from java/src/example/AudioBandsVisual.java
rename to java/src/c22485282/AudioBandsVisual.java
index b6b99d6e5..e9a422e0c 100644
--- a/java/src/example/AudioBandsVisual.java
+++ b/java/src/c22485282/AudioBandsVisual.java
@@ -1,25 +1,25 @@
-package example;
-
-import processing.core.*;
-
-// This is an example of a visual that uses the audio bands
-public class AudioBandsVisual
-{
- MyVisual mv;
-
- public AudioBandsVisual(MyVisual mv)
- {
- this.mv = mv;
- }
-
- public void render()
- {
- float gap = mv.width / (float) mv.getBands().length;
- mv.noStroke();
- for(int i = 0 ; i < mv.getBands().length ; i ++)
- {
- mv.fill(PApplet.map(i, 0, mv.getBands().length, 255, 0), 255, 255);
- mv.rect(i * gap, mv.height, gap,-mv.getSmoothedBands()[i] * 0.2f);
- }
- }
+package c22485282;
+
+import processing.core.*;
+
+// This is an example of a visual that uses the audio bands
+public class AudioBandsVisual
+{
+ MyVisual mv;
+
+ public AudioBandsVisual(MyVisual mv)
+ {
+ this.mv = mv;
+ }
+
+ public void render()
+ {
+ float gap = mv.width / (float) mv.getBands().length;
+ mv.noStroke();
+ for(int i = 0 ; i < mv.getBands().length ; i ++)
+ {
+ mv.fill(PApplet.map(i, 0, mv.getBands().length, 255, 0), 255, 255);
+ mv.rect(i * gap, mv.height, gap,-mv.getSmoothedBands()[i] * 0.2f);
+ }
+ }
}
\ No newline at end of file
diff --git a/java/src/c22485282/Balls.java b/java/src/c22485282/Balls.java
new file mode 100644
index 000000000..28d61317d
--- /dev/null
+++ b/java/src/c22485282/Balls.java
@@ -0,0 +1,79 @@
+package c22485282;
+
+public class Balls {
+ MyVisual mv;
+ int xspacing = 8; // Distance of each horizontal location
+ int w; // Width of entire balls
+ int maxballs = 2; // Amount of balls to add together
+
+ float theta = 0.0f; // Angle initialized for ball oscillation
+ float[] amplitude = new float[maxballs]; // Stores height of ball
+ float[] dx = new float[maxballs]; // Value for incrementing X
+ float[] yvalues; // Stores height values of the ball
+
+
+ // Constructor for the ball class, taking a MyVisual instance as input
+ public Balls(MyVisual mv) {
+ this.mv = mv; //The passed MyVisual instance assigned to the local mv variable
+ w = mv.width + 16; // Width of the ball visualization adjusted to the width of the sketch
+
+
+ // // Initialize ball parameters
+ for (int i = 0; i < maxballs; i++) {
+ amplitude[i] = mv.random(50,80); // Random amplitudes set for each ball
+ float period = mv.random(200,1000); // Random period set for each ball
+ dx[i] = (mv.TWO_PI / period) * xspacing;
+ } // End for
+ yvalues = new float[w/xspacing]; // Num of vertical locations based on the width and xspacing
+ } // End public Balls()
+
+ public void render() {
+ mv.hint(mv.DISABLE_DEPTH_TEST);
+ calcBalls();
+ renderBalls();
+ mv.hint(mv.ENABLE_DEPTH_TEST);
+ } // End render()
+
+ void calcBalls() {
+ theta += 0.02;
+
+ for (int i = 0; i < yvalues.length; i++) {
+ float x = theta + (i * dx[0] / xspacing);
+ float ballHeight = 0;
+ for (int j = 0; j < maxballs; j++) {
+ // Calculate the influence of audio input on the ball's movement
+ float audioValue = mv.getAudioBuffer().get(i); // Get audio value at index i
+ float mappedAmplitude = mv.map(audioValue, 0, 1, 50, 200); // Map audio value to desired amplitude range
+
+ if (j % 2 == 0) {
+ ballHeight += mv.sin(x) * amplitude[j] * mappedAmplitude;
+ } else {
+ ballHeight += mv.cos(x) * amplitude[j] * mappedAmplitude;
+ }
+ x += dx[j];
+ }
+ yvalues[i] =ballHeight;
+ }
+ } // End calcBalls()
+
+ void renderBalls() {
+ // Draw ball with an ellipse at each location
+ mv.stroke(0);
+ mv.strokeWeight(4);
+ // Smoothly change colors
+ float hue = 0;
+ float hueIncrement = 255.0f / yvalues.length;
+
+ for (int x = 0; x < yvalues.length; x++) {
+ float y = mv.height / 2 + yvalues[x];
+ float y2 = mv.height / 2 - yvalues[x];
+ mv.fill(hue, 255, 255);
+ mv.ellipse(x * xspacing, y, 100, 50);
+ mv.fill((hue %255)-50, 255, 255);
+ mv.ellipse(x * xspacing, y2, 65, 50); // Draw ellipse for second ball
+ hue += hueIncrement;
+ } // End for
+ } // End renderBalls()
+
+
+} // End Balls()
diff --git a/java/src/example/CubeVisual.java b/java/src/c22485282/CubeVisual.java
similarity index 95%
rename from java/src/example/CubeVisual.java
rename to java/src/c22485282/CubeVisual.java
index ff8e58798..8a0667a75 100644
--- a/java/src/example/CubeVisual.java
+++ b/java/src/c22485282/CubeVisual.java
@@ -1,90 +1,90 @@
-package example;
-
-import ie.tudublin.Visual;
-
-public class CubeVisual extends Visual
-{
- boolean twocubes = false;
-
- public void settings()
- {
- size(800, 800, P3D);
- println("CWD: " + System.getProperty("user.dir"));
- //fullScreen(P3D, SPAN);
- }
-
- public void keyPressed()
- {
- if (key == ' ')
- {
- getAudioPlayer().cue(0);
- getAudioPlayer().play();
-
- }
- if (key == '1')
- {
- twocubes = ! twocubes;
-
- }
- }
-
- public void setup()
- {
- colorMode(HSB);
- noCursor();
-
- setFrameSize(256);
-
- startMinim();
- loadAudio("heroplanet.mp3");
- //getAp().play();
- //startListening();
-
- }
-
- float smoothedBoxSize = 0;
-
- public void draw()
- {
- calculateAverageAmplitude();
- background(0);
- noFill();
- lights();
- stroke(map(getSmoothedAmplitude(), 0, 1, 0, 255), 255, 255);
- camera(0, 0, 0, 0, 0, -1, 0, 1, 0);
- translate(0, 0, -250);
-
- float boxSize = 50 + (getAmplitude() * 300);//map(average, 0, 1, 100, 400);
- smoothedBoxSize = lerp(smoothedBoxSize, boxSize, 0.2f);
- if (twocubes)
- {
- pushMatrix();
- translate(-100, 0, 0);
- rotateY(angle);
- rotateX(angle);
- box(smoothedBoxSize);
- //strokeWeight(1);
- //sphere(smoothedBoxSize);
- popMatrix();
- pushMatrix();
- translate(100, 0, 0);
- rotateY(angle);
- rotateX(angle);
- strokeWeight(5);
- box(smoothedBoxSize);
- popMatrix();
- }
- else
- {
- rotateY(angle);
- rotateX(angle);
- //strokeWeight(1);
- //sphere(smoothedBoxSize/ 2);
- strokeWeight(5);
-
- box(smoothedBoxSize);
- }
- angle += 0.01f;
- }
- float angle = 0;
+package c22485282;
+
+import ie.tudublin.Visual;
+
+public class CubeVisual extends Visual
+{
+ boolean twocubes = false;
+
+ public void settings()
+ {
+ size(800, 800, P3D);
+ println("CWD: " + System.getProperty("user.dir"));
+ //fullScreen(P3D, SPAN);
+ }
+
+ public void keyPressed()
+ {
+ if (key == ' ')
+ {
+ getAudioPlayer().cue(0);
+ getAudioPlayer().play();
+
+ }
+ if (key == '1')
+ {
+ twocubes = ! twocubes;
+
+ }
+ }
+
+ public void setup()
+ {
+ colorMode(HSB);
+ noCursor();
+
+ setFrameSize(256);
+
+ startMinim();
+ loadAudio("heroplanet.mp3");
+ //getAp().play();
+ //startListening();
+
+ }
+
+ float smoothedBoxSize = 0;
+
+ public void draw()
+ {
+ calculateAverageAmplitude();
+ background(0);
+ noFill();
+ lights();
+ stroke(map(getSmoothedAmplitude(), 0, 1, 0, 255), 255, 255);
+ camera(0, 0, 0, 0, 0, -1, 0, 1, 0);
+ translate(0, 0, -250);
+
+ float boxSize = 50 + (getAmplitude() * 300);//map(average, 0, 1, 100, 400);
+ smoothedBoxSize = lerp(smoothedBoxSize, boxSize, 0.2f);
+ if (twocubes)
+ {
+ pushMatrix();
+ translate(-100, 0, 0);
+ rotateY(angle);
+ rotateX(angle);
+ box(smoothedBoxSize);
+ //strokeWeight(1);
+ //sphere(smoothedBoxSize);
+ popMatrix();
+ pushMatrix();
+ translate(100, 0, 0);
+ rotateY(angle);
+ rotateX(angle);
+ strokeWeight(5);
+ box(smoothedBoxSize);
+ popMatrix();
+ }
+ else
+ {
+ rotateY(angle);
+ rotateX(angle);
+ //strokeWeight(1);
+ //sphere(smoothedBoxSize/ 2);
+ strokeWeight(5);
+
+ box(smoothedBoxSize);
+ }
+ angle += 0.01f;
+ }
+ float angle = 0;
}
\ No newline at end of file
diff --git a/java/src/example/CubeVisual1.java b/java/src/c22485282/CubeVisual1.java
similarity index 93%
rename from java/src/example/CubeVisual1.java
rename to java/src/c22485282/CubeVisual1.java
index 8eebd97f8..e8f55b4a3 100644
--- a/java/src/example/CubeVisual1.java
+++ b/java/src/c22485282/CubeVisual1.java
@@ -1,53 +1,53 @@
-package example;
-
-import ie.tudublin.Visual;
-
-public class CubeVisual1 extends Visual
-{
- public void settings()
- {
- size(800, 600, P3D);
- //fullScreen(P3D, SPAN);
- }
-
- public void setup()
- {
- startMinim();
- //startListening();
- loadAudio("heroplanet.mp3");
- colorMode(HSB);
- }
-
- public void keyPressed()
- {
- if (key == ' ')
- {
- getAudioPlayer().cue(0);
- getAudioPlayer().play();
- }
- }
-
- float angle = 0;
-
- public void draw()
- {
- background(0);
- calculateAverageAmplitude();
- stroke(map(getSmoothedAmplitude(), 0, 1, 0, 255), 255, 255);
- strokeWeight(5);
- noFill();
- lights();
- pushMatrix();
- //
- camera(0, 0, 0, 0, 0, -1, 0, 1, 0);
- translate(0, 0, -200);
- rotateX(angle);
- rotateZ(angle);
- float boxSize = 50 + (200 * getSmoothedAmplitude());
- box(boxSize);
- popMatrix();
- angle += 0.01f;
- }
-
-
+package c22485282;
+
+import ie.tudublin.Visual;
+
+public class CubeVisual1 extends Visual
+{
+ public void settings()
+ {
+ size(800, 600, P3D);
+ //fullScreen(P3D, SPAN);
+ }
+
+ public void setup()
+ {
+ startMinim();
+ //startListening();
+ loadAudio("heroplanet.mp3");
+ colorMode(HSB);
+ }
+
+ public void keyPressed()
+ {
+ if (key == ' ')
+ {
+ getAudioPlayer().cue(0);
+ getAudioPlayer().play();
+ }
+ }
+
+ float angle = 0;
+
+ public void draw()
+ {
+ background(0);
+ calculateAverageAmplitude();
+ stroke(map(getSmoothedAmplitude(), 0, 1, 0, 255), 255, 255);
+ strokeWeight(5);
+ noFill();
+ lights();
+ pushMatrix();
+ //
+ camera(0, 0, 0, 0, 0, -1, 0, 1, 0);
+ translate(0, 0, -200);
+ rotateX(angle);
+ rotateZ(angle);
+ float boxSize = 50 + (200 * getSmoothedAmplitude());
+ box(boxSize);
+ popMatrix();
+ angle += 0.01f;
+ }
+
+
}
\ No newline at end of file
diff --git a/java/src/c22485282/GradientShape.java b/java/src/c22485282/GradientShape.java
new file mode 100644
index 000000000..47362bc95
--- /dev/null
+++ b/java/src/c22485282/GradientShape.java
@@ -0,0 +1,58 @@
+package c22485282;
+
+import processing.core.PApplet;
+
+public class GradientShape {
+ MyVisual mv;
+
+ int dim; // Size of the gradient circles
+ int height, width; // Dimensions of the canvas
+ float audioAmplitude; // Stores the audio amplitude
+
+ public GradientShape(MyVisual mv) {
+ this.mv = mv;
+ this.height = mv.height;
+ this.width = mv.width;
+ dim = width / 2;
+ } // End public GradientShape()
+
+ public void render() {
+ mv.background(0);
+
+ // Get the audio amplitude from the MyVisual instance
+ audioAmplitude = mv.getAudioBuffer().get(0);
+
+ // Draw the gradient circles based on audio amplitude
+ for (int x = 0; x <= width; x += dim) {
+ drawGradient(x, height / 2, audioAmplitude);
+ } // End for
+
+ } // End render()
+
+ private void drawGradient(float x, float y, float amplitude) {
+ int radius = dim / 2;
+
+ // Calculate the initial hue based on amplitude
+ float h = PApplet.map(amplitude, -1, 1, 0, 360);
+
+ // Draw each circle with a smoothly changing hue
+ for (int r = radius; r > 0; --r) {
+ // Adjust saturation and brightness for a more vivid color
+ float saturation = PApplet.map(r, 0, radius, 90, 100);
+ float brightness = PApplet.map(r, 0, radius, 90, 100);
+
+ // Set fill color using HSB color mode
+ mv.fill(h, saturation, brightness);
+ mv.ellipse(x, y, r, r);
+
+ // Gradually change the hue for the next circle
+ h = (h + 1) % 360;
+
+ } // End for
+
+
+ } // End drawGradient()
+
+
+
+} // End public class GradientShape
diff --git a/java/src/c22485282/MyVisual.java b/java/src/c22485282/MyVisual.java
new file mode 100644
index 000000000..31e497b02
--- /dev/null
+++ b/java/src/c22485282/MyVisual.java
@@ -0,0 +1,109 @@
+
+package c22485282;
+
+import ie.tudublin.*;
+
+public class MyVisual extends Visual {
+ WaveForm wf;
+ AudioBandsVisual abv;
+ Worm worm;
+ RotatingBlocks rotatingBlocks;
+ Balls balls;
+ GradientShape gradientShape;
+ Snow snow;
+
+
+ public void settings() {
+ size(1024, 500);
+
+ // Use this to make fullscreen
+ // fullScreen();
+
+ // Use this to make fullscreen and use P3D for 3D graphics
+ fullScreen(P3D, SPAN);
+ }
+
+ public void setup() {
+ startMinim();
+
+ // Call loadAudio to load an audio file to process
+ loadAudio("music/tagmp3_MCLuigiCircuit.mp3");
+ // Call this instead to read audio from the microphone
+ // startListening();
+
+ getAudioPlayer().cue(0);
+ getAudioPlayer().play();
+
+ wf = new WaveForm(this);
+ abv = new AudioBandsVisual(this);
+ worm = new Worm(this);
+ rotatingBlocks = new RotatingBlocks(this);
+ balls = new Balls(this);
+ gradientShape= new GradientShape(this);
+ snow = new Snow(this);
+
+ }
+
+ int current = 0;
+
+ public void keyPressed() {
+ if (key == '0') {
+
+ wf.render();
+ abv.render();
+ current = 0;
+ }
+ else if (key == '1') {
+ worm.render();
+ current = 1;
+ } else if (key == '2') {
+ rotatingBlocks.render();
+ current = 2;
+ } else if (key == '3') {
+ balls.render();
+ current = 3;
+ } else if (key == '4') {
+ gradientShape.render();
+ wf.render();
+ abv.render();
+ current = 4;
+ }
+
+
+ } // End keyPressed()
+
+
+ public void draw() {
+ background(20,50,90);
+
+
+
+ if (current == 0) {
+ snow.render();
+ wf.render();
+ abv.render();
+
+ }
+ else if (current == 1) {
+ snow.render();
+ worm.render();
+ }
+ else if (current == 2) {
+ snow.render();
+ rotatingBlocks.render();
+ }
+ else if(current == 3)
+ {
+ // snow.render();
+ balls.render();
+ }
+ else if(current == 4)
+ {
+ gradientShape.render();
+ // snow.render();
+ }
+
+ // wf.render();
+ // abv.render();
+ } // End draw()
+}
\ No newline at end of file
diff --git a/java/src/example/RotatingAudioBands.java b/java/src/c22485282/RotatingAudioBands.java
similarity index 94%
rename from java/src/example/RotatingAudioBands.java
rename to java/src/c22485282/RotatingAudioBands.java
index 72fd7a223..395ac29bd 100644
--- a/java/src/example/RotatingAudioBands.java
+++ b/java/src/c22485282/RotatingAudioBands.java
@@ -1,89 +1,89 @@
-package example;
-
-import ie.tudublin.Visual;
-import ie.tudublin.VisualException;
-
-public class RotatingAudioBands extends Visual {
-
-
- public void settings()
- {
- size(800, 800, P3D);
- println("CWD: " + System.getProperty("user.dir"));
- //fullScreen(P3D, SPAN);
- }
-
- public void keyPressed()
- {
- if (key == ' ')
- {
- getAudioPlayer().cue(0);
- getAudioPlayer().play();
-
- }
-
- }
-
- public void setup()
- {
- colorMode(HSB);
- noCursor();
-
- setFrameSize(256);
-
- startMinim();
- loadAudio("heroplanet.mp3");
- getAudioPlayer().play();
- //startListening();
-
- }
-
- float radius = 200;
-
- float smoothedBoxSize = 0;
-
- float rot = 0;
-
- public void draw()
- {
- calculateAverageAmplitude();
- try
- {
- calculateFFT();
- }
- catch(VisualException e)
- {
- e.printStackTrace();
- }
- calculateFrequencyBands();
- background(0);
- noFill();
- stroke(255);
- lights();
- stroke(map(getSmoothedAmplitude(), 0, 1, 0, 255), 255, 255);
- camera(0, -500, 500, 0, 0, 0, 0, 1, 0);
- //translate(0, 0, -250);
-
- rot += getAmplitude() / 8.0f;
-
- rotateY(rot);
- float[] bands = getSmoothedBands();
- for(int i = 0 ; i < bands.length ; i ++)
- {
- float theta = map(i, 0, bands.length, 0, TWO_PI);
-
- stroke(map(i, 0, bands.length, 0, 255), 255, 255);
- float x = sin(theta) * radius;
- float z = cos(theta) * radius;
- float h = bands[i];
- pushMatrix();
- translate(x, - h / 2 , z);
- rotateY(theta);
- box(50, h, 50);
- popMatrix();
- }
-
- }
- float angle = 0;
-
+package c22485282;
+
+import ie.tudublin.Visual;
+import ie.tudublin.VisualException;
+
+public class RotatingAudioBands extends Visual {
+
+
+ public void settings()
+ {
+ size(800, 800, P3D);
+ println("CWD: " + System.getProperty("user.dir"));
+ //fullScreen(P3D, SPAN);
+ }
+
+ public void keyPressed()
+ {
+ if (key == ' ')
+ {
+ getAudioPlayer().cue(0);
+ getAudioPlayer().play();
+
+ }
+
+ }
+
+ public void setup()
+ {
+ colorMode(HSB);
+ noCursor();
+
+ setFrameSize(256);
+
+ startMinim();
+ loadAudio("heroplanet.mp3");
+ getAudioPlayer().play();
+ //startListening();
+
+ }
+
+ float radius = 200;
+
+ float smoothedBoxSize = 0;
+
+ float rot = 0;
+
+ public void draw()
+ {
+ calculateAverageAmplitude();
+ try
+ {
+ calculateFFT();
+ }
+ catch(VisualException e)
+ {
+ e.printStackTrace();
+ }
+ calculateFrequencyBands();
+ background(0);
+ noFill();
+ stroke(255);
+ lights();
+ stroke(map(getSmoothedAmplitude(), 0, 1, 0, 255), 255, 255);
+ camera(0, -500, 500, 0, 0, 0, 0, 1, 0);
+ //translate(0, 0, -250);
+
+ rot += getAmplitude() / 8.0f;
+
+ rotateY(rot);
+ float[] bands = getSmoothedBands();
+ for(int i = 0 ; i < bands.length ; i ++)
+ {
+ float theta = map(i, 0, bands.length, 0, TWO_PI);
+
+ stroke(map(i, 0, bands.length, 0, 255), 255, 255);
+ float x = sin(theta) * radius;
+ float z = cos(theta) * radius;
+ float h = bands[i];
+ pushMatrix();
+ translate(x, - h / 2 , z);
+ rotateY(theta);
+ box(50, h, 50);
+ popMatrix();
+ }
+
+ }
+ float angle = 0;
+
}
\ No newline at end of file
diff --git a/java/src/c22485282/RotatingBands.java b/java/src/c22485282/RotatingBands.java
new file mode 100644
index 000000000..d9c76f888
--- /dev/null
+++ b/java/src/c22485282/RotatingBands.java
@@ -0,0 +1 @@
+package c22485282;
diff --git a/java/src/c22485282/RotatingBlocks.java b/java/src/c22485282/RotatingBlocks.java
new file mode 100644
index 000000000..82b126cda
--- /dev/null
+++ b/java/src/c22485282/RotatingBlocks.java
@@ -0,0 +1,78 @@
+package c22485282;
+
+import c22485282.MyVisual;
+import processing.core.PApplet;
+import processing.core.PVector;
+
+public class RotatingBlocks {
+ MyVisual mv;
+ int lastColorChange = 0;
+ int colorChangeInterval = 1500; // Change colors every 1.5 seconds
+ float[] blockColors; // Stores the hue of each block
+ float a = 0.0f; // Angle of rotation
+ float offset = (float) (mv.PI / 24.0); // Angle offset between boxes
+ int num = 12; // num of boxes
+ PVector[] boxPositions; // Stores the position of each box
+
+ public RotatingBlocks(MyVisual mv) {
+ this.mv = mv; // Initialize the MyVisual reference
+ blockColors = new float[num]; // Initializes array to store block colors
+ boxPositions = new PVector[num]; // Initializes array to store box positions
+ initializeBlockColors(); // Call method to initialize block colors
+ initializeBoxPositions(); // Call method to initialize box positions
+ } // End RotatingShape(M)
+
+ void initializeBlockColors() {
+ // Initialize block colors with random hues
+ for (int i = 0; i < num; i++) {
+ blockColors[i] = mv.random(360); // A random hue initialized to each block
+ }
+ } // End initializeBlockColors()
+
+ void initializeBoxPositions() {
+ float radius = 325; // Radius of the circular arrangement
+ float angle = 0; // Initial angle
+ // Positions of each box around a circle is calculated
+ for (int i = 0; i < num; i++) {
+ float x = radius * (float) Math.cos(angle); // X-coordinate of box position
+ float y = radius * (float) Math.sin(angle); // Y-coordinate of box position
+ boxPositions[i] = new PVector(x, y, 0); // Box position stored in the array
+ angle += mv.TWO_PI / num; // Angle incremented for the next box
+ }
+ } // End initializeBoxPositions()
+
+ public void render() {
+ mv.stroke(0);
+ mv.strokeWeight(4);
+ float amt = (float) (mv.millis() - lastColorChange) / colorChangeInterval; // Color change amount calculated
+ int audioIndex = (int) (mv.random(30, 512)); // Random audio buffer index
+ float audioValue = mv.getAudioBuffer().get(audioIndex); // Get audio value from the buffer
+ mv.pushMatrix(); // Current transformation matrix saved
+ mv.colorMode(mv.HSB, 360, 100, 100); // Color mode set to HSB
+
+ mv.translate(mv.width / 2, mv.height / 2 - 150); // Translate to the center
+
+ if (amt >= 1.0) {
+ initializeBlockColors(); // Block colors after interval are to be reset
+ lastColorChange = mv.millis(); // Last color change timestamp updated
+ }
+ // Render each rotating box
+ for (int i = 0; i < num; i++) {
+ float hue = mv.lerp(blockColors[i], mv.lerp(0, 360, audioValue), amt); // Interpolate hue based on audio value
+ mv.fill(hue, 100, 100); // Fill color set using HSB
+ mv.pushMatrix(); // Current transformation matrix saved
+ mv.rotateY(a + offset * i); // Rotate around Y-axis
+ mv.rotateX(a / 2 + offset * i); // Rotate around X-axis
+ mv.translate(boxPositions[i].x, boxPositions[i].y, 0); // Translate to box position
+ mv.box(50); // Draw a box
+ mv.popMatrix(); // Previous transformation matrix restored
+ }
+ a += 0.01; // Increment rotation angle
+ mv.popMatrix(); // Restore the original transformation matrix
+ } // End render()
+
+ }
+ // End rotatingBlocks()
+
+
+
diff --git a/java/src/c22485282/Snow.java b/java/src/c22485282/Snow.java
new file mode 100644
index 000000000..0c3dfb36b
--- /dev/null
+++ b/java/src/c22485282/Snow.java
@@ -0,0 +1,80 @@
+package c22485282;
+
+import java.util.ArrayList;
+import java.lang.Math; // import the Math class
+
+public class Snow {
+ MyVisual mv;
+ ArrayList snowflakes;
+ float angle = (float) Math.toRadians(20); // use Math.toRadians() instead
+
+ public Snow(MyVisual mv) {
+ this.mv = mv;
+ snowflakes = new ArrayList<>();
+ }
+
+ public void render() {
+ // mv.background(0, 0, 139); // Set background color to dark blue
+
+ // Simulate falling snow by adding new snowflakes
+ addSnowflakes(8);
+
+ // Update and display all snowflakes
+ for (int i = snowflakes.size() - 1; i >= 0; i--) {
+ Snowflake flake = snowflakes.get(i);
+ flake.update();
+ flake.display();
+ if (flake.isOffscreen()) {
+ snowflakes.remove(i); // Remove snowflake if it's offscreen
+ }
+ }
+ }
+
+
+ void addSnowflakes(int num) {
+ // Add new snowflakes at the top of the screen
+ for (int i = 0; i < num; i++) {
+ float x = mv.random(mv.width); // Random x position within canvas width
+ float y = mv.random(-50, -10); // Random y position above the screen
+ float diameter = mv.random(5, 15); // Random diameter of snowflake
+
+ snowflakes.add(new Snowflake(x, y, diameter)); // Add new snowflake to the list
+ }
+ }
+
+
+ class Snowflake {
+ float x, y;
+ float diameter; // Snowflake size
+ float speed; // Falling speed
+
+ Snowflake(float x, float y, float diameter) {
+ this.x = x;
+ this.y = y;
+ this.diameter = diameter;
+ this.speed = mv.random(1, 3); // Random falling speed
+ }
+
+
+ void update() {
+ y += speed; // Snowflake move down
+ x += mv.random(-1, 1); // Horizontal drift simulating wind effect
+ }
+
+ void display() {
+ mv.noStroke();
+ mv.fill(255);
+ mv.ellipse(x, y, diameter, diameter);
+ }
+
+ boolean isOffscreen() {
+ // Check if snowflake is completely off the screen
+ return y > mv.height + diameter;
+ }
+
+ }
+
+
+
+
+} // End Snow()
\ No newline at end of file
diff --git a/java/src/example/WaveForm.java b/java/src/c22485282/WaveForm.java
similarity index 93%
rename from java/src/example/WaveForm.java
rename to java/src/c22485282/WaveForm.java
index 5d38aa700..aaec0509c 100644
--- a/java/src/example/WaveForm.java
+++ b/java/src/c22485282/WaveForm.java
@@ -1,31 +1,31 @@
-package example;
-
-import processing.core.*;
-
-// This is an example of a visual that renders the waveform
-public class WaveForm
-{
- MyVisual mv;
- float cy = 0;
-
- public WaveForm(MyVisual mv)
- {
- this.mv = mv;
- cy = this.mv.height / 2;
- }
-
- public void render()
- {
- mv.colorMode(PApplet.HSB);
- for(int i = 0 ; i < mv.getAudioBuffer().size() ; i ++)
- {
- mv.stroke(
- PApplet.map(i, 0, mv.getAudioBuffer().size(), 0, 255)
- , 255
- , 255
- );
-
- mv.line(i, cy, i, cy + cy * mv.getAudioBuffer().get(i));
- }
- }
+package c22485282;
+
+import processing.core.*;
+
+// This is an example of a visual that renders the waveform
+public class WaveForm
+{
+ MyVisual mv;
+ float cy = 0;
+
+ public WaveForm(MyVisual mv)
+ {
+ this.mv = mv;
+ cy = this.mv.height / 2;
+ }
+
+ public void render()
+ {
+ mv.colorMode(PApplet.HSB);
+ for(int i = 0 ; i < mv.getAudioBuffer().size() ; i ++)
+ {
+ mv.stroke(
+ PApplet.map(i, 0, mv.getAudioBuffer().size(), 0, 255)
+ , 255
+ , 255
+ );
+
+ mv.line(i, cy, i, cy + cy * mv.getAudioBuffer().get(i));
+ }
+ }
}
\ No newline at end of file
diff --git a/java/src/c22485282/Worm.java b/java/src/c22485282/Worm.java
new file mode 100644
index 000000000..d3cd0d11c
--- /dev/null
+++ b/java/src/c22485282/Worm.java
@@ -0,0 +1,92 @@
+package c22485282;
+
+public class Worm {
+
+ MyVisual mv;
+ int xspacing = 8; // Distance of each horizontal location
+ int w; // Width of entire worm
+ int maxworms = 2; // Amount of worms to add together
+
+ float theta = 0.0f; // Angle initialized for worm oscillation
+ float[] amplitude = new float[maxworms]; // Stores height of worm
+ float[] dx = new float[maxworms]; // Value for incrementing X
+ float[] yvalues; // Stores height values of the worm
+
+ // Constructor for the Worm class, taking a MyVisual instance as input
+ public Worm(MyVisual mv) {
+ this.mv = mv; //The passed MyVisual instance assigned to the local mv variable
+ w = mv.width + 16; // Width of the worm visualization adjusted to the width of the sketch
+
+ // // Initialize worm parameters
+ for (int i = 0; i < maxworms; i++) {
+ amplitude[i] = mv.random(100,120); // Random amplitudes set for each worm
+ float period = mv.random(300,1000); // Random period set for each worm
+ dx[i] = (mv.TWO_PI / period) * xspacing;
+ } // End for
+ yvalues = new float[w/xspacing]; // Num of vertical locations based on the width and xspacing
+ } // End public worm()
+
+
+ public void render() {
+ // mv.hint(mv.DISABLE_DEPTH_TEST);
+
+ // Calculate worm heights based on audio input
+ calcWorm();
+
+ // Render the worm visualization
+ renderWorm();
+
+ // mv.hint(mv.ENABLE_DEPTH_TEST);
+ }
+
+ void calcWorm() {
+
+ theta += 0.02; // Increment theta for oscillation effect
+
+ // Get the audio buffer from the MyVisual instance
+ float[] audioBuffer = mv.getAudioBuffer().toArray();
+
+ // Iterate over the yvalues array and update based on audio amplitude
+ for (int i = 0; i < yvalues.length; i++) {
+ float wormHeight = 0;
+
+ // Calculate the worm height based on audio amplitude
+ for (int j = 0; j < maxworms; j++) {
+ // Use audio amplitude to modulate the worm's amplitude dynamically
+ int index = (int) (mv.map(i, 0, yvalues.length - 1, 0, audioBuffer.length - 1)); // Map index to audioBuffer range
+ float audioValue = audioBuffer[index];
+
+
+ amplitude[j] = mv.map(audioValue, -1, 1, 20, 100); // Map audio amplitude to worm amplitude range
+
+ if (j % 2 == 0) {
+ wormHeight += mv.sin(theta + (i * dx[j] / xspacing)) * amplitude[j];
+ } else {
+ wormHeight += mv.cos(theta + (i * dx[j] / xspacing)) * amplitude[j];
+ }
+ } // End for
+ yvalues[i] = wormHeight;
+ }
+ }
+
+
+void renderWorm() {
+ // Draw worm with an ellipse at each location
+ mv.stroke(0);
+ mv.strokeWeight(4);
+ // Smoothly change colors
+ float hue = 0;
+ float hueIncrement = 255.0f / yvalues.length;
+ for (int x = 0; x < yvalues.length; x++) {
+ float y = mv.height / 2 + yvalues[x];
+ float y2 = mv.height / 2 - yvalues[x];
+ mv.fill(hue, 255, 255);
+ mv.ellipse(x * xspacing, y, 100, 50);
+ mv.fill((hue %255)-50, 255, 255);
+ mv.ellipse(x * xspacing, y2, 65, 50); // Draw ellipse for second worm
+ hue += hueIncrement;
+ }
+}
+}
+
+
diff --git a/java/src/c22485282/testing.java b/java/src/c22485282/testing.java
new file mode 100644
index 000000000..45a5bfa37
--- /dev/null
+++ b/java/src/c22485282/testing.java
@@ -0,0 +1,5 @@
+package c22485282;
+
+public class testing {
+
+}
diff --git a/java/src/example/MyVisual.java b/java/src/example/MyVisual.java
deleted file mode 100644
index 8a71fe3f6..000000000
--- a/java/src/example/MyVisual.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package example;
-
-import ie.tudublin.*;
-
-public class MyVisual extends Visual {
- WaveForm wf;
- AudioBandsVisual abv;
-
- public void settings() {
- size(1024, 500);
-
- // Use this to make fullscreen
- // fullScreen();
-
- // Use this to make fullscreen and use P3D for 3D graphics
- // fullScreen(P3D, SPAN);
- }
-
- public void setup() {
- startMinim();
-
- // Call loadAudio to load an audio file to process
- // loadAudio("heroplanet.mp3");
-
- // Call this instead to read audio from the microphone
- startListening();
-
- wf = new WaveForm(this);
- abv = new AudioBandsVisual(this);
- }
-
- public void keyPressed() {
- if (key == ' ') {
- getAudioPlayer().cue(0);
- getAudioPlayer().play();
- }
- }
-
- public void draw() {
- background(0);
- try {
- // Call this if you want to use FFT data
- calculateFFT();
- } catch (VisualException e) {
- e.printStackTrace();
- }
- // Call this is you want to use frequency bands
- calculateFrequencyBands();
-
- // Call this is you want to get the average amplitude
- calculateAverageAmplitude();
- wf.render();
- abv.render();
- }
-}
diff --git a/java/src/example/RotatingBands.java b/java/src/example/RotatingBands.java
deleted file mode 100644
index e69de29bb..000000000
diff --git a/java/src/ie/tudublin/Main.java b/java/src/ie/tudublin/Main.java
index 67e93d892..e475ba6b8 100644
--- a/java/src/ie/tudublin/Main.java
+++ b/java/src/ie/tudublin/Main.java
@@ -1,8 +1,8 @@
package ie.tudublin;
-import example.CubeVisual;
-import example.MyVisual;
-import example.RotatingAudioBands;
+import c22485282.CubeVisual;
+import c22485282.MyVisual;
+import c22485282.RotatingAudioBands;
public class Main {