Trying to get decibel levels from an audio file through javascript - javascript

I've been looking at the information here:
Is there a way get something like decibel levels from an audio file and transform that information into a json array?
But when I try to run the JSBin here:
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Get Audio Data</title>
<link rel="stylesheet" type="text/css" href="index.css">
<script type="text/javascript" src="music.js"></script>
</head>
<body>
<div id=meter></div>
</body>
</html>
#meter {
width: 500px;
height: 15px;
margin: 2px 0;
background: green;
-webkit-transition;
width .05s;
}
function() {
var ctx = new webkitAudioContext(),
url = 'test.mp3',
audio = new Audio(url),
processor = ctx.createJavaScriptNode(2048, 1, 1),
meter = document.getElementById('meter'),
source;
audio.addEventListener('canplaythrough', function() {
source = ctx.createMediaElementSource(audio);
source.connect(processor);
source.connect(ctx.destination);
processor.connect(ctx.destination);
audio.play();
}, false);
processor.onaudioprocess = function(evt) {
var input = evt.inputBuffer.getChannelData(0),
len = input.length,
total = i = 0,
rms;
while(i<len)
total += Math.abs(input[i++]);
rms = Math.sqrt(total/len);
meter.style.width = (rms*100) + '%';
};
};
I'm not really sure what it's doing. Can anyone give me more info?

Your code does generate RMS output once you replace defunct API calls
old webkitAudioContext
new
try {
window.AudioContext = window.AudioContext ||
window.webkitAudioContext ||
window.mozAudioContext ||
window.oAudioContext ||
window.msAudioContext;
ctx = new AudioContext();
console.log("cool audio context established ... ctx ");
} catch (e) {
alert("Web Audio API is not supported by this browser\n ... http://caniuse.com/#feat=audio-api");
}
and
old createJavaScriptNode
new createScriptProcessor

Related

cv.undistort "Assertion failed" error in Javascript

