From dc5ea691804d924e50f7402670dc2effb4847799 Mon Sep 17 00:00:00 2001 From: Dorian Date: Sun, 8 Mar 2026 17:16:27 +0000 Subject: [PATCH] feat: style-specific music synths, add .pnpm-store to gitignore Music now uses per-track synthStyle for bass/lead/pad/arp instead of generic synths. Add .pnpm-store and .npmrc to gitignore. Co-Authored-By: Claude Opus 4.6 --- .gitignore | 2 ++ frontend/src/game/sounds.ts | 28 ++++++++-------------------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index 948c31b..8d9520a 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ __pycache__/ loop/loop.log server/data/ loop/ +.pnpm-store/ +.npmrc diff --git a/frontend/src/game/sounds.ts b/frontend/src/game/sounds.ts index 9a01a73..4921185 100644 --- a/frontend/src/game/sounds.ts +++ b/frontend/src/game/sounds.ts @@ -2763,39 +2763,27 @@ function playMusicBar() { } } - // Chord pad for the whole bar — louder during chorus + // Chord pad for the whole bar — style-specific pad synth const barDur = STEPS * step - const padVol = isChorus ? 0.06 : 0.04 const padFreqs = activeTrack.chords[bar].map(f => f * 2) - const padC = getCtx() - for (const freq of padFreqs) { - const osc = padC.createOscillator() - osc.type = 'triangle' - osc.frequency.value = freq - const g = padC.createGain() - g.gain.setValueAtTime(padVol, now) - g.gain.setValueAtTime(padVol, now + barDur * 0.8) - g.gain.exponentialRampToValueAtTime(0.001, now + barDur) - osc.connect(g); g.connect(musicGain) - osc.start(now); osc.stop(now + barDur) - } + STYLE_PAD[activeTrack.synthStyle](padFreqs, barDur, musicGain, now) for (let i = 0; i < STEPS; i++) { const t = now + i * step const idx = off + i const nd = step - 0.01 - // Layer 1: Bass — always plays - if (activeTrack.bass[idx] > 0) thickBass(activeTrack.bass[idx], nd, musicGain, t) + // Layer 1: Bass — style-specific synth + if (activeTrack.bass[idx] > 0) STYLE_BASS[activeTrack.synthStyle](activeTrack.bass[idx], nd, musicGain, t) - // Layer 2: FM lead — verse: needs higher intensity; chorus: plays freely + // Layer 2: Lead — style-specific synth; verse: needs higher intensity; chorus: plays freely if (activeTrack.lead[idx] > 0 && currentIntensity > leadThreshold) { - fmLead(activeTrack.lead[idx], nd * 0.8, musicGain, t) + STYLE_LEAD[activeTrack.synthStyle](activeTrack.lead[idx], nd * 0.8, musicGain, t) } - // Layer 3: Arpeggio — verse: needs high intensity; chorus: plays freely + // Layer 3: Arpeggio — style-specific waveform; verse: needs high intensity; chorus: plays freely if (activeTrack.arp[idx] > 0 && currentIntensity > arpThreshold) { - chorusTone(activeTrack.arp[idx], 'triangle', nd * 0.6, musicGain, t, 0.04 + currentIntensity * 0.04) + chorusTone(activeTrack.arp[idx], STYLE_ARP_TYPE[activeTrack.synthStyle], nd * 0.6, musicGain, t, 0.04 + currentIntensity * 0.04) } // Layer 4: Drums — intensity controls density