mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-24 05:57:17 -04:00
tests: reverb
This commit is contained in:
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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>,
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user