Make struck piano instruments decay while held

This commit is contained in:
Jage9
2026-02-23 01:20:27 -05:00
parent 4aa7f0bf4d
commit 4e1415aa1c
2 changed files with 18 additions and 2 deletions

View File

@@ -1,5 +1,5 @@
// Maintainer-controlled web client version. // Maintainer-controlled web client version.
// Format: YYYY.MM.DD Rn (example: 2026.02.20 R2) // Format: YYYY.MM.DD Rn (example: 2026.02.20 R2)
window.CHGRID_WEB_VERSION = "2026.02.23 R212"; window.CHGRID_WEB_VERSION = "2026.02.23 R213";
// Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid. // Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid.
window.CHGRID_TIME_ZONE = "America/Detroit"; window.CHGRID_TIME_ZONE = "America/Detroit";

View File

@@ -40,6 +40,7 @@ type InstrumentPreset = {
filter?: { type: BiquadFilterType; frequency: number; q?: number }; filter?: { type: BiquadFilterType; frequency: number; q?: number };
gain: number; gain: number;
sustainRatio?: number; sustainRatio?: number;
holdSustain?: boolean;
releaseScale?: number; releaseScale?: number;
vibrato?: { rateHz: number; depthCents: number }; vibrato?: { rateHz: number; depthCents: number };
}; };
@@ -53,6 +54,7 @@ const PRESETS: Record<Exclude<PianoInstrumentId, 'drum_kit'>, InstrumentPreset>
filter: { type: 'lowpass', frequency: 5200, q: 0.7 }, filter: { type: 'lowpass', frequency: 5200, q: 0.7 },
gain: 0.32, gain: 0.32,
sustainRatio: 0.5, sustainRatio: 0.5,
holdSustain: false,
releaseScale: 0.9, releaseScale: 0.9,
}, },
electric_piano: { electric_piano: {
@@ -63,6 +65,7 @@ const PRESETS: Record<Exclude<PianoInstrumentId, 'drum_kit'>, InstrumentPreset>
filter: { type: 'lowpass', frequency: 4200, q: 0.8 }, filter: { type: 'lowpass', frequency: 4200, q: 0.8 },
gain: 0.3, gain: 0.3,
sustainRatio: 0.52, sustainRatio: 0.52,
holdSustain: false,
releaseScale: 0.8, releaseScale: 0.8,
}, },
guitar: { guitar: {
@@ -73,6 +76,7 @@ const PRESETS: Record<Exclude<PianoInstrumentId, 'drum_kit'>, InstrumentPreset>
filter: { type: 'lowpass', frequency: 3200, q: 0.9 }, filter: { type: 'lowpass', frequency: 3200, q: 0.9 },
gain: 0.24, gain: 0.24,
sustainRatio: 0.48, sustainRatio: 0.48,
holdSustain: false,
releaseScale: 0.7, releaseScale: 0.7,
}, },
organ: { organ: {
@@ -84,6 +88,7 @@ const PRESETS: Record<Exclude<PianoInstrumentId, 'drum_kit'>, InstrumentPreset>
filter: { type: 'lowpass', frequency: 6500, q: 0.6 }, filter: { type: 'lowpass', frequency: 6500, q: 0.6 },
gain: 0.18, gain: 0.18,
sustainRatio: 0.72, sustainRatio: 0.72,
holdSustain: true,
releaseScale: 1.4, releaseScale: 1.4,
}, },
bass: { bass: {
@@ -94,6 +99,7 @@ const PRESETS: Record<Exclude<PianoInstrumentId, 'drum_kit'>, InstrumentPreset>
filter: { type: 'lowpass', frequency: 1500, q: 1.1 }, filter: { type: 'lowpass', frequency: 1500, q: 1.1 },
gain: 0.28, gain: 0.28,
sustainRatio: 0.45, sustainRatio: 0.45,
holdSustain: false,
releaseScale: 0.9, releaseScale: 0.9,
}, },
violin: { violin: {
@@ -104,6 +110,7 @@ const PRESETS: Record<Exclude<PianoInstrumentId, 'drum_kit'>, InstrumentPreset>
filter: { type: 'lowpass', frequency: 3600, q: 1.0 }, filter: { type: 'lowpass', frequency: 3600, q: 1.0 },
gain: 0.24, gain: 0.24,
sustainRatio: 0.68, sustainRatio: 0.68,
holdSustain: true,
releaseScale: 1.5, releaseScale: 1.5,
vibrato: { rateHz: 5.7, depthCents: 12 }, vibrato: { rateHz: 5.7, depthCents: 12 },
}, },
@@ -115,6 +122,7 @@ const PRESETS: Record<Exclude<PianoInstrumentId, 'drum_kit'>, InstrumentPreset>
filter: { type: 'lowpass', frequency: 5400, q: 0.9 }, filter: { type: 'lowpass', frequency: 5400, q: 0.9 },
gain: 0.2, gain: 0.2,
sustainRatio: 0.6, sustainRatio: 0.6,
holdSustain: true,
releaseScale: 1, releaseScale: 1,
vibrato: { rateHz: 6.8, depthCents: 9 }, vibrato: { rateHz: 6.8, depthCents: 9 },
}, },
@@ -126,6 +134,7 @@ const PRESETS: Record<Exclude<PianoInstrumentId, 'drum_kit'>, InstrumentPreset>
filter: { type: 'lowpass', frequency: 3300, q: 1.05 }, filter: { type: 'lowpass', frequency: 3300, q: 1.05 },
gain: 0.22, gain: 0.22,
sustainRatio: 0.62, sustainRatio: 0.62,
holdSustain: true,
releaseScale: 0.92, releaseScale: 0.92,
vibrato: { rateHz: 5.1, depthCents: 5 }, vibrato: { rateHz: 5.1, depthCents: 5 },
}, },
@@ -137,6 +146,7 @@ const PRESETS: Record<Exclude<PianoInstrumentId, 'drum_kit'>, InstrumentPreset>
filter: { type: 'lowpass', frequency: 5200, q: 1.2 }, filter: { type: 'lowpass', frequency: 5200, q: 1.2 },
gain: 0.22, gain: 0.22,
sustainRatio: 0.62, sustainRatio: 0.62,
holdSustain: true,
releaseScale: 0.65, releaseScale: 0.65,
}, },
}; };
@@ -292,8 +302,14 @@ export class PianoSynth {
voiceGain.gain.setValueAtTime(0.0001, now); voiceGain.gain.setValueAtTime(0.0001, now);
const peakGain = Math.max(0.0001, preset.gain * spatialMix.gain); const peakGain = Math.max(0.0001, preset.gain * spatialMix.gain);
const sustainGain = Math.max(0.0001, peakGain * (preset.sustainRatio ?? 0.55)); const sustainGain = Math.max(0.0001, peakGain * (preset.sustainRatio ?? 0.55));
const holdsSustain = preset.holdSustain !== false;
voiceGain.gain.exponentialRampToValueAtTime(peakGain, now + attackSeconds); voiceGain.gain.exponentialRampToValueAtTime(peakGain, now + attackSeconds);
if (holdsSustain) {
voiceGain.gain.exponentialRampToValueAtTime(sustainGain, now + attackSeconds + decaySeconds * 0.6); 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);
}
let tailNode: AudioNode = voiceGain; let tailNode: AudioNode = voiceGain;
if (preset.filter) { if (preset.filter) {