Skip to content

Instantly share code, notes, and snippets.

@AnastasiaDunbar
Last active November 24, 2020 05:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AnastasiaDunbar/d75e19d93a5c439d8185343f1fd54da1 to your computer and use it in GitHub Desktop.
Save AnastasiaDunbar/d75e19d93a5c439d8185343f1fd54da1 to your computer and use it in GitHub Desktop.
var PI=Math.PI,TAU=Math.PI*2,E=Math.E;
var sin=Math.sin,cos=Math.cos,tan=Math.tan,asin=Math.asin,acos=Math.acos,atan=Math.atan;
var sqrt=Math.sqrt,pow=Math.pow,log=Math.log,exp=Math.exp;
function floor(x){return arguments.length==2?Math.floor(x/arguments[1])*arguments[1]:Math.floor(x);}
var ceil=Math.ceil;
var abs=Math.abs,sign=Math.sign;
function random(...x){return 2===x.length?x[0]+Math.random()*(x[1]-x[0]):Math.random()*(x[0]||1);}
function min(...x){if(x.length===1&&Array.isArray(x[0])){x=x[0];}return Math.min(...x);}
function max(...x){if(x.length===1&&Array.isArray(x[0])){x=x[0];}return Math.max(...x);}
function mod(a,b){return((a%b)+b)%b;}
function cmod(a,b){return a-(Math.ceil((a/b)-1)*b);}
function fract(x){return((x%1)+1)%1;}
function mix(x,y,a){return(a*(y-x))+x;}
function invMix(x,y,a){return(a-x)/(y-x);}
function clamp(x,minVal,maxVal){return Math.min(Math.max(x,minVal),maxVal);}
function clamps(x){return clamp(x,0,1);}
function smoothstep(a,b,x){var t=clamp((x-a)/(b-a),0,1);return t*t*(3-(2*t));}
function atan(a,b){return Math.atan2(a,b);}
//Extra
var RNDSEED=mix(400,500,Math.random()); function prandom(t){t+=RNDSEED/100;return fract(Math.sin(t*RNDSEED)*47453.5453);}
function pow2(a,b){return Math.pow(Math.abs(a),b)*Math.sign(a);}
function sine(x){return Math.sin(Math.PI*2*x);}
function saw(x){return(fract(x)*2)-1;}
function pulse(x){return fract(x)>0.5?-1:1;}
function tri(x){return(Math.abs(mod((x-.25)*2,2)-1)*2)-1;}
function noteHz(x){return Math.pow(2,(x-49)/12)*440;} //A4 (or A440) is `noteHz(49)`.
function inverseNoteHz(y){return(12*Math.log(y/55)+13*Math.LN2)/Math.LN2;}
function fibonacci(n){return((Math.pow(1+Math.sqrt(5),n))-(Math.pow(1-Math.sqrt(5),n)))/(Math.pow(2,n)*Math.sqrt(5));}
function isPrime(v){for(var i=2;i<v;i++){if(v%i===0){return false;}}return v>1;}
function curveSmooth(x,a){var b=Math.pow(x*2,a)/2;if(x>0.5){b=1-Math.pow(2-(x*2),a)/2;}return b;}
function fractSmooth(x,a){return(a>0)?Math.max(1-(fract(x)/a),fract(x)):Math.min(fract(x),fract(-x)/-a);}
function noise(x){return(prandom(x)*2)-1;}
function noiseSmooth(x,p){return mix(noise(Math.floor(x*p)),noise(Math.floor(x*p)+1),fract(x*p));}
function floorSmooth(x,c){var a=fract(x),b=Math.floor(x);return((pow2(a,c)-pow2(1-a,c))/2)+b;}
function integral(a,b,N,f){var area=(f(a)+f(b))/2,w=(b-a)/N;for(var i=1;i<N;i++){area+=f(a+i*w);}return w*area;}
function catmullRomInterpolation(p0,p1,p2,p3,t){return((2*p1)+((-p0+p2)*t)+((2*p0-5*p1+4*p2-p3)*Math.pow(t,2))+((-p0+3*p1-3*p2+p3)*Math.pow(t,3)))/2;}
function cyclicSum(a,x){for(var s=0,i=0;i<a.length;i++){s+=a[i]*Math.floor((x+(a.length-i-1))/a.length);}return s+fract(x)*a[Math.floor(mod(x,a.length))];}
function gcd(a,b){if(b===0){return a;}return gcd(b,mod(a,b));}
function lcm(a,b){return Math.abs(a*b)/gcd(a,b);}
//function randomBool(){return Math.random()<.5;}
function shiftBits(int,bits,shift){shift=Math.floor(mod(shift,bits));if(bits>=32){return((int<<shift)|(int>>>(bits-shift)))>>>0;}return((int<<shift)|(int>>(bits-shift)))&((1<<bits)-1);}
function encodeNumber(n){
var b=new ArrayBuffer(8);(new Float64Array(b))[0]=n; //8*8=64.
return[(new Uint32Array(b))[0],(new Uint32Array(b))[1]]; //32-bit integers because `Number.MAX_SAFE_INTEGER < (2**64)-1`, therefore no `Uint64Array`.
}
function decodeNumber(a){var b=new ArrayBuffer(8);[new Uint32Array(b)[0],new Uint32Array(b)[1]]=a;return new Float64Array(b)[0];}
function doubleToBinaryString(a){if(typeof a==="number"){a=encodeNumber(a);}return a[1].toString(2).padStart(32,"0")+a[0].toString(2).padStart(32,"0");}
function binaryStringToDouble(s){var l=s.length;return decodeNumber([parseInt(s.substring(l-32,l),2),parseInt(s.substring(l-64,l-32),2)]);}
function listDivisors(n){var small=[],large=[],end=Math.floor(Math.sqrt(n));for(var i=1;i<=end;i++){if(n%i===0){small.push(i);if(i*i!==n){large.push(n/i);}}}large.reverse();return small.concat(large);}
function findClosest(array,n){if(array.length){return array.reduce((p,c)=>Math.abs(c-n)<Math.abs(p-n)?c:p);}}
//Objects
Object.prototype.clone=function(){var n=this.constructor();for(var k in this){if(this[k]&&typeof this[k]==="object"){n[k]=Object.clone.call(this[k]);}else if(this.hasOwnProperty(k)){n[k]=this[k];}}return n;};
Object.prototype.readByArray=function(a){return a.reduce(function(t,e){return t[e];},this);};
//Arrays
function createArray(s,v){for(var f=(typeof v==="function"),a=[],i=0;i<s;i++){a[i]=f?v(i):v;}return a;}
Array.prototype.repeat=function(n){var a=[];for(var i=0;i<n;i++){a=a.concat(this);}return a;}
Array.prototype.add=function(n){var a=this.slice(0);if(Array.isArray(n)){for(var i=0;i<a.length;i++){a[i]+=n[i];}}else{for(var i=0;i<a.length;i++){a[i]+=n;}}return a;};
Array.prototype.sub=function(n){var a=this.slice(0);if(Array.isArray(n)){for(var i=0;i<a.length;i++){a[i]-=n[i];}}else{for(var i=0;i<a.length;i++){a[i]-=n;}}return a;};
Array.prototype.mult=function(n){var a=this.slice(0);if(Array.isArray(n)){for(var i=0;i<a.length;i++){a[i]*=n[i];}}else{for(var i=0;i<a.length;i++){a[i]*=n;}}return a;};
Array.prototype.div=function(n){var a=this.slice(0);if(Array.isArray(n)){for(var i=0;i<a.length;i++){a[i]/=n[i];}}else{for(var i=0;i<a.length;i++){a[i]/=n;}}return a;};
Array.prototype.maximum=function(){var n=this[0];for(var i=1;i<this.length;i++){n=Math.max(n,this[i])}return n;};
Array.prototype.minimum=function(){var n=this[0];for(var i=1;i<this.length;i++){n=Math.min(n,this[i])}return n;};
Array.prototype.maxID=function(){var n=0;for(var i=1;i<this.length;i++){if(this[i]>this[n]){n=i;}}return n;};
Array.prototype.minID=function(){var n=0;for(var i=1;i<this.length;i++){if(this[i]<this[n]){n=i;}}return n;};
Array.prototype.sum=function(){return this.reduce(function(t,e){return t+e;},0);};
Array.prototype.mean=function(){var s=0;for(var i=0;i<this.length;i++){s+=this[i];}return s/this.length;};
Array.prototype.read=function(i){return this[mod(Math.floor(i),this.length)];};
Array.prototype.flatten=function(){return[].concat.apply([],this);};
Array.prototype.emptyByArray=function(a,e){return this.readByArray(a).splice(0,this.length);};
Array.prototype.concatByArray=function(a,e){var c=this.readByArray(a);for(var i=0;i<e.length;i++){c.push(e[i]);}};
Array.prototype.setByArray=function(a,e){return this.readByArray(a).splice(0,this.length,e);};
Array.prototype.readInterval=function(i){return this.read(i*this.length);};
Array.prototype.readSmooth=function(indx){return mix(this.read(indx),this.read(indx+1),fract(indx));};
Array.prototype.readIntervalSmooth=function(indx){return this.readSmooth(indx*this.length);};
Array.prototype.insert=function(i,v){this.splice(i,0,v);};
//Array.prototype.swap=function(a,b){var e=this[a];this[a]=this[b];this[b]=e;return this;};
Array.prototype.swap=function(a,b){[this[a],this[b]]=[this[b],this[a]];return this;};//ES6
Array.prototype.sortIndex=function(){var l=this.map(function(e,i){return{v: e,i: i};});l.sort(function(a,b){return((a.v<b.v)?-1:((a.v==b.v)?0:1));});return l.map(function(e){return e.i;});};
Array.prototype.shuffle=function(){var l=this.length,s,i;while(l){i=Math.floor(Math.random()*l--);s=this[l];this[l]=this[i];this[i]=s;}return this;};
Array.prototype.unique=function(){return Array.from(new Set(this));};
Array.prototype.rotate=function(n){n=((n%this.length)+this.length)%this.length;return this.slice(n,this.length).concat(this.slice(0,n));};
//https://gist.github.com/withakay/1286731
function euclideanRhythm(s,p){if(p===0||s===0){return[];}if(p>s){return new Array(s).fill(1);}var div=s-p,ptr=[],cnt=[],rmd=[p],l=0;while(true){cnt.push(Math.floor(div/rmd[l]));rmd.push(div%rmd[l]);div=rmd[l];l++;if(rmd[l]<=1){break;}}cnt.push(div);var r=0,b=function(l){r++;if(l>-1){for(var i=0;i<cnt[l];i++){b(l-1);}if(rmd[l]!==0){b(l-2);}}else if(l===-1){ptr.push(0);}else if(l===-2){ptr.push(1);}};b(l);return ptr.reverse();}
Array.prototype.extendedSlice=function(start,end,step){var a=[];if(step>=0){for(var i=start;i<end;i+=step){a.push(this[i]);}}else{for(var i=start;i>end;i+=step){a.push(this[i]);}}return a;} //Pythonic.
//Strings
String.prototype.read=function(indx){return this[mod(Math.floor(indx),this.length)];};
String.prototype.count=function(s){return this.split(s).length-1;};
String.prototype.reversed=function(){var o="";for(var i=this.length-1;i>=0;i--){o+=this[i];}return o;};
String.prototype.replaceAll=function(o,n){return this.split(o).join(n);};
String.prototype.stringCopy=function(a,b){return this.substr(a,b);};
String.prototype.replaceAt=function(i,s){return this.substr(0,i)+s+this.substr(i+s.length);};
String.prototype.swap=function(a,b){var s=this;s=s.replaceAt(a,s[b]);s=s.replaceAt(b,this[a]);return s;};
String.prototype.repeatCharacters=function(t){var s='';for(var i=0;i<this.length;i++){s+=this[i].repeat(t);}return s;};
String.prototype.regexReplace=function(regex,n){return this.replace(regex,n);};
String.prototype.stringInsert=function(s,at){return this.substr(0,at)+s+this.substr(at,this.length-1);};
String.prototype.indexOfList=function(word){var result=[];var i=0;while(this.includes(word, i)){var match=this.indexOf(word,i);result.push(match);i=match+1;}return result;};
String.prototype.rot13=function(n){return this.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+n)?c:c-26);});};
String.prototype.tr=function(from,to){var str=this;for(var i=0;i<from.length;i++){var subst=(to[i])?to[i]:to[to.length-1];str=str.replace(new RegExp(str[str.indexOf(from[i])],'g'),subst);}return str;};
String.prototype.leftpad=function(len,chr){var str=this;chr=String(chr);var l=len-str.length;for(var i=0;i<l;i++){str=chr[((l-i)-1)%chr.length]+str;}return str;};
String.prototype.splitNChars=function(n,r){var a=[];if(r){for(var i=cmod(this.length,n)-n;i<this.length;i+=n){a.push(this.substring(i,i+n));}}else{for(var i=0;i<this.length;i+=n){a.push(this.substr(i,n));}}return a;};
function decToBinary(d){return(d>>>0).toString(2);}
function binaryToDec(d){return parseInt(d,2);}
function decToHex(d){return d.toString(16);}
function hexToDec(d){return parseInt(d,16);}
String.prototype.stringToChar=function(){var s=this.split('');return s.map(function(e){return e.charCodeAt(0);}).join(' ');};
String.prototype.charToString=function(){var s=this.split(' ');return s.map(function(e){return String.fromCharCode(e);}).join('');};
String.prototype.stringToBinary=function(){var s=this.split('');return s.map(function(e){return decToBinary(e.charCodeAt(0)).leftpad(8,0);}).join(' ');};
String.prototype.binaryToString=function(){var s=this.replaceAll(' ','').splitNChars(8);return s.map(function(e){return String.fromCharCode(binaryToDec(e));}).join('');};
String.prototype.stringToHex=function(){var s=this.split('');return s.map(function(e){return decToHex(e.charCodeAt(0));}).join(' ');};
String.prototype.hexToString=function(){var s=this.split(' ');return s.map(function(e){return String.fromCharCode(hexToDec(e));}).join('');};
//Sound Effects
if(typeof sampleRate==="undefined"){var sampleRate=typeof SAMPLE_RATE!=="undefined"?SAMPLE_RATE:48000;}
function fastLP(n){var v=0;return function(x){return v+=(x-v)/n;};}
function fastHP(n){var v=0;return function(x){return v+=x-v*n;};}
function fastDelay(t,f){var a=0,b=[],i,o;for(i=0;i<t*sampleRate;i++){b.push(0);}return function(x){o=b[a];b[a]=(b[a]+x)*f;a=(a+1)%b.length;return x+o;};}
@AnastasiaDunbar
Copy link
Author

