"use strict"; // // Vocoder front-end Javascript // // https://learnxinyminutes.com/docs/javascript/ // https://developer.mozilla.org/en-US/docs/web/javascript/reference // var archiveUrl = "http://localhost:5000/add-to-archive"; var canvasColour = "white"; var canvasHeight = 400; var canvasWidth = 800; var frameRate = 30; var microphone; var newSoundJustRecorded = false; var playButton; var recordButton; var recorder; var recording; var recordingTimeout = 30000; // 30 seconds (in milliseconds) var shapes = []; var stopButton; 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 setupRecording() { /** * Setup logic for recording. **/ microphone = new p5.AudioIn(); microphone.start(); recorder = new p5.SoundRecorder(); recorder.setInput(microphone); recording = new p5.SoundFile(); // TODO: buttons are just for experimenting ... recordButton = createButton("record"); recordButton.position(10, 90); recordButton.mousePressed(record); stopButton = createButton("stop"); stopButton.position(120, 90); stopButton.mousePressed(stop); playButton = createButton("play"); playButton.position(210, 90); playButton.mousePressed(play); playButton = createButton("archive"); playButton.position(300, 90); playButton.mousePressed(archive); } function getSoundInfo() { /** * Retrieve sound information like pitch, amplitude, duration, etc. **/ amplitude = recording.getPeaks(); duration = recording.duration(); // pitch? // nuance? } class GeneratedShape { constructor() { /** * Initialise the new shape. **/ this.w = 20; this.h = 20; this.x = random(width); this.y = random(height); this.xSpeed = 1.8; this.ySpeed = 1.8; this.xDirection = 1; this.yDirection = 1; this.synth = new p5.MonoSynth(); } 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; } } display() { /** * Show the shape on the canvas. **/ // TODO: use getSoundInfo function to influence how shape is drawn ellipse(this.x, this.y, this.w, this.h); // TODO: experimenting for now ... } } function setup() { /** * The p5.js initial setup function. **/ createCanvas(canvasWidth, canvasHeight); // TODO: experimenting for now ... setupRecording(); frameRate(frameRate); } function draw() { /** * The p5.js draw loop. **/ background(canvasColour); 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(); } } }