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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//! A tremolo filter.
//!
//! Tremolo modifies the amplitude of an incoming signal (in the first channel), using
//! the output of a low frequency oscillator (in the second channel). It creates
//! a shuddering effect in the output audio.
//!
//! A intensity is set, in decibels. This controls how much gain or attenuation
//! the tremolo will apply. The LFO will then be used to oscillate this gain
//! over time.
//!
//! # Example
//!
//! To set up a tremolo, the channels must be properly configured. The following
//! will apply a tremolo to our microphone input, using a 10Hz LFO:
//!
//! ```no_run
//! # extern crate oxcable;
//! # extern crate oxcable_basic_devices;
//! # fn main() {
//! use oxcable::graph::DeviceGraph;
//! use oxcable::io::audio::AudioEngine;
//! use oxcable::oscillator::*;
//!
//! use oxcable_basic_devices::tremolo::Tremolo;
//!
//! let engine = AudioEngine::with_buffer_size(256).unwrap();
//! let mut graph = DeviceGraph::new();
//!
//! let lfo = graph.add_node(Oscillator::new(Sine).freq(10.0));
//! let microphone = graph.add_node(engine.default_input(1).unwrap());
//! let tremolo = graph.add_node(Tremolo::new(3.0)); // 3dB tremolo
//! let speaker = graph.add_node(engine.default_output(1).unwrap());
//!
//! graph.add_edge(microphone, 0, tremolo, 0); // first channnel is input signal
//! graph.add_edge(lfo, 0, tremolo, 1); // second channel is LFO output
//! graph.add_edge(tremolo, 0, speaker, 0);
//! # }
//! ```

use num::traits::Float;
use oxcable::types::{AudioDevice, MessageReceiver, Sample, Time};


/// Defines the messages that the Tremolo supports.
#[derive(Clone, Copy, Debug)]
pub enum Message {
    /// Set the tremolo intensity, in decibels.
    SetIntensity(f32)
}
pub use self::Message::*;


/// A tremolo filter.
pub struct Tremolo {
    intensity: f32,
}

impl Tremolo {
    /// Returns a new single-channel tremolo filter.
    ///
    /// `intensity` is in decibels.
    pub fn new(intensity: f32) -> Self {
        Tremolo {
            intensity: intensity
        }
    }
}

impl MessageReceiver for Tremolo {
    type Msg = Message;
    fn handle_message(&mut self, msg: Message) {
        match msg {
            SetIntensity(intensity) => self.intensity = intensity
        }
    }
}

impl AudioDevice for Tremolo {
    fn num_inputs(&self) -> usize {
        2
    }

    fn num_outputs(&self) -> usize {
        1
    }

    fn tick(&mut self, _: Time, inputs: &[Sample], outputs: &mut[Sample]) {
        let gain = 10.0.powf(inputs[1] * self.intensity/10.0);
        outputs[0] = gain*inputs[0];
    }
}