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 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
use crate::{Input, Message, Output, Signal};
use alloc::vec::Vec;
/// To implement [`Source`] means something can be a source of sound/voltage,
///
/// Two things are required by the trait:
///
/// 1) keeping track of what the source is using an unique `usize` id
/// 2) using the sample method to fill one or multiple [`Signal`] buffers with f32 data.
///
/// A very basic example might be to implement a DC offset module
///
/// ```
/// use screech::traits::{Tracker, Source};
/// use screech::{Screech, Input, Output};
///
/// struct Offset {
/// id: usize,
/// input: Input,
/// output: Output,
/// offset: f32,
/// }
///
/// impl Offset {
/// fn new(screech: &mut Screech, offset: f32) -> Self {
/// // obtain a unique identifier from the main sreech instance
/// let id = screech.create_source_id();
///
/// Offset {
/// id,
/// // initialize a new input to keep track of input connected to our source
/// input: screech.init_input(&id, "signal_in"),
/// // initialize a new output [`Signal`] buffer for our id and name
/// output: screech.init_output(&id, "signal_out"),
/// offset,
/// }
/// }
/// }
///
/// impl Source for Offset {
/// fn sample(&mut self, tracker: &mut dyn Tracker, sample_rate: usize) {
/// for i in 0..*tracker.get_buffer_size() {
/// // set offset as initial value
/// let mut signal = self.offset;
///
/// // add all inputs to the signal
/// for input in tracker.get_input(&self.input).unwrap().into_iter() {
/// if let Some(s) = tracker.get_output(&input).and_then(|o| o.samples.get(i)) {
/// signal += s;
/// }
/// }
///
/// // add signal to the final output
/// let output = tracker.get_mut_output(&self.output).unwrap();
/// output.samples[i] = signal;
/// }
/// }
///
/// fn get_source_id(&self) -> &usize {
/// &self.id
/// }
/// }
/// ```
pub trait Source<MessageData = ()>: Send {
/// function that gets called by [`crate::Screech`] during sampling.
///
/// use the reference to the tracker to update relevant [`Signal`]s
fn sample(&mut self, tracker: &mut dyn Tracker<MessageData>, sample_rate: usize);
/// get reference to the id for the source,
/// this is used to uniquely identify this source when sampling [`Signal`]s
fn get_source_id(&self) -> &usize;
}
/// Tracker trait to keep track of buffers and connections between [`Output`]s and [`Input`]s
///
/// for implementation examples see [`crate::BasicTracker`] or [`crate::DynamicTracker`]
pub trait Tracker<MessageData = ()> {
/// return the buffer size
fn get_buffer_size(&self) -> &usize;
/// resize internal buffers
fn resize_buffers(&mut self, buffer_size: usize);
/// Return a unique ID for keeping track of [`Source`]es
fn create_source_id(&mut self) -> usize;
/// clear source id and associated buffers
fn clear_source(&mut self, id: usize);
/// get all source ids required for a given source id
fn get_sources(&self, id: &usize) -> Vec<usize>;
/// get a reference to an output's [`Signal`]
fn get_output(&self, output: &Output) -> Option<&Signal>;
/// get a mutable reference to an output's [`Signal`]
fn get_mut_output(&mut self, output: &Output) -> Option<&mut Signal>;
/// initialize empty [`Signal`] for output
fn init_output(&mut self, output: &Output);
/// initialize input for tracking outputs connected to it
fn init_input(&mut self, input: &Input);
/// return a reference to a list of outputs for a given input
fn get_input(&self, e: &Input) -> Option<&[Output]>;
/// connect an [`Output`] to an [`Input`]
fn connect_signal(&mut self, output: &Output, input: &Input);
/// clear [`Output`] connection from an [`Input`]
fn clear_connection(&mut self, output: &Output, input: &Input);
/// send message to source id
fn send_message(&mut self, id: &usize, message: Message<MessageData>);
/// get all messages for given source id
fn get_messages(&self, id: &usize) -> Option<&[Message<MessageData>]>;
/// clear all messages for all sources
fn clear_messages(&mut self);
}
/// Trait to implement conversion from a slice of sized types to a generic
pub trait FromPoints<T: Sized, U> {
/// Create new instance based on sequence of points
fn from_points(points: Vec<T>) -> U;
}