website/random/cassettevid/cv.js
2024-04-22 03:13:17 -05:00

131 lines
2.9 KiB
JavaScript

"use strict";
class VC
{
constructor( canvas, config )
{
const defConfig =
{
clearInterval: 50,
overScan: 0.82,
hOffset: 0.06525,
pulseLength: ( 0.2 / 1000 ),
lineWidth: 2.5,
brightness: 1,
saturation: 1,
blend: false,
hFreq: 225.0,
vFreq: 3
};
config = Object.assign( defConfig, config );
this.lines = [];
this.lastClear = 0;
this.clearInterval = config.clearInterval;
this.canvas = canvas;
this.width = this.canvas.width;
this.height = this.canvas.height;
this.lineWidth = config.lineWidth;
this.blend = config.blend;
this.config = config;
this.graphicsContext = null;
this.audioContext = null;
this.audioInput = null;
this.decoder = null;
}
async start()
{
this.graphicsContext = this.canvas.getContext( "2d" );
this.audioContext = new window.AudioContext();
let stream = await navigator.mediaDevices.getUserMedia(
{
audio: {
echoCancellation: false,
noiseSuppression: false,
autoGainControl: false,
channelCount: {
exact: 2
}
}
} );
this.audioInput = this.audioContext.createMediaStreamSource( stream );
await this.audioContext.audioWorklet.addModule( 'cv-decoder.js' )
this.decoder = new AudioWorkletNode( this.audioContext, 'cv-decoder',
{
numberOfInputs: 2,
numberOfOutputs: 0,
processorOptions: this.config
}
);
this.decoder.port.onmessage = event =>
{
if( this.lines.length < 1024 )
this.lines.push( event.data )
};
this.audioInput.connect( this.decoder );
requestAnimationFrame( () => this.draw() );
}
activate()
{
this.audioContext.resume();
}
draw()
{
if( Date.now() - this.lastClear > this.clearInterval )
{
this.graphicsContext.fillStyle = 'rgba(0,0,0,0.05)';
this.graphicsContext.globalCompositeOperation = 'source-over';
this.graphicsContext.fillRect( 0, 0, this.width, this.height );
this.lastClear = Date.now();
}
if( this.blend )
this.graphicsContext.globalCompositeOperation = 'screen';
else
this.graphicsContext.globalCompositeOperation = 'source-over';
this.graphicsContext.lineWidth = this.lineWidth;
const width = this.width;
const height = this.height;
for( let line of this.lines )
{
var gradient = this.graphicsContext.createLinearGradient( line.x1 * width, line.y * height, line.x2 * width, line.y * height );
for( let color of line.colors )
gradient.addColorStop( color.phase / line.maxPhase, 'rgb(' + color.r + ',' + color.g + ',' + color.b + ')' );
this.graphicsContext.beginPath();
this.graphicsContext.moveTo( line.x1 * width + Math.random() * 2.0 - 1.0, line.y * height + Math.random() * 2.0 - 1.0 );
this.graphicsContext.lineTo( line.x2 * width + Math.random() * 2.0 - 1.0, line.y * height + Math.random() * 2.0 - 1.0 );
this.graphicsContext.strokeStyle = gradient;
this.graphicsContext.stroke();
}
this.lines = [];
requestAnimationFrame( () => this.draw() );
}
}