From 965794712e435bcd5d157dfaf6eace8a03a999df Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Fri, 25 Aug 2023 12:39:47 +0200 Subject: [PATCH] fscope + scaling options --- packages/core/scope.mjs | 66 ++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 14 deletions(-) diff --git a/packages/core/scope.mjs b/packages/core/scope.mjs index 62b08e62..908ed254 100644 --- a/packages/core/scope.mjs +++ b/packages/core/scope.mjs @@ -2,8 +2,12 @@ import { Pattern } from './pattern.mjs'; import { getDrawContext } from './draw.mjs'; import { analyser } from '@strudel.cycles/webaudio'; -export function drawTimeScope(analyser, dataArray, { align = true, color = 'white', thickness = 2 } = {}) { +export function drawTimeScope( + analyser, + { align = true, color = 'white', thickness = 3, scale = 1, pos = 0.75, next = 1 } = {}, +) { const canvasCtx = getDrawContext(); + const dataArray = getAnalyzerData('time'); canvasCtx.lineWidth = thickness; canvasCtx.strokeStyle = color; @@ -13,16 +17,18 @@ export function drawTimeScope(analyser, dataArray, { align = true, color = 'whit const bufferSize = analyser.frequencyBinCount; const triggerValue = 256 / 2; - const triggerIndex = align + let triggerIndex = align ? Array.from(dataArray).findIndex((v, i, arr) => i && arr[i - 1] < triggerValue && v >= triggerValue) : 0; + triggerIndex = Math.max(triggerIndex, 0); // fallback to 0 when no trigger is found const sliceWidth = (canvas.width * 1.0) / bufferSize; let x = 0; for (let i = triggerIndex; i < bufferSize; i++) { const v = dataArray[i] / 128.0; - const y = (v * (canvas.height / 2)) / 2 + canvas.height / 2; + const y = (scale * (v - 1) + pos) * canvas.height; + if (i === 0) { canvasCtx.moveTo(x, y); } else { @@ -33,16 +39,48 @@ export function drawTimeScope(analyser, dataArray, { align = true, color = 'whit canvasCtx.stroke(); } -Pattern.prototype.scope = function (config = {}) { - return this.analyze(1).draw((ctx) => { - let data = getAnalyzerData('time'); - const { smear = 0 } = config; - if (!smear) { - ctx.clearRect(0, 0, window.innerWidth, window.innerHeight); - } else { - ctx.fillStyle = `rgba(0,0,0,${1 - smear})`; - ctx.fillRect(0, 0, window.innerWidth, window.innerHeight); - } - data && drawTimeScope(analyser, data, config); +export function drawFrequencyScope(analyser, { color = 'white', scale = 1, pos = 0.75, lean = 0.5 } = {}) { + const dataArray = getAnalyzerData('frequency'); + const canvasCtx = getDrawContext(); + const canvas = canvasCtx.canvas; + + canvasCtx.fillStyle = color; + const bufferSize = analyser.frequencyBinCount; + const sliceWidth = (canvas.width * 1.0) / bufferSize; + + let x = 0; + for (let i = 0; i < bufferSize; i++) { + const v = (dataArray[i] / 256.0) * scale; + const h = v * canvas.height; + const y = (pos - v * lean) * canvas.height; + + canvasCtx.fillRect(x, y, Math.max(sliceWidth, 1), h); + x += sliceWidth; + } +} + +function clearScreen(smear = 0, smearRGB = `0,0,0`) { + const canvasCtx = getDrawContext(); + if (!smear) { + canvasCtx.clearRect(0, 0, canvasCtx.canvas.width, canvasCtx.canvas.height); + } else { + canvasCtx.fillStyle = `rgba(${smearRGB},${1 - smear})`; + canvasCtx.fillRect(0, 0, canvasCtx.canvas.width, canvasCtx.canvas.height); + } +} + +Pattern.prototype.fscope = function (config = {}) { + return this.analyze(1).draw(() => { + clearScreen(config.smear); + analyser && drawFrequencyScope(analyser, config); }); }; + +Pattern.prototype.tscope = function (config = {}) { + return this.analyze(1).draw(() => { + clearScreen(config.smear); + analyser && drawTimeScope(analyser, config); + }); +}; + +Pattern.prototype.scope = Pattern.prototype.tscope;