summaryrefslogtreecommitdiff
path: root/src/synth
diff options
context:
space:
mode:
Diffstat (limited to 'src/synth')
-rw-r--r--src/synth/math.rs9
-rw-r--r--src/synth/mod.rs48
-rw-r--r--src/synth/param.rs4
-rw-r--r--src/synth/saw.rs25
-rw-r--r--src/synth/sine.rs6
-rw-r--r--src/synth/square.rs29
-rw-r--r--src/synth/triangle.rs32
7 files changed, 136 insertions, 17 deletions
diff --git a/src/synth/math.rs b/src/synth/math.rs
index 66a86a0..91e58e3 100644
--- a/src/synth/math.rs
+++ b/src/synth/math.rs
@@ -1,5 +1,7 @@
use super::*;
+use std::mem;
+#[derive(Debug)]
pub struct Add {
pub terms: Vec<GenBox>,
pub buf: SampleBuffer,
@@ -18,8 +20,12 @@ impl Generator for Add {
}
&self.buf
}
+ fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {
+ mem::replace(&mut self.buf, buf)
+ }
}
+#[derive(Debug)]
pub struct Mul {
pub factors: Vec<GenBox>,
pub buf: SampleBuffer,
@@ -38,4 +44,7 @@ impl Generator for Mul {
}
&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 d0c837a..bf73200 100644
--- a/src/synth/mod.rs
+++ b/src/synth/mod.rs
@@ -1,14 +1,18 @@
use std::{iter, cmp, slice, mem};
+use std::fmt::Debug;
use std::ops::{Index, IndexMut};
use std::collections::HashMap;
use super::*;
-#[derive(PartialEq,Eq,Clone,Copy)]
+use ::byteorder::ByteOrder;
+
+#[derive(PartialEq,Eq,Clone,Copy,Debug)]
pub enum Rate {
Sample,
Control,
}
+#[derive(Debug)]
pub struct SampleBuffer {
pub samples: Vec<Sample>,
pub rate: Rate,
@@ -82,7 +86,11 @@ impl SampleBuffer {
pub fn sum_into(&mut self, other: &SampleBuffer) {
match self.rate {
Rate::Sample => {
- for i in 0..cmp::min(self.len(), other.len()) {
+ let bound = match other.rate {
+ Rate::Sample => cmp::min(self.len(), other.len()),
+ Rate::Control => self.len(),
+ };
+ for i in 0..bound {
self.samples[i] += match other.rate {
Rate::Sample => other.samples[i],
Rate::Control => other.samples[0],
@@ -98,7 +106,11 @@ impl SampleBuffer {
pub fn mul_into(&mut self, other: &SampleBuffer) {
match self.rate {
Rate::Sample => {
- for i in 0..cmp::min(self.len(), other.len()) {
+ let bound = match other.rate {
+ Rate::Sample => cmp::min(self.len(), other.len()),
+ Rate::Control => self.len(),
+ };
+ for i in 0..bound {
self.samples[i] *= match other.rate {
Rate::Sample => other.samples[i],
Rate::Control => other.samples[0],
@@ -117,13 +129,13 @@ impl SampleBuffer {
}
}
- pub fn bytes<'a>(&'a self) -> &'a [u8] {
- unsafe {
- slice::from_raw_parts(
- self.samples.as_ptr() as *const u8,
- self.samples.len() * mem::size_of::<Sample>(),
- )
- }
+ pub fn size(&self) -> usize {
+ mem::size_of::<Sample>() * self.samples.len()
+ }
+
+ pub fn bytes(&self, buf: &mut [u8]) {
+ // FIXME: Depends on f32 instead of Sample alias
+ ::byteorder::LittleEndian::write_f32_into(&self.samples, buf);
}
}
@@ -136,8 +148,9 @@ impl IndexMut<usize> for SampleBuffer {
fn index_mut(&mut self, idx: usize) -> &mut Sample { &mut self.samples[idx] }
}
-pub trait Generator {
+pub trait Generator : Debug {
fn eval<'a>(&'a mut self, params: &Parameters) -> &'a SampleBuffer;
+ fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer;
}
pub type GenBox = Box<Generator>;
@@ -148,8 +161,11 @@ pub mod math;
pub use self::math::{Add, Mul};
pub mod sine;
pub use self::sine::Sine;
-//pub mod saw;
-//pub use saw::Saw;
-//pub mod triangle;
-//pub use triangle::Triangle;
-
+pub mod saw;
+pub use self::saw::Saw;
+pub mod triangle;
+pub use self::triangle::Triangle;
+pub mod square;
+pub use self::square::Square;
+//pub mod asdr;
+//pub use self::asdr::ASDR;
diff --git a/src/synth/param.rs b/src/synth/param.rs
index ced5900..f679b56 100644
--- a/src/synth/param.rs
+++ b/src/synth/param.rs
@@ -1,5 +1,6 @@
use super::*;
+#[derive(Debug)]
pub struct Param {
pub name: String,
pub default: Sample,
@@ -11,4 +12,7 @@ impl Generator for Param {
self.buf.set(*params.vars.get(&self.name).unwrap_or(&self.default));
&self.buf
}
+ fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {
+ mem::replace(&mut self.buf, buf)
+ }
}
diff --git a/src/synth/saw.rs b/src/synth/saw.rs
new file mode 100644
index 0000000..bfd3cb0
--- /dev/null
+++ b/src/synth/saw.rs
@@ -0,0 +1,25 @@
+use super::*;
+
+#[derive(Debug)]
+pub struct Saw {
+ pub freq: GenBox,
+ pub phase: f32,
+ pub buf: SampleBuffer,
+}
+
+impl Generator for Saw {
+ fn eval<'a>(&'a mut self, params: &Parameters) -> &'a SampleBuffer {
+ self.buf.rate = Rate::Sample;
+
+ let pvel = self.freq.eval(params).first() / params.env.sample_rate;
+ for i in 0..self.buf.len() {
+ self.buf[i] = 2.0 * ((self.phase + pvel * (i as f32)) % 1.0) - 1.0;
+ }
+
+ self.phase = (self.phase + pvel * (self.buf.len() as f32)) % 1.0;
+ &self.buf
+ }
+ fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {
+ mem::replace(&mut self.buf, buf)
+ }
+}
diff --git a/src/synth/sine.rs b/src/synth/sine.rs
index 212ab21..90f3200 100644
--- a/src/synth/sine.rs
+++ b/src/synth/sine.rs
@@ -3,6 +3,7 @@ use super::*;
const TAU: f32 = 2f32 * PI;
+#[derive(Debug)]
pub struct Sine {
pub freq: GenBox,
pub phase: f32,
@@ -11,7 +12,7 @@ pub struct Sine {
impl Generator for Sine {
fn eval<'a>(&'a mut self, params: &Parameters) -> &'a SampleBuffer {
- self.buf.rate = Rate::Control;
+ self.buf.rate = Rate::Sample;
let pvel = TAU * self.freq.eval(params).first() / params.env.sample_rate;
for i in 0..self.buf.len() {
@@ -21,4 +22,7 @@ impl Generator for Sine {
self.phase = (self.phase + pvel * (self.buf.len() as f32)) % TAU;
&self.buf
}
+ fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {
+ mem::replace(&mut self.buf, buf)
+ }
}
diff --git a/src/synth/square.rs b/src/synth/square.rs
new file mode 100644
index 0000000..8197110
--- /dev/null
+++ b/src/synth/square.rs
@@ -0,0 +1,29 @@
+use super::*;
+
+#[derive(Debug)]
+pub struct Square {
+ pub freq: GenBox,
+ pub phase: f32,
+ pub buf: SampleBuffer,
+}
+
+impl Generator for Square {
+ fn eval<'a>(&'a mut self, params: &Parameters) -> &'a SampleBuffer {
+ self.buf.rate = Rate::Sample;
+
+ let pvel = self.freq.eval(params).first() / params.env.sample_rate;
+ for i in 0..self.buf.len() {
+ self.buf[i] = if ((self.phase + pvel * (i as f32)) % 1.0) < 0.5 {
+ -1.0
+ } else {
+ 1.0
+ };
+ }
+
+ self.phase = (self.phase + pvel * (self.buf.len() as f32)) % 1.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
new file mode 100644
index 0000000..c8380a1
--- /dev/null
+++ b/src/synth/triangle.rs
@@ -0,0 +1,32 @@
+use super::*;
+
+#[derive(Debug)]
+pub struct Triangle {
+ pub freq: GenBox,
+ pub phase: f32,
+ pub buf: SampleBuffer,
+}
+
+impl Generator for Triangle {
+ fn eval<'a>(&'a mut self, params: &Parameters) -> &'a SampleBuffer {
+ self.buf.rate = Rate::Sample;
+
+ let pvel = self.freq.eval(params).first() / params.env.sample_rate;
+ for i in 0..self.buf.len() {
+ let ph = (self.phase + pvel * (i as f32)) % 1.0;
+ self.buf[i] = if ph < 0.25 {
+ 4.0 * ph
+ } else if ph > 0.75 {
+ 4.0 * ph - 4.0
+ } else {
+ -4.0 * ph + 2.0
+ };
+ }
+
+ self.phase = (self.phase + pvel * (self.buf.len() as f32)) % 1.0;
+ &self.buf
+ }
+ fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {
+ mem::replace(&mut self.buf, buf)
+ }
+}