AnastasiaDunbar commented Feb 14, 2019

I realized there was something wrong if you'd do [1,2,3,{clone:"replaced!"}].clone() but have fixed that by replacing x.clone() with Object.clone.call(x). That's why you don't create custom prototypes, folks. There are still issues with it but shouldn't be taken seriously as I intended. I also used this.constructor() instead of checking with something like this instanceof Array (has to be on the same iframe or window?), Array.isArray(this) or Object.prototype.toString.call(this)==="[object Array]".

@AnastasiaDunbar
Copy link
Author

Double-precision floating-point numbers to binary strings and vice versa:

function encodeNumber(n){var b=new ArrayBuffer(8);(new Float64Array(b))[0]=n;return[(new Uint32Array(b))[0],(new Uint32Array(b))[1]];}
function doubleToBinaryString(a){
	if(typeof a==="number"){a=encodeNumber(a);}
	return a[1].toString(2).padStart(32,"0")+a[0].toString(2).padStart(32,"0");
	/*var s="",i;
	for(i=31;i>=0;i--){s+=(a[1]>>>i)&1;}
	for(i=31;i>=0;i--){s+=(a[0]>>>i)&1;}
	return s;*/
}
function decodeNumber(a){var b=new ArrayBuffer(8);[new Uint32Array(b)[0],new Uint32Array(b)[1]]=a;return new Float64Array(b)[0];}
function binaryStringToDouble(s){
	//if(s.length>64){s=s.slice(-64);}
	/*if(s.length<64){s="0".repeat(64-s.length)+s;}
	return decodeNumber([parseInt(s.slice(32,64),2),parseInt(s.slice(0,32),2)]);*/
	var l=s.length;return decodeNumber([parseInt(s.substring(l-32,l),2),parseInt(s.substring(l-64,l-32),2)]);
	/*var a=[0,0];
	for(i=31;i>=0;i--){if(s[i+32]==="1"){a[0]+=2**(31-i);}}
	for(i=31;i>=0;i--){if(s[i]==="1"){a[1]+=2**(31-i);}}
	return decodeNumber(a);*/
}

