diff --git a/.vscode/launch.json b/.vscode/launch.json
index 5f0c7af3b..43cad1738 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -1,5 +1,62 @@
{
"configurations": [
+ {
+ "type": "java",
+ "name": "CerensSongVisualizer",
+ "request": "launch",
+ "mainClass": "ie.tudublin.CerensSongVisualizer",
+ "projectName": "java"
+ },
+ {
+ "type": "java",
+
+ "name": "MainVisual",
+ "request": "launch",
+ "mainClass": "ie.tudublin.MainVisual",
+ "projectName": "java"
+ },
+ {
+ "type": "java",
+ "name": "IsaVisual",
+ "request": "launch",
+ "mainClass": "ie.tudublin.IsaVisual",
+ "projectName": "java"
+ },
+ {
+ "type": "java",
+ "name": "EnhancedMountainLandscape",
+ "request": "launch",
+ "mainClass": "ie.tudublin.EnhancedMountainLandscape",
+ "projectName": "java"
+ },
+ {
+ "type": "java",
+ "name": "AudioLandscape",
+ "request": "launch",
+ "mainClass": "ie.tudublin.AudioLandscape",
+ "projectName": "java"
+ },
+ {
+ "type": "java",
+ "name": "MountainLandscape",
+ "request": "launch",
+ "mainClass": "ie.tudublin.MountainLandscape",
+ "projectName": "java"
+ },
+ {
+ "type": "java",
+ "name": "SpiralVisual",
+ "request": "launch",
+ "mainClass": "ie.tudublin.SpiralVisual",
+ "projectName": "java"
+ },
+ {
+ "type": "java",
+ "name": "AudioVisual",
+ "request": "launch",
+ "mainClass": "ie.tudublin.AudioVisual",
+ "projectName": "java"
+ },
{
"type": "java",
"name": "CodeLens (Launch) - Main",
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 000000000..c995aa5ce
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "java.debug.settings.onBuildFailureProceed": true
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index 19ba88c75..87aa6ed6f 100644
--- a/README.md
+++ b/README.md
@@ -1,89 +1,127 @@
# Music Visualiser Project
-Name:
+Name: Rana Hayes, Isadora Valentini, Ceren Ucan
-Student Number:
+Student Number: C21920856, D21125681, D21124013
-## 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
+# Youtube Video
-# Description of the assignment
-
-# Instructions
-
-# How it works
-
-# What I am most proud of in the assignment
-
-# Markdown Tutorial
-
-This is *emphasis*
+[
](https://youtu.be/6G2v33o0zi0)
-This is a bulleted list
-
-- Item
-- Item
-
-This is a numbered list
-
-1. Item
-1. Item
-
-This is a [hyperlink](http://bryanduggan.org)
+# Description of the assignment
-# Headings
-## Headings
-#### Headings
-##### Headings
+## Ceren
+Java program called "CerensSongVisualizer" creates a song visualizer with particles that move and change size based on audio input. It uses the Minim library for audio processing and the Processing library for graphics rendering.
-This is code:
+## Extra
+A Music Visualizer program developed in Java using the Processing library. It analyzes audio for beats and generates visual effects. It utilizes the Minim library for audio playback, beat detection, and FFT analysis.
-```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);
-}
-```
+## Rana
+"MountainLandscape" assignment creates an interactive visualization of a mountain terrain using noise generation and mapping techniques. It utilizes the Processing library and is structured as a subclass of the "Visual" class.
-So is this without specifying the language:
+## Isadora
+The "IsaVisual" assignment is a creative visualization project that combines audio processing and visual effects. It uses the Processing and Minim libraries to create a fractal tree that responds to audio input.
-```
-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);
-}
-```
+## Combined Visuals
+The assignment combines four visual effects: Mountain Landscape, Particles, Cubes, and a Fractal Tree (Flower shape). It uses the Processing and Minim libraries and combines elements of the other assignments into a single program.
-This is an image using a relative URL:
+# Instructions
-
+## Ceren's Visual
+Import the Minim library.
+Extend the CerensSongVisualizer class from PApplet.
+Set the display window size in the settings() method.
+Initialize the Minim library, create particles, load audio, set color mode, and convert audio buffer to an array in the setup() method.
+Use the draw() method to update and display particles, draw audio waveform, and rotate star shape.
+Implement the drawWaveform() method to draw the audio waveform graph.
+Implement the rotateStar() method to rotate and draw the star shape based on audio amplitude.
+Define the Particle class for particle properties and behavior.
+Initialize particle properties in the Particle constructor.
+Implement the update() method to update particle properties.
+Implement the display() method to draw particles.
+Run the CerensSongVisualizer program.
+
+## Extra
+Ensure you have Java and Processing installed on your system.
+Import the required libraries: ddf.minim.*, ddf.minim.analysis.*, and processing.core.PApplet.
+Set the size of the sketch window by calling the settings() function and specifying the desired width and height.
+Implement the setup() function to initialize the program. Load the audio file using the Minim library, configure the beat detection and FFT analysis objects, and create an ArrayList to store the particles.
+Implement the draw() function, which is the main loop of the program. Within this function, the audio is analyzed for beats, and the visual effect is updated and rendered accordingly. Particles are created and updated based on beat detection, and the squares in the corners of the screen are drawn and rotated.
+Implement the changeVisualEffect() function to modify the design element based on the beat. This function randomly adjusts the size, speed, and background color of the visual effect.
+Implement the drawVisualEffect() function to draw the squares in the four corners of the screen. Particles are also emitted from the squares when beats are detected.
+Implement the Particle class to define the behavior of the particles. Each particle has position, velocity, and acceleration vectors, as well as properties such as lifespan, size, and hue. The particles are updated, displayed, and eventually removed when their lifespan reaches zero.
+Finally, implement the stop() function to handle the clean-up tasks, such as closing the audio player and stopping the Minim library.
+
+## Isadora
+Ensure you have the required libraries: Processing, Minim, and ddf.minim.analysis.
+Import the "ie.tudublin" package.
+Create a new instance of the "IsaVisual" class.
+Set the size of the window using the "settings" method (e.g., size(1400, 800)).
+Provide the path to an audio file (e.g., "Parasite.mp3") and load it using the "minim.loadFile" method.
+Call the "play" method on the "AudioPlayer" object to start playing the audio.
+Customize the visual effects by modifying the parameters in the code, such as branch lengths, angles, and colors.
+Run the program and observe the visual display that reacts to the audio input.
+
+## Rana
+Ensure you have the required libraries: Processing and ddf.minim.analysis.
+Import the "ie.tudublin" package.
+Create a new instance of the "MountainLandscape" class.
+Set the size of the window using the "settings" method (e.g., size(1280, 720, P3D)).
+Customize the visual effects by modifying the parameters in the code, such as terrain size, scaling, and colors.
+Run the program and observe the visual display of the mountain landscape.
+
+## Combined Visuals
+Make sure you have the Processing library and the Minim library installed.
+Copy the provided code into a new Processing sketch.
+Place an audio file named "Parasite.mp3" in the same folder as the sketch.
+Run the sketch.
+Once the sketch is running, you can switch between the visual effects by pressing the corresponding number keys:
+Press '1' to switch to the Mountain Landscape visual effect.
+Press '2' to switch to the Music Visualizer visual effect.
+Press '3' to switch to the Isa Visual effect.
+Press '4' to switch to Ceren's Song Visualizer.
-This is an image using an absolute URL:
+# How it works
-
+## Ceren
+Set up the display window, initialize the Minim library, and load the audio file.
+Create an array of particles with random properties.
+In the draw() method, update and display particles.
+Draw the audio waveform using the drawWaveform() method.
+Rotate and draw the star shape based on audio amplitude.
+The Particle class defines particle properties and behavior.
+Continuously loop through the draw() method to animate the visualization.
+
+## Extra
+The Music Visualizer program uses audio analysis to generate visual effects synchronized with beats. It loads and plays audio using the Minim library. Beat detection triggers visual effect changes. Rotating squares change size, speed, and color with beat detection. Particles are emitted, creating an animated effect. Visuals are continuously updated based on audio input.
+
+## Isadora
+The program uses the Minim library for audio processing. It creates an instance of the IsaVisual class and sets the window size. An audio file is loaded and played. Visual effects are customized by modifying parameters such as branch lengths and colors. The program continuously updates the visual display based on the audio input.
+
+## Rana
+The program uses the noise function to generate a height map for the mountain landscape. It creates a 2D array called "terrain" to store the heights of each point on the landscape. The noise function is called for each point, and the resulting value is mapped to a suitable range to determine the height. The terrain is divided into triangles and rendered using triangle strips.
+In the "draw" method, the background is cleared, and the flyover parameter is updated based on the amplitude of the audio input. The camera and target vectors are adjusted according to the flyover and amplitude values. The landscape is then translated, rotated, and lit to achieve the desired perspective and lighting effects. Triangle strips are used to render the terrain, with each vertex having a corresponding color based on its position and height.
+
+## Combined Visual
+To run the program that combines the Mountain Landscape, Music Visualizer, and Isa Visual effects, follow these instructions:
+Import the Minim library and the Processing library into your Java project.
+Create a new class, let's name it "CombinedVisuals", and extend it from the PApplet class.
+In the setup() method, initialize the Minim library for audio processing, create instances of the MountainLandscape, MusicVisualizer, and IsaVisual classes.
+Load the audio file and start playing it using the MusicVisualizer class.
+Set up the display window size and any other necessary settings for the MountainLandscape and IsaVisual classes.
+In the draw() method, update and display the visual effects from all three classes.
+Run the CombinedVisuals program.
-This is a youtube video:
+# What I am most proud of in the assignment
-[](https://www.youtube.com/watch?v=J2kHSSFA4NU)
+## Ceren
+In this assignment, I'm actually most proud of how comfortable I have become with using git, branches, merging, committing and collaborating. I am most proud of successfully implementing the particle system and integrating it with audio visualization. The particles move and change size based on the audio input, creating an engaging and visually appealing effect. Additionally, the waveform and rotating star shape add an extra layer of visual interest to the overall visualization.
-This is a table:
+## Isadora
+I am most proud of the creativity and interactivity achieved in the assignment. The combination of audio processing and visual effects creates a visually stimulating experience. The use of recursion in the "Branch" class allows for the creation of intricate branching patterns. The interaction between the audio input and the visual display adds a dynamic element to the assignment. Overall, the assignment demonstrates the ability to create captivating and responsive visualizations using code.
-| 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 |
+## Rana
+I am most proud of the realistic and dynamic nature of the mountain landscape visualization. The use of noise functions to generate the terrain creates an organic and natural appearance. The integration of audio input to control the flyover and amplitude adds an interactive element to the visualization. The implementation of lighting effects further enhances the realism of the landscape. Overall, the assignment demonstrates the ability to create visually appealing and interactive visualizations using code.
+I am also very proud of implementing the MainVisual (combined visual) as it required lots of re-works and changes to the visual).
+# Markdown Tutorial
diff --git a/java/.project b/java/.project
index 0d5afed93..55836abf3 100644
--- a/java/.project
+++ b/java/.project
@@ -16,12 +16,12 @@
- 1616413840733
+ 1678805499117
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/data/Parasite.mp3 b/java/data/Parasite.mp3
new file mode 100644
index 000000000..9d1d8c9bd
Binary files /dev/null and b/java/data/Parasite.mp3 differ
diff --git a/java/src/ie/tudublin/CerensSongVisualizer.java b/java/src/ie/tudublin/CerensSongVisualizer.java
new file mode 100644
index 000000000..2d6b01932
--- /dev/null
+++ b/java/src/ie/tudublin/CerensSongVisualizer.java
@@ -0,0 +1,169 @@
+package ie.tudublin;
+
+import ddf.minim.AudioBuffer;
+import ddf.minim.AudioPlayer;
+import ddf.minim.Minim;
+import processing.core.PApplet;
+
+public class CerensSongVisualizer extends PApplet {
+ Minim minim; // Audio library object
+ AudioPlayer ap; // Audio player object
+ AudioBuffer ab; // Audio buffer object
+
+ private static final int NUM_PARTICLES = 5000; // Number of particles
+ private Particle[] particles; // Array to store particles
+
+ private float[] waveform; // Array to store the waveform data
+
+ private float rotationAngle = 0; // Angle for rotation
+ private float rotationSpeed = 0.01f; // Speed of rotation
+
+ public void settings() {
+ size(800, 600); // Set the size of the window
+ }
+
+ public void setup() {
+ minim = new Minim(this); // Initialize the minim object
+ particles = new Particle[NUM_PARTICLES]; // Initialize the particle array
+
+ for (int i = 0; i < NUM_PARTICLES; i++) {
+ float angle = random(TWO_PI); // Random angle
+ float radius = random(width * 0.4f); // Random radius within a range
+ float speed = random(0.5f, 2.0f); // Random speed within a range
+ float size = random(1, 4); // Random size within a range
+
+ particles[i] = new Particle(angle, radius, speed, size); // Create a new particle
+ }
+
+ smooth(); // Enable smoothing of edges
+
+ ap = minim.loadFile("java/data/Parasite.mp3", 1024); // Load the audio file
+ ap.play(); // Start playing the audio
+ ab = ap.mix; // Get the audio buffer
+
+ colorMode(HSB, 360, 100, 100); // Set the color mode
+
+ waveform = ab.toArray(); // Convert audio buffer to an array
+ }
+
+ public void draw() {
+ background(0); // Clear the background
+
+ // Update and display particles
+ for (Particle particle : particles) {
+ particle.update(); // Update the particle
+ particle.display(); // Display the particle
+ }
+
+ drawWaveform(); // Draw the waveform
+ rotateStar(); // Rotate the star
+ }
+
+ private void drawWaveform() {
+ float waveformHeight = height / 2; // Height of the waveform
+ noFill(); // Don't fill shapes
+ strokeWeight(1); // Set stroke weight
+
+ // Draw waveform graph
+ beginShape();
+ for (int i = 0; i < waveform.length; i += 10) {
+ float waveX = map(i, 0, waveform.length - 1, 0, width); // Map x-coordinate
+ float waveY = map(waveform[i], -1, 1, waveformHeight, -waveformHeight); // Map y-coordinate based on
+ // waveform data
+ stroke(i % 360, 100, 100); // Set stroke color based on index
+ vertex(waveX, waveY); // Add vertex to the shape
+ }
+ endShape();
+ }
+
+ private void rotateStar() {
+ translate(width / 2, height / 2); // Translate to the center of the window
+ rotate(rotationAngle); // Apply rotation transformation
+
+ float amplitude = max(abs(ap.left.get(0)), abs(ap.right.get(0))); // Get the maximum amplitude
+ float starSize = map(amplitude, 0, 1, 50, 200); // Map amplitude to star size
+
+ noStroke(); // Disable stroke
+ int npoints = floor(map(sin(starSize * 0.3f), -1, 1, 1, 12)); // Calculate the number of points for the star
+ // shape
+ drawStar(0, 0, starSize, starSize / 2, npoints); // Draw a star shape with variable number of points
+ drawStar(0, 0, starSize, starSize / 2, 5); // Draw a 5-pointed star
+ rotationAngle += rotationSpeed; // Update the rotation angle
+ }
+
+ private void drawStar(float x, float y, float radius1, float radius2, int npoints) {
+ float amplitude = max(abs(ap.left.get(0)), abs(ap.right.get(0))); // Get the maximum amplitude
+ float hueValue = map(amplitude, 0, 1, 0, 360); // Map amplitude to hue value
+
+ fill(hueValue, 100, 100); // Set fill color based on hue value
+ drawStarShape(x, y, radius1, radius2, npoints); // Draw the star shape
+ }
+
+ // Helper method to draw a star shape
+ private void drawStarShape(float x, float y, float radius1, float radius2, int npoints) {
+ float angle = TWO_PI / npoints; // Calculate the angle between each point
+ float halfAngle = angle / 2.0f; // Calculate the half angle
+
+ beginShape();
+ for (float a = 0; a < TWO_PI; a += angle) {
+ float sx = x + cos(a) * radius2; // Calculate x-coordinate for outer radius
+ float sy = y + sin(a) * radius2; // Calculate y-coordinate for outer radius
+ vertex(sx, sy); // Add vertex to the shape
+ sx = x + cos(a + halfAngle) * radius1; // Calculate x-coordinate for inner radius
+ sy = y + sin(a + halfAngle) * radius1; // Calculate y-coordinate for inner radius
+ vertex(sx, sy); // Add vertex to the shape
+ }
+ endShape(CLOSE); // Close the shape
+ }
+
+ private class Particle {
+ private float angle; // Angle of the particle
+ private float radius; // Distance from the center of the screen
+ private float speed; // Speed at which the particle moves
+ private float size; // Size of the particle
+ private float rotation; // Rotation angle of the particle
+
+ Particle(float angle, float radius, float speed, float size) {
+ this.angle = angle;
+ this.radius = radius;
+ this.speed = random(2.0f, 1.0f); // Adjust the speed range here
+ this.size = size;
+ this.rotation = 0;
+ }
+
+ void update() {
+ radius += speed; // Update the radius based on the speed
+ if (radius > 400) {
+ radius = 0; // Reset the radius if it exceeds a certain value
+ }
+ }
+
+ void display() {
+ float x = width / 2 + cos(angle) * radius; // Calculate the x-coordinate of the particle
+ float y = height / 2 + sin(angle) * radius; // Calculate the y-coordinate of the particle
+
+ // Get the amplitude from the audio buffer based on the angle
+ float amplitude = ab.get((int) (angle * 10)) * 100;
+
+ // Vary the hue based on the sum of the angle and amplitude
+ float hueValue = (angle + amplitude) % 360;
+
+ // Vary the size based on the amplitude
+ float sizeValue = size + amplitude * 0.05f;
+
+ pushMatrix(); // Save the current transformation matrix
+ translate(x, y); // Translate to the particle's position
+ rotate(rotation); // Apply rotation transformation
+
+ noStroke(); // Disable stroke
+ fill(hueValue, 100, 100); // Set fill color based on hue value
+ ellipse(0, 0, sizeValue, sizeValue); // Draw the particle as an ellipse
+
+ popMatrix(); // Restore the previous transformation matrix
+ }
+ }
+
+ public static void main(String[] args) {
+ PApplet.main("ie.tudublin.CerensSongVisualizer"); // Launch the application
+ }
+}
diff --git a/java/src/ie/tudublin/IsaVisual.java b/java/src/ie/tudublin/IsaVisual.java
new file mode 100644
index 000000000..68675921b
--- /dev/null
+++ b/java/src/ie/tudublin/IsaVisual.java
@@ -0,0 +1,155 @@
+package ie.tudublin;
+
+import ddf.minim.*;
+import processing.core.*;
+import ddf.minim.analysis.*;
+
+public class IsaVisual extends Visual {
+
+ //String[] visualizers = {"IsaVisual", "CerenVisual", "MountainLandscape"};
+ //int currentVisualizer = 0;
+
+
+ Minim minim;
+ AudioPlayer ap;
+ FFT fft;
+
+ Branch branch1;
+ Branch branch2;
+
+ int counter = 0;
+ int branchCounter = 0;
+
+
+ public void settings() {
+ size(1400, 800);
+ //size(1024, 500);
+ }
+
+ public void setup() {
+ minim = new Minim(this);
+ ap = minim.loadFile("Parasite.mp3");
+ ap.play();
+ fft = new FFT(ap.bufferSize(), ap.sampleRate());
+ colorMode(HSB);
+ ellipseMode(RADIUS);
+ }
+
+ /*void drawButtons() {
+ textAlign(RIGHT);
+ textSize(15);
+ fill(255);
+ text(visualizers[currentVisualizer], width - 20, 30);
+ rectMode(CORNER);
+ rect(width - 80, 10, 70, 30);
+ rect(width - 160, 10, 70, 30);
+ rect(width - 240, 10, 70, 30);
+ fill(0);
+ textAlign(CENTER);
+ text("Isa", width - 45, 30);
+ text("Ceren", width - 115, 30);
+ text("Rana", width - 185, 30);
+ }
+
+ public void mousePressed() {
+ if (mouseY < 40) {
+ if (mouseX > width - 80) {
+ currentVisualizer = 0;
+ } else if (mouseX > width - 160) {
+ currentVisualizer = 1;
+ } else if (mouseX > width - 240) {
+ currentVisualizer = 2;
+ }
+ String visualizerClassName = "ie.tudublin." + visualizers[currentVisualizer];
+ PApplet.main(visualizerClassName);
+ }
+ }*/
+
+
+
+ class Branch {
+
+ private IsaVisual iv;
+ private float start;
+ private float amplitude;
+ private float angle = 0;
+
+ private Branch[] branches;
+
+ Branch(IsaVisual iv, float start, float amplitude, float angle, int branches) {
+ this.iv = iv;
+ this.start = start;
+ this.amplitude = amplitude;
+ this.angle = angle;
+
+ branch(branches);
+ }
+
+ void display() {
+
+ iv.rotate(this.angle);
+ iv.line(0, 0, 0, amplitude);
+
+ if (branches != null) {
+ iv.translate(0, amplitude);
+ iv.pushMatrix();
+ branches[0].display();
+ iv.popMatrix();
+ branches[1].display();
+
+ }
+ }
+
+ void branch(int numOfBranches) {
+
+ if (numOfBranches > 0) {
+ branches = new Branch[2];
+ iv.branchCounter++;
+
+ float angle = IsaVisual.map(iv.smothedAmplitude, 0, 1, 3.14f / 5f, 3.14f / 2f);
+
+ branches[0] = new Branch(iv, start - amplitude, amplitude / 1.5f, angle, numOfBranches - 2);
+ branches[1] = new Branch(iv, start - amplitude, amplitude / 1.5f, -angle, numOfBranches - 2);
+ }
+ }
+ }
+
+ public void draw() {
+
+ //background(0);
+ //drawButtons();
+
+ strokeWeight(0.7f);
+ fill(0, 70);
+ rect(-1, -1, width + 1, height + 1);
+ fft.forward(ap.mix);
+ smothedAmplitude = lerp(smothedAmplitude, fft.getBand(512), 0.01f);
+ counter++;
+
+ for (int i = 0; i < 8; i++) {
+
+ resetMatrix();
+
+ translate(width / 2, height / 2);
+ branchCounter = 0;
+
+ rotate(map(counter % 360, 0, 360, 0, PI * 1.5f));
+ rotate(map((float) i, 0f, 6f, 0f, PI*1.5f));
+
+ branch1 = new Branch(this, 0f, map(smothedAmplitude*2f, 0, .6f, -height / 30f, -height / 3.5f), 0, 14);
+ branch2 = new Branch(this, 0f, map(smothedAmplitude*2f, 0, .6f, -height / 15f, -height / 3.5f), 0, 16);
+
+ fill((counter) % 255);
+ stroke((counter) % random(255));
+ branch1.display();
+
+ fill((counter / 2) % 255);
+ stroke((counter / 2) % 255, 255, 255);
+ branch2.display();
+ }
+ }
+
+ public static void main(String[] args) {
+ PApplet.main("ie.tudublin.IsaVisual");
+ }
+}
diff --git a/java/src/ie/tudublin/Main.java b/java/src/ie/tudublin/Main.java
deleted file mode 100644
index 27489f824..000000000
--- a/java/src/ie/tudublin/Main.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package ie.tudublin;
-
-import example.CubeVisual;
-import example.MyVisual;
-import example.RotatingAudioBands;
-
-public class Main
-{
-
- public void startUI()
- {
- String[] a = {"MAIN"};
- processing.core.PApplet.runSketch( a, new MyVisual());
- }
-
- public static void main(String[] args)
- {
- Main main = new Main();
- main.startUI();
- }
-}
\ No newline at end of file
diff --git a/java/src/ie/tudublin/MainVisual.java b/java/src/ie/tudublin/MainVisual.java
new file mode 100644
index 000000000..108591666
--- /dev/null
+++ b/java/src/ie/tudublin/MainVisual.java
@@ -0,0 +1,527 @@
+// Rana's combined code modified
+
+package ie.tudublin;
+
+import ddf.minim.*;
+import ddf.minim.analysis.*;
+import processing.core.PApplet;
+import processing.core.PVector;
+import java.util.ArrayList;
+
+public class MainVisual extends PApplet {
+
+ int currentVisual = 1; // 1 for MountainLandscape, 2 for MusicVisualizer
+
+ // MountainLandscape variables
+ Minim minim;
+ AudioPlayer player;
+ FFT fft;
+
+ int cols, rows;
+ int scl = 20;
+ float w = 2000;
+ float h = 1500;
+ float[][] terrain;
+
+ float flyover = 0;
+ PVector camera = new PVector(0, -100, 500);
+ PVector target = new PVector(0, 0, 0);
+ float theta = 0;
+
+ // MusicVisualizer variables
+ BeatDetect beat;
+ float angle = 0;
+ float size = 50;
+ float posX, posY;
+ float speedX, speedY;
+ ArrayList particles;
+
+ //Isa Visual Variables
+
+ Branch branch1;
+ Branch branch2;
+ int counter = 0;
+ int branchCounter = 0;
+ float smothedAmplitude = 0;
+
+ //CerensSong vvariables
+ AudioPlayer ap; // Audio player object
+ AudioBuffer ab; // Audio buffer object
+ private static final int NUM_PARTICLES = 5000; // Number of particles
+ private ArrayList Cerensparticles;
+
+ private float[] waveform; // Array to store the waveform data
+
+ private float rotationAngle = 0; // Angle for rotation
+ private float rotationSpeed = 0.01f; // Speed of rotations
+
+
+
+
+ public void settings() {
+ size(1280, 720, P3D);
+ //fullScreen();
+ }
+
+
+ public void setup() {
+ minim = new Minim(this);
+ player = minim.loadFile("Parasite.mp3", 1024);
+ fft = new FFT(player.bufferSize(), player.sampleRate());
+ beat = new BeatDetect();
+
+ // Start audio processing in a separate thread
+ new Thread(() -> player.play()).start();
+
+ cols = (int) (w / scl);
+ rows = (int) (h / scl);
+ terrain = new float[cols][rows];
+ particles = new ArrayList<>(); // Initialize the list
+
+ posX = width / 2;
+ posY = height / 2;
+ speedX = random(-2, 2);
+ speedY = random(-2, 2);
+ ellipseMode(RADIUS);
+ colorMode(HSB);
+
+ Cerensparticles = new ArrayList();
+ minim = new Minim(this); // Initialize the minim object
+ ap = minim.loadFile("java/data/Parasite.mp3", 1024); // Load the audio file
+ ap.play(); // Start playing the audio
+ ab = ap.mix; // Get the audio buffer
+ colorMode(HSB, 360, 100, 100); // Set the color mode
+
+ waveform = ab.toArray(); // Convert audio buffer to an array
+
+
+ for (int i = 0; i < NUM_PARTICLES; i++) {
+ float angle = random(TWO_PI); // Random angle
+ float radius = random(width * 0.4f); // Random radius within a range
+ float speed = random(0.5f, 2.0f); // Random speed within a range
+ float size = random(1, 4); // Random size within a range
+
+ Cerensparticles.add(new CerensParticle(angle, radius, speed, size));
+ }
+
+ smooth(); // Enable smoothing of edges
+ }
+
+
+ public void draw() {
+ if (currentVisual == 1) {
+ drawMountainLandscape();
+ } else if (currentVisual == 2) {
+ drawMusicVisualizer();
+ } else if (currentVisual == 3) {
+ drawIsaVisual();
+ } else if (currentVisual == 4) {
+ drawCerensSongVisualizer();
+ }
+ }
+
+ public void keyPressed() {
+ if (key == '1') {
+ currentVisual = 1;
+ } else if (key == '2') {
+ currentVisual = 2;
+ } else if (key == '3') {
+ currentVisual = 3;
+ } else if (key == '4') {
+ currentVisual = 4;
+ }
+ }
+
+ public void drawMountainLandscape() {
+ // ... MountainLandscape draw() code here ...
+ background(0);
+
+ fft.forward(player.mix);
+ float smoothedAmplitude = 0;
+ for (int i = 0; i < player.bufferSize(); i++) {
+ smoothedAmplitude += abs(player.mix.get(i));
+ }
+ smoothedAmplitude /= player.bufferSize();
+ smoothedAmplitude = lerp(smoothedAmplitude, 0, 0.1f);
+
+ flyover += map(smoothedAmplitude, 0, 1, 0.2f, 1);
+
+ camera.z = flyover;
+ camera.y = -100 + map(smoothedAmplitude, 0, 1, -10, 10);
+ target.x = sin(theta);
+ target.z = cos(theta);
+
+ translate(width / 2, height / 2, 0);
+ rotateX(PI / 3);
+ translate(-w / 2, -h / 2);
+
+ // Set up the lighting
+ ambientLight(100, 100, 100);
+ directionalLight(255, 255, 255, 1, 1, -1);
+
+ hint(DISABLE_DEPTH_TEST);
+ noFill();
+ stroke(255);
+
+ for (int x = 0; x < cols; x++) {
+ for (int y = 0; y < rows; y++) {
+ terrain[x][y] = map(noise(x * 0.1f, y * 0.1f, flyover * 0.01f), 0, 1, -100, 100) * smoothedAmplitude * 10;
+ }
+ }
+
+ for (int y = 0; y < rows - 1; y++) {
+ beginShape(TRIANGLE_STRIP);
+ for (int x = 0; x < cols; x++) {
+ float r = map(y, 0, rows, 50, 255);
+ float g = map(x, 0, cols, 50, 255);
+ float b = map(terrain[x][y], -50, 50, 100, 200);
+ stroke(r, g, b);
+ vertex(x * scl, y * scl, terrain[x][y]);
+ vertex(x * scl, (y + 1) * scl, terrain[x][y + 1]);
+ }
+ endShape();
+ }
+
+ theta += map(smoothedAmplitude, 0, 1, 0, 0.05f);
+
+
+ }
+
+ public void drawMusicVisualizer() {
+ // ... MusicVisualizer draw() code here ...
+ background(0); // Set the background color
+
+ // Analyze the audio for beats
+ beat.detect(player.mix);
+
+ // If a beat is detected, change the visual effect
+ if (beat.isOnset()) {
+ changeVisualEffect();
+ }
+
+ // Update the position of the design element
+ posX += speedX;
+ posY += speedY;
+
+ // Check boundaries and change direction if necessary
+ if (posX < 0 || posX > width) {
+ speedX *= -1;
+ }
+ if (posY < 0 || posY > height) {
+ speedY *= -1;
+ }
+
+ // Create particles based on the beat
+ if (beat.isOnset()) {
+ for (int i = 0; i < 10; i++) {
+ Particle p = new Particle(posX, posY, speedX, speedY);
+ particles.add(p);
+ }
+ }
+
+ // Update and draw particles
+ for (int i = particles.size() - 1; i >= 0; i--) {
+ Particle p = particles.get(i);
+ p.update();
+ p.display();
+ if (p.isDead()) {
+ particles.remove(i);
+ }
+ }
+
+ // Draw the current visual effect
+ drawVisualEffect();
+
+ // Calculate the FFT to get frequency data
+ fft.forward(player.mix);
+
+ }
+
+ // ... MusicVisualizer methods and Particle class here ...
+ void changeVisualEffect() {
+ // Modify the design element based on the beat
+ size = random(10, 100); // Randomize the size of the design element
+ speedX = random(-5, 5); // Randomize the horizontal speed of the design element
+ speedY = random(-5, 5); // Randomize the vertical speed of the design element
+ background(random(255), random(255), random(255)); // Randomize the background color
+ }
+
+ void drawVisualEffect() {
+ // Draw the design element in all four corners
+ for (int i = 0; i < 4; i++) {
+ float cornerX = i % 2 == 0 ? posX : width - posX;
+ float cornerY = i < 2 ? posY : height - posY;
+
+ pushMatrix();
+ translate(cornerX, cornerY);
+ rotate(angle);
+ rectMode(CENTER);
+ fill(random(255), random(255), random(255)); // Randomize the fill color of the design element
+ rect(0, 0, size, size);
+ popMatrix();
+
+ // Create particles based on the beat
+ if (beat.isOnset()) {
+ for (int j = 0; j < 10; j++) {
+ Particle p = new Particle(cornerX, cornerY, speedX, speedY);
+ particles.add(p);
+ }
+ }
+ }
+
+ // Rotate the design element gradually
+ angle += 0.05;
+ }
+
+
+ class Particle {
+ PVector position;
+ PVector velocity;
+ PVector acceleration;
+ float lifespan;
+ float size;
+ float hue;
+
+ Particle(float x, float y, float speedX, float speedY) {
+ position = new PVector(x, y);
+ velocity = new PVector(speedX, speedY).add(PVector.random2D().mult(random(1, 5))); // Randomize the initial velocity of particles
+ acceleration = new PVector(0, 0.05f); // Set the constant acceleration for particles
+ lifespan = 255;
+ size = random(4, 16); // Randomize the size of particles
+ hue = random(360); // Randomize the hue value of particles
+ }
+
+ void update() {
+ velocity.add(acceleration); // Update the velocity of particles
+ position.add(velocity); // Update the position of particles based on velocity
+ lifespan -= 2; // Decrease the lifespan of particles
+ }
+
+ void display() {
+ colorMode(HSB);
+ noStroke();
+ fill(hue, 255, 255, lifespan); // Set the fill color of particles with transparency based on lifespan
+ ellipse(position.x, position.y, size, size); // Draw particles as ellipses
+ }
+
+ boolean isDead() {
+ return lifespan <= 0; // Check if the lifespan of particles has reached zero
+ }
+ }
+
+ public void stop() {
+ player.close();
+ minim.stop();
+ super.stop();
+ }
+ public void drawIsaVisual() {
+ background(0);
+ //drawButtons();
+
+ strokeWeight(0.7f);
+ fill(0, 70);
+ rect(-1, -1, width + 1, height + 1);
+ fft.forward(player.mix);
+ smothedAmplitude = lerp(smothedAmplitude, fft.getBand(512), 0.01f);
+ counter++;
+
+ for (int i = 0; i < 8; i++) {
+
+ resetMatrix();
+
+ perspective(PI / 1.5f, (float)width/(float)height, 0.1f, 1000.0f);
+ translate(width/2 - 640, height/2 - 360, -300);
+
+ branchCounter = 0;
+
+ rotate(map(counter % 360, 0, 360, 0, PI * 1.5f));
+ rotate(map((float) i, 0f, 6f, 0f, PI*1.5f));
+
+ branch1 = new Branch(this, 0f, map(smothedAmplitude*2f, 0, .6f, -height / 30f, -height / 3.5f), 0, 14);
+ branch2 = new Branch(this, 0f, map(smothedAmplitude*2f, 0, .6f, -height / 15f, -height / 3.5f), 0, 16);
+
+
+ fill((counter) % 255);
+ stroke((counter) % random(255));
+ branch1.display();
+
+ fill((counter / 2) % 255);
+ stroke((counter / 2) % 255, 255, 255);
+ branch2.display();
+
+ }
+ }
+
+
+ class Branch {
+
+ private MainVisual cv;
+ private float start;
+ private float amplitude;
+ private float angle = 0;
+
+ private Branch[] branches;
+
+ Branch(MainVisual mainVisual, float start, float amplitude, float angle, int branches) {
+ this.cv = mainVisual;
+ this.start = start;
+ this.amplitude = amplitude;
+ this.angle = angle;
+
+ branch(branches);
+ }
+
+ void display() {
+
+ cv.rotate(this.angle);
+ cv.line(0, 0, 0, amplitude);
+
+ if (branches != null) {
+ cv.translate(0, amplitude);
+ cv.pushMatrix();
+ branches[0].display();
+ cv.popMatrix();
+ branches[1].display();
+
+ }
+ }
+
+ void branch(int numOfBranches) {
+
+ if (numOfBranches > 0) {
+ branches = new Branch[2];
+ cv.branchCounter++;
+
+ float angle = map(cv.smothedAmplitude, 0, 1, 3.14f / 5f, 3.14f / 2f);
+
+ branches[0] = new Branch(cv, start - amplitude, amplitude / 1.5f, angle, numOfBranches - 2);
+ branches[1] = new Branch(cv, start - amplitude, amplitude / 1.5f, -angle, numOfBranches - 2);
+ }
+ }
+ }
+
+
+ public void drawCerensSongVisualizer() {
+ // ... CerensSongVisualizer draw() code
+ background(0);
+ for (CerensParticle particle : Cerensparticles) {
+ particle.update();
+ particle.display();
+ }
+
+ drawWaveform(); // Draw the waveform
+ rotateStar(); // Rotate the star
+ }
+
+ private void drawWaveform() {
+ float waveformHeight = height / 2; // Height of the waveform
+ noFill(); // Don't fill shapes
+ strokeWeight(1); // Set stroke weight
+
+ // Draw waveform graph
+ beginShape();
+ for (int i = 0; i < waveform.length; i += 10) {
+ float waveX = map(i, 0, waveform.length - 1, 0, width); // Map x-coordinate
+ float waveY = map(waveform[i], -1, 1, waveformHeight, -waveformHeight); // Map y-coordinate based on
+ // waveform data
+ stroke(i % 360, 100, 100); // Set stroke color based on index
+ vertex(waveX, waveY); // Add vertex to the shape
+ }
+ endShape();
+ }
+
+ private void rotateStar() {
+ translate(width / 2, height / 2); // Translate to the center of the window
+ rotate(rotationAngle); // Apply rotation transformation
+
+ float amplitude = max(abs(ap.left.get(0)), abs(ap.right.get(0))); // Get the maximum amplitude
+ float starSize = map(amplitude, 0, 1, 50, 200); // Map amplitude to star size
+
+ noStroke(); // Disable stroke
+ int npoints = floor(map(sin(starSize * 0.3f), -1, 1, 1, 12)); // Calculate the number of points for the star
+ // shape
+ drawStar(0, 0, starSize, starSize / 2, npoints); // Draw a star shape with variable number of points
+ drawStar(0, 0, starSize, starSize / 2, 5); // Draw a 5-pointed star
+ rotationAngle += rotationSpeed; // Update the rotation angle
+ }
+
+ private void drawStar(float x, float y, float radius1, float radius2, int npoints) {
+ float amplitude = max(abs(ap.left.get(0)), abs(ap.right.get(0))); // Get the maximum amplitude
+ float hueValue = map(amplitude, 0, 1, 0, 360); // Map amplitude to hue value
+
+ fill(hueValue, 100, 100); // Set fill color based on hue value
+ drawStarShape(x, y, radius1, radius2, npoints); // Draw the star shape
+ }
+
+ // Helper method to draw a star shape
+ private void drawStarShape(float x, float y, float radius1, float radius2, int npoints) {
+ float angle = TWO_PI / npoints; // Calculate the angle between each point
+ float halfAngle = angle / 2.0f; // Calculate the half angle
+
+ beginShape();
+ for (float a = 0; a < TWO_PI; a += angle) {
+ float sx = x + cos(a) * radius2; // Calculate x-coordinate for outer radius
+ float sy = y + sin(a) * radius2; // Calculate y-coordinate for outer radius
+ vertex(sx, sy); // Add vertex to the shape
+ sx = x + cos(a + halfAngle) * radius1; // Calculate x-coordinate for inner radius
+ sy = y + sin(a + halfAngle) * radius1; // Calculate y-coordinate for inner radius
+ vertex(sx, sy); // Add vertex to the shape
+ }
+ endShape(CLOSE); // Close the shape
+ }
+
+ private class CerensParticle {
+ private float angle; // Angle of the particle
+ private float radius; // Distance from the center of the screen
+ private float speed; // Speed at which the particle moves
+ private float size; // Size of the particle
+ private float rotation; // Rotation angle of the particle
+
+ CerensParticle(float angle, float radius, float speed, float size) {
+ this.angle = angle;
+ this.radius = radius;
+ this.speed = random(2.0f, 1.0f); // Adjust the speed range here
+ this.size = size;
+ this.rotation = 0;
+ }
+
+ void update() {
+ radius += speed; // Update the radius based on the speed
+ if (radius > 400) {
+ radius = 0; // Reset the radius if it exceeds a certain value
+ }
+ }
+
+ void display() {
+ float x = width / 2 + cos(angle) * radius; // Calculate the x-coordinate of the particle
+ float y = height / 2 + sin(angle) * radius; // Calculate the y-coordinate of the particle
+
+ // Get the amplitude from the audio buffer based on the angle
+ float amplitude = ab.get((int) (angle * 10)) * 100;
+
+ // Vary the hue based on the sum of the angle and amplitude
+ float hueValue = (angle + amplitude) % 360;
+
+ // Vary the size based on the amplitude
+ float sizeValue = size + amplitude * 0.05f;
+
+ pushMatrix(); // Save the current transformation matrix
+ translate(x, y); // Translate to the particle's position
+ rotate(rotation); // Apply rotation transformation
+
+ noStroke(); // Disable stroke
+ fill(hueValue, 100, 100); // Set fill color based on hue value
+ ellipse(0, 0, sizeValue, sizeValue); // Draw the particle as an ellipse
+
+ popMatrix(); // Restore the previous transformation matrix
+ }
+ }
+
+
+
+
+
+ public static void main(String[] args) {
+ PApplet.main("ie.tudublin.MainVisual");
+ }
+}
diff --git a/java/src/ie/tudublin/MountainLandscape.java b/java/src/ie/tudublin/MountainLandscape.java
new file mode 100644
index 000000000..a07709090
--- /dev/null
+++ b/java/src/ie/tudublin/MountainLandscape.java
@@ -0,0 +1,97 @@
+package ie.tudublin;
+
+import ddf.minim.*;
+import ddf.minim.analysis.*;
+import processing.core.PApplet;
+import processing.core.PVector;
+
+public class MountainLandscape extends PApplet {
+
+ Minim minim;
+ AudioPlayer player;
+ FFT fft;
+
+ int cols, rows;
+ int scl = 20;
+ float w = 2000;
+ float h = 1500;
+ float[][] terrain;
+
+ float flyover = 0;
+ PVector camera = new PVector(0, -100, 500);
+ PVector target = new PVector(0, 0, 0);
+ float theta = 0;
+
+ public void settings() {
+ size(1280, 720, P3D);
+ }
+
+ public void setup() {
+ minim = new Minim(this);
+ player = minim.loadFile("Parasite.mp3", 1024);
+ fft = new FFT(player.bufferSize(), player.sampleRate());
+
+ player.play();
+
+ cols = (int) (w / scl);
+ rows = (int) (h / scl);
+ terrain = new float[cols][rows];
+ frameRate(30);
+ }
+
+ public void draw() {
+ background(0);
+
+ fft.forward(player.mix);
+ float smoothedAmplitude = 0;
+ for (int i = 0; i < player.bufferSize(); i++) {
+ smoothedAmplitude += abs(player.mix.get(i));
+ }
+ smoothedAmplitude /= player.bufferSize();
+ smoothedAmplitude = lerp(smoothedAmplitude, 0, 0.1f);
+
+ flyover += map(smoothedAmplitude, 0, 1, 0.2f, 1);
+
+ camera.z = flyover;
+ camera.y = -100 + map(smoothedAmplitude, 0, 1, -10, 10);
+ target.x = sin(theta);
+ target.z = cos(theta);
+
+ translate(width / 2, height / 2, 0);
+ rotateX(PI / 3);
+ translate(-w / 2, -h / 2);
+
+ // Set up the lighting
+ ambientLight(100, 100, 100);
+ directionalLight(255, 255, 255, 1, 1, -1);
+
+ hint(DISABLE_DEPTH_TEST);
+ noFill();
+ stroke(255);
+
+ for (int x = 0; x < cols; x++) {
+ for (int y = 0; y < rows; y++) {
+ terrain[x][y] = map(noise(x * 0.1f, y * 0.1f, flyover * 0.01f), 0, 1, -100, 100) * smoothedAmplitude * 10;
+ }
+ }
+
+ for (int y = 0; y < rows - 1; y++) {
+ beginShape(TRIANGLE_STRIP);
+ for (int x = 0; x < cols; x++) {
+ float r = map(y, 0, rows, 50, 255);
+ float g = map(x, 0, cols, 50, 255);
+ float b = map(terrain[x][y], -50, 50, 100, 200);
+ stroke(r, g, b);
+ vertex(x * scl, y * scl, terrain[x][y]);
+ vertex(x * scl, (y + 1) * scl, terrain[x][y + 1]);
+ }
+ endShape();
+ }
+
+ theta += map(smoothedAmplitude, 0, 1, 0, 0.05f);
+ }
+
+ public static void main(String[] args) {
+ PApplet.main("ie.tudublin.MountainLandscape");
+ }
+}
diff --git a/java/src/ie/tudublin/MusicVisualizer.java b/java/src/ie/tudublin/MusicVisualizer.java
new file mode 100644
index 000000000..8e8481bbb
--- /dev/null
+++ b/java/src/ie/tudublin/MusicVisualizer.java
@@ -0,0 +1,175 @@
+package ie.tudublin;
+
+import ddf.minim.*; // Import Minim library for audio processing
+import ddf.minim.analysis.*;
+import processing.core.PApplet;
+import java.util.ArrayList;
+import processing.core.PVector;
+
+public class MusicVisualizer extends PApplet {
+ Minim minim; // Minim object for audio processing
+ AudioPlayer player; // AudioPlayer object for playing audio
+ BeatDetect beat; // BeatDetect object for beat detection
+ FFT fft; // FFT object for frequency analysis
+
+ float angle = 0; // Angle for rotation
+ float size = 50; // Size of design element
+ float posX, posY; // Position of design element
+ float speedX, speedY; // Speed of design element
+
+ ArrayList particles; // List to store particles
+
+ public void settings() {
+ size(800, 600); // Set the size of the window
+ }
+
+ public void setup() {
+ minim = new Minim(this); // Initialize the Minim object
+
+ posX = width / 2; // Set initial X position of design element
+ posY = height / 2; // Set initial Y position of design element
+ speedX = random(-2, 2); // Set initial X speed of design element
+ speedY = random(-2, 2); // Set initial Y speed of design element
+
+ player = minim.loadFile("java/data/Parasite.mp3"); // Load the audio file
+ player.play(); // Start playing the audio
+
+ beat = new BeatDetect(); // Initialize the BeatDetect object
+ fft = new FFT(player.bufferSize(), player.sampleRate()); // Initialize the FFT object
+
+ particles = new ArrayList(); // Initialize the list for particles
+ }
+
+ public void draw() {
+ background(0); // Set the background color
+
+ // Analyze the audio for beats
+ beat.detect(player.mix);
+
+ // If a beat is detected, change the visual effect
+ if (beat.isOnset()) {
+ changeVisualEffect();
+ }
+
+ // Update the position of the design element
+ posX += speedX;
+ posY += speedY;
+
+ // Check boundaries and change direction if necessary
+ if (posX < 0 || posX > width) {
+ speedX *= -1;
+ }
+ if (posY < 0 || posY > height) {
+ speedY *= -1;
+ }
+
+ // Create particles based on the beat
+ if (beat.isOnset()) {
+ for (int i = 0; i < 10; i++) {
+ Particle p = new Particle(posX, posY, speedX, speedY);
+ particles.add(p);
+ }
+ }
+
+ // Update and draw particles
+ for (int i = particles.size() - 1; i >= 0; i--) {
+ Particle p = particles.get(i);
+ p.update();
+ p.display();
+ if (p.isDead()) {
+ particles.remove(i);
+ }
+ }
+
+ // Draw the current visual effect
+ drawVisualEffect();
+
+ // Calculate the FFT to get frequency data
+ fft.forward(player.mix);
+
+ // Draw the spectrum visualization
+
+ }
+
+ void changeVisualEffect() {
+ // Modify the design element based on the beat
+ size = random(10, 100); // Randomize the size of the design element
+ speedX = random(-5, 5); // Randomize the horizontal speed of the design element
+ speedY = random(-5, 5); // Randomize the vertical speed of the design element
+ background(random(255), random(255), random(255)); // Randomize the background color
+ }
+
+ void drawVisualEffect() {
+ // Draw the design element in all four corners
+ for (int i = 0; i < 4; i++) {
+ float cornerX = i % 2 == 0 ? posX : width - posX;
+ float cornerY = i < 2 ? posY : height - posY;
+
+ pushMatrix();
+ translate(cornerX, cornerY);
+ rotate(angle);
+ rectMode(CENTER);
+ fill(random(255), random(255), random(255)); // Randomize the fill color of the design element
+ rect(0, 0, size, size);
+ popMatrix();
+
+ // Create particles based on the beat
+ if (beat.isOnset()) {
+ for (int j = 0; j < 10; j++) {
+ Particle p = new Particle(cornerX, cornerY, speedX, speedY);
+ particles.add(p);
+ }
+ }
+ }
+
+ // Rotate the design element gradually
+ angle += 0.05;
+ }
+
+
+ class Particle {
+ PVector position;
+ PVector velocity;
+ PVector acceleration;
+ float lifespan;
+ float size;
+ float hue;
+
+ Particle(float x, float y, float speedX, float speedY) {
+ position = new PVector(x, y);
+ velocity = new PVector(speedX, speedY).add(PVector.random2D().mult(random(1, 5))); // Randomize the initial velocity of particles
+ acceleration = new PVector(0, 0.05f); // Set the constant acceleration for particles
+ lifespan = 255;
+ size = random(4, 16); // Randomize the size of particles
+ hue = random(360); // Randomize the hue value of particles
+ }
+
+ void update() {
+ velocity.add(acceleration); // Update the velocity of particles
+ position.add(velocity); // Update the position of particles based on velocity
+ lifespan -= 2; // Decrease the lifespan of particles
+ }
+
+ void display() {
+ colorMode(HSB);
+ noStroke();
+ fill(hue, 255, 255, lifespan); // Set the fill color of particles with transparency based on lifespan
+ ellipse(position.x, position.y, size, size); // Draw particles as ellipses
+ }
+
+ boolean isDead() {
+ return lifespan <= 0; // Check if the lifespan of particles has reached zero
+ }
+ }
+
+ public void stop() {
+ player.close();
+ minim.stop();
+ super.stop();
+ }
+ public static void main(String[] args) {
+ PApplet.main("ie.tudublin.MusicVisualizer");
+}
+
+}
+
diff --git a/java/src/ie/tudublin/Visual.java b/java/src/ie/tudublin/Visual.java
index 927fe57b1..20fda465a 100644
--- a/java/src/ie/tudublin/Visual.java
+++ b/java/src/ie/tudublin/Visual.java
@@ -2,11 +2,11 @@
import processing.core.PApplet;
import ddf.minim.*;
-import ddf.minim.analysis.FFT;
+import ddf.minim.analysis.*;
public abstract class Visual extends PApplet
{
- private int frameSize = 512;
+ private int frameSize = 1024;
private int sampleRate = 44100;
private float[] bands;
@@ -14,12 +14,14 @@ public abstract class Visual extends PApplet
private Minim minim;
private AudioInput ai;
- private AudioPlayer ap;
+ public AudioSample as;
+ public AudioPlayer ap;
private AudioBuffer ab;
- private FFT fft;
+ public BeatDetect beat;
+ public FFT fft;
private float amplitude = 0;
- private float smothedAmplitude = 0;
+ public float smothedAmplitude = 0;
@@ -87,8 +89,8 @@ public void startListening()
public void loadAudio(String filename)
{
- ap = minim.loadFile(filename, frameSize);
- ab = ap.mix;
+ as = minim.loadSample(filename, frameSize);
+ ab = as.left;
}
public int getFrameSize() {
@@ -123,7 +125,6 @@ public AudioInput getAudioInput() {
return ai;
}
-
public AudioBuffer getAudioBuffer() {
return ab;
}
@@ -132,7 +133,7 @@ public float getAmplitude() {
return amplitude;
}
- public float getSmoothedAmplitude() {
+ public float getSmothedAmplitude() {
return smothedAmplitude;
}
@@ -143,4 +144,11 @@ public AudioPlayer getAudioPlayer() {
public FFT getFFT() {
return fft;
}
-}
+
+ public BeatDetect BeatDetect()
+ {
+ beat = new BeatDetect();
+ return beat;
+ }
+
+}
\ No newline at end of file
diff --git a/java/src/ie/tudublin/VisualException.java b/java/src/ie/tudublin/VisualException.java
deleted file mode 100644
index 65381bcb2..000000000
--- a/java/src/ie/tudublin/VisualException.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package ie.tudublin;
-
-public class VisualException extends Throwable
-{
- /**
- *
- */
- private static final long serialVersionUID = 1L;
-
- private String message;
-
- public VisualException(String message)
- {
- this.message = message;
- }
-
- public String toString()
- {
- return message;
- }
-}
\ No newline at end of file