User:Pailiaq/common.js: Difference between revisions
Jump to navigation
Jump to search
testing |
No edit summary |
||
| Line 32: | Line 32: | ||
var now = c.currentTime; | var now = c.currentTime; | ||
var base = 261.63; // middle C | var base = 261.63; // middle C | ||
var attack = 0.02, sustain = | var attack = 0.02, sustain = 0.3, release = 2.5; | ||
var totalDur = attack + sustain + release; | var totalDur = attack + sustain + release; | ||
var peak = 0.18 / Math.sqrt(centsArr.length); | var peak = 0.18 / Math.sqrt(centsArr.length); | ||
Revision as of 01:38, 26 May 2026
(function () {
'use strict';
var ctx = null;
var activeNodes = [];
var activeBtn = null;
function getCtx() {
if (!ctx) ctx = new (window.AudioContext || window.webkitAudioContext)();
return ctx;
}
function stopAll() {
if (!ctx) return;
var now = ctx.currentTime;
activeNodes.forEach(function (n) {
try {
n.gain.gain.cancelScheduledValues(now);
n.gain.gain.setValueAtTime(n.gain.gain.value, now);
n.gain.gain.exponentialRampToValueAtTime(0.0001, now + 0.05);
n.osc.stop(now + 0.06);
} catch (e) {}
});
activeNodes = [];
if (activeBtn) { activeBtn.classList.remove('playing'); activeBtn = null; }
}
function playChord(centsArr, btn) {
stopAll();
var c = getCtx();
if (c.state === 'suspended') c.resume();
var now = c.currentTime;
var base = 261.63; // middle C
var attack = 0.02, sustain = 0.3, release = 2.5;
var totalDur = attack + sustain + release;
var peak = 0.18 / Math.sqrt(centsArr.length);
centsArr.forEach(function (cents) {
var osc = c.createOscillator();
var gain = c.createGain();
osc.type = 'triangle';
osc.frequency.value = base * Math.pow(2, cents / 1200);
gain.gain.setValueAtTime(0, now);
gain.gain.linearRampToValueAtTime(peak, now + attack);
gain.gain.setValueAtTime(peak, now + attack + sustain);
gain.gain.exponentialRampToValueAtTime(0.0001, now + totalDur);
osc.connect(gain).connect(c.destination);
osc.start(now);
osc.stop(now + totalDur + 0.1);
activeNodes.push({ osc: osc, gain: gain });
});
if (btn) {
btn.classList.add('playing');
activeBtn = btn;
setTimeout(function () {
if (activeBtn === btn) { btn.classList.remove('playing'); activeBtn = null; }
}, totalDur * 1000);
}
}
function handle(e) {
var btn = e.target.closest && e.target.closest('.edo-chord-play');
if (!btn) return;
e.preventDefault();
if (btn === activeBtn) { stopAll(); return; } // click again to stop
var edo = parseInt(btn.dataset.edo, 10);
var steps = (btn.dataset.steps || '').split(',').map(Number);
if (!edo || !steps.length) return;
var stepSize = 1200 / edo;
playChord(steps.map(function (s) { return s * stepSize; }), btn);
}
document.addEventListener('click', handle);
document.addEventListener('keydown', function (e) {
if ((e.key === 'Enter' || e.key === ' ') && e.target.classList && e.target.classList.contains('edo-chord-play')) {
handle(e);
}
});
}());