diff --git a/client/public/version.js b/client/public/version.js index 78693e1..bbbf0ce 100644 --- a/client/public/version.js +++ b/client/public/version.js @@ -1,5 +1,5 @@ // Maintainer-controlled web client version. // Format: YYYY.MM.DD Rn (example: 2026.02.20 R2) -window.CHGRID_WEB_VERSION = "2026.02.23 R214"; +window.CHGRID_WEB_VERSION = "2026.02.23 R215"; // Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid. window.CHGRID_TIME_ZONE = "America/Detroit"; diff --git a/client/src/audio/pianoSynth.ts b/client/src/audio/pianoSynth.ts index d4193cc..9ded5d3 100644 --- a/client/src/audio/pianoSynth.ts +++ b/client/src/audio/pianoSynth.ts @@ -41,6 +41,7 @@ type InstrumentPreset = { gain: number; sustainRatio?: number; holdSustain?: boolean; + heldDecayScale?: number; releaseScale?: number; vibrato?: { rateHz: number; depthCents: number }; }; @@ -55,6 +56,7 @@ const PRESETS: Record, InstrumentPreset> gain: 0.32, sustainRatio: 0.5, holdSustain: false, + heldDecayScale: 2.0, releaseScale: 0.9, }, electric_piano: { @@ -66,6 +68,7 @@ const PRESETS: Record, InstrumentPreset> gain: 0.3, sustainRatio: 0.52, holdSustain: false, + heldDecayScale: 2.0, releaseScale: 0.8, }, guitar: { @@ -77,6 +80,7 @@ const PRESETS: Record, InstrumentPreset> gain: 0.24, sustainRatio: 0.48, holdSustain: false, + heldDecayScale: 2.0, releaseScale: 0.7, }, organ: { @@ -308,7 +312,8 @@ export class PianoSynth { voiceGain.gain.exponentialRampToValueAtTime(sustainGain, now + attackSeconds + decaySeconds * 0.6); } else { // Struck/plucked timbres naturally decay even if the key remains held. - voiceGain.gain.exponentialRampToValueAtTime(0.0001, now + attackSeconds + decaySeconds); + const heldDecaySeconds = Math.max(0.25, decaySeconds * (preset.heldDecayScale ?? 2.0)); + voiceGain.gain.exponentialRampToValueAtTime(0.0001, now + attackSeconds + heldDecaySeconds); } let tailNode: AudioNode = voiceGain;