|
1 | 1 | use web_sys as web; |
| 2 | +use app_core::Waveform; |
2 | 3 |
|
3 | 4 | pub struct FxBuses { |
4 | 5 | pub master_gain: web::GainNode, |
@@ -145,3 +146,40 @@ pub fn build_fx_buses(audio_ctx: &web::AudioContext) -> Result<FxBuses, ()> { |
145 | 146 | delay_wet, |
146 | 147 | }) |
147 | 148 | } |
| 149 | + |
| 150 | +// Fire a simple one-shot oscillator routed through a voice's gain and sends |
| 151 | +pub fn trigger_one_shot( |
| 152 | + audio_ctx: &web::AudioContext, |
| 153 | + waveform: Waveform, |
| 154 | + frequency_hz: f32, |
| 155 | + velocity: f32, |
| 156 | + duration_sec: f64, |
| 157 | + voice_gain: &web::GainNode, |
| 158 | + delay_send: &web::GainNode, |
| 159 | + reverb_send: &web::GainNode, |
| 160 | +) { |
| 161 | + if let Ok(src) = web::OscillatorNode::new(audio_ctx) { |
| 162 | + match waveform { |
| 163 | + Waveform::Sine => src.set_type(web::OscillatorType::Sine), |
| 164 | + Waveform::Square => src.set_type(web::OscillatorType::Square), |
| 165 | + Waveform::Saw => src.set_type(web::OscillatorType::Sawtooth), |
| 166 | + Waveform::Triangle => src.set_type(web::OscillatorType::Triangle), |
| 167 | + } |
| 168 | + src.frequency().set_value(frequency_hz); |
| 169 | + if let Ok(g) = web::GainNode::new(audio_ctx) { |
| 170 | + g.gain().set_value(0.0); |
| 171 | + let now = audio_ctx.current_time(); |
| 172 | + let t0 = now + 0.005; |
| 173 | + let _ = g.gain().linear_ramp_to_value_at_time(velocity, t0 + 0.02); |
| 174 | + let _ = g |
| 175 | + .gain() |
| 176 | + .linear_ramp_to_value_at_time(0.0, t0 + duration_sec); |
| 177 | + let _ = src.connect_with_audio_node(&g); |
| 178 | + let _ = g.connect_with_audio_node(voice_gain); |
| 179 | + let _ = g.connect_with_audio_node(delay_send); |
| 180 | + let _ = g.connect_with_audio_node(reverb_send); |
| 181 | + let _ = src.start_with_when(t0); |
| 182 | + let _ = src.stop_with_when(t0 + duration_sec + 0.05); |
| 183 | + } |
| 184 | + } |
| 185 | +} |
0 commit comments