use crate::fixtures::graph_of;
use sva_engine::{RenderConfig, Tier, render};
const RATE: u32 = 8_000;
fn digest(files: &[(&str, &str)], target: &str, secs: f64) -> u64 {
let g = graph_of("through", files);
let config = RenderConfig::seconds(RATE, secs);
let render =
render(&g, target, config, &Tier::default()).unwrap_or_else(|e| panic!("{target}: {e}"));
let id = render.id(target).expect("the root");
let samples = render.output(id).expect("a buffer").plane(0).to_vec();
assert!(samples.iter().any(|v| *v != 0.0), "silence tests nothing");
samples.iter().fold(0xcbf2_9ce4_8422_2325u64, |held, v| {
v.to_bits().to_le_bytes().iter().fold(held, |h, b| {
(h ^ u64::from(*b)).wrapping_mul(0x100_0000_01b3)
})
})
}
#[test]
fn a_kink_two_refs_down_splits_the_form_reading_it() {
let files = [
("ramp", "max(t - 0.25, 0)\n"),
("mid", "@ramp(t)*0.5 + @ramp(t)*0.5\n"),
("top", "crop(exp(-3*@mid(t))*sin(2*pi*220*t), 0s, 1s)\n"),
];
assert_eq!(digest(&files, "top", 1.0), 0x5b93_8aeb_39ee_b29f);
}
#[test]
fn a_written_form_read_at_a_moving_time_reads_each_ref_it_holds() {
let files = [
("n0", "crop(sin(2*pi*220*t), 0s, 1s)\n"),
("n1", "max(@n0(t), 0)*0.5 + @n0(t)*0.3 + @n0(t)*0.2\n"),
("n2", "max(@n1(t), 0)*0.5 + @n1(t)*0.3 + @n1(t)*0.2\n"),
("top", "crop(@n2(t + 0.002*sin(2*pi*5*t)), 0s, 0.5s)\n"),
];
assert_eq!(digest(&files, "top", 0.5), 0x9929_8012_9a93_a725);
}
#[test]
fn an_index_of_a_time_held_in_refs_reads_the_step_nearest_it() {
let files = [
(
"x",
"lowpass(crop(sample(sin(2*pi*220*t)), 0s, 0.05s), cutoff=900)\n",
),
("wobble", "0.002s*sin(2*pi*5*t)\n"),
("late", "t - 0.003s - @wobble(t)\n"),
("when", "@late(t) - 0.002s\n"),
("top", "@x[idx(@when(t))]\n"),
];
assert_eq!(digest(&files, "top", 0.1), 0x04ac_fddc_9b3a_bbfd);
}
#[test]
fn a_solver_argument_held_in_refs_switches_where_its_crop_opens() {
let files = [
("lift", "crop(min(1, (t - 0.1)/0.03), 0.1s, inf)\n"),
("felt", "0.1*@lift(t)\n"),
("top", "chaigne_askenfelt(261.63, damper_r=@felt(t))\n"),
];
assert_eq!(digest(&files, "top", 0.3), 0x4330_40d6_4d9f_d526);
}
#[test]
fn a_stored_energy_coefficient_held_in_refs_only_jumps() {
let files = [
("jump", "crop(1, 0.1s, inf)\n"),
("spring", "1e3*@jump(t)\n"),
("top", "chaigne_askenfelt(261.63, damper_k=@spring(t))\n"),
];
assert_eq!(digest(&files, "top", 0.3), 0x2bce_0950_14ae_d401);
}
#[test]
fn a_closed_loop_reads_each_ref_its_body_reads_at_each_terms_time() {
let files = [
("tone", "crop(sin(2*pi*220*t), 0s, 0.1s)\n"),
("pair", "@tone(t)*0.5 + @tone(t)*0.5\n"),
("top", "@pair(t) + 0.5*self(t - 17ms)\n"),
];
assert_eq!(digest(&files, "top", 0.5), 0x451a_bb5d_2453_5915);
}
#[test]
fn a_series_term_reading_a_form_at_its_instant_is_that_form_written_in() {
let read = [
("x", "0.5 + 0.25*sin(2*pi*3*t)\n"),
(
"top",
"crop(sum(k, 1, inf, @x(t)*sin(2*pi*110*k*t)/(k*k)), 0s, 0.1s)\n",
),
];
let written = [(
"top",
"crop(sum(k, 1, inf, (0.5 + 0.25*sin(2*pi*3*t))*sin(2*pi*110*k*t)/(k*k)), 0s, 0.1s)\n",
)];
assert_eq!(digest(&read, "top", 0.1), digest(&written, "top", 0.1));
}