TinyChan

New reply in topic: Random discussions thread

You are not recognized as the original poster of this topic.

:

You are required to fill in a captcha for your first 5 posts. Sorry, but this is required to stop people from posting while drunk. Please be responsible and don't drink and post!
If you receive this often, consider not clearing your cookies.

Please familiarise yourself with the rules and markup syntax before posting.


Replying to Anonymous Z-31…

/*
	(2025-03-19 09:34) 01:57 remaining, thinking about additive harmonic synthesis.
	Every online notepad is completely ad-ridden with GDPR cookie pop-ups, so I had to use Sublime Text…
	(10:34) 00:57, almost done… (11:08) 00:23, I think I'm done…
*/
const TAU=Math.PI*2,
      clamp=(x,mn=0,mx=1)=>Math.min(Math.max(x,mn),mx),
      pointInRect=(x,y,rx,ry,rw,rh)=>x>=rx&&x<rx+rw&&y>=ry&&y<ry+rh,
      sineHarm=(x,phase,n)=>Math.sin(TAU*(phase+n*x));
class Graph{
	constructor(x,y,w,h,numBars=16){
		this.x=x;this.y=y;this.w=w;this.h=h;
		this.levels=Array(numBars).fill(0);
		this.dragging=false;
		this.fillColor=[255,255,255];this.bgColor=[16,16,16];
	}
	pressed(mx,my){
		this.dragging=pointInRect(mouseX,mouseY,this.x,this.y,this.w,this.h);
		if(this.dragging)this.drag(mx,my); //click
	}
	released(mx,my){
		this.dragging=false;
	}
	drag(mx,my){
		if(!this.dragging)return;
		let l=this.levels.length,
		    i=Math.floor(clamp(((mx-this.x)/this.w)*l,0,l-1)),
		    y=1-clamp((my-this.y)/this.h,0,1);
		this.levels[i]=y;
	}
	display(){
		let l=this.levels.length;
		fill(this.bgColor);stroke(this.dragging*4);
		rect(this.x,this.y,this.w,this.h);
		for(let i=1;i<l;i++){
			let x=(this.w/l)*i;
			line(this.x+x,this.y,this.x+x,this.y+this.h);
		}
		fill(this.fillColor);
		for(let i=0;i<l;i++){
			let h=clamp(this.levels[i],0,1)*this.h;
			rect(this.x+i*(this.w/l),this.y+(this.h-h),this.w/l,h);
		}
	}
}
class Plot{
	constructor(x,y,w,h,numPoints=16,color=[0,0,255]){
		this.x=x;this.y=y;this.w=w;this.h=h;
		this.points=Array(numPoints).fill(0);
		this.bottomRange=-1;this.upperRange=1;
		this.color=color;
	}
	display(){
		stroke(0,64);noFill();
		rect(this.x,this.y,this.w,this.h);
		line(this.x,this.y+this.h*.5,this.x+this.w,this.y+this.h*.5);
		let l=this.points.length,step=this.w/(l-1);
		stroke(this.color);
		beginShape();
		for(let i=0;i<l;i++){
			let x=this.x+i*step,
			    y=map(this.points[i],this.bottomRange,this.upperRange,this.y+this.h,this.y);
			vertex(x,y);
		}
		endShape();
	}
}
class Button{
	constructor(x,y,w,h,label,onPress){
		this.x=x;this.y=y;this.w=w;this.h=h;
		this.label=label;
		this.onPress=onPress;
	}
	display(){
		let hover=pointInRect(mouseX,mouseY,this.x,this.y,this.w,this.h);
		fill(hover?100:64);stroke(0);
		rect(this.x,this.y,this.w,this.h);
		fill(255);noStroke();
		textSize(14);textAlign(CENTER,CENTER);
		text(this.label,this.x+this.w*.5,this.y+this.h*.5);
	}
	pressed(mx,my){
		if(pointInRect(mx,my,this.x,this.y,this.w,this.h)){
			this.onPress();
			return true;
		}
		return false;
	}
}
let amp=new Graph(16,16,300,128,32),
    phase=new Graph(amp.x,amp.y+amp.h,amp.w,amp.h,amp.levels.length),
    waveform=new Plot(phase.x,phase.y+phase.h,phase.w,phase.h,phase.levels.length*4),
    bW=120,bH=32,bS=3,buttons=[
		{label:"Clear",onPress:()=>{
			for(let i=0;i<amp.levels.length;i++)amp.levels[i]=0;
			for(let i=0;i<phase.levels.length;i++)phase.levels[i]=0;
		}},
		{label:"Sine",onPress:()=>{
			for(let i=0;i<amp.levels.length;i++)amp.levels[i]=0;
			amp.levels[0]=1;
			for(let i=0;i<phase.levels.length;i++)phase.levels[i]=0;
		}},
		{label:"Test",onPress:()=>{
			let n=amp.levels.length;
			for(let i=0;i<n;i++){
				amp.levels[i]=i%2?TAU/(TAU*i):0;
				phase.levels[i]=(i%4)<2?0:.5;
			}
		}},
		{label:"Pulse",onPress:()=>{
			for(let i=0;i<amp.levels.length;i++){
				if(i%2===0){
					amp.levels[i]=1/(i+1);
					phase.levels[i]=0;
				}else{
					amp.levels[i]=0;
					phase.levels[i]=0;
				}
			}
		}},
		{label:"Triangle",onPress:()=>{
			for(let i=0;i<amp.levels.length;i++){
				if(i%2===0){
					amp.levels[i]=1/Math.pow(i+1,2);
					let k=i/2;
					phase.levels[i]=k%2===1?.5:0;
				}else{
					amp.levels[i]=0;
					phase.levels[i]=0;
				}
			}
		}}
    ].map((e,i)=>new Button(waveform.x+bW*(i%bS),waveform.y+waveform.h+16+Math.floor(i/bS)*bH,bW,bH,e.label,e.onPress));
amp.levels[0]=1;amp.bgColor=[51,82,59];amp.fillColor=[154,201,101];
phase.bgColor=[50,63,97];phase.fillColor=[91,174,222];
waveform.update=function(){
	let l=this.points.length;
	for(let i=0;i<l;i++){
		let sum=0;
		for(let j=0;j<amp.levels.length;j++)
			sum+=sineHarm(i/l,phase.levels[j],1+j)*amp.levels[j];
		this.points[i]=sum;
	}
	let minVal=Math.min(...this.points),maxVal=Math.max(...this.points),
	    allEqual=this.points.every((val,i,arr)=>val===arr[0]);
	this.bottomRange=allEqual?this.points[0]-1:minVal;
	this.upperRange=allEqual?this.points[0]+1:maxVal;
};
waveform.update();
function setup(){
	createCanvas(windowWidth,windowHeight);
}
function draw(){
	background(200);
	for(let o of[amp,phase,waveform,...buttons])o.display();
}
function mousePressed(){
	for(let o of[amp,phase,...buttons])o.pressed(mouseX,mouseY);
	waveform.update();
}
function mouseDragged(){
	for(let o of[amp,phase])o.drag(mouseX,mouseY);
	waveform.update();
}
function mouseReleased(){
	for(let o of[amp,phase])o.released(mouseX,mouseY);
}