|
@@ -0,0 +1,139 @@
|
|
|
+// detto - cesco@ventuordici.org - 2020
|
|
|
+
|
|
|
+/* THE CHINOTTO-WARE LICENSE" (Revision 42):
|
|
|
+ * cesco@ventuordici.org wrote this code.
|
|
|
+ * As long as you retain this notice you can do whatever you want with this stuff.
|
|
|
+ * I reserve the right to do the absolute minimum provided by law, up to and including absolutely nothing.
|
|
|
+ * If we meet some day, and you think this stuff is worth it, you can buy me a chinotto in return.
|
|
|
+ */
|
|
|
+
|
|
|
+var audioCtx;
|
|
|
+const canvas = document.querySelector('.visualizer');
|
|
|
+canvasCtx = canvas.getContext("2d");
|
|
|
+
|
|
|
+document.addEventListener('DOMContentLoaded', function() {
|
|
|
+ if(window.location.hash) {
|
|
|
+ document.getElementById('visualizer').style.display = 'none';
|
|
|
+ document.getElementById('record_audio').style.display = 'none';
|
|
|
+ document.getElementById('url').style.display = 'none';
|
|
|
+ document.getElementById('stop_record').style.display = 'none';
|
|
|
+
|
|
|
+ var downloadbutton = document.getElementById('download');
|
|
|
+ if (downloadbutton) { downloadbutton.addEventListener('click', content_download, false); }
|
|
|
+ } else {
|
|
|
+ document.getElementById('player').style.display = 'none';
|
|
|
+ document.getElementById('download').style.display = 'none';
|
|
|
+ var recordbutton = document.getElementById('record_audio');
|
|
|
+ if (recordbutton) {
|
|
|
+ recordbutton.addEventListener('click', processa_audio, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ var stopbutton = document.getElementById('stop_record');
|
|
|
+ if (stopbutton) { stopbutton.addEventListener('click', stop_recorder, false); }
|
|
|
+ }
|
|
|
+}, false);
|
|
|
+
|
|
|
+function processa_audio(){
|
|
|
+ filename = "";
|
|
|
+ fileext = ".webm";
|
|
|
+ var constraints = { audio: true };
|
|
|
+ var options = {
|
|
|
+ audioBitsPerSecond : 64000,
|
|
|
+ mimeType : 'audio/webm;codecs=opus'
|
|
|
+ }
|
|
|
+ audioCtx = new AudioContext();
|
|
|
+
|
|
|
+ navigator.mediaDevices.getUserMedia(constraints).then(stream => {
|
|
|
+ document.getElementById("record_audio").disabled = true;
|
|
|
+ window.localStream = stream;
|
|
|
+ const recorder = new MediaRecorder(stream, options);
|
|
|
+ window.localRecorder = recorder;
|
|
|
+ console.log("creato recorder " + recorder );
|
|
|
+ visualize(stream);
|
|
|
+ const chunks = [];
|
|
|
+
|
|
|
+ recorder.ondataavailable = function(e) {
|
|
|
+ // console.log("aggiungo chunk");
|
|
|
+ chunks.push(e.data);
|
|
|
+ }
|
|
|
+
|
|
|
+ recorder.onstop = function(e) {
|
|
|
+ console.log("stoppato recorder");
|
|
|
+ const blob = new Blob(chunks, { type: 'audio/webm' });
|
|
|
+ var reader = new FileReader();
|
|
|
+ reader.onload = function(event) {
|
|
|
+ console.log("reader loaded");
|
|
|
+ var content = event.target.result;
|
|
|
+ critta(content);
|
|
|
+ document.getElementById("record_audio").disabled = false;
|
|
|
+ }
|
|
|
+ reader.readAsArrayBuffer(blob);
|
|
|
+ }
|
|
|
+ recorder.start(1000);
|
|
|
+
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function stop_recorder(stream){
|
|
|
+ console.log("stopping");
|
|
|
+ localRecorder.stop();
|
|
|
+ localStream.getAudioTracks()[0].stop();
|
|
|
+ localStream.getTracks().forEach(track => track.stop());
|
|
|
+}
|
|
|
+
|
|
|
+function visualize(stream) {
|
|
|
+ console.log("start visualize");
|
|
|
+
|
|
|
+ if(!audioCtx) {
|
|
|
+ audioCtx = new AudioContext();
|
|
|
+ console.log("creating audioctx" + audioCtx);
|
|
|
+ }
|
|
|
+
|
|
|
+ const source = audioCtx.createMediaStreamSource(stream);
|
|
|
+
|
|
|
+ const analyser = audioCtx.createAnalyser();
|
|
|
+ console.log("created analyser" + analyser);
|
|
|
+
|
|
|
+ analyser.fftSize = 2048;
|
|
|
+ const bufferLength = analyser.frequencyBinCount;
|
|
|
+ const dataArray = new Uint8Array(bufferLength);
|
|
|
+
|
|
|
+ source.connect(analyser);
|
|
|
+ draw()
|
|
|
+
|
|
|
+ function draw() {
|
|
|
+ // console.log("start draw");
|
|
|
+ WIDTH = canvas.width
|
|
|
+ HEIGHT = canvas.height;
|
|
|
+
|
|
|
+ requestAnimationFrame(draw);
|
|
|
+ analyser.getByteTimeDomainData(dataArray);
|
|
|
+
|
|
|
+ canvasCtx.fillStyle = 'rgb(255, 255, 255)';
|
|
|
+ canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);
|
|
|
+ canvasCtx.lineWidth = 2;
|
|
|
+ canvasCtx.strokeStyle = 'rgb(150, 0, 0)';
|
|
|
+
|
|
|
+ canvasCtx.beginPath();
|
|
|
+
|
|
|
+ let sliceWidth = WIDTH * 1.0 / bufferLength;
|
|
|
+ let x = 0;
|
|
|
+
|
|
|
+
|
|
|
+ for(let i = 0; i < bufferLength; i++) {
|
|
|
+
|
|
|
+ let v = dataArray[i] / 128.0;
|
|
|
+ let y = v * HEIGHT/2;
|
|
|
+
|
|
|
+ if(i === 0) {
|
|
|
+ canvasCtx.moveTo(x, y);
|
|
|
+ } else {
|
|
|
+ canvasCtx.lineTo(x, y);
|
|
|
+ }
|
|
|
+ x += sliceWidth;
|
|
|
+ }
|
|
|
+
|
|
|
+ canvasCtx.lineTo(canvas.width, canvas.height/2);
|
|
|
+ canvasCtx.stroke();
|
|
|
+ }
|
|
|
+}
|