Renders a spectrum analyzer for the incoming audio signal. @name spectrum @tags visualization @param {object} config optional config with options: @param {integer} thickness line thickness in px (default 3) @param {integer} speed scroll speed (default 1) @param {integer} min min db (default -80) @param {integer} max max db (default 0) @example n("<0 4 <2 3> 1>*3") .off(1/8, add(n(5))) .off(1/5, add(n(7))) .scale("d3:minor:pentatonic") .s('sine') .dec(.3).room(.5) ._spectrum()
23let latestColor = {}; 24Pattern.prototype.spectrum = function (config = {}) { 25 let id = config.id ?? 1; 26 return this.analyze(id).draw( 27 (haps) => { 28 config.color = haps[0]?.value?.color || latestColor[id] || getTheme().foreground; 29 latestColor[id] = config.color; 30 drawSpectrum(analysers[id], config); 31 }, 32 { id }, 33 ); 34};
36Pattern.prototype.scope = Pattern.prototype.tscope; 37 38const lastFrames = new Map(); 39 40function drawSpectrum( 41 analyser, 42 { thickness = 3, speed = 1, min = -80, max = 0, ctx = getDrawContext(), id = 1, color } = {}, 43) { 44 ctx.lineWidth = thickness; 45 ctx.strokeStyle = color; 46 47 if (!analyser) { 48 // if analyser is undefined, draw straight line 49 // it may be undefined when no sound has been played yet 50 return; 51 } 52 const scrollSize = speed; 53 const dataArray = getAnalyzerData('frequency', id); 54 const canvas = ctx.canvas; 55 ctx.fillStyle = color; 56 const bufferSize = analyser.frequencyBinCount; 57 let imageData = lastFrames.get(id) || ctx.getImageData(0, 0, canvas.width, canvas.height); 58 lastFrames.set(id, imageData); 59 ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); 60 ctx.putImageData(imageData, -scrollSize, 0); 61 let q = canvas.width - speed; 62 for (let i = 0; i < bufferSize; i++) { 63 const normalized = clamp((dataArray[i] - min) / (max - min), 0, 1); 64 ctx.globalAlpha = normalized; 65 const next = (Math.log(i + 1) / Math.log(bufferSize)) * canvas.height; 66 const size = 2; //next - pos; 67 ctx.fillRect(q, canvas.height - next, scrollSize, size); 68 } 69 lastFrames.set(id, ctx.getImageData(0, 0, canvas.width, canvas.height)); 70}