"use strict"; // // Voicegardens front-end Javascript // var archiveUrl = window.location + "add-to-archive"; var canvas; var microphone; var frameRate = 60; var mouseInitialDrag = false; var newSoundJustRecorded = false; var playButton; var recordButton; var recorder; var recording; var recordingTimeout = 30000; // 30 seconds (in milliseconds) var screenX; var screenY; var shapes = []; var stopButton; var color; var centerX; var centerY; var numberOfEdges; var radius; var angle; function record() { /** * Starting recording. **/ if (microphone.enabled) { setTimeout(recorder.record(recording), recordingTimeout); } } function stop() { /** * Stop recording a new recording. **/ if (recorder.recording) { recorder.stop(); newSoundJustRecorded = true; } } function play() { /** * Play the recording. **/ if (recording.isLoaded()) { recording.play(); } } function archive() { /** * Send the recording to the back-end. **/ var soundBlob = recording.getBlob(); var formData = new FormData(); var date = new Date(); var filename = date.getTime().toString() + ".wav"; formData.append("file", soundBlob, filename); var config = new Headers({ "Content-Type": "multipart/form-data" }); axios.post(archiveUrl, formData, config).catch(function(error) { console.log( "Upload failed!", "Received the following message:", error.response.data ); }); } function showArchive() { window.location.href = "/archive"; } function setupRecording() { /** * Setup logic for recording. **/ microphone = new p5.AudioIn(); microphone.start(); recorder = new p5.SoundRecorder(); recorder.setInput(microphone); recording = new p5.SoundFile(); recordButton = createButton("record"); recordButton.position(10, 5); recordButton.mousePressed(record); stopButton = createButton("stop"); stopButton.position(10, 40); stopButton.mousePressed(stop); playButton = createButton("play"); playButton.position(10, 75); playButton.mousePressed(play); playButton = createButton("archive"); playButton.position(10, 110); playButton.mousePressed(archive); playButton = createButton("view archive"); playButton.position(10, 145); playButton.mousePressed(showArchive); } function getSoundInfo() { /** * Retrieve sound information like pitch, amplitude, duration, etc. **/ amplitude = recording.getPeaks(); duration = recording.duration(); // pitch (frequency?) I think we can use fft.analyze() and then find the // highest value (0 -> 1024) that has a non-zero value this gives us the // highest frequency from the recording // https://p5js.org/reference/#/p5.FFT // https://p5js.org/reference/#/p5.FFT/analyze // nuance? // "I meant the amount of variation in the voice - i.e is it one single // monotone note or does it go up and down octaves or start soft and high and // become deep and guttural etc." // // How do to do this? Unsure ... } class GeneratedShape { constructor() { /** * Initialise the new shape. **/ this.xSpeed = 1.4; this.ySpeed = 1.6; this.xDirection = 1; this.yDirection = 1; this.synth = new p5.MonoSynth(); this.points = []; this.calculatePoints(); } collide(shapes) { /** * Detect if the shape collides with another shape. **/ if (shapes.length === 1) { return false; } for (var shape of shapes) { if (this === shape) { continue; } var collision = collideCircleCircle( this.x, this.y, this.w, shape.x, shape.y, shape.w ); if (collision === true) { return true; } } return false; } sound() { /** * Play a sound after a collision is detected. **/ var notes = ["G2", "C3", "G3"]; var duration = 0.8; var time = 0; var velocity = 0.5; var index = random(0, notes.length + 1); this.synth.play(notes[index], velocity, time, duration); } move() { /** * Move the shape around the canvas. **/ // this.x = this.x + this.xSpeed * this.xDirection; // this.y = this.y + this.ySpeed * this.yDirection; // if (this.x > width - this.w || this.x < this.w) { // this.xDirection *= -1; // } // if (this.y > height - this.h || this.y < this.h) { // this.yDirection *= -1; // } // TODO: make the polygon move ... // for each vector in this.points, add/subtract/etc. for (var i = 0; i < this.points.length; i++) { this.points[i].x = this.points[i].x + this.xSpeed * this.xDirection; this.points[i].y = this.points[i].y + this.ySpeed * this.yDirection; if (this.points[i].x > width || this.points[i].x <= 0) { this.xDirection *= -1; console.log('this is the max width: ', width); } if (this.points[i].y > height || this.points[i].y <= 0) { this.yDirection *= -1; console.log('this is the max height: ', height); } } } display() { /** * Show the shape on the canvas. **/ // TODO: use getSoundInfo function to influence how shape is drawn this.createShape(); } calculatePoints() { /* Calculate the points of the shape */ for (var i = 0; i < numberOfEdges; i++) { var pointX = cos(angle * i) * radius + random(-77, 77); var pointY = sin(angle * i) * radius + random(-77, 77); var vector = createVector(pointX, pointY); this.points.push(vector); } } /*function for drawing the shape on the screen*/ createShape() { beginShape(); var lastItem = this.points.length - 1; curveVertex(this.points[lastItem].x, this.points[lastItem].y); for (var i = 0; i < this.points.length; i++){ curveVertex(this.points[i].x, this.points[i].y); } var firstItem = 0 curveVertex(this.points[firstItem].x, this.points[firstItem].y); endShape(CLOSE); } } function setup() { /** * The p5.js initial setup function. **/ createCanvas(windowWidth, windowHeight); smooth(); setupRecording(); frameRate(frameRate); fill("#F38630"); //center of the window centerX = windowWidth/2; centerY = windowHeight/2; //defining all variables numberOfEdges = 4; angle = radians(360 / numberOfEdges); radius = random(120, 140); } function draw() { /** * The p5.js draw loop. **/ background("#69D2E7"); translate(centerX, centerX); if (newSoundJustRecorded === true) { shapes.push(new GeneratedShape()); newSoundJustRecorded = false; } for (var shape of shapes) { shape.move(); shape.display(); if (shape.collide(shapes) === true) { shape.sound(); } } }