1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use std::f64::consts::PI;

/// List of periodic functions can be synthesised,
/// also includes a Null synthesizer for generating 
/// signals with `0` values.
pub enum PerodicFunction {
    Sine,
    Square,
    Triangle,
    Sawtooth,
    /// This method is equavalient to intialising a vector with `0` values.
    Null,
}

/// Synthesizes a periodic waveform with a arbitary frequency and samplerate.
/// Note that, frequency should be less than half the samplerate (as of the nyquist theorem).
/// 
/// #### Functions implemented:
/// - Sine
/// - Square
/// - Triangle
/// - Sawtooth
/// 
/// **Note:** the size of the output vector is considered the samplerate,
/// the output vector must be resized before synthesizing.
/// 
/// ## Arguments
/// * `samples` — Vector to render oscillated samples into.
/// * `pfunc` — Periodic function used to oscillate.
/// * `freq` — Frequency of the function to oscillate on.
pub fn synth(samples: &mut Vec<f64>, pfunc: PerodicFunction, freq: f64) {
    let sample_rate = samples.len();
    
    match pfunc {
        Sine => {
            for (i, s) in samples.iter_mut().enumerate() {
                let p = i as f64 / sample_rate as f64; 
                *s = ((2.0 * PI * freq) / p).sin();
            }
        },
        Square => {
            for (i, s) in samples.iter_mut().enumerate() {
                let p = i as f64 / sample_rate as f64; 
                *s = ((2.0 * PI * freq) / p).sin().signum();
            }
        },
        Triangle => {
            for (i, s) in samples.iter_mut().enumerate() {
                let p = i as f64 / sample_rate as f64; 
                *s = 4.0/p * (freq - p/2.0 * (2.0*freq / p + 0.5).floor());
            }
        },
        Sawtooth => {
            for (i, s) in samples.iter_mut().enumerate() {
                let p = i as f64 / sample_rate as f64; 
                *s = 2.0 * (freq/p - (0.5 + freq/p).floor());
            }
        },
        Null => {
            for s in samples.iter_mut() {
                *s = 0.0;
            }
        }
    }
}