voicegardens/vocoder/static/vocoder.js

231 lines
4.5 KiB
JavaScript
Raw Normal View History

2019-12-18 16:38:11 +01:00
"use strict";
2019-12-16 15:19:26 +01:00
//
2019-12-16 10:19:45 +01:00
// Vocoder front-end Javascript
2019-12-16 15:19:26 +01:00
//
// https://learnxinyminutes.com/docs/javascript/
// https://developer.mozilla.org/en-US/docs/web/javascript/reference
//
2019-12-16 10:19:45 +01:00
2019-12-21 08:39:03 +01:00
var archiveUrl = "http://localhost:5000/add-to-archive";
2019-12-18 17:52:58 +01:00
var canvasColour = "white";
2019-12-19 12:18:09 +01:00
var canvasHeight = 400;
var canvasWidth = 800;
2019-12-18 17:52:58 +01:00
var frameRate = 30;
var microphone;
var newSoundJustRecorded = false;
var playButton;
var recordButton;
var recorder;
var recording;
2019-12-18 13:45:00 +01:00
var recordingTimeout = 30000; // 30 seconds (in milliseconds)
var shapes = [];
var stopButton;
2019-12-18 16:26:56 +01:00
function record() {
/**
* Starting recording.
**/
if (microphone.enabled) {
setTimeout(recorder.record(recording), recordingTimeout);
}
}
2019-12-16 15:19:26 +01:00
2019-12-18 16:26:56 +01:00
function stop() {
/**
* Stop recording a new recording.
**/
if (recorder.recording) {
recorder.stop();
newSoundJustRecorded = true;
}
}
2019-12-16 15:19:26 +01:00
2019-12-18 16:26:56 +01:00
function play() {
/**
* Play the recording.
**/
if (recording.isLoaded()) {
recording.play();
}
}
2019-12-16 15:19:26 +01:00
2019-12-18 16:26:56 +01:00
function archive() {
/**
* Send the recording to the back-end.
**/
var soundBlob = recording.getBlob();
2019-12-16 15:19:26 +01:00
2019-12-21 08:39:03 +01:00
var formData = new FormData();
var date = new Date();
var filename = date.getTime().toString() + ".wav";
formData.append("file", soundBlob, filename);
2019-12-16 15:19:26 +01:00
2019-12-21 08:39:03 +01:00
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();
2019-12-16 15:19:26 +01:00
// TODO: buttons are just for experimenting ...
2019-12-18 13:45:00 +01:00
recordButton = createButton("record");
recordButton.position(10, 90);
2019-12-18 16:26:56 +01:00
recordButton.mousePressed(record);
2019-12-16 15:19:26 +01:00
2019-12-18 13:45:00 +01:00
stopButton = createButton("stop");
stopButton.position(120, 90);
2019-12-18 16:26:56 +01:00
stopButton.mousePressed(stop);
2019-12-16 15:19:26 +01:00
2019-12-18 13:45:00 +01:00
playButton = createButton("play");
playButton.position(210, 90);
2019-12-18 16:26:56 +01:00
playButton.mousePressed(play);
2019-12-16 15:19:26 +01:00
2019-12-18 13:45:00 +01:00
playButton = createButton("archive");
playButton.position(300, 90);
2019-12-18 16:26:56 +01:00
playButton.mousePressed(archive);
2019-12-16 15:19:26 +01:00
}
function getSoundInfo() {
/**
* Retrieve sound information like pitch, amplitude, duration, etc.
**/
amplitude = recording.getPeaks();
duration = recording.duration();
// pitch?
// nuance?
}
2019-12-18 16:27:03 +01:00
class GeneratedShape {
2019-12-18 16:38:33 +01:00
constructor() {
/**
* Initialise the new shape.
**/
2019-12-19 12:18:09 +01:00
this.w = 20;
this.h = 20;
2019-12-18 17:52:58 +01:00
this.x = random(width);
this.y = random(height);
2019-12-19 12:18:09 +01:00
this.xSpeed = 1.8;
this.ySpeed = 1.8;
2019-12-18 17:52:58 +01:00
this.xDirection = 1;
this.yDirection = 1;
2019-12-19 12:55:32 +01:00
this.synth = new p5.MonoSynth();
}
2019-12-19 12:18:09 +01:00
collide(shapes) {
/**
* Detect if the shape collides with another shape.
**/
2019-12-19 12:18:09 +01:00
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.
**/
2019-12-19 12:55:32 +01:00
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);
2019-12-18 16:38:33 +01:00
}
2019-12-18 16:27:03 +01:00
move() {
/**
2019-12-18 17:52:58 +01:00
* Move the shape around the canvas.
2019-12-18 16:27:03 +01:00
**/
2019-12-18 17:52:58 +01:00
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;
}
2019-12-18 16:27:03 +01:00
}
display() {
/**
* Show the shape on the canvas.
**/
// TODO: use getSoundInfo function to influence how shape is drawn
2019-12-18 17:52:58 +01:00
ellipse(this.x, this.y, this.w, this.h); // TODO: experimenting for now ...
2019-12-18 16:27:03 +01:00
}
}
2019-12-18 13:45:00 +01:00
function setup() {
/**
* The p5.js initial setup function.
**/
createCanvas(canvasWidth, canvasHeight); // TODO: experimenting for now ...
2019-12-18 13:45:00 +01:00
setupRecording();
2019-12-18 17:52:58 +01:00
frameRate(frameRate);
2019-12-16 10:19:45 +01:00
}
2019-12-18 13:45:00 +01:00
function draw() {
/**
* The p5.js draw loop.
**/
2019-12-18 17:52:58 +01:00
background(canvasColour);
if (newSoundJustRecorded === true) {
2019-12-18 16:47:55 +01:00
shapes.push(new GeneratedShape());
newSoundJustRecorded = false;
}
2019-12-19 12:18:09 +01:00
for (var shape of shapes) {
2019-12-18 17:52:58 +01:00
shape.move();
2019-12-19 12:18:09 +01:00
shape.display();
2019-12-19 12:18:09 +01:00
if (shape.collide(shapes) === true) {
shape.sound();
}
}
2019-12-18 07:06:32 +01:00
}