aerothesis

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

main.rs (3012B)


      1 use aerothesis::Aerothesis;
      2 use nih_plug::prelude::util;
      3 use rustfft::{num_complex::Complex, FftPlanner};
      4 use textplots::{Chart, Plot, Shape};
      5 
      6 fn main() -> Result<(), Box<dyn std::error::Error>> {
      7     let mut plugin = Aerothesis::default();
      8     let sample_rate = 44100.0;
      9     let seconds = 1.0;
     10     let num_samples = (sample_rate * seconds) as usize;
     11 
     12     plugin.sample_rate = sample_rate;
     13     plugin.note_frequency = util::midi_note_to_freq(60); // C4 (u8)
     14                                                          // plugin.note_frequency = util::midi_note_to_freq(54); // F#3 (u8)
     15 
     16     // For simulation in main.rs, we use the default parameters from AerothesisParams::default()
     17     // because nih-plug parameters are designed to be managed by a host and don't have
     18     // simple setter methods for plain values without a ParamSetter context.
     19     // Default resonance: OpenPipe, Decay: 0.9
     20 
     21     let mut displacements = Vec::with_capacity(num_samples);
     22     let mut osc = Vec::with_capacity(num_samples);
     23 
     24     for i in 0..num_samples {
     25         // let x_current = self.resonance() - self.avg_x_history();
     26 
     27         // for sample in channel_samples {
     28         //     *sample = (x_current * gain).clamp(-1.0, 1.0);
     29         // }
     30 
     31         // Simple attack envelope for breath pressure
     32         plugin.v_breath = if i < 2000 {
     33             (i as f32 / 2000.0) * 100.0
     34         } else {
     35             100.0
     36         };
     37 
     38         let sample = plugin.displacement() - plugin.avg_x_history();
     39         osc.push(plugin.osc_x());
     40         displacements.push(sample);
     41     }
     42 
     43     let len = (sample_rate * 0.05) as usize;
     44 
     45     let data: Vec<(f32, f32)> = (0..len)
     46         .map(|i| (i as f32, displacements[i + (sample_rate * 0.1) as usize]))
     47         .collect();
     48 
     49     println!("--- Waveform ---");
     50     Chart::new(360, 60, 0.0, len as f32)
     51         .lineplot(&Shape::Lines(&data))
     52         .display();
     53 
     54     let fft_len = displacements.len().next_power_of_two();
     55     let mut planner = FftPlanner::new();
     56     let fft = planner.plan_fft_forward(fft_len);
     57 
     58     let mut buffer: Vec<Complex<f32>> = displacements
     59         .iter()
     60         .map(|&s| Complex { re: s, im: 0.0 })
     61         .collect();
     62     buffer.resize(fft_len, Complex { re: 0.0, im: 0.0 });
     63 
     64     fft.process(&mut buffer);
     65 
     66     let mut spectrum_data = Vec::with_capacity(fft_len / 2);
     67     for (i, complex) in buffer.iter().enumerate().take(fft_len / 2) {
     68         let freq = (i as f32 * sample_rate) / fft_len as f32;
     69         if freq > 2000.0 {
     70             break;
     71         }
     72         spectrum_data.push((freq, complex.norm()));
     73     }
     74     if let Some(max) = spectrum_data
     75         .iter()
     76         .enumerate()
     77         .max_by(|(_, a), (_, b)| a.1.partial_cmp(&b.1).unwrap())
     78     {
     79         println!("max freq is {} Hz", max.0);
     80     }
     81 
     82     println!("\n--- Spectrum (0 - 2000Hz) ---");
     83     Chart::new(180, 60, 0.0, 2000.0)
     84         .lineplot(&Shape::Lines(&spectrum_data))
     85         .display();
     86 
     87     Ok(())
     88 }