diff --git a/src/samples/drums/tom-high.ts b/src/samples/drums/tom-high.ts index 3d070b1..91202ac 100644 --- a/src/samples/drums/tom-high.ts +++ b/src/samples/drums/tom-high.ts @@ -1,5 +1,9 @@ -import {playTom1Low} from './tom-low.ts'; +import {triggerTom} from './tom-low.ts'; export function playTom2High(volume = 100) { - playTom1Low(120, 400, volume); + triggerTom(volume, { + frequency: 250, + decayTime: 0.3, + pitchDecay: 0.15 + }); } diff --git a/src/samples/drums/tom-low.ts b/src/samples/drums/tom-low.ts index a306f29..a855d04 100644 --- a/src/samples/drums/tom-low.ts +++ b/src/samples/drums/tom-low.ts @@ -1,27 +1,56 @@ import {createAudioContext} from '../sample-utils.ts'; -export function playTom1Low(hz = 99, durationInMs = 500, volume = 100) { - const audioContext = createAudioContext(); - // --- 1. Create an oscillator for the base tone --- - const oscillator = audioContext.createOscillator(); - oscillator.type = 'sine'; // Use a sine wave for the base - oscillator.frequency.setValueAtTime(hz, audioContext.currentTime); // Lower frequency for a deep tom sound - - // --- 2. Create a gain node for controlling volume --- - const gainNode = audioContext.createGain(); - gainNode.gain.setValueAtTime(volume / 100, audioContext.currentTime); // Increase initial gain for louder sound - gainNode.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.5); // Quick decay - - // --- 3. Add a slight detuning effect to make the tom sound richer --- - oscillator.detune.setValueAtTime(-5, audioContext.currentTime); // Small detuning for realism - - // --- 4. Connect nodes: oscillator -> gain -> output --- - oscillator.connect(gainNode); - gainNode.connect(audioContext.destination); - - // Start the oscillator - oscillator.start(); - - // Stop after 0.5 seconds (length of the sound) - oscillator.stop(audioContext.currentTime + (durationInMs / 1000)); +const defaults = { + frequency: 200, // Starting frequency + decayTime: 0.4, // How long the sound lasts + pitchDecay: 0.2, // How quickly the pitch drops +}; +export function triggerTom(volume = 50, settings = defaults) { + const context = createAudioContext(); + const time = context.currentTime; + // Convert volume (0-100) to gain (0-1) + const maxGain = Math.min(Math.max(volume, 0), 100) / 100; + const gainValue = Math.pow(maxGain, 2); + + // Create nodes + const osc = context.createOscillator(); + const gain = context.createGain(); + + // Set initial frequency + osc.frequency.setValueAtTime(settings.frequency, time); + + // Frequency envelope - faster decay than kick + osc.frequency.exponentialRampToValueAtTime( + settings.frequency * 0.01, + time + settings.pitchDecay + ); + + // Amplitude envelope + gain.gain.setValueAtTime(gainValue, time); + + // Smoother decay for the tom sound + gain.gain.exponentialRampToValueAtTime( + gainValue * 0.01, + time + settings.decayTime - 0.02 + ); + gain.gain.linearRampToValueAtTime( + 0, + time + settings.decayTime + ); + + // Connect nodes + osc.connect(gain); + gain.connect(context.destination); + + // Start and stop the oscillator + osc.start(time); + osc.stop(time + settings.decayTime + 0.02); +} + +export function playTom1Low(volume = 100) { + triggerTom(volume, { + frequency: 140, + decayTime: 0.4, + pitchDecay: 0.25 + }); }