Similarity Matrix chart js plugin? - javascript

I want to draw a self-similarity matrix based on data points, I'm wondering if there is a JavaScript plugin to render it, similar to xy.js or chart.js
this chart should look like:
searching google keeps giving me results using D3 or cubism which seem to target realtime data flow, while I only have a single list of numbers that does not change.

I did not manage to find an answer, so I made my own (so plugins still appreciated)
(function(w){
function extend (target, source) {
target = target || {};
for (var prop in source) {
if (typeof source[prop] === 'object') {
target[prop] = extend(target[prop], source[prop]);
} else {
target[prop] = source[prop];
}
}
return target;
}
w.Squares = function(ctx, options){
var default_opts = {
};
options = extend(default_opts, options);
if(!this instanceof Squares){
return new Squares(ctx, options);
}
var amount = 0;
this.draw = function(data){
var max_x = 0, max_y = 0, max_z = 0;
// count the number of data points
data.forEach(function(row, x){
if(x+1 > max_x) {
max_x = x+1;
}
row.forEach(function(val, y){
if(y+1 > max_y) {
max_y = y+1;
}
if(val > max_z) {
max_z = val;
}
});
});
var w = parseInt(ctx.canvas.width / max_x, 10);
var h = parseInt(ctx.canvas.height / max_y, 10);
if(w>0 && h>0) {
// draw the graph
data.forEach(function (row, x) {
row.forEach(function (val, y) {
amount = parseInt(val / max_z * 255, 10);
ctx.fillStyle = "rgb(" + parseInt(amount / 1.5, 10) + "," + parseInt(amount / 1.5, 10) + "," + amount + ")";
ctx.fillRect(x * w, y * h, w, h);
});
});
}
};
};
})(window);
How to use
html:
<canvas id="canvas" width="900" height="900"></canvas>
<script>
var data = [];
for (var i = 0; i < 10; i ++) {
if(!data[i]){
data[i] = [];
}
for (var j = 0; j < 10; j ++) {
data[i][j] = Math.random();
}
}
var ctx = document.getElementById('canvas').getContext('2d');
var sqr = new Squares(ctx, {});
sqr.draw(data);
</script>
it looks like this

Related

how to generate random points in a circle (fractal trees)

