tests: reverb

This commit is contained in:
Vasilii Milovidov
2023-10-05 16:16:53 +04:00
parent e793cb671a
commit c0c6963112
5 changed files with 96 additions and 41 deletions
+41
View File
@@ -970,6 +970,47 @@ const generic_params = [
*
*/
[['room', 'size']],
/**
* Reverb lowpass starting frequency (in hertz).
* When this property is changed, the reverb will be recaculated, so only change this sparsely..
*
* @name roomlp
* @synonyms rlp
* @param {number} frequency between 0 and 20000hz
* @example
* s("bd sd").room(0.5).rlp(10000)
* @example
* s("bd sd").room(0.5).rlp(5000)
*/
['roomlp', 'rlp'],
/**
* Reverb lowpass frequency at -60dB (in hertz).
* When this property is changed, the reverb will be recaculated, so only change this sparsely..
*
* @name roomdim
* @synonyms rdim
* @param {number} frequency between 0 and 20000hz
* @example
* s("bd sd").room(0.5).rlp(10000).rdim(8000)
* @example
* s("bd sd").room(0.5).rlp(5000).rdim(400)
*
*/
['roomdim', 'rdim'],
/**
* Reverb fade time (in seconds).
* When this property is changed, the reverb will be recaculated, so only change this sparsely..
*
* @name roomfade
* @synonyms rfade
* @param {number} seconds for the reverb to fade
* @example
* s("bd sd").room(0.5).rlp(10000).rfade(0.5)
* @example
* s("bd sd").room(0.5).rlp(5000).rfade(4)
*
*/
['roomfade', 'rfade'],
/**
* Sets the sample to use as an impulse response for the reverb.
*
+18 -12
View File
@@ -39,7 +39,10 @@ export const desktopAudio = async (value, deadline, hapDuration) => {
delaytime,
orbit = 1,
room,
size,
roomfade,
roomlp,
roomdim,
roomsize,
ir,
i = 0,
velocity = 1,
@@ -139,16 +142,16 @@ export const desktopAudio = async (value, deadline, hapDuration) => {
let url;
if (ir !== undefined) {
if (getSound(ir).data.baseUrl !== undefined) {
baseUrl = getSound(ir).data.baseUrl;
if (baseUrl === './piano/') {
ir_path = 'https://strudel.tidalcycles.org/';
} else if (baseUrl === './EmuSP12/') {
ir_path = 'https://strudel.tidalcycles.org/';
} else {
ir_path = '';
if (getSound(ir).data.baseUrl !== undefined) {
baseUrl = getSound(ir).data.baseUrl;
if (baseUrl === './piano/') {
ir_path = 'https://strudel.tidalcycles.org/';
} else if (baseUrl === './EmuSP12/') {
ir_path = 'https://strudel.tidalcycles.org/';
} else {
ir_path = '';
}
}
}
let ir_samples = getSound(ir);
if (Array.isArray(ir_samples)) {
url =
@@ -156,7 +159,10 @@ export const desktopAudio = async (value, deadline, hapDuration) => {
? ir_path + ir_samples[n % ir_samples.length].replace('./', '')
: ir_samples[n % ir_samples.length].replace('./', '');
} else if (typeof ir_samples === 'object') {
console.log('obk', Object.values(ir_samples.data.samples)[i & Object.values(ir_samples.data.samples).length].replace('./', ''))
console.log(
'obk',
Object.values(ir_samples.data.samples)[i & Object.values(ir_samples.data.samples).length].replace('./', ''),
);
url =
ir_path !== undefined
? ir_path +
@@ -180,7 +186,7 @@ export const desktopAudio = async (value, deadline, hapDuration) => {
const packages = {
loop: [loop, loopBegin, loopEnd],
delay: [delay, delaytime, delayfeedback],
reverb: [room, size, ir, url],
reverb: [room, roomsize, roomfade, roomlp, roomdim,ir, url],
lpf: [cutoff, resonance],
hpf: [hcutoff, hresonance],
bpf: [bandf, bandq],
+12
View File
@@ -1,4 +1,5 @@
use rand_distr::{Distribution, Normal};
use web_audio_api::AudioBuffer;
fn apply_decay(input: &mut [f32], decay_factor: f32) {
let len = input.len();
@@ -101,5 +102,16 @@ pub fn write_to_wav(filename: &str, data: &[f32]) {
writer.finalize().unwrap();
}
pub fn write_to_buffer(buffer: &mut AudioBuffer, data: &[f32]) {
let num_chans = buffer.number_of_channels();
for i in 0..num_chans {
let chan = buffer.get_channel_data_mut(i);
for j in 0..chan.len() {
chan[j] = data[j];
}
}
}
+4 -1
View File
@@ -19,7 +19,10 @@ pub struct DelayMessage {
#[derive(Clone, Debug)]
pub struct ReverbMessage {
pub room: Option<f32>,
pub size: Option<f32>,
pub roomsize: Option<f32>,
pub roomfade: Option<f32>,
pub roomlp: Option<f32>,
pub roomdim: Option<f32>,
pub ir: Option<String>,
pub url: Option<String>,
}
+21 -28
View File
@@ -22,7 +22,7 @@ use web_audio_api::{
};
use web_audio_api::context::OfflineAudioContext;
use web_audio_api::node::{ConvolverNode, ConvolverOptions, DelayNode};
use crate::reverbgen::{create_impulse_response, generate_coefficients_lp, write_to_wav};
use crate::reverbgen::{create_impulse_response, generate_coefficients_lp, write_to_buffer, write_to_wav};
use crate::superdough::{ADSRMessage, apply_filter_adsr, BPFMessage, DelayMessage, Delay, FilterADSRMessage, HPFMessage, LoopMessage, LPFMessage, Sampler, Synth, WebAudioInstrument, ReverbMessage, Reverb};
@@ -171,6 +171,7 @@ pub fn init(
_ => {
// CREATE FILEPATHS
let t = audio_context.current_time();
let (url, file_path, file_path_clone) = create_filepath(&message);
// DOWNLOAD FILE IS IT DOESN'T EXIST
@@ -191,7 +192,6 @@ pub fn init(
// IF BUFFER IS CACHED - PLAY IT
if let Some(audio_buffer) = cache.get(&file_path_clone) {
let t = audio_context.current_time();
let audio_buffer_duration = audio_buffer.duration();
let mut sampler = Sampler::new(&mut audio_context, audio_buffer);
@@ -229,40 +229,30 @@ pub fn init(
};
// REVERB
// SAMPLES AS IRs
if message.reverb.room.is_some() {
let file_path = "/Users/vasiliymilovidov/TEMP/filters/filters/impulse94.wav/impulse101.wav".to_string();
if let Some(ir) = cache.get(&file_path) {
if message.reverb.ir.is_none() && message.reverb.room.unwrap_or(0.0) > 0.0 {
let key = format!("reverb: {}{}{}{}{}", message.reverb.room.unwrap_or(0.0), message.reverb.roomsize.unwrap_or(1.0), message.reverb.roomlp.unwrap_or(0.0), message.reverb.roomfade.unwrap_or(0.0), message.reverb.roomdim.unwrap_or(0.0));
if let Some(ir) = cache.get(&key) {
let mut reverb = audio_context.create_convolver();
reverb.set_buffer(ir);
reverb.connect(&compressor);
sampler.envelope.connect(&reverb);
} else {
// PREPARE IR GENERATION
let len = (audio_context.sample_rate() * message.reverb.size.unwrap_or(1.0)) as usize;
let len = (audio_context.sample_rate() * message.reverb.roomsize.unwrap_or(1.0)) as usize;
let decay = 4.0;
let num_coeffs = 101;
let fade = 2.4;
let cutoff = 500.0 / audio_context.sample_rate();
let cache_cache = cache.clone();
let mut buffer = audio_context.create_buffer(2, len, 44100.0);
tokio::spawn(async move {
// GENERATE IR
let fir = generate_coefficients_lp(num_coeffs, cutoff);
let ir = create_impulse_response(len, decay, &fir, 44100.0, fade);
write_to_wav("/Users/vasiliymilovidov/TEMP/filters/filters/impulse101.wav", &ir);
let context = OfflineAudioContext::new(2, 400, 44100.0);
let file = File::open("/Users/vasiliymilovidov/TEMP/filters/filters/impulse101.wav").expect("File booom!");
let buf = context.decode_audio_data_sync(file).unwrap();
cache_cache.insert("/Users/vasiliymilovidov/samples/ir3.wav".to_string(), buf);
write_to_buffer(&mut buffer, &ir);
cache_cache.insert(key, buffer);
});
}
}
// IR GENERATION
if message.reverb.ir.is_some() {
} else if message.reverb.ir.is_some() && message.reverb.room.unwrap() > 0.0 {
let (ir_url, ir_file_path, ir_file_path_clone) = create_ir_filepath(&message);
tokio::spawn(async move {
@@ -280,14 +270,14 @@ pub fn init(
}
});
let requested_size = message.reverb.size.unwrap_or(2.0).clone();
if let Some(ir_buffer) = ir_cache.get(&ir_file_path_clone) {
let requested_size = message.reverb.roomsize.unwrap_or(2.0).clone();
if let Some(ir_buffer) = cache.get(&ir_file_path_clone) {
let mut reverb = audio_context.create_convolver();
reverb.set_buffer(ir_buffer);
reverb.connect(&compressor);
sampler.envelope.connect(&reverb);
} else if let Ok(file) = File::open(&ir_file_path_clone) {
let ir_cache_clone = ir_cache.clone();
let ir_cache_clone = cache.clone();
tokio::spawn(async move {
let context = OfflineAudioContext::new(2, 400, 44100.0);
let ir_buffer = context.decode_audio_data_sync(file).expect("IR OOOOPS");
@@ -349,7 +339,7 @@ fn create_ir_filepath(message: &WebAudioMessage) -> (Url, String, String) {
.and_then(Iterator::last)
.and_then(|name| if name.is_empty() { None } else { Some(name) })
.unwrap_or("tmp.ben");
let file_path = format!("/Users/vasiliymilovidov/samples/{}", filename);
let file_path = format!("/Users/vasiliymilovidov/samples/{}{}", message.dirname,filename);
let file_path_clone = file_path.clone();
(url, file_path, file_path_clone)
}
@@ -376,7 +366,7 @@ pub struct MessageFromJS {
duration: f64,
velocity: f32,
delay: (Option<f32>, Option<f32>, Option<f32>),
reverb: (Option<f32>, Option<f32>, Option<String>, Option<String>),
reverb: (Option<f32>, Option<f32>, Option<f32>, Option<f32>, Option<f32>,Option<String>, Option<String>),
orbit: usize,
speed: f32,
begin: f64,
@@ -429,9 +419,12 @@ pub async fn sendwebaudio(
},
reverb: ReverbMessage {
room: m.reverb.0,
size: m.reverb.1,
ir: m.reverb.2,
url: m.reverb.3,
roomsize: m.reverb.1,
roomfade: m.reverb.2,
roomlp: m.reverb.3,
roomdim: m.reverb.4,
ir: m.reverb.5,
url: m.reverb.6,
},
orbit: m.orbit,
speed: m.speed,