面板
This commit is contained in:
+21
-74
@@ -369,83 +369,30 @@ function playIntroSound() {
|
||||
const now = ctx.currentTime;
|
||||
const master = ctx.createGain();
|
||||
master.gain.setValueAtTime(0.0001, now);
|
||||
master.gain.linearRampToValueAtTime(0.55, now + 0.06);
|
||||
master.gain.linearRampToValueAtTime(0.5, now + 0.05);
|
||||
master.connect(ctx.destination);
|
||||
|
||||
// 1. 深空底噪:50Hz + 100Hz 正弦,贯穿全程
|
||||
[50, 100].forEach(f => {
|
||||
const o = ctx.createOscillator(); o.type = 'sine'; o.frequency.value = f;
|
||||
const g = ctx.createGain();
|
||||
g.gain.setValueAtTime(0.0001, now);
|
||||
g.gain.linearRampToValueAtTime(0.05, now + 0.8);
|
||||
g.gain.setValueAtTime(0.05, now + 4.2);
|
||||
g.gain.linearRampToValueAtTime(0.0001, now + 5.2);
|
||||
o.connect(g).connect(master); o.start(now); o.stop(now + 5.3);
|
||||
});
|
||||
// 干净的「铃」音:正弦主音 + 高八度泛音增亮,平滑指数衰减
|
||||
function bell(freq, start, dur, vol) {
|
||||
const o1 = ctx.createOscillator(); o1.type = 'sine'; o1.frequency.value = freq;
|
||||
const o2 = ctx.createOscillator(); o2.type = 'sine'; o2.frequency.value = freq * 2;
|
||||
const g1 = ctx.createGain();
|
||||
g1.gain.setValueAtTime(0.0001, start);
|
||||
g1.gain.exponentialRampToValueAtTime(vol, start + 0.012);
|
||||
g1.gain.exponentialRampToValueAtTime(0.0001, start + dur);
|
||||
const g2 = ctx.createGain();
|
||||
g2.gain.setValueAtTime(0.0001, start);
|
||||
g2.gain.exponentialRampToValueAtTime(vol * 0.3, start + 0.012);
|
||||
g2.gain.exponentialRampToValueAtTime(0.0001, start + dur * 0.55);
|
||||
o1.connect(g1).connect(master); o1.start(start); o1.stop(start + dur + 0.05);
|
||||
o2.connect(g2).connect(master); o2.start(start); o2.stop(start + dur + 0.05);
|
||||
}
|
||||
|
||||
// 2. 低频滤波噪声扫过(0.2s - 1.5s)
|
||||
const len = Math.floor(ctx.sampleRate * 1.4);
|
||||
const buf = ctx.createBuffer(1, len, ctx.sampleRate);
|
||||
const data = buf.getChannelData(0);
|
||||
for (let i = 0; i < len; i++) data[i] = (Math.random() * 2 - 1) * Math.pow(1 - i / len, 1.4);
|
||||
const noise = ctx.createBufferSource(); noise.buffer = buf;
|
||||
const nf = ctx.createBiquadFilter(); nf.type = 'lowpass';
|
||||
nf.frequency.setValueAtTime(800, now + 0.2); nf.frequency.linearRampToValueAtTime(2200, now + 0.9); nf.frequency.linearRampToValueAtTime(600, now + 1.5);
|
||||
const ng = ctx.createGain();
|
||||
ng.gain.setValueAtTime(0.0001, now + 0.2); ng.gain.linearRampToValueAtTime(0.16, now + 0.7); ng.gain.linearRampToValueAtTime(0.0001, now + 1.5);
|
||||
noise.connect(nf).connect(ng).connect(master); noise.start(now + 0.2); noise.stop(now + 1.6);
|
||||
|
||||
// 3. 数字 glitch 短鸣(0.5 / 0.9 / 1.3s)
|
||||
[0.5, 0.9, 1.3].forEach((t, i) => {
|
||||
const o = ctx.createOscillator(); o.type = 'square';
|
||||
o.frequency.setValueAtTime(1200 + i * 600, now + t); o.frequency.exponentialRampToValueAtTime(1800 + i * 400, now + t + 0.04);
|
||||
const g = ctx.createGain();
|
||||
g.gain.setValueAtTime(0.0001, now + t); g.gain.exponentialRampToValueAtTime(0.05, now + t + 0.01); g.gain.exponentialRampToValueAtTime(0.0001, now + t + 0.08);
|
||||
o.connect(g).connect(master); o.start(now + t); o.stop(now + t + 0.1);
|
||||
});
|
||||
|
||||
// 4. 上扬合成器扫频(1.2s - 2.7s)
|
||||
const sweep = ctx.createOscillator(); sweep.type = 'sawtooth';
|
||||
sweep.frequency.setValueAtTime(180, now + 1.2); sweep.frequency.exponentialRampToValueAtTime(1100, now + 2.5);
|
||||
const sg = ctx.createGain();
|
||||
sg.gain.setValueAtTime(0.0001, now + 1.2); sg.gain.linearRampToValueAtTime(0.11, now + 2.0); sg.gain.linearRampToValueAtTime(0.0001, now + 2.7);
|
||||
const sf = ctx.createBiquadFilter(); sf.type = 'lowpass';
|
||||
sf.frequency.setValueAtTime(600, now + 1.2); sf.frequency.linearRampToValueAtTime(3200, now + 2.5);
|
||||
sweep.connect(sf).connect(sg).connect(master); sweep.start(now + 1.2); sweep.stop(now + 2.8);
|
||||
|
||||
// 5. 冲击点(2.4s):噪声爆发 + 低频重击
|
||||
const impactLen = Math.floor(ctx.sampleRate * 0.35);
|
||||
const impactBuf = ctx.createBuffer(1, impactLen, ctx.sampleRate);
|
||||
const id = impactBuf.getChannelData(0);
|
||||
for (let i = 0; i < impactLen; i++) id[i] = (Math.random() * 2 - 1) * Math.pow(1 - i / impactLen, 1.2);
|
||||
const impactNoise = ctx.createBufferSource(); impactNoise.buffer = impactBuf;
|
||||
const impactF = ctx.createBiquadFilter(); impactF.type = 'bandpass'; impactF.frequency.value = 450; impactF.Q.value = 1.2;
|
||||
const impactG = ctx.createGain();
|
||||
impactG.gain.setValueAtTime(0.0001, now + 2.4); impactG.gain.exponentialRampToValueAtTime(0.24, now + 2.42); impactG.gain.exponentialRampToValueAtTime(0.0001, now + 2.85);
|
||||
impactNoise.connect(impactF).connect(impactG).connect(master); impactNoise.start(now + 2.4); impactNoise.stop(now + 2.9);
|
||||
const thump = ctx.createOscillator(); thump.type = 'sine';
|
||||
thump.frequency.setValueAtTime(90, now + 2.4); thump.frequency.exponentialRampToValueAtTime(35, now + 2.8);
|
||||
const thumpG = ctx.createGain();
|
||||
thumpG.gain.setValueAtTime(0.0001, now + 2.4); thumpG.gain.exponentialRampToValueAtTime(0.28, now + 2.43); thumpG.gain.exponentialRampToValueAtTime(0.0001, now + 2.9);
|
||||
thump.connect(thumpG).connect(master); thump.start(now + 2.4); thump.stop(now + 2.95);
|
||||
|
||||
// 6. 科技琶音(2.9s - 4.3s)
|
||||
[523.25, 659.25, 783.99, 1046.50, 783.99, 659.25].forEach((f, i) => {
|
||||
const t = now + 2.9 + i * 0.24;
|
||||
const o = ctx.createOscillator(); o.type = 'triangle'; o.frequency.value = f;
|
||||
const g = ctx.createGain();
|
||||
g.gain.setValueAtTime(0.0001, t); g.gain.exponentialRampToValueAtTime(0.08, t + 0.02); g.gain.exponentialRampToValueAtTime(0.0001, t + 0.55);
|
||||
o.connect(g).connect(master); o.start(t); o.stop(t + 0.6);
|
||||
});
|
||||
|
||||
// 7. 最终揭示和弦(4.4s - 5.2s)
|
||||
[392.00, 523.25, 659.25, 783.99].forEach((f, i) => {
|
||||
const t = now + 4.4 + i * 0.04;
|
||||
const o = ctx.createOscillator(); o.type = 'sine'; o.frequency.value = f;
|
||||
const g = ctx.createGain();
|
||||
g.gain.setValueAtTime(0.0001, t); g.gain.exponentialRampToValueAtTime(0.12, t + 0.05); g.gain.exponentialRampToValueAtTime(0.0001, t + 1.0);
|
||||
o.connect(g).connect(master); o.start(t); o.stop(t + 1.1);
|
||||
});
|
||||
// 开场:极轻星光一闪(光点感)
|
||||
bell(1046.50, now + 0.2, 0.45, 0.06);
|
||||
// 揭示「叮咚」门铃:高音 ding -> 低音 dong
|
||||
bell(1567.98, now + 3.6, 0.55, 0.22); // G6 叮
|
||||
bell(1046.50, now + 4.25, 0.95, 0.22); // C6 咚
|
||||
|
||||
return master;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user