I am making a tree with space-colonization algorithm in javascript. (with p5.js)
I followed the tutorial of https://www.youtube.com/watch?v=kKT0v3qhIQY&ab_channel=TheCodingTrain
or in C#
http://www.jgallant.com/procedurally-generating-trees-with-space-colonization-algorithm-in-xna/
I want to make a customized area (in this case a circle) where the leaves are generated randomly.
in Leaf.js I try to include some calculations of how the leaves get the random Coordinates within the circle.
So there is sketch.js , leaf.js, branch.js, tree.js
//leaf.js
function Leaf() {
function getChord(){
var r = 150;
var angle = random(0, 2 * PI);
var xChord = 2*r + sqrt(r) * cos(angle);
var yChord = r + sqrt(r) * sin(angle);
return (createVector(xChord, yChord));
}
this.pos = getChord();
this.reached = false;
// // var t = 2 * PI * random(0,1);
// // var r = sqrt(random(0,1));
// // var x = r * cos(t);
// // var y = r * sin(t);
// // this.pos = createVector(x, y);
// this.reached = false;
this.show = function() {
fill(58, 126, 34);
noStroke();
ellipse(this.pos.x, this.pos.y, 4, 4);
};
}
//branch.js
function Branch(parent, pos, dir) {
this.pos = pos;
this.parent = parent;
this.dir = dir;
this.origDir = this.dir.copy();
this.count = 0;
this.len = 3;
this.reset = function() {
this.dir = this.origDir.copy();
this.count = 0;
};
this.next = function() {
var nextDir = p5.Vector.mult(this.dir, this.len);
var nextPos = p5.Vector.add(this.pos, nextDir);
var nextBranch = new Branch(this, nextPos, this.dir.copy());
return nextBranch;
};
this.show = function() {
if (parent != null) {
stroke(151, 53, 48);
strokeWeight(1);
line(this.pos.x, this.pos.y, this.parent.pos.x, this.parent.pos.y);
}
};
}
And then in tree.js I push every leaf into leaves.
//tree.js
function Tree() {
this.leaves = [];
this.branches = [];
for (var i = 0; i < 1500; i++) {
this.leaves.push(new Leaf());
}
var pos = createVector(width / 2, height);
var dir = createVector(0, -1);
var root = new Branch(null, pos, dir);
this.branches.push(root);
var current = root;
var found = false;
while (!found) {
for (var i = 0; i < this.leaves.length; i++) {
var d = p5.Vector.dist(current.pos, this.leaves[i].pos);
if (d < max_dist) {
found = true;
}
}
if (!found) {
var branch = current.next();
current = branch;
this.branches.push(current);
}
}
this.grow = function() {
for (var i = 0; i < this.leaves.length; i++) {
var leaf = this.leaves[i];
var closestBranch = null;
var record = max_dist;
for (var j = 0; j < this.branches.length; j++) {
var branch = this.branches[j];
var d = p5.Vector.dist(leaf.pos, branch.pos);
if (d < min_dist) {
leaf.reached = true;
closestBranch = null;
break;
} else if (d < record) {
closestBranch = branch;
record = d;
}
}
if (closestBranch != null) {
var newDir = p5.Vector.sub(leaf.pos, closestBranch.pos);
newDir.normalize();
closestBranch.dir.add(newDir);
closestBranch.count++;
}
}
for (var i = this.leaves.length - 1; i >= 0; i--) {
if (this.leaves[i].reached) {
this.leaves.splice(i, 1);
}
}
for (var i = this.branches.length - 1; i >= 0; i--) {
var branch = this.branches[i];
if (branch.count > 0) {
branch.dir.div(branch.count + 1);
this.branches.push(branch.next());
branch.reset();
}
}
};
this.show = function() {
for (var i = 0; i < this.leaves.length; i++) {
this.leaves[i].show();
}
for (var i = 0; i < this.branches.length; i++) {
this.branches[i].show();
}
};
}
//sketch.js
var tree;
var max_dist = 30;
var min_dist = 10;
function setup() {
createCanvas(600, 600);
tree = new Tree();
}
function draw() {
background(111, 149, 231);
tree.show();
tree.grow();
}
Some how in the function getChord I think there is an infinite loop or having trouble getting the random value? Because it is not loading at all... It works when I change this.pos = getChord(); to this.pos = createVector(random(width),random(height-100);
Does anyone know how to solve this?
Or how to write codes to make an area of the circle where the leaves can be generated?
Thank you!

Uncaught TypeError: current.distance is not a function

I'm developing a little game of nothing at all more commonly called "Pathfinding"; and I am crashing on a small error that I have never encountered (I am young dev);
I have searched everywhere but I do not understand why this error appears.
I am experiencing this error:
Uncaught TypeError: current.distance is not a function
at search_min_distance (pathfinding.js:127)
at game (pathfinding.js:151)
at HTMLDocument. (pathfinding.js:173)
document.addEventListener("DOMContentLoaded", function() {
const NBR_POINT = 10;
const MIN_SPACING = 100;
const HEIGHT = window.innerHeight;
const WIDTH = window.innerWidth;
class point {
constructor(x, y, name, id) {
this.x = x;
this.y = y;
this.part = document.createElement("div");
this.part.className = name;
this.part.id = id;
}
distance(cmp) {
return Math.sqrt(Math.pow(cmp.x - this.x, 2) + Math.pow(cmp.y - this.y, 2));
}
}
function random(mode) {
if (!mode)
return Math.random() * ((WIDTH - 100) - 100) + 100;
else
return Math.random() * ((HEIGHT - 100) - 100) + 100;
}
function printPoint(stk, crt) {
var block = 0;
do {
block = 0;
var x = random(0);
var y = random(1);
if (stk.length != 0) {
for (let i = 0; i < stk.length; i++) {
if (x < (stk[i].x + MIN_SPACING) && x > (stk[i].x - MIN_SPACING) && y < (stk[i].y + MIN_SPACING) && y > (stk[i].y - MIN_SPACING)) {
block = 1;
break;
}
}
}
} while (block == 1);
var ids = stk.length + 1;
if (crt == "current")
var p = new point(x, y, "point courant", ids);
else
var p = new point(x, y, "point", ids);
p.part.style.bottom = p.y + "px";
p.part.style.left = p.x + "px";
document.body.appendChild(p.part);
return p;
}
function polyPoint() {
var stk = new Array();
for (let i = 0; i < NBR_POINT - 1; i++) {
stk.push(printPoint(stk, null));
}
printPoint(stk, "current");
return stk;
}
function imp_session() {
var dark_status = sessionStorage.getItem('dark_mode');
if (dark_status == 1)
document.body.classList.add("darkmode");
if (dark_status == 0)
document.body.classList.remove("darkmode");
}
function srv_DarkMode() {
document.addEventListener("keypress", function(event) {
let keypress = event.key;
var dark_status = sessionStorage.getItem('dark_mode');
if (keypress == "d") {
if (dark_status == null) {
dark_status = 0;
sessionStorage.setItem('dark_mode', dark_status);
}
if (dark_status == 1) {
this.body.classList.remove("darkmode");
dark_status = 0;
//To be able to delete sessions and not add them afterwards and error duplicate key.
sessionStorage.removeItem('dark_mode');
sessionStorage.setItem('dark_mode', dark_status);
} else {
this.body.classList.add("darkmode");
dark_status = 1;
//To be able to delete sessions and not add them afterwards and error duplicate key.
sessionStorage.removeItem('dark_mode');
sessionStorage.setItem('dark_mode', dark_status);
}
}
});
}
function search_min_distance(stk, current) {
let min = current.distance(stk[0]);
let tmp;
let real = min;
for (let i = 1; i < stk.length; i++) {
if (stk[i].id = current.id)
continue;
tmp = current.distance(stk[i]);
if (tmp < min)
real = i;
}
return real;
}
function game(stk) {
var cp = document.getElementsByClassName('courant');
cp[0].addEventListener("click", function(event) {
alert("txt");
});
var distId = search_min_distance(stk, cp[0]);
var p = document.getElementsByClassName('point');
for (let i = 0; i < p.length; i++) {
if (p[i].id != cp[0].id || p[i].id != distId) {
p[i].addEventListener("click", function(event) {
alert("txt");
});
}
}
}
function init() {
imp_session();
srv_DarkMode();
return polyPoint();
}
game(init());
});
-> current and stk [0] are indeed of "type" point.
All the remaining code does not seem important to me, but if necessary I will provide it.
I thank you in advance ! Be indulgent...
The point you are getting using the getElement function just returns
the js object, it does not contain any functions from the class.
You need to create a new class instance from this obtained point as follows inside the search_min_distance function
const { x, y, name, id } = current;
const currentPoint = new Point(x, y, name, id);
let min = currentPoint.distance(stk[0]);
I suggest you write a util function to calculate the distance between two points, passing the two points as arguments. It will be a cleaner approach.
Bind distance function to this inside constructor
class point {
constructor(x, y, name, id) {
this.x = x;
this.y = y;
this.part = document.createElement("div");
this.part.className = name;
this.part.id = id;
// bind distance method
this.distance = this.distance.bind(this);
}
distance(cmp) {
return Math.sqrt(Math.pow(cmp.x - this.x, 2) + Math.pow(cmp.y - this.y, 2));
}
}
The name of error is "TypeError". And That's not just for fun. Possible problems in search_min_distance:
stk is not defined or its length is 0
stk is not array of points (typeof point[])
point is not defined or it's not point (typeof point)
Sure problems:
point.id is not defined, it's only in point.part
if (stk[i].id = current.id)
to
if (stk[i].part.id = current.part.id)
Your code is only errors.
Finally all this for a simple mistake of inattention; I took dom for my array and put an assignment where there should have been an equal .. thanks everyone.
if (stk[i].id = current.id)
as
if (stk[i].id == current.id)
and
var distId = search_min_distance(stk, cp[0]);
as
var distId = search_min_distance(stk, stk[cp[0].id]);

Flood Fill tool P5.js

I'm here again because I'm still having trouble trying to implement a flood fill tool in my drawing app.
I am attempting to make a fairly simple 2d paint application using p5.js with each drawing tool having its own constructor function. I've been having trouble understanding what I am doing wrong and why it is not working which is causing lots of frustration.
I have read a few articles on here and followed a tutorial on youtube but I still don't quite understand it. I will include what I have done so far so you can see. Specifically, I am not sure what to write for the draw function. I would like the flood fill to happen on mouseX and mouseY coordinates when the mouse is pressed. Also, I would like for the target colour to be a colour selected from a separate constructor function ColourPalette().
HTML:
<!DOCTYPE html>
<html>
<head>
<script src="lib/p5.min.js"></script>
<script src="lib/p5.dom.js"></script>
<script src="sketch.js"></script>
<!-- add extra scripts below -->
...
<script src="fillTool.js"></script>
</body>
</html>
The sketch file:
function setup() {
//create a canvas to fill the content div from index.html
canvasContainer = select('#content');
var c = createCanvas(canvasContainer.size().width, canvasContainer.size().height);
c.parent("content");
//create helper functions and the colour palette
helpers = new HelperFunctions();
colourP = new ColourPalette();
...
toolbox.addTool(new FillTool());
background(255);
}
function draw() {
//call the draw function from the selected tool.
//if there isn't a draw method the app will alert the user
if (toolbox.selectedTool.hasOwnProperty("draw")) {
toolbox.selectedTool.draw();
} else {
alert("it doesn't look like your tool has a draw method!");
}
}
The flood fill constructor function I need help with. I'm getting "Uncaught ReferenceError: floodFill is not defined" for line 112 (within the draw function) in the console and I'm a little stuck on how to fix it.:
function FillTool() {
//set an icon and a name for the object
this.icon = "assets/freehand.jpg";
this.name = "FillTool";
var colourNew = ColourPalette(colourP); //Placeholder - How do I do this?
function getPixelData(x,y){
var colour = [];
for (var i = 0; i < d; i++) {
for (var j = 0; j < d; j++) {
idx = 4 * ((y * d + j) * width * d + (x * d + i));
colour[0] = pixels[idx];
colour[1] = pixels[idx+1];
colour[2] = pixels[idx+2];
colour[3] = pixels[idx+3];
}
}
return colour;
}
function setPixelData(x, y, colourNew) {
for (var i = 0; i < d; i++) {
for (var j = 0; j < d; j++) {
idx = 4 * ((y * d + j) * width * d + (x * d + i));
pixels[idx] = colourNew[0];
pixels[idx+1] = colourNew[1];
pixels[idx+2] = colourNew[2];
pixels[idx+3] = colourNew[3];
}
}
}
function matchColour(xPos,yPos,oldColour){
var current = get(xPos,yPos);
if(current[0] == oldColour[0] && current[1] == oldColour[1] && current[2] == oldColour[2] && current[3] == oldColour[3]){
return true;
}
}
function checkPixel(x1,y1,pixelArray){
for (var i = 0 ; i < pixelArray.length; i+=2){
if(x1 == pixelArray[i] && y1 == pixelArray[i+1]){
return false;
}
else {
console.log(pixelArray.length)
return true;
}
}
}
function floodFill (xPos,yPos){
loadPixels();
colourOld = getPixelData(xPos, yPos);
var stack = [];
var pixelList = [];
stack.push(xPos,yPos);
pixelList.push(xPos,yPos);
console.log(stack);
while(stack.length > 0){
var yPos1 = stack.pop();
var xPos1 = stack.pop();
setPixelData(xPos1,yPos1,colourNew);
if(xPos1 + 1 <= width && xPos1 + 1 > 0 ){
if(matchColour(xPos1+1,yPos1,colourOld) && checkPixel(xPos1+1,yPos1,pixelList)){
stack.push(xPos1+1,yPos1);
pixelList.push(xPos1+1,yPos1);
}
}
if(xPos1+1 <= width && xPos1+1 > 0 ){
if(matchColour(xPos1-1,yPos1,colourOld) && checkPixel(xPos1-1,yPos1,pixelList)){
stack.push(xPos1-1,yPos1);
pixelList.push(xPos1-1,yPos1);
}
}
if(yPos1+1 <= height && yPos1+1 > 0 ){
if(matchColour(xPos1,yPos1+1,colourOld) && checkPixel(xPos1,yPos1+1,pixelList)){
stack.push(xPos1,yPos1+1);
pixelList.push(xPos1,yPos1+1);
}
}
if(yPos1-1 <= height && yPos1-1 > 0 ){
if(matchColour(xPos1,yPos1-1,colourOld) && checkPixel(xPos1,yPos1-1,pixelList)){
stack.push(xPos1,yPos1-1);
pixelList.push(xPos1,yPos1-1);
}
}
}
updatePixels();
console.log(pixelList);
}
}
this.draw = function() {
if(mouseIsPressed){
floodFill(mouseX,mouseY);
}
}
Sorry if its a bit of a mess, it's an accurate representation of my brain at the moment.
The function checkPixel was very very slow because pixelArray grows as you draw new pixels, so verifying if a new pixel was in the stack or had already been drawn took longer each time.
In javascript it is possible to use an object {} to store key/value pair like :
var colours = { 'red':{'r':255,'g':0,'b':0,'a':255}, 'black':{'r':0,'g':0,'b':0,'a':255} };
And calling the method hasOwnPorperty to verify the presence of the key is very fast.
colours.hasOwnPorperty('red') // is true
colours.hasOwnPorperty('green') // is false
If you had a 1,000,000 colours in colours, it would not take longer for hasOwnPorperty to find a colour in colours than if you had only 1 colour in colours. (It's O(1) has opposed to O(n) for your version of checkPixel)
Try clicking inside the circle ... or outside
let toolbox, d;
function setup() {
createCanvas(600, 400);
d = pixelDensity();
//create helper functions and the colour palette
//...
let colourRed = ColourPalette(255,0,0,255);
//...
toolbox = {'selectedTool': new FillTool() };
toolbox.selectedTool.setColour(colourRed);
background(255);
push();
strokeWeight(1);
stroke(0);
circle(75,75,100);
noStroke();
fill(0,255,0,255);
circle(125,75,100);
pop();
}
function draw() {
if (! toolbox.selectedTool.hasOwnProperty("draw")) {
alert("it doesn't look like your tool has a draw method!");
return;
}
toolbox.selectedTool.draw();
}
function FillTool() {
let self = this;
//set an icon and a name for the object
self.icon = "assets/freehand.jpg";
self.name = "FillTool";
self.colour = ColourPalette(0,0,0,255);
self.draw = function () {
if (mouseIsPressed) {
floodFill(mouseX, mouseY);
}
};
self.setColour = function (col) {
self.colour = col;
};
function matchColour (pos, oldColour) {
var current = getPixelData(pos.x, pos.y);
return ( current[0] === oldColour[0] && current[1] === oldColour[1]
&& current[2] === oldColour[2] && current[3] === oldColour[3] );
}
function getKey (pos) {
return ""+pos.x+"_"+pos.y;
}
function checkPixel(pos, positionSet) {
return ! positionSet.hasOwnProperty( getKey(pos) );
}
function floodFill (xPos, yPos) {
var stack = [];
var pixelList = {};
var first = {'x':xPos,'y':yPos};
stack.push( first );
pixelList[ getKey(first) ] = 1;
//console.log( JSON.stringify(stack) );
loadPixels();
var firstColour = getPixelData(xPos, yPos);
while (stack.length > 0) {
var pos1 = stack.pop();
setPixelData(pos1.x, pos1.y, self.colour);
var up = {'x':pos1.x, 'y':pos1.y-1};
var dn = {'x':pos1.x, 'y':pos1.y+1};
var le = {'x':pos1.x-1,'y':pos1.y};
var ri = {'x':pos1.x+1,'y':pos1.y};
if (0 <= up.y && up.y < height && matchColour(up, firstColour)) addPixelToDraw(up);
if (0 <= dn.y && dn.y < height && matchColour(dn, firstColour)) addPixelToDraw(dn);
if (0 <= le.x && le.x < width && matchColour(le, firstColour)) addPixelToDraw(le);
if (0 <= ri.x && ri.x < width && matchColour(ri, firstColour)) addPixelToDraw(ri);
}
updatePixels();
//console.log( JSON.stringify(pixelList) );
function addPixelToDraw (pos) {
if (checkPixel(pos, pixelList) ) {
stack.push( pos );
pixelList[ getKey(pos) ] = 1;
}
}
}
}
function ColourPalette (r,g,b,a) {
var self = (this !== window ? this : {});
if (arguments.length === 0) {
self['0'] = 0; self['1'] = 0; self['2'] = 0; self['3'] = 0;
} else if (arguments.length === 1) {
self['0'] = r[0]; self['1'] = r[1]; self['2'] = r[2]; self['3'] = r[3];
} else if (arguments.length === 4) {
self['0'] = r; self['1'] = g; self['2'] = b; self['3'] = a;
} else {
return null;
}
return self;
}
function getPixelData (x, y) {
var colour = [];
for (var i = 0; i < d; ++i) {
for (var j = 0; j < d; ++j) {
let idx = 4 * ((y * d + j) * width * d + (x * d + i));
colour[0] = pixels[idx];
colour[1] = pixels[idx+1];
colour[2] = pixels[idx+2];
colour[3] = pixels[idx+3];
}
}
return colour;
}
function setPixelData (x, y, colour) {
for (var i = 0; i < d; ++i) {
for (var j = 0; j < d; ++j) {
let idx = 4 * ((y * d + j) * width * d + (x * d + i));
pixels[idx] = colour[0];
pixels[idx+1] = colour[1];
pixels[idx+2] = colour[2];
pixels[idx+3] = colour[3];
}
}
}
body { background-color:#efefef; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>

How to fix similar predictions in tenserflow.js

I'm doing a coding challenge from the coding train, and I'm trying to improve on his code. The idea is that the cars are driving around a race track. When I went back to check something, I noticed that I misspelled "activation: sigmoid", as in activation function. When I fixed it, the cars seemed to be driving in circles.
I'm a very new coder (as I am 12 years old), so many things in my code are broken, hard to understand, or just not finished. I'm also pretty new to stack overflow, so I might be breaking a lot of rules.
The link to download my project is here: https://1drv.ms/u/s!ApmY_SAko19ChzCKe5uNT7I9EZAX?e=YUg2ff
The misspelled words are at lines 29 and 34 in the nn.js file.
car.js
function pldistance(p1, p2, x, y) {
const num = abs((p2.y - p1.y) * x - (p2.x - p1.x) * y + p2.x * p1.y - p2.y * p1.x);
const den = p5.Vector.dist(p1, p2);
return num / den;
}
class Car {
constructor(brain, color = [random(255), random(255), random(255)]) {
this.colorGene = color;
this.dead = false;
this.finished = false;
this.fitness = 0;
this.rays = [];
this.wallRays = [];
this.degreeOfSight = degreeOfSight;
this.degreeOfRays = degreeOfSight / (numOfRays - 1);
if (this.degreeOfSight == 360) {
this.degreeOfRays = degreeOfSight / numOfRays;
}
this.pos = createVector(start.x, start.y);
this.vel = createVector();
this.acc = createVector();
this.sight = sight;
this.maxspeed = maxspeed;
this.maxforce = maxTurningSpeed;
this.currentGoal = 0;
this.timeTillDeadC = timeTillDead;
this.timeTillDead = this.timeTillDeadC;
this.goal;
this.rate = mutationRate;
if (degreeOfSight != 360) {
for (let a = -(this.degreeOfSight / 2); a <= this.degreeOfSight / 2; a += this.degreeOfRays) {
this.rays.push(new Ray(this.pos, radians(a)));
}
} else {
for (let a = -(this.degreeOfSight / 2); a < this.degreeOfSight / 2; a += this.degreeOfRays) {
this.rays.push(new Ray(this.pos, radians(a)));
}
}
for (let a = 0; a < 360; a += 45) {
this.wallRays.push(new Ray(this.pos, radians(a)));
}
if (brain) {
this.brain = brain.copy();
} else {
this.brain = new NeuralNetwork(this.rays.length + 2, 16, 2);
}
}
applyForce(force) {
this.acc.add(force);
}
update(x, y) {
this.timeTillDead--;
if (this.timeTillDead <= 0) {
this.dead = true;
}
if (!this.dead || this.finished) {
this.pos.add(this.vel);
this.vel.add(this.acc);
this.vel.limit(this.maxspeed);
this.acc.set(0, 0);
}
for (let i = 0; i < this.rays.length; i++) {
this.rays[i].rotate(this.vel.heading());
}
for (let i = 0; i < this.wallRays.length; i++) {
this.wallRays[i].rotate(this.vel.heading());
}
}
show(walls) {
push();
translate(this.pos.x, this.pos.y);
if (visualization) {
fill(this.colorGene[0], this.colorGene[1], this.colorGene[1]);
} else {
fill(0);
}
stroke(255);
const heading = this.vel.heading();
rotate(heading);
rectMode(CENTER);
rect(0, 0, 10, 5);
pop();
if (!this.dead) {
checkpoints[this.currentGoal].show();
}
for (let i = 0; i < this.rays.length; i++) {
let closest = null;
let record = this.sight;
for (let wall of walls) {
const pt = this.rays[i].cast(wall);
if (pt) {
const d = p5.Vector.dist(this.pos, pt);
if (d < record && d < this.sight) {
record = d;
closest = pt;
}
}
}
if (closest) {
if (showLines) {
ellipse(closest.x, closest.y, 4)
stroke(255, 100)
line(this.pos.x, this.pos.y, closest.x, closest.y);
}
}
}
}
check(checkpoints, walls) {
if (!this.dead) {
this.goal = checkpoints[this.currentGoal];
const d = pldistance(this.goal.a, this.goal.b, this.pos.x, this.pos.y);
if (d < 5) {
this.fitness++;
this.currentGoal++;
this.timeTillDead = this.timeTillDeadC;
if (this.currentGoal == checkpoints.length) {
this.finished = true;
this.fitness = this.fitness * 1.5;
if (endBarrier) {
this.dead = true;
} else {
this.currentGoal = 0;
}
}
}
}
for (let i = 0; i < this.wallRays.length; i++) {
let closest = null;
let record = this.sight;
for (let wall of walls) {
const pt = this.wallRays[i].cast(wall);
if (pt) {
const d = p5.Vector.dist(this.pos, pt);
if (d < record) {
record = d;
closest = pt;
}
}
}
if (record < 4) {
this.dead = true;
}
}
}
look(walls) {
const inputs = [];
for (let i = 0; i < this.wallRays.length; i++) {
let closest = null;
let record = this.sight;
for (let wall of walls) {
const pt = this.rays[i].cast(wall);
if (pt) {
const d = p5.Vector.dist(this.pos, pt);
if (d < record && d < this.sight) {
record = d;
closest = pt;
}
}
}
inputs[i] = map(record, 0, 50, 1, 0);
}
inputs.push(end.x);
inputs.push(end.y);
const output = this.brain.predict(inputs);
let angle = map(output[0], 0, 1, -PI, PI);
let speed = map(output[1], 0, 1, -this.maxspeed, this.maxspeed);
angle += this.vel.heading();
const steering = p5.Vector.fromAngle(angle);
steering.setMag(speed);
steering.limit(this.maxforce);
this.applyForce(steering);
}
mutateDemBabies() {
if (this.finished) {
this.rate = finishingMutationRate;
}
this.brain.mutate(this.rate);
let changeColor = this.brain.mutated();
if (changeColor) {
for (let color of this.colorGene) {
let r = map(random(20), 0, 20, -25, 25);
color += r;
}
}
this.rate = mutationRate;
}
dispose() {
this.brain.dispose();
}
}
nn.js
//<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs#1.1.0/dist/tf.min.js"></script>
class NeuralNetwork {
//this how many inputs, hidden, and output nodes there are. modelC is the brain that we want to copy to give to the new bird
constructor(inputNumber, hiddenNumber, outputNumber, modelC) {
if (modelC instanceof tf.Sequential) {
//this is the making a copy of the neural network
this.input_nodes = inputNumber;
this.hidden_nodes = hiddenNumber;
this.output_nodes = outputNumber;
this.model = modelC;
} else {
//this is the creating a random brain
this.input_nodes = inputNumber;
this.hidden_nodes = hiddenNumber;
this.output_nodes = outputNumber;
this.model = this.createBrain();
}
this.changeColor = false;
}
createBrain() {
//the model is the neural network
const model = tf.sequential();
//configuring the hidden layer
const hiddenLayer = tf.layers.dense({
units: this.hidden_nodes,
inputShape: [this.input_nodes],
activaation: "sigmoid"
});
//configuring the output layer
const outputLayer = tf.layers.dense({
units: this.output_nodes,
activaation: "sigmoid"
});
//adding the hidden layer to the model
model.add(hiddenLayer);
//adding the output layer to the model
model.add(outputLayer);
//returning the model
return model;
}
predict(inputs) {
//clearing the tensors after using them
//then returning the output
return tf.tidy(() => {
//creating a tensor with the inputs
const xs = tf.tensor2d([inputs]);
//running the inputs through the neural network
const ys = this.model.predict(xs);
//getting the raw numbers from the tensor object
const outputs = ys.dataSync();
//returning the outputs
return outputs;
});
}
copy() {
//clearing the tensors after using them
//then returning the output
return tf.tidy(() => {
//creating a new neural network
const modelCopy = this.createBrain();
//getting the weights from the old neural network
const weights = this.model.getWeights();
//setting the new weights
modelCopy.setWeights(weights);
//making a new network but this time with all the weights then returning it
return new NeuralNetwork(
this.input_nodes,
this.hidden_nodes,
this.output_nodes,
modelCopy
);
});
}
mutate(rate, colorGene) {
//clearing the tensors after using them
tf.tidy(() => {
this.changeColor = false;
//getting the weights so that we can change them later
const weights = this.model.getWeights();
//the variable that will be holding the mutated weights
const mutatedWeights = [];
for (let i = 0; i < weights.length; i++) {
//getting the shape of the current weights
let shape = weights[i].shape;
//making a copy of the raw numbers from the object tensor
//dataSync gets the numbers, but doesn't make a copy, so slice will make the copy
let values = weights[i].dataSync().slice();
for (let j = 0; j < values.length; j++) {
//if the random number is less than mutation rate the it runs the code
if (random(1) < rate) {
this.changeColor = true;
//mutating the value
//randomGaussianis returns a float from a series of numbers with a mean of 0
values[j] = values[j] + randomGaussian();
}
}
//holding the new value of each weight
mutatedWeights[i] = tf.tensor(values, shape);
}
//setting the mutated weights as the new weights
this.model.setWeights(mutatedWeights);
});
}
mutated() {
if (this.changeColor) {
this.changeColor = false;
return true;
} else {
this.changeColor = false;
return false;
}
}
dispose() {
//disposing the brain so that memory doesn't leak
this.model.dispose();
}
}

How to change voice pitch without noise using web audio javascript?

How do I change voice pitch without noise using web audio in JavaScript?
I tried the code below.
I got my voice with noisy and bit echo mixed.
I want a voice module which is like noiseless.
var pitchShifter = (function () {
var context, audioContext, pitchShifterProcessor, spectrumAudioAnalyser,
sonogramAudioAnalyser;
var validGranSizes = [256, 512, 1024, 2048, 4096, 8192],
grainSize = validGranSizes[1],
pitchRatio = 2.0,
overlapRatio = 0.50;
var filter, compressor;
hannWindow = function (length) {
var window = new Float32Array(length);
for (var i = 0; i < length; i++) {
window[i] = 0.5 * (1 - Math.cos(2 * Math.PI * i / (length - 1)));
}
return window;
};
linearInterpolation = function (a, b, t) {
return a + (b - a) * t;
};
initProcessor = function () {
if (navigator.getUserMedia) {
navigator.getUserMedia({
audio: true
},
function (stream) {
var convolver = audioContext.createConvolver();
compressor = audioContext.createDynamicsCompressor();
compressor.threshold.value = -50;
compressor.knee.value = 40;
compressor.ratio.value = 12;
compressor.reduction.value = -20;
compressor.attack.value = 0;
compressor.release.value = 0.25;
filter = audioContext.createBiquadFilter();
filter.Q.value = 8.30;
filter.frequency.value = 355;
filter.gain.value = 3.0;
filter.type = 'bandpass';
filter.connect(compressor);
compressor.connect(audioContext.destination);
filter.connect(audioContext.destination);
var microphone_stream = audioContext.createMediaStreamSource(
stream);
microphone_stream.connect(filter);
var source = audioContext.createBufferSource();
microphone_stream.connect(pitchShifterProcessor);
},
function (e) {
alert('Error capturing audio.');
}
);
}
if (pitchShifterProcessor) {
pitchShifterProcessor.disconnect();
}
if (audioContext.createScriptProcessor) {
pitchShifterProcessor = audioContext.createScriptProcessor(
grainSize, 1, 1);
} else if (audioContext.createJavaScriptNode) {
pitchShifterProcessor = audioContext.createJavaScriptNode(grainSize,
1, 1);
}
pitchShifterProcessor.buffer = new Float32Array(grainSize * 2);
pitchShifterProcessor.grainWindow = hannWindow(grainSize);
pitchShifterProcessor.onaudioprocess = function (event) {
var inputData = event.inputBuffer.getChannelData(0);
var outputData = event.outputBuffer.getChannelData(0);
for (i = 0; i < inputData.length; i++) {
// Apply the window to the input buffer
inputData[i] *= this.grainWindow[i];
// Shift half of the buffer
this.buffer[i] = this.buffer[i + grainSize];
// Empty the buffer tail
this.buffer[i + grainSize] = 0.0;
}
// Calculate the pitch shifted grain re-sampling and looping the input
var grainData = new Float32Array(grainSize * 2);
for (var i = 0, j = 0.0; i < grainSize; i++, j += pitchRatio) {
var index = Math.floor(j) % grainSize;
var a = inputData[index];
var b = inputData[(index + 1) % grainSize];
grainData[i] += linearInterpolation(a, b, j % 1.0) * this.grainWindow[
i];
}
// Copy the grain multiple times overlapping it
for (i = 0; i < grainSize; i += Math.round(grainSize * (1 -
overlapRatio))) {
for (j = 0; j <= grainSize; j++) {
this.buffer[i + j] += grainData[j];
}
}
// Output the first half of the buffer
for (i = 0; i < grainSize; i++) {
outputData[i] = this.buffer[i];
}
};
pitchShifterProcessor.connect(audioContext.destination);
};
return {
init: function () {
if ('AudioContext' in window) {
audioContext = new AudioContext();
} else {
alert('Your browser does not support the Web Audio API');
return;
}
initProcessor();
}
}
}());
window.requestAnimFrame = (function () {
return (window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
});
})();
window.addEventListener("DOMContentLoaded", pitchShifter.init, true);
You can use the PitchShifter in SoundTouchJS for this. I currently use this in my CDGPlayer for changing the 'key' for a user.

Categories

Resources