summaryrefslogtreecommitdiff
path: root/src/synth
diff options
context:
space:
mode:
Diffstat (limited to 'src/synth')
-rw-r--r--src/synth/logic.rs63
-rw-r--r--src/synth/math.rs52
-rw-r--r--src/synth/mod.rs16
-rw-r--r--src/synth/noise.rs26
-rw-r--r--src/synth/rel.rs78
-rw-r--r--src/synth/triangle.rs1
6 files changed, 233 insertions, 3 deletions
diff --git a/src/synth/logic.rs b/src/synth/logic.rs
new file mode 100644
index 0000000..5071d95
--- /dev/null
+++ b/src/synth/logic.rs
@@ -0,0 +1,63 @@
+use std::{mem, cmp};
+use super::*;
+
+#[derive(Debug)]
+pub struct IfElse {
+ pub cond: GenBox,
+ pub iftrue: GenBox,
+ pub iffalse: GenBox,
+ pub buf: SampleBuffer,
+}
+
+impl Generator for IfElse {
+ fn eval<'a>(&'a mut self, params: &Parameters) -> &'a SampleBuffer {
+ let cond_buf = self.cond.eval(params);
+ let iftrue_buf = self.iftrue.eval(params);
+ let iffalse_buf = self.iffalse.eval(params);
+
+ if (
+ cond_buf.rate == Rate::Control &&
+ iftrue_buf.rate == Rate::Control &&
+ iffalse_buf.rate == Rate::Control
+ ) {
+ self.buf.set(if cond_buf.first() >= 0.5 {
+ iftrue_buf.first()
+ } else {
+ iffalse_buf.first()
+ });
+ return &self.buf;
+ }
+
+ self.buf.rate = Rate::Sample;
+
+ let mut bound = self.buf.len();
+ if cond_buf.rate == Rate::Sample { bound = cmp::min(bound, cond_buf.len()); }
+ if iftrue_buf.rate == Rate::Sample { bound = cmp::min(bound, iftrue_buf.len()); }
+ if iffalse_buf.rate == Rate::Sample { bound = cmp::min(bound, iffalse_buf.len()); }
+
+ for i in 0..bound {
+ let tv = match iftrue_buf.rate {
+ Rate::Sample => iftrue_buf[i],
+ Rate::Control => iftrue_buf.first(),
+ };
+ let fv = match iffalse_buf.rate {
+ Rate::Sample => iffalse_buf[i],
+ Rate::Control => iffalse_buf.first(),
+ };
+ let cv = match cond_buf.rate {
+ Rate::Sample => cond_buf[i],
+ Rate::Control => cond_buf.first(),
+ };
+ self.buf[i] = if cv >= 0.5 {
+ tv
+ } else {
+ fv
+ };
+ }
+
+ &self.buf
+ }
+ fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {
+ mem::replace(&mut self.buf, buf)
+ }
+}
diff --git a/src/synth/math.rs b/src/synth/math.rs
index 91e58e3..8adad4b 100644
--- a/src/synth/math.rs
+++ b/src/synth/math.rs
@@ -48,3 +48,55 @@ impl Generator for Mul {
mem::replace(&mut self.buf, buf)
}
}
+
+#[derive(Debug)]
+pub struct Negate {
+ pub value: GenBox,
+ pub buf: SampleBuffer,
+}
+
+impl Generator for Negate {
+ fn eval<'a>(&'a mut self, params: &Parameters) -> &'a SampleBuffer {
+ self.buf.update_from(self.value.eval(params));
+ match self.buf.rate {
+ Rate::Sample => {
+ for v in self.buf.iter_mut() {
+ *v *= -1.0;
+ }
+ },
+ Rate::Control => {
+ self.buf[0] *= -1.0;
+ },
+ }
+ &self.buf
+ }
+ fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {
+ mem::replace(&mut self.buf, buf)
+ }
+}
+
+#[derive(Debug)]
+pub struct Reciprocate {
+ pub value: GenBox,
+ pub buf: SampleBuffer,
+}
+
+impl Generator for Reciprocate {
+ fn eval<'a>(&'a mut self, params: &Parameters) -> &'a SampleBuffer {
+ self.buf.update_from(self.value.eval(params));
+ match self.buf.rate {
+ Rate::Sample => {
+ for v in self.buf.iter_mut() {
+ *v = v.powf(-1.0);
+ }
+ },
+ Rate::Control => {
+ self.buf[0] = self.buf[0].powf(-1.0);
+ },
+ }
+ &self.buf
+ }
+ fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {
+ mem::replace(&mut self.buf, buf)
+ }
+}
diff --git a/src/synth/mod.rs b/src/synth/mod.rs
index bf73200..4f23a01 100644
--- a/src/synth/mod.rs
+++ b/src/synth/mod.rs
@@ -60,6 +60,10 @@ impl SampleBuffer {
self.samples.len()
}
+ pub fn iter_mut<'a>(&'a mut self) -> slice::IterMut<'a, f32> {
+ self.samples.iter_mut()
+ }
+
pub fn first(&self) -> Sample {
*self.samples.first().unwrap()
}
@@ -158,7 +162,11 @@ pub type GenBox = Box<Generator>;
pub mod param;
pub use self::param::Param;
pub mod math;
-pub use self::math::{Add, Mul};
+pub use self::math::{Add, Mul, Negate, Reciprocate};
+pub mod rel;
+pub use self::rel::{Rel, RelOp};
+pub mod logic;
+pub use self::logic::IfElse;
pub mod sine;
pub use self::sine::Sine;
pub mod saw;
@@ -167,5 +175,7 @@ pub mod triangle;
pub use self::triangle::Triangle;
pub mod square;
pub use self::square::Square;
-//pub mod asdr;
-//pub use self::asdr::ASDR;
+pub mod noise;
+pub use self::noise::Noise;
+//pub mod adsr;
+//pub use self::adsr::ADSR;
diff --git a/src/synth/noise.rs b/src/synth/noise.rs
new file mode 100644
index 0000000..4d90f3b
--- /dev/null
+++ b/src/synth/noise.rs
@@ -0,0 +1,26 @@
+use std::mem;
+use super::*;
+
+use ::rand::{XorShiftRng, Rng};
+
+#[derive(Debug)]
+pub struct Noise {
+ pub rng: XorShiftRng,
+ pub buf: SampleBuffer,
+}
+
+impl Generator for Noise {
+ fn eval<'a>(&'a mut self, params: &Parameters) -> &'a SampleBuffer {
+ self.buf.rate = Rate::Sample;
+
+ for i in 0..self.buf.len() {
+ self.buf[i] = self.rng.next_f32();
+ }
+
+ &self.buf
+ }
+ fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {
+ mem::replace(&mut self.buf, buf)
+ }
+}
+
diff --git a/src/synth/rel.rs b/src/synth/rel.rs
new file mode 100644
index 0000000..76b6c04
--- /dev/null
+++ b/src/synth/rel.rs
@@ -0,0 +1,78 @@
+use std::{cmp, mem};
+use super::*;
+
+#[derive(Debug)]
+pub enum RelOp {
+ Greater,
+ GreaterEqual,
+ Equal,
+ NotEqual,
+ LessEqual,
+ Less,
+}
+
+#[derive(Debug)]
+pub struct Rel {
+ pub left: GenBox,
+ pub right: GenBox,
+ pub op: RelOp,
+ pub buf: SampleBuffer,
+}
+
+impl Generator for Rel {
+ fn eval<'a>(&'a mut self, params: &Parameters) -> &'a SampleBuffer {
+ let left_buf = self.left.eval(params);
+ let right_buf = self.right.eval(params);
+
+ match left_buf.rate {
+ Rate::Sample => {
+ self.buf.rate = Rate::Sample;
+
+ let bound = match right_buf.rate {
+ Rate::Sample => cmp::min(left_buf.len(), right_buf.len()),
+ Rate::Control => left_buf.len(),
+ };
+ for i in 0..bound {
+ let val = left_buf[i];
+ let thres = match right_buf.rate {
+ Rate::Sample => right_buf[i],
+ Rate::Control => right_buf.first(),
+ };
+ self.buf[i] = if match self.op {
+ RelOp::Greater => val > thres,
+ RelOp::GreaterEqual => val >= thres,
+ RelOp::Equal => val == thres,
+ RelOp::NotEqual => val != thres,
+ RelOp::LessEqual => val <= thres,
+ RelOp::Less => val < thres,
+ } {
+ 1.0
+ } else {
+ 0.0
+ };
+ }
+ },
+ Rate::Control => {
+ let val = left_buf.first();
+ let thres = right_buf.first();
+ self.buf.set(if match self.op {
+ RelOp::Greater => val > thres,
+ RelOp::GreaterEqual => val >= thres,
+ RelOp::Equal => val == thres,
+ RelOp::NotEqual => val != thres,
+ RelOp::LessEqual => val <= thres,
+ RelOp::Less => val < thres,
+ } {
+ 1.0
+ } else {
+ 0.0
+ });
+ },
+ }
+
+ &self.buf
+ }
+ fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {
+ mem::replace(&mut self.buf, buf)
+ }
+}
diff --git a/src/synth/triangle.rs b/src/synth/triangle.rs
index c8380a1..5c0c69a 100644
--- a/src/synth/triangle.rs
+++ b/src/synth/triangle.rs
@@ -1,3 +1,4 @@
+use std::mem;
use super::*;
#[derive(Debug)]