use plotters::prelude::*; use std::path::Path; use wavegen::{sawtooth, sine, square, wf, Waveform}; fn main() -> Result<(), Box> { let sample_rate = 800.0f32; draw( sample_rate, "sine.png", "Sine", Waveform::with_components(sample_rate, vec![sine!(1.)]), )?; draw( sample_rate, "sine_double.png", "Sines", wf!(f32, sample_rate, sine!(1.0), sine!(1.0, 1.0, 0.25)), )?; draw( sample_rate, "sawtooth.png", "Sawtooth", wf!(f32, sample_rate, sawtooth!(2., 1., 0.0)), )?; draw( sample_rate, "sawtooth_sinesised.png", "Sawtooth with sine", wf!( f32, sample_rate, sawtooth!(2., 1., 0.0), sine!(frequency: 50., amplitude: 0.1) ), )?; draw( sample_rate, "square.png", "Square", wf!(f32, sample_rate, square!(2.)), )?; draw( sample_rate, "funky.png", "Something funky", wf!( f32, sample_rate, sine!(10., 0.3), sawtooth!(2., 0.3), square!(3., 0.3) ), )?; draw( sample_rate, "sines_300_50_hz.png", "Sine 300Hz + 50 Hz", wf!( f32, sample_rate, sine!(frequency: 300.), sine!(frequency: 50., amplitude: 0.3) ), )?; Ok(()) } fn draw( sample_rate: f32, path: impl AsRef, label: impl AsRef, waveform: Waveform, ) -> Result<(), Box> { draw_internal( path, label.as_ref(), waveform .iter() .enumerate() .map(|(i, x)| (i as f32 / sample_rate, x)) .take(sample_rate as usize), ) } fn draw_internal, P: AsRef>( path: P, label: &str, iter: I, ) -> Result<(), Box> { let img_path = Path::new("img").join(path); let root = BitMapBackend::new(&img_path, (800, 600)).into_drawing_area(); root.fill(&WHITE)?; let mut chart = ChartBuilder::on(&root) // .caption(label, ("sans-serif", 50).into_font()) .margin(5) .x_label_area_size(30) .y_label_area_size(30) .build_cartesian_2d(-0f32..1f32, -2f32..2f32)?; chart.configure_mesh().draw()?; chart .draw_series(LineSeries::new(iter, RED))? .label(label) .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], RED)); chart .configure_series_labels() .background_style(WHITE.mix(0.8)) .border_style(BLACK) .draw()?; Ok(()) }