games: rotate through foley takes on every play, not just by v
Take-selection was keyed only on the caller's v, but callers pass small constants (chip is always v:0), so only the first take of each sound ever played. Add a per-name cursor that advances every call: consecutive plays now walk the takes, v just offsets simultaneous sounds and drives pitch.
This commit is contained in:
@@ -147,6 +147,13 @@
|
||||
var buffers = {};
|
||||
var warmed = false;
|
||||
|
||||
// A rotating cursor per sound, so that even a run of identical calls walks
|
||||
// through the takes rather than replaying the first one. Callers pass `v` to
|
||||
// separate simultaneous sounds (the cards of one deal), but many pass the same
|
||||
// constant every time — the cursor is what keeps a stack of chips from being the
|
||||
// same click over and over.
|
||||
var turn = {};
|
||||
|
||||
// decode fetches a file and turns it into a buffer, exactly once per filename.
|
||||
// decodeAudioData exists in a modern promise flavour and an old callback one;
|
||||
// this handles both so the foley works on older Safari too.
|
||||
@@ -179,14 +186,17 @@
|
||||
function sample(name, t0, v) {
|
||||
var cfg = SAMPLES[name];
|
||||
if (!cfg) return false;
|
||||
var i = Math.abs(Math.round(v));
|
||||
var buf = buffers[cfg.files[i % cfg.files.length]];
|
||||
// Advance the cursor, then offset it by v. The cursor guarantees consecutive
|
||||
// calls move to the next take; v spreads apart sounds fired together (one
|
||||
// deal's cards) so they don't all land on the same take at once.
|
||||
var k = (turn[name] = (turn[name] || 0) + 1) + Math.abs(Math.round(v));
|
||||
var buf = buffers[cfg.files[k % cfg.files.length]];
|
||||
if (!buf) return false; // not decoded yet, or failed: let synth cover it
|
||||
var src = ctx.createBufferSource();
|
||||
src.buffer = buf;
|
||||
// A few percent off pitch, spread across a small range keyed to v, so a run of
|
||||
// the same sound never reads as a loop.
|
||||
if (cfg.vary) src.playbackRate.value = 1 + (((i % 5) - 2) * cfg.vary);
|
||||
// A few percent off pitch, walking with the same cursor, so even a single-take
|
||||
// sound like the shuffle isn't pitch-identical twice in a row.
|
||||
if (cfg.vary) src.playbackRate.value = 1 + (((k % 5) - 2) * cfg.vary);
|
||||
var g = ctx.createGain();
|
||||
g.gain.value = cfg.gain == null ? 0.6 : cfg.gain;
|
||||
src.connect(g).connect(master);
|
||||
|
||||
Reference in New Issue
Block a user