I am trying to undistort an image with opencv.js before scanning aruco markers with my camera.
Scanning the codes is not a problem but when i try to undistort the image first with cv.undistort i run into an Assertion failed error which looks something like this.
Minimal working example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script id="cv" async src="opencv.js"></script>
</head>
<body>
<canvas id="canvasOutput" width="640" height="480"></canvas>
</body>
<script>
document.getElementById('cv').addEventListener('load', async () => {
if (cv.getBuildInformation) {
console.log(cv.getBuildInformation());
onloadCallback();
}
else {
// WASM
if (cv instanceof Promise) {
cv = await cv;
console.log(cv.getBuildInformation());
onloadCallback();
} else {
cv['onRuntimeInitialized'] = () => {
console.log(cv.getBuildInformation());
onloadCallback();
}
}
}
});
function onloadCallback() {
var canvas = document.getElementById('canvasOutput')
var ctx = canvas.getContext("2d", { willReadFrequently: true });
var video_element = document.createElement("video")
video_element.id = "video-stream"
navigator.mediaDevices.getUserMedia({
video: {}}).then(function (stream) {
video_element.srcObject = stream;
video_element.play();
video_element.addEventListener('canplay', function () {
requestAnimationFrame(() => {processImage()});
}, false);
});
function processImage() {
if (video_element.readyState === video_element.HAVE_ENOUGH_DATA) {
ctx.drawImage(video_element, 0, 0, canvas.width,canvas.height);
var inputImage = cv.imread("canvasOutput");
var cameraMatrix = cv.matFromArray(3, 3, cv.CV_64F, [740.50225182, 0, 369.29446792, 0, 740.73074392, 252.55216544, 0, 0, 1]);
var newCameraMatrix = cv.matFromArray(3, 3, cv.CV_64F, [719.72668457, 0, 374.17970017, 0, 711.57000732, 251.96928564, 0, 0, 1]);
var distCoeffs = cv.matFromArray(1, 5, cv.CV_64F, [0.0798354, -0.55563903, -0.00168822, 0.00225224, 0.28264803]);
cv.cvtColor(inputImage, inputImage, cv.COLOR_RGBA2RGB, 0);
var markerIds = new cv.Mat();
var markerCorners = new cv.MatVector();
var rvecs = new cv.Mat();
var tvecs = new cv.Mat();
var dictionary = new cv.Dictionary(cv.DICT_6X6_1000);
cv.undistort(inputImage,cameraMatrix,distCoeffs,newCameraMatrix);
cv.detectMarkers(inputImage,dictionary, markerCorners, markerIds);
if (markerIds.rows > 0) {
cv.drawDetectedMarkers(inputImage,markerCorners,markerIds);
cv.estimatePoseSingleMarkers(markerCorners, 0.1, cameraMatrix,distCoeffs,rvecs,tvecs);
for (let i = 0; i < markerIds.rows; ++i) {
rvec = cv.matFromArray(3, 1, cv.CV_64F, [rvecs.doublePtr(0, i)[0],rvecs.doublePtr(0, i)[1],rvecs.doublePtr(0, i)[2]]);
tvec = cv.matFromArray(3, 1, cv.CV_64F, [tvecs.doublePtr(0, i)[0],tvecs.doublePtr(0, i)[1],tvecs.doublePtr(0, i)[2]]);
cv.drawAxis(inputImage,cameraMatrix,distCoeffs,rvec, tvec, 0.1);
rvec.delete();
tvec.delete();
}
}
cv.imshow("canvasOutput",inputImage);
inputImage.delete();
dictionary.delete();
markerIds.delete();
markerCorners.delete();
rvecs.delete();
tvecs.delete();
cameraMatrix.delete();
newCameraMatrix.delete();
distCoeffs.delete();
}
requestAnimationFrame(() => {processImage()});
}
}
</script>
</html>
where the opencv.js file in the head can be any OpenCV js version (example https://docs.opencv.org/3.4.0/opencv.js)
I have no idea what this means and i'm not sure how to make it work.
I think I defined the size of the camera matrix correctly as well as the sizes of all other parameters but I just keep getting the same error.
When I try to do this in python everything works fine. I can't seem to figure out what I'm doing wrong when I try to replicate this in javascript.
The problem was that the cv.undistort method didn't have proper parameters passed to it, more specificaly it was called with 4 parameters instead of 5 and it didn't have the output parameter defined:
cv.undistort(inputImage,cameraMatrix,distCoeffs,newCameraMatrix);
should be
var output = new cv.Mat();
cv.undistort(inputImage, output,cameraMatrix, distCoeffs, newCameraMatrix );

I want to convert paper.js Examples from paperscript to javascript

I am Japanese and I apologize for my unnatural English, but I would appreciate it if you could read it.
I learned how to convert paperscript to javascript from the official documentation.
Its means are as follows
Change the type attribute of the script tag to text/paperscript. <script type="text/paperscript" src="./main.js"></script>
Enable Paperscope for global use.  paper.install(window)
Specify the target of the canvas. paper.setup(document.getElementById("myCanvas"))
Write the main code in the onload window.onload = function(){ /* add main code */ }
Finally, add paper.view.draw()
The onFrame and onResize transforms as follows. view.onFrame = function(event) {}
onMouseDown, onMouseUp, onMouseDrag, onMouseMove, etc. are converted as follows. var customTool = new Tool(); customTool.onMouseDown = function(event) {};
I have tried these methods, but applying these to the Examples on the paper.js official site does not work correctly.
The following code is the result of trying these.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="https://unpkg.com/paper"></script>
<script type="text/javascript" src="./main.js"></script>
<title>Document</title>
</head>
<body>
<canvas id="myCanvas"></canvas>
</body>
</html>
paper.install(window);
console.log("run test")
var myCanvas = document.getElementById("myCanvas")
var customTool = new Tool();
window.onload = function(){
paper.setup(myCanvas)
var points = 25;
// The distance between the points:
var length = 35;
var path = new Path({
strokeColor: '#E4141B',
strokeWidth: 20,
strokeCap: 'round'
});
var start = view.center / [10, 1];
for (var i = 0; i < points; i++)
path.add(start + new Point(i * length, 0));
customTool.onMouseMove=function(event) {
path.firstSegment.point = event.point;
for (var i = 0; i < points - 1; i++) {
var segment = path.segments[i];
var nextSegment = segment.next;
var vector = segment.point - nextSegment.point;
vector.length = length;
nextSegment.point = segment.point - vector;
}
path.smooth({ type: 'continuous' });
}
customTool.onMouseDown=function(event) {
path.fullySelected = true;
path.strokeColor = '#e08285';
}
customTool.onMouseUp=function(event) {
path.fullySelected = false;
path.strokeColor = '#e4141b';
}
view.draw();
}
The original paperscript can be found here.
What is the problem with this code?
Thank you for reading to the end!
The var vector in the for loop is not getting the correct values in your code. Change the math operators and it will work like the paperjs demo.
Math operators (+ - * /) for vector only works in paperscript. In Javascript, use .add() .subtract() .multiply() .divide(). see http://paperjs.org/reference/point/#subtract-point
// paperscript
segment.point - nextSegment.point
// javascript
segment.point.subtract(nextSegment.point)
Here's a working demo of your example
paper.install(window);
console.log("run test")
var myCanvas = document.getElementById("myCanvas")
var customTool = new Tool();
window.onload = function() {
paper.setup(myCanvas)
var points = 15; //25
// The distance between the points:
var length = 20; //35
var path = new Path({
strokeColor: '#E4141B',
strokeWidth: 20,
strokeCap: 'round'
});
var start = view.center / [10, 1];
for (var i = 0; i < points; i++) {
path.add(start + new Point(i * length, 0));
}
customTool.onMouseMove = function(event) {
path.firstSegment.point = event.point;
for (var i = 0; i < points - 1; i++) {
var segment = path.segments[i];
var nextSegment = segment.next;
//var vector = segment.point - nextSegment.point;
var vector = segment.point.subtract(nextSegment.point);
vector.length = length;
//nextSegment.point = segment.point - vector;
nextSegment.point = segment.point.subtract(vector);
}
path.smooth({
type: 'continuous'
});
}
customTool.onMouseDown = function(event) {
path.fullySelected = true;
path.strokeColor = '#e08285';
}
customTool.onMouseUp = function(event) {
path.fullySelected = false;
path.strokeColor = '#e4141b';
}
view.draw();
}
html,
body {
margin: 0
}
canvas {
border: 1px solid red;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="https://unpkg.com/paper"></script>
<!-- you can add this back in -->
<!-- <script type="text/javascript" src="./main.js"></script> -->
<title>Document</title>
</head>
<body>
<!-- set any size you want, or use CSS/JS to make this resizable -->
<canvas id="myCanvas" width="600" height="150"></canvas>
</body>
</html>

iOS 15: Web Audio playback stops working in Safari after locking screen for a few minutes

This seems to be an issue after I upgraded my iPod Touch to iOS 15 (15.0.1).
When running the example below, it works fine on the first load, playing the sound as many times as I want. However, if I lock the screen on my iPod Touch, then return after a couple minutes, the sound no longer plays. To troubleshoot I set up a state change listener on the AudioContext instance and verified that Safari sets the state back to running after it was set to interrupted when the screen was locked. Yet, the sound does not play.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>audio-test</title>
</head>
<body>
<script>
const AudioContext = window.AudioContext || window.webkitAudioContext;
const audioContext = new AudioContext();
// Create AudioBuffer and fill with two seconds of white noise.
const channels = 2;
const frameCount = audioContext.sampleRate * 2.0;
const audioBuffer = audioContext.createBuffer(channels, frameCount, audioContext.sampleRate);
for (var channel = 0; channel < channels; channel++) {
var nowBuffering = audioBuffer.getChannelData(channel);
for (var i = 0; i < frameCount; i++) {
nowBuffering[i] = Math.random() * 2 - 1;
}
}
const button = document.createElement('button');
button.textContent = 'Play Audio';
document.body.append(button);
button.addEventListener('click', () => {
const currentSourceNode = new AudioBufferSourceNode(audioContext, {
buffer: audioBuffer,
});
currentSourceNode.connect(audioContext.destination);
currentSourceNode.start();
});
</script>
</body>
</html>
Strangely, if I add an audio element to the HTML that points to some mp3 file, which isn't even referenced in the code at all, then locking the screen for a while then returning to the page no longer affects the audio playback.
Updated code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>audio-test</title>
</head>
<body>
<script>
const AudioContext = window.AudioContext || window.webkitAudioContext;
const audioContext = new AudioContext();
// Create AudioBuffer and fill with two seconds of white noise.
const channels = 2;
const frameCount = audioContext.sampleRate * 2.0;
const audioBuffer = audioContext.createBuffer(channels, frameCount, audioContext.sampleRate);
for (var channel = 0; channel < channels; channel++) {
var nowBuffering = audioBuffer.getChannelData(channel);
for (var i = 0; i < frameCount; i++) {
nowBuffering[i] = Math.random() * 2 - 1;
}
}
const button = document.createElement('button');
button.textContent = 'Play Audio';
document.body.append(button);
button.addEventListener('click', () => {
const currentSourceNode = new AudioBufferSourceNode(audioContext, {
buffer: audioBuffer,
});
currentSourceNode.connect(audioContext.destination);
currentSourceNode.start();
});
</script>
<audio src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/858/outfoxing.mp3" crossorigin="anonymous"></audio>
</body>
</html>
Screen lock does not allow scripts to run on IOS.
My workaround is to run 2 audio player elements.
One audioElementWithSound and, another with an empty-10s.mp3 file.
Clicking play starts both elements.
I then have an event listner listening to 'ended' on the empty.mp3, re-starting the empty.mp3 if the withSound is not done playing yet.
It would look something like this :
let audioElement();
let stayAwakeAudio();
function playSound(){
audioElement.src = "/assets/audioClip.mp3"
audioElement.play;
stayAwake()
}
function stayAwake() {
console.log("I'm awake");
stayAwakeAudio.src = "/assets/empty10sSoundFile.mp3";
stayAwakeAudio.play();
}
stayAwakeAudio.addEventListener('ended', function () {
if (audioElement.play) {
console.log('Audio still playing')
stayAwake();
}
else {
console.log('No audio playing, letting screen time out');
}
}, false);

I can't see progress in the browsr when trying to make a game

Hi I'm trying to learn game dev with javascript .... When I ope my html file in my browser, it's blank and this is the error I keep on getting...
createjs-2013.12.12.min.js:13 Uncaught TypeError: f.isVisible is not a functionb.draw
# createjs-2013.12.12.min.js:13b.update
# createjs-2013.12.12.min.js:13window.onload # init.js:25 "
var canvas;
var stage ;
var img = new Image();
var bmpSeq;
var text;
window.onload = function()
{
canvas = document.getElementById("myCanvas");
context = canvas.getContext('2d');
context.canvas.width = 900;
context.canvas.height = 500;
stage = new createjs.Stage(canvas);
text = new Text("TEXT HERE","36px Ariel","black");
text.x =100;
text.y = 200;
stage.addChild(text);
var circle = new createjs.Shape();
circle.graphics.beginFill("red").drawCircle(0, 0, 50);
circle.x = 100;
circle.y = 100;
stage.addChild(circle);
stage.update();
//img.onload = ImageLoaded;
//img.src = "assets/dude.png" ;
}
function ImageLoaded(e)
{
//stage = new createjs.Stage("canvas");
var ss = new createjs.SpriteSheet({
images : [img],
frames : {width:32,height:64},
animations: {
face : 4,
walk : [4,8] }
});
//bitmap sequence
//bmp = new createjs.BitmapAnimation(ss);
//bmp.regX = bmp.spriteSheet.frameWidth/2|0; //reg pt in the center of the frame
// bmp.regY = bmp.spriteSheet.frameHeight/2|0;
//bmp.gotoAndPlay("w_r");
//bmp.x = canvas.width/2;
//bmp.y = canvas.height/2;
stage.addChild(ss); //won't do anything yet
//stage.update();
}
<!DOCTYPE html>
<html>
<head>
<title>GAme Trial</title>
<link href="normalize.css" type="text/css" rel="stylesheet" />
<script language="javascript" type="text/javascript" src="http://code.createjs.com/createjs-2013.12.12.min.js" ></script> <!--Getting the Library-->
<script language="javascript" type="text/javascript" src="init.js" ></script>
</head>
<body>
<canvas id="myCanvas"></canvas> <!--graphical surface in which the game is played-->
</body>
</html>
You created a new Text() object, instead of the createjs.Text() object.
Change this
text = new Text("TEXT HERE","36px Ariel","black");
to this
text = new createjs.Text("TEXT HERE","36px Ariel","black");
And you're good to go. Take care to add createjs. before the objects that were made available by that library.

Image data transfer on drag and draw on canvas

I am uploading an image from PC. Then I read the file with file reader and display image by creating an img tag. Then I drag the image from the img tag into the canvas and draw it onto canvas. I'm using dragstart and onDrop events. I use datatransfer.setdata() and datatransfer.getdata() for the functionality. But on drop, the image drawn on canvas is not as original. It is a zoomed version. I don't know why is this happening!
Here is my code:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Drag Demo</title>
<link href="copy.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="container">
<div style = "border:2px solid black;">
<canvas id = "canvas" style = "position:relative;width:1000px;height:1000px;top:0px;left:200px; border:2px solid black;" ondrop="dropIt(event);" ondragover="event.preventDefault();"> </canvas>
</div>
<div>
<input type="file" id="fileElem" accept="image/*" style="display:none" >
<div id="fileSelect" class="drop-area">Select some files</div>
</div>
<div id="thumbnail"></div>
</div>
<script type="text/javascript">
function dragIt(event) {
event.dataTransfer.setData("URL", event.target.id)
};
function dropIt(event) {
var theData = event.dataTransfer.getData("URL");
dt = document.getElementById(theData);
alert(dt.width);
alert(dt.height);
event.preventDefault();
var c = document.getElementById("canvas");
var ctx = c.getContext('2d');
ctx.drawImage(dt, 0, 0);
};
var count = 0;
var fileSelect = document.getElementById("fileSelect"),
fileElem = document.getElementById("fileElem");
fileElem.addEventListener("change",function(e){
var files = this.files
handleFiles(files)
},false)
fileSelect.addEventListener("click", function (e) {
fileElem.click();
e.preventDefault();
}, false);
function handleFiles(files) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
var imageType = /image.*/;
if(!file.type.match(imageType)){
console.log("Not an Image");
continue;
}
var image = document.createElement("img");
var thumbnail = document.getElementById("thumbnail");
image.file = file;
function handlefilereader(evt){
var target = evt.target || evt.srcElement;
image.src = evt.target.result;
}
if(document.all) {
image.src = document.getElementById('fileElem').value;
}
else {
var reader = new FileReader()
reader.onload = handlefilereader;
reader.readAsDataURL(file);
}
image.id = count;
count++;
thumbnail.appendChild(image);
alert(image.width);
image.draggable = true;
image.ondragstart = dragIt;
}
}
</script>
</body>
</html>
With canvas there are 2 'size' settings:
Through CSS you'll set the DISPLAY size, so to set the PHYSICAL size of the canvas, you MUST use its attributes. So NO CSS/Style.
Think about it this way: you create a IMAGE with physical size: (let's say) 400px*400px.
Then just as a normal image (jpg,png,gif) that has a physical size, you can still choose to change the DISPLAYED size and thus aspect-ratio: like 800px*600px. Even % is normally supported.
Hope this explains clearly WHY this happened and why your solution in your comment is also the correct solution!!

Categories