...
 
Commits (3)
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "ansi_term"
version = "0.11.0"
......
......@@ -7,99 +7,127 @@ extern crate audio_adaptive;
extern crate rand;
use rand::prelude::*;
use rand::distributions::Uniform;
use rand::prelude::*;
use audio_adaptive::audiograph::*;
use audio_adaptive::samplerate;
fn osc_bench(c : &mut Criterion) {
fn osc_bench(c: &mut Criterion) {
let mut rng = SmallRng::seed_from_u64(345987);
let unity_interval = Uniform::new_inclusive(-1.,1.);
c.bench_function_over_inputs("osc", move |b: &mut Bencher, n: &usize| {
let mut osc = Oscillator::new(0., 440, 1.);
let mut input = vec![DspEdge::new(1, 1, *n, 44100);1];
//let size = input[0].buffer().len();
input[0].buffer_mut().copy_from_slice(&rng.sample_iter(&unity_interval).take(*n).collect::<Vec<f32>>());
b.iter( ||
{
let mut output = vec![DspEdge::new(1, 1, *n, 44100);1];
osc.process(&input, &mut output)}
)},
vec![64, 128,256,512,1024,2048,4096]);
let unity_interval = Uniform::new_inclusive(-1., 1.);
c.bench_function_over_inputs(
"osc",
move |b: &mut Bencher, n: &usize| {
let mut osc = Oscillator::new(0., 440, 1.);
let mut input = vec![DspEdge::new(1, 1, *n, 44100); 1];
//let size = input[0].buffer().len();
input[0].buffer_mut().copy_from_slice(
&rng.sample_iter(&unity_interval)
.take(*n)
.collect::<Vec<f32>>(),
);
b.iter(|| {
let mut output = vec![DspEdge::new(1, 1, *n, 44100); 1];
osc.process(&input, &mut output)
})
},
vec![64, 128, 256, 512, 1024, 2048, 4096],
);
}
fn mod_bench(c : &mut Criterion) {
fn mod_bench(c: &mut Criterion) {
let mut rng = SmallRng::seed_from_u64(345987);
let unity_interval = Uniform::new_inclusive(-1.,1.);
c.bench_function_over_inputs("mod", move |b: &mut Bencher, n: &usize| {
let mut modu = Modulator::new(0., 440, 1.);
let mut input = vec![DspEdge::new(1, 1, *n, 44100);1];
//let size = input[0].buffer().len();
input[0].buffer_mut().copy_from_slice(&rng.sample_iter(&unity_interval).take(*n).collect::<Vec<f32>>());
b.iter( ||
{
let mut output = vec![DspEdge::new(1, 1, *n, 44100);1];
modu.process(&input, &mut output)}
)},
vec![64, 128,256,512,1024,2048,4096]);
let unity_interval = Uniform::new_inclusive(-1., 1.);
c.bench_function_over_inputs(
"mod",
move |b: &mut Bencher, n: &usize| {
let mut modu = Modulator::new(0., 440, 1.);
let mut input = vec![DspEdge::new(1, 1, *n, 44100); 1];
//let size = input[0].buffer().len();
input[0].buffer_mut().copy_from_slice(
&rng.sample_iter(&unity_interval)
.take(*n)
.collect::<Vec<f32>>(),
);
b.iter(|| {
let mut output = vec![DspEdge::new(1, 1, *n, 44100); 1];
modu.process(&input, &mut output)
})
},
vec![64, 128, 256, 512, 1024, 2048, 4096],
);
}
fn resampler_bench(c : &mut Criterion) {
let parameters = vec![samplerate::ConverterType::SincBestQuality, samplerate::ConverterType::SincMediumQuality,
samplerate::ConverterType::SincFastest, samplerate::ConverterType::ZeroOrderHold,
samplerate::ConverterType::Linear];
fn resampler_bench(c: &mut Criterion) {
let parameters = vec![
samplerate::ConverterType::SincBestQuality,
samplerate::ConverterType::SincMediumQuality,
samplerate::ConverterType::SincFastest,
samplerate::ConverterType::ZeroOrderHold,
samplerate::ConverterType::Linear,
];
let mut rng = SmallRng::seed_from_u64(345987);
let unity_interval = Uniform::new_inclusive(-1.,1.);
let unity_interval = Uniform::new_inclusive(-1., 1.);
c.bench(
"resampler",
ParameterizedBenchmark::new(
"resampler",
move |b, conv_type| {
let mut conv = Resampler::new(conv_type.clone(), 0.5);
let mut input = vec![DspEdge::new(1, 1, 256, 44100);1];
let mut input = vec![DspEdge::new(1, 1, 256, 44100); 1];
let size = input[0].buffer().len();
input[0].buffer_mut().copy_from_slice(&rng.sample_iter(&unity_interval).take(size).collect::<Vec<f32>>());
input[0].buffer_mut().copy_from_slice(
&rng.sample_iter(&unity_interval)
.take(size)
.collect::<Vec<f32>>(),
);
b.iter(|| {
let mut output = vec![DspEdge::new(1, 1, 128, 44100);1];
let mut output = vec![DspEdge::new(1, 1, 128, 44100); 1];
conv.process(&input, &mut output)
})},
parameters
)
})
},
parameters,
),
);
}
fn mixer_bench(c : &mut Criterion) {
fn mixer_bench(c: &mut Criterion) {
let n = 6;
let mut parameters = Vec::with_capacity(n*n);
let mut parameters = Vec::with_capacity(n * n);
for i in 1..n {
for j in 1..n {
if i % j == 0 || j % i == 0 {parameters.push((j,i));}
if i % j == 0 || j % i == 0 {
parameters.push((j, i));
}
}
}
let mut rng = SmallRng::seed_from_u64(345987);
let unity_interval = Uniform::new_inclusive(-1.,1.);
let unity_interval = Uniform::new_inclusive(-1., 1.);
c.bench(
"mixer",
ParameterizedBenchmark::new(
"mixer",
move |b, (nb_inlets, nb_outlets)| {
let mut conv = InputsOutputsAdaptor::new(*nb_inlets, *nb_outlets);
let mut inputs = vec![DspEdge::new(1, 1, 256, 44100);*nb_inlets];
let mut inputs = vec![DspEdge::new(1, 1, 256, 44100); *nb_inlets];
let size = inputs[0].buffer().len();
for input in inputs.iter_mut() {
input.buffer_mut().copy_from_slice(&rng.sample_iter(&unity_interval).take(size).collect::<Vec<f32>>());
input.buffer_mut().copy_from_slice(
&rng.sample_iter(&unity_interval)
.take(size)
.collect::<Vec<f32>>(),
);
}
b.iter(|| {
let mut outputs = vec![DspEdge::new(1, 1, 256, 44100);*nb_outlets];
let mut outputs = vec![DspEdge::new(1, 1, 256, 44100); *nb_outlets];
conv.process(&inputs, &mut outputs)
})},
parameters
)
})
},
parameters,
),
);
}
criterion_group!(benches, osc_bench, mod_bench, resampler_bench, mixer_bench);
criterion_main!(benches);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
//! Parse a fileformat describing audiographs
use std::error::Error;
use pest::Parser;
use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use pest::Parser;
use std::collections::HashMap;
use petgraph::graph::NodeIndex;
......@@ -13,7 +13,7 @@ use pest::error::Error as ParseError;
use audiograph::*;
#[derive(Debug, Default)]
pub struct Node {
pub struct Node {
pub id: String,
pub nb_inlets: u32,
pub nb_outlets: u32,
......@@ -21,19 +21,20 @@ pub struct Node {
pub text: Option<String>,
pub wcet: Option<f64>,
pub more: HashMap<String, String>,
pub volume: f32
pub volume: f32,
}
impl Node {
pub fn new() -> Node {
Node { id : String::new(),
nb_inlets : 0,
nb_outlets : 0,
class_name : String::new(),
text : None,
wcet : None,
pub fn new() -> Node {
Node {
id: String::new(),
nb_inlets: 0,
nb_outlets: 0,
class_name: String::new(),
text: None,
wcet: None,
volume: 1.,
more : HashMap::new()
more: HashMap::new(),
}
}
}
......@@ -46,17 +47,23 @@ pub struct Edge {
dst_port: u32,
}
#[derive(Parser)]
#[grammar = "audiograph.pest"]
pub struct AudiographParser;
pub fn parse_audiograph(audiograph : &str, buffer_size: usize, nb_channels: usize, samplerate: u32) -> Result<AudioGraph, ParseError<Rule>> {
let audiograph = AudiographParser::parse(Rule::file, audiograph)?.next().unwrap();
pub fn parse_audiograph(
audiograph: &str,
buffer_size: usize,
nb_channels: usize,
samplerate: u32,
) -> Result<AudioGraph, ParseError<Rule>> {
let audiograph = AudiographParser::parse(Rule::file, audiograph)?
.next()
.unwrap();
use pest::iterators::*;
fn parse_node(pair : Pair<Rule>) -> Node {
fn parse_node(pair: Pair<Rule>) -> Node {
let mut inner_rules = pair.into_inner();
let mut node = Node::new();
node.id = inner_rules.next().unwrap().as_str().to_string();
......@@ -72,7 +79,9 @@ pub fn parse_audiograph(audiograph : &str, buffer_size: usize, nb_channels: usiz
"kind" => node.class_name = v.to_string(),
"wcet" => node.wcet = Some(v.parse().unwrap()),
"volume" => node.volume = v.parse().unwrap(),
_ => {node.more.insert(id.to_string(), v.to_string());},
_ => {
node.more.insert(id.to_string(), v.to_string());
}
}
}
node
......@@ -80,7 +89,7 @@ pub fn parse_audiograph(audiograph : &str, buffer_size: usize, nb_channels: usiz
use std::vec::IntoIter;
fn parse_edge(pair : Pair<Rule>) -> IntoIter<Edge> {
fn parse_edge(pair: Pair<Rule>) -> IntoIter<Edge> {
let mut inner_rules = pair.into_inner();
let mut port_ident = inner_rules.next().unwrap().into_inner();
let mut src_id = port_ident.next().unwrap().as_str().to_string();
......@@ -92,21 +101,28 @@ pub fn parse_audiograph(audiograph : &str, buffer_size: usize, nb_channels: usiz
port_ident = inner_rule.into_inner().next().unwrap().into_inner();
let dst_id = port_ident.next().unwrap().as_str().to_string();
let dst_port = port_ident.next().unwrap().as_str().parse().unwrap();
edges.push(Edge {src_id, src_port, dst_id : dst_id.clone(), dst_port});
edges.push(Edge {
src_id,
src_port,
dst_id: dst_id.clone(),
dst_port,
});
src_id = dst_id;
src_port = dst_port;
}
edges.into_iter()
}
let (nodes, edges) : (Vec<_>, Vec<_>)= audiograph.into_inner().flat_map(|r| r.into_inner())
.filter(|ref r| r.as_rule() != Rule::deadline)
//.inspect(|x| println!("Statement: {:?}.", x))
.partition(|ref r| r.as_rule() == Rule::node);
let (nodes, edges): (Vec<_>, Vec<_>) = audiograph
.into_inner()
.flat_map(|r| r.into_inner())
.filter(|ref r| r.as_rule() != Rule::deadline)
//.inspect(|x| println!("Statement: {:?}.", x))
.partition(|ref r| r.as_rule() == Rule::node);
let nodes = nodes.into_iter().map(parse_node).collect::<Vec<_>>();
let edges = edges.into_iter().flat_map(parse_edge).collect::<Vec<_>>();
let mut node_indexes : HashMap<String, NodeIndex> = HashMap::new();
let mut node_indexes: HashMap<String, NodeIndex> = HashMap::new();
let mut audiograph = AudioGraph::new(buffer_size as u32, nb_channels as u32, samplerate);
......@@ -134,11 +150,17 @@ pub fn parse_audiograph(audiograph : &str, buffer_size: usize, nb_channels: usiz
Ok(audiograph)
}
pub fn parse_audiograph_from_file(filename : &str, buffer_size: usize, nb_channels: usize, samplerate: u32) -> Result<AudioGraph, ParseError<Rule>> {
pub fn parse_audiograph_from_file(
filename: &str,
buffer_size: usize,
nb_channels: usize,
samplerate: u32,
) -> Result<AudioGraph, ParseError<Rule>> {
let path = Path::new(filename);
let mut file = File::open(&path).expect("Impossible to open file.");
let mut s = String::new();
file.read_to_string(&mut s).expect("Impossible to read file.");
file.read_to_string(&mut s)
.expect("Impossible to read file.");
parse_audiograph(&s, buffer_size, nb_channels, samplerate)
}
......@@ -150,22 +172,33 @@ mod tests {
fn parse_audiograph_test() {
let mut file = File::open("audiograph_wcet_test.ag").expect("Impossible to open file.");
let mut s = String::new();
file.read_to_string(&mut s).expect("Impossible to read file.");
file.read_to_string(&mut s)
.expect("Impossible to read file.");
assert!(AudiographParser::parse(Rule::file, &s).is_ok());
}
#[test]
fn build_audiograph_test() {
let audiograph = parse_audiograph_from_file("audiograph_wcet_test.ag", 64, 2, 44_100).expect("Impossible to open file.");
println!("Nodes={} and edges={}", audiograph.nb_nodes(), audiograph.nb_edges() );
let audiograph = parse_audiograph_from_file("audiograph_wcet_test.ag", 64, 2, 44_100)
.expect("Impossible to open file.");
println!(
"Nodes={} and edges={}",
audiograph.nb_nodes(),
audiograph.nb_edges()
);
assert!(audiograph.nb_nodes() == 5);
assert!(audiograph.nb_edges() == 6);
}
#[test]
fn build_audiograph_down_test() {
let audiograph = parse_audiograph_from_file("downsampling_test.ag", 64, 2, 44_100).expect("Impossible to open file.");
println!("Nodes={} and edges={}", audiograph.nb_nodes(), audiograph.nb_edges() );
let audiograph = parse_audiograph_from_file("downsampling_test.ag", 64, 2, 44_100)
.expect("Impossible to open file.");
println!(
"Nodes={} and edges={}",
audiograph.nb_nodes(),
audiograph.nb_edges()
);
assert!(audiograph.nb_nodes() == 6);
assert!(audiograph.nb_edges() == 7);
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -16,69 +16,67 @@ pub enum NodeClass {
Output,
}
pub trait GraphGenerator<T : Copy + fmt::Display + AudioEffect + Eq > {
pub trait GraphGenerator<T: Copy + fmt::Display + AudioEffect + Eq> {
//Generate several audio nodes
//Give a function that generates an audio node as argument, maybe.
// Or a vector of possible nodes?
// Depending on the topology of the graph?
fn generate(&mut self, node : &Fn(NodeClass, &mut ThreadRng) -> T) -> AudioGraph<T>;
fn generate(&mut self, node: &Fn(NodeClass, &mut ThreadRng) -> T) -> AudioGraph<T>;
//fn generate(&mut self) -> AudioGraph<DspNode>;
}
pub struct RandomGenerator {
rng : ThreadRng,
p: f64,//probability of getting an edge
adjacency_matrix : Vec<Vec<bool>>
rng: ThreadRng,
p: f64, //probability of getting an edge
adjacency_matrix: Vec<Vec<bool>>,
}
impl fmt::Debug for RandomGenerator {
fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.adjacency_matrix.fmt(f)
}
}
impl RandomGenerator {
pub fn new(size : usize, p : f64) -> RandomGenerator {
let seed : &[_] = &[1, 21, 37, 4];
pub fn new(size: usize, p: f64) -> RandomGenerator {
let _seed: &[_] = &[1, 21, 37, 4];
//let rng : StdRng = SeedableRng::from_seed(seed);
let rng = thread_rng();
RandomGenerator {
rng,
p,
adjacency_matrix : vec![Vec::with_capacity(size); size]
adjacency_matrix: vec![Vec::with_capacity(size); size],
}
}
pub fn gen_matrix(&mut self) {
//generate low triangular adjacency matrix
for (i,row) in self.adjacency_matrix.iter_mut().enumerate() {
row.resize(i,false);
for (i, row) in self.adjacency_matrix.iter_mut().enumerate() {
row.resize(i, false);
for column in row[0..i].iter_mut() {
*column = self.rng.gen_bool(self.p)
//gen_bool to change the probability of getting a link? The proportion of edges
//Or use sample_slice? sample_iter? sample_slice_ref?
//Or with a more complex distribution? Normal? gen_bool = Bernoulli...
}
}
}
}
impl<T : fmt::Display+ AudioEffect + Copy + Hash + Eq> GraphGenerator<T> for RandomGenerator {
fn generate(&mut self, node : &Fn(NodeClass, &mut ThreadRng) -> T) -> AudioGraph<T> {
impl<T: fmt::Display + AudioEffect + Copy + Hash + Eq> GraphGenerator<T> for RandomGenerator {
fn generate(&mut self, node: &Fn(NodeClass, &mut ThreadRng) -> T) -> AudioGraph<T> {
//Gen low triangular matrix
self.gen_matrix();
let size = self.adjacency_matrix.len();
//Fin input and outputs
let mut children_cnt = vec![0;size];
let mut parents_cnt = vec![0;size];
let mut children_cnt = vec![0; size];
let mut parents_cnt = vec![0; size];
//Inputs have 0 parents, outputs have 0 children.
for (i, row) in self.adjacency_matrix.iter().enumerate() {
for (j,node) in row.iter().enumerate() {
for (j, node) in row.iter().enumerate() {
if *node {
children_cnt[i] += 1;
parents_cnt[j] += 1;
......@@ -98,54 +96,53 @@ impl<T : fmt::Display+ AudioEffect + Copy + Hash + Eq> GraphGenerator<T> for Ran
//Insert a generator of sound
let new_node = node(NodeClass::Input, &mut self.rng);
indexes.push(graph.add_node(new_node));
}
else {
} else {
let new_node = node(NodeClass::Transformer, &mut self.rng);
indexes.push(graph.add_node(new_node));
}
}
};
for (i,row) in self.adjacency_matrix.iter().enumerate() {
for (j,node) in row.iter().enumerate() {
for (i, row) in self.adjacency_matrix.iter().enumerate() {
for (j, node) in row.iter().enumerate() {
if *node {
graph.add_connection(indexes[i], indexes[j]);
};
};
};
}
}
//TODO: we should check if there is no cycles!!
graph
}
}
#[cfg(test)]
mod tests {
use super::*;
use effect::*;
use rand::{thread_rng, Rng};
use rand::{Rng};
#[test]
fn test_graph_gen() {
let size = 10;
let generators = vec![DspNode::Modulator(5., 500, 1.0), DspNode::LowPass([5.,6.,7.,8.],200.,0.8)];
let generators = vec![
DspNode::Modulator(5., 500, 1.0),
DspNode::LowPass([5., 6., 7., 8.], 200., 0.8),
];
let mut rand_gen = RandomGenerator::new(size, 0.5);
{
let graph = rand_gen.generate(& |c, rng|
{
match c {
NodeClass::Input => DspNode::Oscillator(6., 500, 1.0),
NodeClass::Transformer | NodeClass::Output => *rng.choose(&generators).unwrap()
}
}
);
let graph = rand_gen.generate(&|c, rng| match c {
NodeClass::Input => DspNode::Oscillator(6., 500, 1.0),
NodeClass::Transformer | NodeClass::Output => *rng.choose(&generators).unwrap(),
});
println!("{}", graph);
}
//Check if it is low triangular indeed
assert!(rand_gen.adjacency_matrix.iter().enumerate().all(|(i,row)| row.len() == i))
assert!(rand_gen
.adjacency_matrix
.iter()
.enumerate()
.all(|(i, row)| row.len() == i))
}
}
This diff is collapsed.
extern crate audio_adaptive;
extern crate rustbox;
extern crate portaudio;
extern crate rand;
extern crate rustbox;
extern crate time;
#[macro_use]
extern crate lazy_static;
use std::env;
use std::error::Error;
use rustbox::Key;
use rustbox::{Color, RustBox};
use std::process::exit;
mod audioengine;
const UP_RATIO : f64 = 1.;
const UP_RATIO: f64 = 1.;
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
......@@ -40,7 +36,14 @@ fn main() {
Result::Err(e) => panic!("{}", e),
};
rustbox.print(1, 1, rustbox::RB_BOLD, Color::White, Color::Black, "Simple test of sound nodes with tradeoff between quality and deadlines.");
rustbox.print(
1,
1,
rustbox::RB_BOLD,
Color::White,
Color::Black,
"Simple test of sound nodes with tradeoff between quality and deadlines.",
);
rustbox.present();
let mut ratio = UP_RATIO;
......@@ -53,25 +56,43 @@ fn main() {
// &format!("CPU load {} ; Input latency: {}s ; Output latency: {}", cpu_load, stream_infos.input_latency, stream_infos.output_latency));
match rustbox.poll_event(false) {
Ok(rustbox::Event::KeyEvent(key)) => {
match key {
Key::Up => {ratio += 1.; audioengine.control_sender.send(ratio).unwrap();},
Key::Down if ratio > 1. => {ratio -= 1.; audioengine.control_sender.send(ratio).unwrap();},
Key::Char('q') => {
audioengine.stream.stop().unwrap();
break;},
_ => {}
Ok(rustbox::Event::KeyEvent(key)) => match key {
Key::Up => {
ratio += 1.;
audioengine.control_sender.send(ratio).unwrap();
}
Key::Down if ratio > 1. => {
ratio -= 1.;
audioengine.control_sender.send(ratio).unwrap();
}
Key::Char('q') => {
audioengine.stream.stop().unwrap();
break;
}
_ => {}
},
Err(e) => panic!("{}", e.description()),
_ => {}
};
rustbox.print(1, 1, rustbox::RB_BOLD, Color::White, Color::Black, "Simple test of sound nodes with tradeoff between quality and deadlines.");
rustbox.print(6, 9, rustbox::RB_BOLD, Color::White, Color::Black, &format!("Ratio : {}", ratio));
rustbox.print(
1,
1,
rustbox::RB_BOLD,
Color::White,
Color::Black,
"Simple test of sound nodes with tradeoff between quality and deadlines.",
);
rustbox.print(
6,
9,
rustbox::RB_BOLD,
Color::White,
Color::Black,
&format!("Ratio : {}", ratio),
);
rustbox.present();
}
println!("End of playback");
}
......@@ -15,15 +15,16 @@ extern crate time;
extern crate portaudio;
pub mod ringbuffer;
pub mod samplerate;
pub mod sndfile;
pub mod ringbuffer;
//pub mod reverb;
pub mod audiograph;
pub mod audiograph_parser;
pub mod effect;
pub mod experiments;
pub mod faust_effect;
pub mod stats;
pub mod audiograph_parser;
pub mod audiograph;
extern crate pest;
#[macro_use]
......
......@@ -5,16 +5,14 @@ extern crate time;
#[macro_use]
extern crate lazy_static;
use std::env;
use std::process::exit;
use std::thread;
use std::time as rust_time;
use std::process::exit;
mod audioengine;
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
......@@ -29,8 +27,12 @@ fn main() {
let mut ratio = 1.;
while audioengine.stream.is_active().unwrap() {
thread::sleep(sleep_duration);
ratio = ((ratio * 10. ) as u32 % 100) as f64 / 10. + 1.;
println!("At {}s, resampling ratio is now: {}", time::precise_time_s(), ratio);
ratio = ((ratio * 10.) as u32 % 100) as f64 / 10. + 1.;
println!(
"At {}s, resampling ratio is now: {}",
time::precise_time_s(),
ratio
);
audioengine.control_sender.send(ratio).unwrap();
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
use time::{PreciseTime};
use time::PreciseTime;
#[derive(Debug, Clone, Copy)]
pub struct Stats {
pub mean : f64,
pub var : f64,//We may use it later, but we don't compute it so far
n : u64,
pub mean: f64,
pub var: f64, //We may use it later, but we don't compute it so far
n: u64,
}
/// Compute an online mean: mean_{n+1} = f(mean_n, x)
/// TODO: make it also possible to use an exponential moving average
impl Stats {
pub fn new() -> Stats {
Stats {mean : 0., var : 0., n : 0}
Stats {
mean: 0.,
var: 0.,
n: 0,
}
}
pub fn init(m : f64) -> Stats {
Stats {mean : m, var : 0., n : 1}
pub fn init(m: f64) -> Stats {
Stats {
mean: m,
var: 0.,
n: 1,
}
}
//Better to make it generic on Num types?
//TODO: rather calculate a moving average
#[inline(always)]
pub fn update(&mut self, x : f64) -> f64 {
pub fn update(&mut self, x: f64) -> f64 {
self.n += 1;
let delta = x - self.mean;
self.mean += delta / self.n as f64;
......@@ -28,11 +36,9 @@ impl Stats {
}
#[inline(always)]
pub fn update_time(&mut self, prev_time : PreciseTime) -> f64 {
pub fn update_time(&mut self, prev_time: PreciseTime) -> f64 {
let time_now = PreciseTime::now();
let duration = prev_time.to(time_now).num_microseconds().unwrap();
self.update(duration as f64)
}
}