use Float32 for higher precision

This commit is contained in:
Felix Roos 2023-08-25 16:29:41 +02:00
parent 988bd8ccdc
commit 2e31c8695a
2 changed files with 16 additions and 9 deletions

View File

@ -1,10 +1,11 @@
import { Pattern } from './pattern.mjs'; import { Pattern } from './pattern.mjs';
import { getDrawContext } from './draw.mjs'; import { getDrawContext } from './draw.mjs';
import { analyser } from '@strudel.cycles/webaudio'; import { analyser } from '@strudel.cycles/webaudio';
import { clamp } from './util.mjs';
export function drawTimeScope( export function drawTimeScope(
analyser, analyser,
{ align = true, color = 'white', thickness = 3, scale = 1, pos = 0.75, next = 1 } = {}, { align = true, color = 'white', thickness = 3, scale = 0.25, pos = 0.75, next = 1 } = {},
) { ) {
const ctx = getDrawContext(); const ctx = getDrawContext();
const dataArray = getAnalyzerData('time'); const dataArray = getAnalyzerData('time');
@ -16,7 +17,7 @@ export function drawTimeScope(
let canvas = ctx.canvas; let canvas = ctx.canvas;
const bufferSize = analyser.frequencyBinCount; const bufferSize = analyser.frequencyBinCount;
const triggerValue = 256 / 2; const triggerValue = 0;
let triggerIndex = align let triggerIndex = align
? Array.from(dataArray).findIndex((v, i, arr) => i && arr[i - 1] < triggerValue && v >= triggerValue) ? Array.from(dataArray).findIndex((v, i, arr) => i && arr[i - 1] < triggerValue && v >= triggerValue)
: 0; : 0;
@ -26,7 +27,7 @@ export function drawTimeScope(
let x = 0; let x = 0;
for (let i = triggerIndex; i < bufferSize; i++) { for (let i = triggerIndex; i < bufferSize; i++) {
const v = dataArray[i] / 128.0; const v = dataArray[i] + 1;
const y = (scale * (v - 1) + pos) * canvas.height; const y = (scale * (v - 1) + pos) * canvas.height;
if (i === 0) { if (i === 0) {
@ -39,7 +40,10 @@ export function drawTimeScope(
ctx.stroke(); ctx.stroke();
} }
export function drawFrequencyScope(analyser, { color = 'white', scale = 1, pos = 0.75, lean = 0.5 } = {}) { export function drawFrequencyScope(
analyser,
{ color = 'white', scale = 0.25, pos = 0.75, lean = 0.5, min = -150, max = 0 } = {},
) {
const dataArray = getAnalyzerData('frequency'); const dataArray = getAnalyzerData('frequency');
const ctx = getDrawContext(); const ctx = getDrawContext();
const canvas = ctx.canvas; const canvas = ctx.canvas;
@ -50,7 +54,8 @@ export function drawFrequencyScope(analyser, { color = 'white', scale = 1, pos =
let x = 0; let x = 0;
for (let i = 0; i < bufferSize; i++) { for (let i = 0; i < bufferSize; i++) {
const v = (dataArray[i] / 256.0) * scale; const normalized = clamp((dataArray[i] - min) / (max - min), 0, 1);
const v = normalized * scale;
const h = v * canvas.height; const h = v * canvas.height;
const y = (pos - v * lean) * canvas.height; const y = (pos - v * lean) * canvas.height;

View File

@ -128,19 +128,21 @@ export function getAnalyser(/* orbit, */ fftSize = 2048) {
analyserNode.fftSize = fftSize; analyserNode.fftSize = fftSize;
// getDestination().connect(analyserNode); // getDestination().connect(analyserNode);
analyser /* s[orbit] */ = analyserNode; analyser /* s[orbit] */ = analyserNode;
analyserData = new Uint8Array(analyser.frequencyBinCount); //analyserData = new Uint8Array(analyser.frequencyBinCount);
analyserData = new Float32Array(analyser.frequencyBinCount);
} }
if (analyser /* s[orbit] */.fftSize !== fftSize) { if (analyser /* s[orbit] */.fftSize !== fftSize) {
analyser /* s[orbit] */.fftSize = fftSize; analyser /* s[orbit] */.fftSize = fftSize;
analyserData = new Uint8Array(analyser.frequencyBinCount); //analyserData = new Uint8Array(analyser.frequencyBinCount);
analyserData = new Float32Array(analyser.frequencyBinCount);
} }
return analyser /* s[orbit] */; return analyser /* s[orbit] */;
} }
export function getAnalyzerData(type = 'time') { export function getAnalyzerData(type = 'time') {
const getter = { const getter = {
time: () => analyser?.getByteTimeDomainData(analyserData), time: () => analyser?.getFloatTimeDomainData(analyserData),
frequency: () => analyser?.getByteFrequencyData(analyserData), frequency: () => analyser?.getFloatFrequencyData(analyserData),
}[type]; }[type];
if (!getter) { if (!getter) {
throw new Error(`getAnalyzerData: ${type} not supported. use one of ${Object.keys(getter).join(', ')}`); throw new Error(`getAnalyzerData: ${type} not supported. use one of ${Object.keys(getter).join(', ')}`);