An online landscape, built as a tool to explore the many aspects of the human voice.
https://voicegardens.org
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
160 lines
3.2 KiB
160 lines
3.2 KiB
"use strict";
|
|
|
|
//
|
|
// Vocoder front-end Javascript
|
|
//
|
|
// https://learnxinyminutes.com/docs/javascript/
|
|
// https://developer.mozilla.org/en-US/docs/web/javascript/reference
|
|
//
|
|
|
|
var archiveUrl = serverUrl + "/add-to-archive/";
|
|
var canvasHeight = 500;
|
|
var canvasWidth = 500;
|
|
var microphone;
|
|
var newSoundJustRecorded = false;
|
|
var playButton;
|
|
var recordButton;
|
|
var recorder;
|
|
var recording;
|
|
var recordingTimeout = 30000; // 30 seconds (in milliseconds)
|
|
var serverUrl = "http://localhost:5000"; // TODO: read from environment
|
|
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 httpRequestOptions = {
|
|
method: "POST",
|
|
body: new FormData().append("soundBlob", soundBlob),
|
|
headers: new Headers({ enctype: "multipart/form-data" })
|
|
};
|
|
|
|
httpDo(archiveUrl, httpRequestOptions); // TODO: add error handling and fix
|
|
}
|
|
|
|
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.displayed = false;
|
|
}
|
|
|
|
move() {
|
|
/**
|
|
* Move the shape in some direction.
|
|
**/
|
|
}
|
|
|
|
display() {
|
|
/**
|
|
* Show the shape on the canvas.
|
|
**/
|
|
ellipse(random(canvasWidth), random(canvasHeight), 10, 10); // TODO: experimenting for now ...
|
|
this.displayed = true;
|
|
}
|
|
}
|
|
|
|
function generateNewShape() {
|
|
/**
|
|
* Create a new p5.js shape.
|
|
**/
|
|
return new GeneratedShape();
|
|
}
|
|
|
|
function setup() {
|
|
/**
|
|
* The p5.js initial setup function.
|
|
**/
|
|
createCanvas(canvasWidth, canvasHeight); // TODO: experimenting for now ...
|
|
setupRecording();
|
|
}
|
|
|
|
function draw() {
|
|
/**
|
|
* The p5.js draw loop.
|
|
**/
|
|
if (newSoundJustRecorded === true) {
|
|
shapes.push(generateNewShape());
|
|
newSoundJustRecorded = false;
|
|
}
|
|
|
|
for (var i = 0; i < shapes.length; i++) {
|
|
var shape = shapes[i];
|
|
if (!shape.displayed) {
|
|
shape.display();
|
|
}
|
|
}
|
|
}
|
|
|