adsr tests

This commit is contained in:
Vasilii Milovidov
2023-09-21 14:54:19 +04:00
parent 97e2d89e61
commit 4ca57b308f
2 changed files with 54 additions and 30 deletions
+48 -27
View File
@@ -78,38 +78,21 @@ pub fn superdough(message: &WebAudioMessage, context: &mut AudioContext) {
}
if message.delay.wet > 0.0 {
let output = context.create_gain();
output.connect(&context.destination());
let delay = delays.get(message.orbit).unwrap();
delay.delay_time().set_value(message.delay.delay_time);
delay.connect(&output);
let feedback = context.create_gain();
feedback.gain().set_value(message.delay.feedback);
feedback.connect(delay);
delay.connect(&feedback);
let pre_gain = context.create_gain();
pre_gain.gain().set_value(message.delay.wet);
pre_gain.connect(&feedback);
let input = context.create_gain();
input.connect(&pre_gain);
input.connect(&context.destination()); // direct sound
env.connect(&input);
create_delay(message, &context, &env, &mut delays, now);
}
let (sustain, velocity, release) = (message.adsr.sustain, message.velocity, message.adsr.release);
// Connect nodes and play synth
connect_nodes(chain, context);
let osc= play_synth(&message, now, osc, filters, &env);
let osc = play_synth(&message, now, osc, filters, &env);
osc.set_onended(move |_| {
for d in &delays {
// env.gain().set_value_at_time(velocity * sustain, now);
// env.gain().exponential_ramp_to_value_at_time(0.0001, now + release);
d.disconnect();
}
});
}
_ => {
match File::open(format!("samples/{}/{}.wav", message.bank, message.waveform)) {
@@ -128,10 +111,23 @@ pub fn superdough(message: &WebAudioMessage, context: &mut AudioContext) {
let env = context.create_gain();
chain.push(&env);
let mut delays = Vec::new();
for _ in 0..=message.orbit {
delays.push(context.create_delay(1.));
}
if message.delay.wet > 0.0 {
create_delay(message, &context, &env, &mut delays, now);
}
// Connect nodes and play sample
connect_nodes(chain, context);
src.playback_rate().set_value(message.speed);
play_sample(message, now, audio_buffer_duration, src, filters, &env);
let src = play_sample(message, now, audio_buffer_duration, src, filters, &env);
src.set_onended(move |_| {
for d in &delays {
d.disconnect();
}
});
}
Err(e) => eprintln!("Failed to open file: {:?}", e),
}
@@ -139,6 +135,30 @@ pub fn superdough(message: &WebAudioMessage, context: &mut AudioContext) {
}
}
fn create_delay(message: &WebAudioMessage, context: &&mut AudioContext, env: &GainNode, delays: &mut Vec<DelayNode>, now: f64) {
let output = context.create_gain();
output.connect(&context.destination());
let delay = delays.get(message.orbit).unwrap();
delay.delay_time().set_value(message.delay.delay_time);
delay.connect(&output);
let feedback = context.create_gain();
feedback.gain().set_value(message.delay.feedback);
feedback.connect(delay);
delay.connect(&feedback);
let pre_gain = context.create_gain();
// pre_gain.gain().set_value_at_time(0.0, now);
pre_gain.gain().set_value_at_time(message.delay.wet, now + message.delay.delay_time as f64);
pre_gain.connect(&feedback);
let input = context.create_gain();
input.connect(&pre_gain);
env.connect(&input);
}
fn play_synth(message: &&WebAudioMessage, now: f64, osc: OscillatorNode, filters: Vec<BiquadFilterNode>, env: &GainNode) -> OscillatorNode {
osc.set_type(create_osc_type(&message));
osc.frequency().set_value(message.note);
@@ -165,7 +185,7 @@ fn create_osc_type(message: &WebAudioMessage) -> OscillatorType {
}
}
fn play_sample(message: &WebAudioMessage, now: f64, audio_buffer_duration: f64, src: AudioBufferSourceNode, filters: Vec<BiquadFilterNode>, env: &GainNode) {
fn play_sample(message: &WebAudioMessage, now: f64, audio_buffer_duration: f64, src: AudioBufferSourceNode, filters: Vec<BiquadFilterNode>, env: &GainNode) -> AudioBufferSourceNode {
let (start_at, stop_at) = if message.speed < 0.0 {
(audio_buffer_duration, now + message.duration + 0.2)
} else {
@@ -201,6 +221,7 @@ fn play_sample(message: &WebAudioMessage, now: f64, audio_buffer_duration: f64,
};
src.stop_at(stop_at);
}
src
}
fn create_filters(context: &mut AudioContext, message: &WebAudioMessage) -> Vec<BiquadFilterNode> {
@@ -288,8 +309,8 @@ fn apply_adsr(
sustain * message.velocity,
now + attack + decay,
)
.set_value_at_time(sustain * message.velocity, now + attack + decay)
.linear_ramp_to_value_at_time(0.0, now + attack + decay + release);
.set_value_at_time(sustain * message.velocity, message.duration)
.linear_ramp_to_value_at_time(0.001, message.duration + release);
}
fn apply_synth_adsr(envelope: &GainNode, message: &WebAudioMessage, now: f64) {
@@ -321,7 +342,7 @@ fn apply_drum_adsr(envelope: &GainNode, message: &WebAudioMessage, now: f64) {
}
fn apply_default_drum_adsr(envelope: &GainNode, message: &WebAudioMessage, now: f64) {
apply_adsr(envelope, message, now, 0.001, message.velocity, 0.05, 0.001);
apply_adsr(envelope, message, now, 0.001, message.velocity, 0.5, 0.5);
}
fn connect_nodes<'a>(nodes: Vec<&'a (dyn AudioNode + 'a)>, context: &'a mut AudioContext) -> Vec<&'a (dyn AudioNode)> {
+6 -3
View File
@@ -3,6 +3,7 @@ use std::{
time::Duration,
thread::sleep
};
use tokio::{
sync::{mpsc, Mutex},
time::Instant
@@ -12,10 +13,9 @@ use web_audio_api::{
context::{AudioContext, AudioContextLatencyCategory, AudioContextOptions},
node::AudioNode
};
use web_audio_api::context::BaseAudioContext;
use crate::superdough::{ADSR, BPF, Delay, FilterADSR, HPF, Loop, LPF, superdough};
const BLOCK_SIZE: usize = 128;
#[derive(Debug)]
pub struct WebAudioMessage {
pub note: f32,
@@ -56,6 +56,8 @@ pub fn init(
............................................................*/
let message_queue_clone = Arc::clone(&message_queue);
tauri::async_runtime::spawn(async move {
loop {
if let Some(package) = async_output_receiver.recv().await {
let mut message_queue = message_queue_clone.lock().await;
@@ -72,6 +74,7 @@ pub fn init(
/* ...........................................................
Prepare audio context
............................................................*/
let latency_hint = match std::env::var("WEB_AUDIO_LATENCY").as_deref() {
Ok("playback") => AudioContextLatencyCategory::Playback,
_ => AudioContextLatencyCategory::default(),
@@ -98,7 +101,7 @@ pub fn init(
return false;
});
sleep(Duration::from_millis(1));
tokio::time::sleep(Duration::from_millis(1)).await;
}
});
}