diff --git a/index.html b/index.html index f37c63e..2336c63 100644 --- a/index.html +++ b/index.html @@ -875,16 +875,17 @@ function noiseSpec() { const n = state.history.filter((t) => t.noise).length, kind = (String(state.seed).match(/\b(brown|pink|rain|white|crackle)\b/i) || [])[1]?.toLowerCase() || NOISES[n % NOISES.length]; return { title: `${kind} noise`, tags: `${kind} noise, room tone, made on this device`, lyrics: "", bpm: 60, key: "—", energy: 0.1, seconds: 300, meter: "4/4", noise: kind, station: state.station || "the noise floor", line: "nothing to learn here, just the room", seed: state.seed, made: Date.now(), look: state.look || "rings", palette: state.palette || "duo" }; } -function makeNoise(kind, seconds) { - const sr = 22050, n = sr * seconds, out = new Int16Array(n), rnd = prng(hash32(kind + seconds) || 1); +async function makeNoise(kind, seconds) { + const sr = 16000, n = sr * seconds, out = new Int16Array(n), rnd = prng(hash32(kind + seconds) || 1); let b = 0, b0 = 0, b1 = 0, b2 = 0, lp = 0, drop = 0, dropLen = 0, dropAmp = 0; for (let i = 0; i < n; i++) { + if (i % (sr * 5) === 0 && i) await new Promise((r) => setTimeout(r, 0)); // a slice at a time: the page keeps breathing const w = rnd() * 2 - 1; let v; if (kind === "white") v = w * 0.25; - else if (kind === "brown") { b = (b + 0.02 * w) / 1.02; v = b * 3.5; } + else if (kind === "brown") { b = (b + 0.02 * w) / 1.02; v = b * 2.2; } else if (kind === "pink") { b0 = 0.99765 * b0 + w * 0.0990460; b1 = 0.96300 * b1 + w * 0.2965164; b2 = 0.57000 * b2 + w * 1.0526913; v = (b0 + b1 + b2 + w * 0.1848) * 0.12; } else if (kind === "rain") { lp += (w - lp) * 0.3; v = lp * 0.5; if (drop <= 0 && rnd() < 0.004) { drop = dropLen = 30 + Math.floor(rnd() * 120); dropAmp = 0.15 + rnd() * 0.35; } if (drop > 0) { v += dropAmp * (drop / dropLen) * w; drop--; } } - else { lp += (w - lp) * 0.08; v = lp * 1.2; if (rnd() < 0.0015) { drop = dropLen = 20 + Math.floor(rnd() * 80); dropAmp = 0.3 + rnd() * 0.5; } if (drop > 0) { v += dropAmp * (drop / dropLen) * w; drop--; } } + else { lp += (w - lp) * 0.08; v = lp * 1.0; if (rnd() < 0.0015) { drop = dropLen = 20 + Math.floor(rnd() * 80); dropAmp = 0.3 + rnd() * 0.5; } if (drop > 0) { v += dropAmp * (drop / dropLen) * w; drop--; } } const fade = Math.min(1, i / (sr * 2), (n - i) / (sr * 2)); out[i] = Math.max(-1, Math.min(1, v * fade)) * 32767; } @@ -912,7 +913,7 @@ async function speak(spec) { return res.blob(); } async function renderTrack(spec, onStatus) { - if (spec.noise) { await new Promise((r) => setTimeout(r, 50)); return makeNoise(spec.noise, spec.seconds || 300); } + if (spec.noise) return makeNoise(spec.noise, spec.seconds || 300); if (spec.spoken) return speak(spec); if (!state.key) { // shared worker: one call, audio back (Runware when the factory has a key, else Venice) const started = Date.now(), tick = setInterval(() => onStatus && onStatus(Math.round((Date.now() - started) / 1000), 0, false), 1000);