@AnastasiaDunbar
Copy link
Author

AnastasiaDunbar commented May 9, 2020

For crossfading/looping music:

//Please notice that `(a*(y-x))+x = (x*(1-a))+(y*a)`, except `(f(a)*(y-x))+x ≠ (x*f(1-a))+(y*f(a))` if `a` isn't 0 or 1 sometimes (or if `f` isn't symmetrical).
function mix_sqrt(x,y,a){return(x*Math.sqrt(1-a))+(y*Math.sqrt(a));}
function mix_both(x,y,a,b){return a*(b-1)*(x-y)+Math.sqrt(1-a)*b*x+Math.sqrt(a)*b*y-(b-1)*x;} //`mix(mix(x,y,a),mix_sqrt(x,y,a),b)`.
function mix_sin(x,y,a){return((a-(Math.sin(TAU*(.5-a))/TAU))*(y-x))+x;}
function mix_sin_pow(x,y,a,b){return a<=0?x:(a>=1?y:(x*Math.pow(sin_ease(1-a),b))+(y*Math.pow(sin_ease(a),b)));}

//function saturate(x){return Math.min(Math.max(x,0),1);}function smoothstep(a,b,x){x=saturate((x-a)/(b-a));return x*x*(3-2*x);} //In GLSL…
function cubic_ease(x){return x*x*(3-2*x);}
function ease(x){return x<.5?2*x*x:1-(2*(1-x)*(1-x));} //Has a pointy derivative.
function int_ease(x){return Math.abs(x-.5)>.25?(x<.5?((16/3)*x*x*x):((16/3)*Math.pow(x-1,3))+1):((-(16*x*x*x/3)+(8*x*x)-(2*x))+(1/6));} //Based on `integrate ease(1-2*abs(x-.5))*2`. Also has a pointy derivative.
function sin_ease(x){return x-(Math.sin(TAU*(.5-x))/TAU);} //Smoothest.

@AnastasiaDunbar
Copy link
Author

AnastasiaDunbar commented Nov 24, 2020

About a pseudorandom function again, here's another idea:

function decodeNumber(a){var b=new ArrayBuffer(8);[new Uint32Array(b)[0],new Uint32Array(b)[1]]=a;return new Float64Array(b)[0];}
function generateRandom(){
	var p=Math.random();
	p=(((Math.log(p-Math.pow(2,-31)*(p-1))/(31*Math.log(2)))+1)*31)&31;
	var n=[0,(p<<20)|1040187392];
	for(var i=31-p;i<52;i++){
		n[i/32|0]|=(Math.random()<.5)<<i%32;
	}
	return decodeNumber(n);
}

Just need to find out what algorithm Math.random() can be replaced with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment