summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGraham Northup <grissess@nexusg.org>2017-10-13 12:54:04 -0400
committerGraham Northup <grissess@nexusg.org>2017-10-13 12:54:04 -0400
commit22cb7d7cbcacbfe3a7d3a2d454e6b8cf49ae989c (patch)
tree4d2d8cb2ce9c4441ce5cc525375665c44c31f9fb
parent255f0aa6de604e0bf9d37ba0ee5362ef3b9f235f (diff)
Added LUTs and ControlRate; improved parser
-rw-r--r--Cargo.toml4
-rw-r--r--gens/test.gen31
-rw-r--r--gens/test_basic.gen1
-rw-r--r--gens/test_lut.gen1
-rw-r--r--gens/test_voice.gen2
-rw-r--r--src/lang/parser.rs226
-rw-r--r--src/lang/tokenizer.rs5
-rw-r--r--src/main.rs11
-rw-r--r--src/proto.rs16
-rw-r--r--src/synth/adsr.rs122
-rw-r--r--src/synth/lut.rs84
-rw-r--r--src/synth/mod.rs49
-rw-r--r--src/synth/param.rs2
-rw-r--r--src/synth/rel.rs13
-rw-r--r--src/synth/saw.rs2
-rw-r--r--src/synth/sine.rs2
-rw-r--r--src/synth/square.rs2
-rw-r--r--src/synth/triangle.rs2
-rw-r--r--src/synth/util.rs60
19 files changed, 544 insertions, 91 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 9f0dba2..3133a17 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,6 +3,10 @@ name = "synfone"
version = "0.1.0"
authors = ["Graham Northup <grissess@nexusg.org>"]
+[[bin]]
+name = "synfone"
+doc = false
+
[features]
default = ['graphics']
diff --git a/gens/test.gen b/gens/test.gen
index be43356..4613c0c 100644
--- a/gens/test.gen
+++ b/gens/test.gen
@@ -1,12 +1,23 @@
[
- #gens/test_voice.gen#,
- #gens/test_voice.gen#,
- #gens/test_voice.gen#,
- #gens/test_voice.gen#,
- #gens/test_voice.gen#,
- #gens/test_voice.gen#,
- #gens/test_voice.gen#,
- #gens/test_voice.gen#,
- #gens/test_voice.gen#,
- #gens/test_voice.gen#
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#,
+ #gens/test_basic.gen#
]
diff --git a/gens/test_basic.gen b/gens/test_basic.gen
new file mode 100644
index 0000000..cbbfbbc
--- /dev/null
+++ b/gens/test_basic.gen
@@ -0,0 +1 @@
+lutgen(sine(lut_freq), 128, v_freq) * ifelse(v_frame < v_deadline, v_amp, 0)
diff --git a/gens/test_lut.gen b/gens/test_lut.gen
new file mode 100644
index 0000000..d9fc9fe
--- /dev/null
+++ b/gens/test_lut.gen
@@ -0,0 +1 @@
+lutgen(sine(lut_freq), 256, 440)
diff --git a/gens/test_voice.gen b/gens/test_voice.gen
index 855568b..41684c1 100644
--- a/gens/test_voice.gen
+++ b/gens/test_voice.gen
@@ -1 +1 @@
-mul(sine(param('v_freq', 500)), ifelse(rel(param('v_frame'), '<', param('v_deadline')), mul(param('v_amp'), add(param('v_frame'), negate(param('v_start'))), reciprocate(add(param('v_deadline'), negate(param('v_start'))))), 0.0))
+(lutgen(sine(lut_freq), 128, v_freq) * controlrate(dahdsr(v_frame < v_deadline, 0, 4 / samplerate(), 0, 1, 1, 8 / samplerate()))) * v_amp
diff --git a/src/lang/parser.rs b/src/lang/parser.rs
index c49cf65..35df372 100644
--- a/src/lang/parser.rs
+++ b/src/lang/parser.rs
@@ -7,6 +7,7 @@ use synth::*;
#[derive(Debug)]
pub enum ErrorKind {
Unexpected(TokType, TokType),
+ Unparseable(TokType, String),
ExpectedOp(char, TokType),
UnknownGen(String),
}
@@ -26,6 +27,7 @@ impl ErrorType {
ret.desc = match ret.kind {
ErrorKind::Unexpected(found, expected) => format!("Found {:?}, expected {:?}", found, expected),
+ ErrorKind::Unparseable(found, ref term) => format!("Cannot consume {:?} token in {}", found, term),
ErrorKind::ExpectedOp(c, found) => format!("Expected {:?}, found {:?}", c, found),
ErrorKind::UnknownGen(ref s) => format!("Unknown generator name {}", s),
};
@@ -76,20 +78,27 @@ impl<T: Iterator<Item=char>> Parser<T> {
pub fn push_back(&mut self, tok: Token) {
match self.pushback {
None => {
- self.pushback = Some(mem::replace(&mut self.token, tok));
+ self.pushback = Some(tok);
},
Some(_) => panic!("too many pushbacks on Parser"),
}
}
+ pub fn cur_token(&self) -> &Token {
+ match self.pushback {
+ Some(ref tok) => tok,
+ None => &self.token,
+ }
+ }
+
pub fn expect(&mut self, ty: TokType) -> Result<Token, Box<Error>> {
- if ty == self.token.to_type() {
- Ok(mem::replace(&mut self.token, match self.pushback {
- Some(_) => mem::replace(&mut self.pushback, None).unwrap(),
- None => self.tzr.next_token()?,
- }))
- } else {
+ if ty != self.cur_token().to_type() {
Err(ErrorType::new(ErrorKind::Unexpected(self.token.to_type(), ty)).into())
+ } else {
+ Ok(match self.pushback {
+ Some(_) => mem::replace(&mut self.pushback, None).unwrap(),
+ None => mem::replace(&mut self.token, self.tzr.next_token()?),
+ })
}
}
@@ -101,9 +110,18 @@ impl<T: Iterator<Item=char>> Parser<T> {
}
pub fn expect_op(&mut self, oper: char) -> Result<(), Box<Error>> {
- match self.token {
+ eprintln!("expect_op: {:?} ({})", self.cur_token(), oper);
+ match *self.cur_token() {
Token::Oper(c) if c == oper => { self.expect(TokType::Oper)?; Ok(()) },
- _ => Err(ErrorType::new(ErrorKind::ExpectedOp(oper, self.token.to_type())).into()),
+ _ => Err(ErrorType::new(ErrorKind::ExpectedOp(oper, self.cur_token().to_type())).into()),
+ }
+ }
+
+ pub fn peek_op(&self, oper: char) -> bool {
+ eprintln!("peek_op: {:?} ({})", self.cur_token(), oper);
+ match *self.cur_token() {
+ Token::Oper(c) if c == oper => true,
+ _ => false
}
}
@@ -117,17 +135,7 @@ impl<T: Iterator<Item=char>> Parser<T> {
break;
}
- /* TODO: Can't yet clone a GenBox safely
- let repeat = match self.token {
- Token::Integer(v) => {
- self.expect_op('*')?;
- v
- },
- _ => 1,
- };
- */
-
- ret.push(self.parse_gen()?);
+ ret.push(self.parse_gen_rel()?);
if self.expect_op(',').is_err() {
self.expect_op(']')?;
@@ -138,17 +146,150 @@ impl<T: Iterator<Item=char>> Parser<T> {
Ok(ret)
}
- pub fn parse_gen(&mut self) -> Result<GenBox, Box<Error>> {
- let name = self.expect_ident()?;
- let mut params = self.parse_factory_params()?;
- let factory = match self.factories.get(&name) {
- Some(fac) => fac,
- None => return Err(ErrorType::new(ErrorKind::UnknownGen(name)).into()),
- };
+ pub fn parse_gen_rel(&mut self) -> Result<GenBox, Box<Error>> {
+ let left = self.parse_gen_terms()?;
+
+ match *self.cur_token() {
+ Token::Oper(c) => {
+ if c == '>' || c == '!' || c == '<' || c == '=' { // TODO: Conflict with param name
+ self.expect(TokType::Oper)?;
+ let relop = match (c, self.cur_token()) {
+ ('<', &Token::Oper('=')) => { self.expect(TokType::Oper)?; RelOp::LessEqual },
+ ('=', &Token::Oper('=')) => { self.expect(TokType::Oper)?; RelOp::Equal },
+ ('>', &Token::Oper('=')) => { self.expect(TokType::Oper)?; RelOp::Greater },
+ ('!', &Token::Oper('=')) => { self.expect(TokType::Oper)?; RelOp::NotEqual },
+ ('<', _) => RelOp::Less,
+ ('>', _) => RelOp::Greater,
+ _ => return Err(ErrorType::new(ErrorKind::Unparseable(TokType::Oper, "rel expr".to_string())).into()),
+ };
+ let mut params = FactoryParameters { env: self.env.clone(), ..Default::default() };
+ params.vars.insert("0".to_string(), ParamValue::Generator(left));
+ params.vars.insert("1".to_string(), ParamValue::String(relop.to_param_string().to_string()));
+ params.vars.insert("2".to_string(), ParamValue::Generator(self.parse_gen_rel()?));
+ let factory = self.factories.get("rel").ok_or(ErrorType::new(ErrorKind::UnknownGen("rel".to_string())))?;
+ factory.new(&mut params).map_err(Into::into)
+ } else {
+ Ok(left)
+ }
+ },
+ _ => Ok(left),
+ }
+ }
+
+ pub fn parse_gen_terms(&mut self) -> Result<GenBox, Box<Error>> {
+ let mut gens: Vec<GenBox> = Vec::new();
+ gens.push(self.parse_gen_factors()?);
+
+ loop {
+ match *self.cur_token() {
+ Token::Oper('+') => {
+ self.expect_op('+')?;
+ gens.push(self.parse_gen_factors()?);
+ },
+ Token::Oper('-') => {
+ self.expect_op('-')?;
+ let mut params = FactoryParameters { env: self.env.clone(), ..Default::default() };
+ params.vars.insert("0".to_string(), ParamValue::Generator(self.parse_gen_factors()?));
+ let factory = self.factories.get("negate").ok_or(ErrorType::new(ErrorKind::UnknownGen("negate".to_string())))?;
+ gens.push(factory.new(&mut params).map_err(GenFactoryErrorType::from)?);
+ },
+ _ => break,
+ }
+ }
+
+ if gens.len() == 1 {
+ return Ok(gens.pop().unwrap());
+ }
+
+ let mut params = FactoryParameters { env: self.env.clone(), ..Default::default() };
+ for (idx, gen) in gens.into_iter().enumerate() {
+ params.vars.insert(idx.to_string(), ParamValue::Generator(gen));
+ }
+ let factory = self.factories.get("add").ok_or(ErrorType::new(ErrorKind::UnknownGen("add".to_string())))?;
+ factory.new(&mut params).map_err(Into::into)
+ }
+
+ pub fn parse_gen_factors(&mut self) -> Result<GenBox, Box<Error>> {
+ let mut gens: Vec<GenBox> = Vec::new();
+ gens.push(self.parse_gen()?);
+
+ loop {
+ match *self.cur_token() {
+ Token::Oper('*') => {
+ self.expect_op('*')?;
+ gens.push(self.parse_gen()?);
+ },
+ Token::Oper('/') => {
+ self.expect_op('/')?;
+ let mut params = FactoryParameters { env: self.env.clone(), ..Default::default() };
+ params.vars.insert("0".to_string(), ParamValue::Generator(self.parse_gen()?));
+ let factory = self.factories.get("reciprocate").ok_or(ErrorType::new(ErrorKind::UnknownGen("reciprocate".to_string())))?;
+ gens.push(factory.new(&mut params).map_err(GenFactoryErrorType::from)?);
+ },
+ _ => break,
+ }
+ }
+
+ if gens.len() == 1 {
+ return Ok(gens.pop().unwrap());
+ }
+
+ let mut params = FactoryParameters { env: self.env.clone(), ..Default::default() };
+ for (idx, gen) in gens.into_iter().enumerate() {
+ params.vars.insert(idx.to_string(), ParamValue::Generator(gen));
+ }
+ let factory = self.factories.get("mul").ok_or(ErrorType::new(ErrorKind::UnknownGen("mul".to_string())))?;
factory.new(&mut params).map_err(Into::into)
}
+ pub fn parse_gen(&mut self) -> Result<GenBox, Box<Error>> {
+ match *self.cur_token() {
+ Token::Integer(v) => {
+ self.expect(TokType::Integer)?;
+ let mut params = FactoryParameters { env: self.env.clone(), ..Default::default() };
+ params.vars.insert("0".to_string(), ParamValue::String("_".to_string()));
+ params.vars.insert("1".to_string(), ParamValue::Integer(v));
+ let factory = self.factories.get("param").ok_or(ErrorType::new(ErrorKind::UnknownGen("param".to_string())))?;
+ factory.new(&mut params).map_err(Into::into)
+ },
+ Token::Float(v) => {
+ self.expect(TokType::Float)?;
+ let mut params = FactoryParameters { env: self.env.clone(), ..Default::default() };
+ params.vars.insert("0".to_string(), ParamValue::String("_".to_string()));
+ params.vars.insert("1".to_string(), ParamValue::Float(v));
+ let factory = self.factories.get("param").ok_or(ErrorType::new(ErrorKind::UnknownGen("param".to_string())))?;
+ factory.new(&mut params).map_err(Into::into)
+ },
+ Token::Ident(_) => {
+ let name = self.expect_ident()?;
+ if self.peek_op('(') {
+ let mut params = self.parse_factory_params()?;
+ let factory = match self.factories.get(&name) {
+ Some(fac) => fac,
+ None => return Err(ErrorType::new(ErrorKind::UnknownGen(name)).into()),
+ };
+ factory.new(&mut params).map_err(Into::into)
+ } else {
+ let mut params = FactoryParameters { env: self.env.clone(), ..Default::default() };
+ params.vars.insert("0".to_string(), ParamValue::String(name));
+ let factory = self.factories.get("param").ok_or(ErrorType::new(ErrorKind::UnknownGen("param".to_string())))?;
+ factory.new(&mut params).map_err(Into::into)
+ }
+ },
+ Token::Oper('(') => {
+ eprintln!("consuming paren in parse_gen");
+ self.expect(TokType::Oper)?;
+ let ret = self.parse_gen_rel()?;
+ eprintln!("parenthesized generator is concluding");
+ self.expect_op(')')?;
+ Ok(ret)
+ },
+ _ => Err(ErrorType::new(ErrorKind::Unparseable(self.cur_token().to_type(), "gen".to_string())).into()),
+ }
+ }
+
pub fn parse_factory_params(&mut self) -> Result<FactoryParameters, Box<Error>> {
+ eprintln!("consuming paren in factory_params");
self.expect_op('(')?;
let mut params: FactoryParameters = FactoryParameters { env: self.env.clone(), ..Default::default() };
@@ -161,7 +302,9 @@ impl<T: Iterator<Item=char>> Parser<T> {
params.vars.insert(nm, vl);
ctr = new_ctr;
- if self.expect_op(',').is_err() {
+ eprintln!("before factory_params comma, tok is {:?}", self.cur_token());
+ if self.expect_op(',').map_err(|e| eprintln!("factory_params consume comma failed: {:?}", e)).is_err() {
+ eprintln!("factory_params is concluding");
self.expect_op(')')?;
break;
}
@@ -177,14 +320,9 @@ impl<T: Iterator<Item=char>> Parser<T> {
if self.expect_op('=').is_ok() {
nm
} else {
- match self.token {
- Token::Oper(c) if c == '(' => {
- self.push_back(Token::Ident(nm));
- ctr += 1;
- (ctr - 1).to_string()
- },
- _ => return Err(ErrorType::new(ErrorKind::Unexpected(self.token.to_type(), TokType::Ident)).into()),
- }
+ self.push_back(Token::Ident(nm));
+ ctr += 1;
+ (ctr - 1).to_string()
}
},
Err(_) => {
@@ -193,16 +331,12 @@ impl<T: Iterator<Item=char>> Parser<T> {
},
};
- let ret = match self.token {
- Token::Integer(v) => Ok((name, ParamValue::Integer(v), ctr)),
- Token::Float(v) => Ok((name, ParamValue::Float(v), ctr)),
- Token::String(ref v) => Ok((name, ParamValue::String(v.clone()), ctr)),
- Token::Ident(_) => return Ok((name, ParamValue::Generator(self.parse_gen()?), ctr)),
- _ => return Err(ErrorType::new(ErrorKind::Unexpected(self.token.to_type(), TokType::Ident)).into()),
- };
+ eprintln!("about to consume param value, token is {:?}", self.cur_token());
- let tp = self.token.to_type();
- self.expect(tp)?;
- ret
+ match self.cur_token().clone() { // FIXME: Does this really need to be cloned?
+ Token::String(ref v) => { self.expect(TokType::String)?; Ok((name, ParamValue::String(v.clone()), ctr)) },
+ Token::Integer(_) | Token::Float(_) | Token::Ident(_) | Token::Oper('(') => Ok((name, ParamValue::Generator(self.parse_gen_rel()?), ctr)),
+ _ => Err(ErrorType::new(ErrorKind::Unparseable(self.cur_token().to_type(), "param value".to_string())).into()),
+ }
}
}
diff --git a/src/lang/tokenizer.rs b/src/lang/tokenizer.rs
index 1d62f3e..6de825b 100644
--- a/src/lang/tokenizer.rs
+++ b/src/lang/tokenizer.rs
@@ -425,9 +425,12 @@ impl<T: Iterator<Item=char>> Tokenizer<T> {
floating = true;
buffer.push(cc);
buffer.push(ncc);
- } else {
+ } else if ncc.is_digit(10) {
buffer.push(cc);
buffer.push(ncc);
+ } else {
+ self.push_back(ncc);
+ return Ok(Token::Integer(0));
}
} else {
buffer.push(cc);
diff --git a/src/main.rs b/src/main.rs
index ad121e7..6aacda1 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -20,6 +20,8 @@ use synfone::lang::*;
use synfone::proto::*;
use synfone::client::*;
+const GFX: bool = false;
+
fn main() {
let env = Environment::default();
@@ -72,7 +74,7 @@ fn main() {
eprintln!("Audio stream started.");
- {
+ let net_thread = {
let client = client.clone();
let net_thread = thread::spawn(move || {
let mut buffer: [u8; Command::SIZE] = [0u8; Command::SIZE];
@@ -91,13 +93,14 @@ fn main() {
}
}
});
- }
+ net_thread
+ };
eprintln!("Network thread started.");
//net_thread.join().expect("Network thread panicked");
- {
+ if GFX {
let last_buffer = last_buffer.clone();
let mut events_loop = glutin::EventsLoop::new();
@@ -348,6 +351,8 @@ fn main() {
//display.swap_buffers().expect("Failed to swap buffers");
}
+ } else {
+ net_thread.join().expect("Network thread panicked");
}
eprintln!("Exiting.");
diff --git a/src/proto.rs b/src/proto.rs
index 630e3e8..279cd3f 100644
--- a/src/proto.rs
+++ b/src/proto.rs
@@ -71,15 +71,15 @@ impl Command {
impl fmt::Debug for Command {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- write!(f, "Command::")?;
+ f.write_str("Command::")?;
match *self {
- Command::KeepAlive => write!(f, "KeepAlive"),
- Command::Ping{data} => write!(f, "Ping {{ data: {:?} }}", &data),
- Command::Quit => write!(f, "Quit"),
- Command::Play{sec, usec, freq, amp, voice} => write!(f, "Play {{ sec: {:?}, usec: {:?}, freq: {:?}, amp: {:?}, voice: {:?} }}", sec, usec, freq, amp, voice),
- Command::Caps{voices, tp, ident} => write!(f, "Caps {{ voices: {:?}, tp: {:?}, ident: {:?} }}", voices, &tp, &ident),
- Command::PCM{samples} => write!(f, "PCM {{ samples: {:?} }}", &samples),
- Command::Unknown{data} => write!(f, "Unknown {{ data: {:?} }}", &data as &[u8]),
+ Command::KeepAlive => f.write_str("KeepAlive"),
+ Command::Ping{data} => f.debug_struct("Ping").field("data", &data).finish(),
+ Command::Quit => f.write_str("Quit"),
+ Command::Play{sec, usec, freq, amp, voice} => f.debug_struct("Play").field("sec", &sec).field("usec", &usec).field("freq", &freq).field("amp", &amp).field("voice", &voice).finish(),
+ Command::Caps{voices, tp, ident} => f.debug_struct("Caps").field("voices", &voices).field("tp", &tp).field("ident", &ident).finish(),
+ Command::PCM{samples} => f.debug_struct("PCM").field("samples", &samples).finish(),
+ Command::Unknown{data} => f.debug_struct("Unknown").field("data", &(&data as &[u8])).finish(),
}
}
}
diff --git a/src/synth/adsr.rs b/src/synth/adsr.rs
new file mode 100644
index 0000000..ca7be9c
--- /dev/null
+++ b/src/synth/adsr.rs
@@ -0,0 +1,122 @@
+use super::*;
+
+#[derive(Debug,Clone,Copy,PartialEq,Eq)]
+pub enum Phase {
+ Delay,
+ Attack,
+ Hold,
+ Decay,
+ Sustain,
+ Release,
+}
+
+#[derive(Debug)]
+pub struct DAHDSR {
+ pub delay: GenBox,
+ pub attack: GenBox,
+ pub hold: GenBox,
+ pub decay: GenBox,
+ pub sustain: GenBox,
+ pub release: GenBox,
+ pub gate: GenBox,
+ pub phase: Phase,
+ pub cur: f32,
+ pub attack_cd: f32,
+ pub decay_cd: f32,
+ pub buf: SampleBuffer,
+}
+
+impl Generator for DAHDSR {
+ fn eval<'a>(&'a mut self, params: &Parameters) -> &'a SampleBuffer {
+ self.buf.rate = Rate::Sample;
+
+ let delay = self.delay.eval(params).first();
+ let attack = self.attack.eval(params).first();
+ let hold = self.attack.eval(params).first();
+ let decay = self.decay.eval(params).first();
+ let sustain = self.sustain.eval(params).first();
+ let release = self.release.eval(params).first();
+ let gate = self.gate.eval(params).first();
+
+ if gate >= 0.5 {
+ if self.phase == Phase::Release {
+ self.phase = Phase::Delay;
+ self.attack_cd = delay;
+ self.cur = 0.0;
+ }
+ } else{
+ self.phase = Phase::Release;
+ }
+
+ for samp in self.buf.samples.iter_mut() {
+ match self.phase {
+ Phase::Delay => {
+ self.attack_cd -= 1.0;
+ if self.attack_cd <= 0.0 {
+ self.phase = Phase::Attack;
+ }
+ },
+ Phase::Attack => {
+ self.cur += attack;
+ if self.cur >= 1.0 {
+ self.cur = 1.0;
+ self.phase = Phase::Hold;
+ self.decay_cd = hold;
+ }
+ },
+ Phase::Hold => {
+ self.decay_cd -= 1.0;
+ if self.decay_cd <= 0.0 {
+ self.phase = Phase::Decay;
+ }
+ },
+ Phase::Decay => {
+ self.cur -= decay;
+ if self.cur <= sustain {
+ self.cur = sustain;
+ self.phase = Phase::Sustain;
+ }
+ },
+ Phase::Sustain => {
+ self.cur = sustain;
+ },
+ Phase::Release => {
+ self.cur -= release;
+ if self.cur < 0.0 {
+ self.cur = 0.0;
+ }
+ },
+ }
+ *samp = self.cur;
+ }
+
+ &self.buf
+ }
+ fn buffer(&self) -> &SampleBuffer { &self.buf }
+ fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {
+ mem::replace(&mut self.buf, buf)
+ }
+}
+
+pub struct DAHDSRFactory;
+
+impl GeneratorFactory for DAHDSRFactory {
+ fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> {
+ Ok(Box::new(DAHDSR {
+ delay: params.remove_param("delay", 1)?.into_gen()?,
+ attack: params.remove_param("attack", 2)?.into_gen()?,
+ hold: params.remove_param("hold", 3)?.into_gen()?,
+ decay: params.remove_param("decay", 4)?.into_gen()?,
+ sustain: params.remove_param("sustain", 5)?.into_gen()?,
+ release: params.remove_param("release", 6)?.into_gen()?,
+ gate: params.remove_param("gate", 0)?.into_gen()?,
+ phase: Phase::Release,
+ cur: 0.0,
+ attack_cd: 0.0,
+ decay_cd: 0.0,
+ buf: SampleBuffer::new(params.env.default_buffer_size),
+ }))
+ }
+}
+
+pub static Factory: DAHDSRFactory = DAHDSRFactory;
diff --git a/src/synth/lut.rs b/src/synth/lut.rs
new file mode 100644
index 0000000..73b5efa
--- /dev/null
+++ b/src/synth/lut.rs
@@ -0,0 +1,84 @@
+use super::*;
+
+#[derive(Debug)]
+pub struct Lut {
+ pub freq: GenBox,
+ pub phase: f32,
+ pub lut: Vec<Sample>,
+ pub buf: SampleBuffer,
+}
+
+impl Generator for Lut {
+ 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] = self.lut[(((self.phase + pvel * (i as f32)) % 1.0) * (self.lut.len() as f32)) as usize];
+ }
+
+ self.phase = (self.phase + pvel * (self.buf.len() as f32)) % 1.0;
+ &self.buf
+ }
+ fn buffer(&self) -> &SampleBuffer { &self.buf }
+ fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {
+ mem::replace(&mut self.buf, buf)
+ }
+}
+
+pub struct LutDataFactory;
+
+impl GeneratorFactory for LutDataFactory {
+ fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> {
+ Ok(Box::new(Lut {
+ freq: params.remove_param("freq", 0)?.into_gen()?,
+ phase: params.get_param("phase", 1, &mut ParamValue::Float(0.0)).as_f32()?,
+ buf: SampleBuffer::new(params.env.default_buffer_size),
+ lut: {
+ let mut lut: Vec<Sample> = Vec::new();
+ let mut i = 0;
+
+ while let Ok(samp) = params.get_req_param("_", 2 + i).and_then(|pv| pv.as_f32()) {
+ lut.push(samp);
+ i += 1;
+ }
+
+ if lut.is_empty() {
+ return Err(GenFactoryError::MissingRequiredParam("samples".to_string(), 2));
+ }
+
+ lut
+ },
+ }))
+ }
+}
+
+pub static FactoryLutData: LutDataFactory = LutDataFactory;
+
+pub struct LutGenFactory;
+
+impl GeneratorFactory for LutGenFactory {
+ fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> {
+ eprintln!("LutGenFactory::new({:?})", params);
+ Ok(Box::new(Lut {
+ freq: params.remove_param("freq", 2)?.into_gen()?,
+ phase: params.get_param("phase", 3, &mut ParamValue::Float(0.0)).as_f32()?,
+ buf: SampleBuffer::new(params.env.default_buffer_size),
+ lut: {
+ let mut gen = params.remove_param("gen", 0)?.into_gen()?;
+ let samps = params.get_req_param("samples", 1)?.as_f32()?;
+ let var = params.get_param("var", 4, &mut ParamValue::String("lut_freq".to_string())).as_string()?;
+ let mut genparams = Parameters { env: params.env.clone(), ..Default::default() };
+ genparams.env.sample_rate = samps;
+ genparams.vars.insert(var, 1.0);
+
+ gen.set_buffer(SampleBuffer::new(samps as usize));
+ gen.eval(&genparams);
+
+ gen.set_buffer(SampleBuffer::new(0)).samples
+ },
+ }))
+ }
+}
+
+pub static FactoryLutGen: LutGenFactory = LutGenFactory;
diff --git a/src/synth/mod.rs b/src/synth/mod.rs
index 55268a7..862ca38 100644
--- a/src/synth/mod.rs
+++ b/src/synth/mod.rs
@@ -249,6 +249,7 @@ pub enum ParamKind {
Generator,
}
+#[derive(Debug)]
pub enum ParamValue {
Integer(isize),
Float(f32),
@@ -266,21 +267,21 @@ impl ParamValue {
}
}
- pub fn as_isize(&self) -> Result<isize, GenFactoryError> {
+ pub fn as_isize(&mut self) -> Result<isize, GenFactoryError> {
match *self {
ParamValue::Integer(v) => Ok(v),
ParamValue::Float(v) => Ok(v as isize),
ParamValue::String(ref v) => v.parse().map_err(|_| GenFactoryError::CannotConvert(ParamKind::String, ParamKind::Integer)),
- ParamValue::Generator(_) => Err(GenFactoryError::CannotConvert(ParamKind::Generator, ParamKind::Integer)),
+ ParamValue::Generator(ref mut g) => Ok(g.eval(&Default::default()).first() as isize),
}
}
- pub fn as_f32(&self) -> Result<f32, GenFactoryError> {
+ pub fn as_f32(&mut self) -> Result<f32, GenFactoryError> {
match *self {
ParamValue::Integer(v) => Ok(v as f32),
ParamValue::Float(v) => Ok(v),
ParamValue::String(ref v) => v.parse().map_err(|_| GenFactoryError::CannotConvert(ParamKind::String, ParamKind::Float)),
- ParamValue::Generator(_) => Err(GenFactoryError::CannotConvert(ParamKind::Generator, ParamKind::Float)),
+ ParamValue::Generator(ref mut g) => Ok(g.eval(&Default::default()).first()),
}
}
@@ -309,25 +310,30 @@ impl<'a> From<&'a ParamValue> for ParamKind {
}
}
-#[derive(Default)]
+#[derive(Debug,Default)]
pub struct FactoryParameters {
pub env: Environment,
pub vars: HashMap<String, ParamValue>,
}
impl FactoryParameters {
- pub fn get_param<'a, 'b : 'a>(&'a self, name: &str, position: usize, default: &'b ParamValue) -> &'a ParamValue {
- (
- self.vars.get(name).or_else(||
- self.vars.get(&position.to_string()).or(Some(default))
- )
- ).unwrap()
+ pub fn get_param<'a, 'b : 'a>(&'a mut self, name: &str, position: usize, default: &'b mut ParamValue) -> &'a mut ParamValue {
+ let position = position.to_string();
+
+ match (self.vars.contains_key(name), self.vars.contains_key(&position)) {
+ (true, _) => self.vars.get_mut(name).unwrap(),
+ (false, true) => self.vars.get_mut(&position).unwrap(),
+ (false, false) => default,
+ }
}
- pub fn get_req_param(&self, name: &str, position: usize) -> Result<&ParamValue, GenFactoryError> {
- match self.vars.get(name).or_else(|| self.vars.get(&position.to_string())) {
- Some(v) => Ok(v),
- None => Err(GenFactoryError::MissingRequiredParam(name.to_string(), position)),
+ pub fn get_req_param(&mut self, name: &str, position: usize) -> Result<&mut ParamValue, GenFactoryError> {
+ let pos = position.to_string();
+
+ match (self.vars.contains_key(name), self.vars.contains_key(&pos)) {
+ (true, _) => Ok(self.vars.get_mut(name).unwrap()),
+ (false, true) => Ok(self.vars.get_mut(&pos).unwrap()),
+ (false, false) => Err(GenFactoryError::MissingRequiredParam(name.to_string(), position)),
}
}
@@ -367,6 +373,10 @@ pub mod rel;
pub use self::rel::{Rel, RelOp};
pub mod logic;
pub use self::logic::IfElse;
+pub mod util;
+pub use self::util::{ControlRate, SampleRate};
+pub mod lut;
+pub use self::lut::Lut;
pub mod sine;
pub use self::sine::Sine;
pub mod saw;
@@ -377,8 +387,8 @@ pub mod square;
pub use self::square::Square;
pub mod noise;
pub use self::noise::Noise;
-//pub mod adsr;
-//pub use self::adsr::ADSR;
+pub mod adsr;
+pub use self::adsr::DAHDSR;
pub fn all_factories() -> HashMap<String, &'static GeneratorFactory> {
let mut ret = HashMap::new();
@@ -390,11 +400,16 @@ pub fn all_factories() -> HashMap<String, &'static GeneratorFactory> {
ret.insert("reciprocate".to_string(), &self::math::FactoryReciprocate as &GeneratorFactory);
ret.insert("rel".to_string(), &self::rel::Factory as &GeneratorFactory);
ret.insert("ifelse".to_string(), &self::logic::Factory as &GeneratorFactory);
+ ret.insert("controlrate".to_string(), &self::util::FactoryControlRate as &GeneratorFactory);
+ ret.insert("samplerate".to_string(), &self::util::FactorySampleRate as &GeneratorFactory);
+ ret.insert("lutdata".to_string(), &self::lut::FactoryLutData as &GeneratorFactory);
+ ret.insert("lutgen".to_string(), &self::lut::FactoryLutGen as &GeneratorFactory);
ret.insert("sine".to_string(), &self::sine::Factory as &GeneratorFactory);
ret.insert("saw".to_string(), &self::saw::Factory as &GeneratorFactory);
ret.insert("triangle".to_string(), &self::triangle::Factory as &GeneratorFactory);
ret.insert("square".to_string(), &self::square::Factory as &GeneratorFactory);
ret.insert("noise".to_string(), &self::noise::Factory as &GeneratorFactory);
+ ret.insert("dahdsr".to_string(), &self::adsr::Factory as &GeneratorFactory);
ret
}
diff --git a/src/synth/param.rs b/src/synth/param.rs
index b020574..602be1d 100644
--- a/src/synth/param.rs
+++ b/src/synth/param.rs
@@ -24,7 +24,7 @@ impl GeneratorFactory for ParamFactory {
fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> {
Ok(Box::new(Param {
name: params.get_req_param("name", 0)?.as_string()?,
- default: params.get_param("default", 1, &ParamValue::Float(0.0)).as_f32()?,
+ default: params.get_param("default", 1, &mut ParamValue::Float(0.0)).as_f32()?,
buf: SampleBuffer::new(1),
}))
}
diff --git a/src/synth/rel.rs b/src/synth/rel.rs
index e3c4216..d2fbb70 100644
--- a/src/synth/rel.rs
+++ b/src/synth/rel.rs
@@ -11,6 +11,19 @@ pub enum RelOp {
Less,
}
+impl RelOp {
+ pub fn to_param_string(&self) -> &'static str {
+ match *self {
+ RelOp::Greater => ">",
+ RelOp::GreaterEqual => ">=",
+ RelOp::Equal => "==",
+ RelOp::NotEqual => "!=",
+ RelOp::LessEqual => "<=",
+ RelOp::Less => "<",
+ }
+ }
+}
+
/* TODO
impl<T: PartialEq<isize>> From<T> for RelOp {
fn from(i: T) -> RelOp {
diff --git a/src/synth/saw.rs b/src/synth/saw.rs
index 054b3c8..3e30ca6 100644
--- a/src/synth/saw.rs
+++ b/src/synth/saw.rs
@@ -31,7 +31,7 @@ impl GeneratorFactory for SawFactory {
fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> {
Ok(Box::new(Saw {
freq: params.remove_param("freq", 0)?.into_gen()?,
- phase: params.get_param("phase", 1, &ParamValue::Float(0.0)).as_f32()?,
+ phase: params.get_param("phase", 1, &mut ParamValue::Float(0.0)).as_f32()?,
buf: SampleBuffer::new(params.env.default_buffer_size),
}))
}
diff --git a/src/synth/sine.rs b/src/synth/sine.rs
index 66f29ef..4476d4a 100644
--- a/src/synth/sine.rs
+++ b/src/synth/sine.rs
@@ -34,7 +34,7 @@ impl GeneratorFactory for SineFactory {
fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> {
Ok(Box::new(Sine {
freq: params.remove_param("freq", 0)?.into_gen()?,
- phase: params.get_param("phase", 1, &ParamValue::Float(0.0)).as_f32()?,
+ phase: params.get_param("phase", 1, &mut ParamValue::Float(0.0)).as_f32()?,
buf: SampleBuffer::new(params.env.default_buffer_size),
}))
}
diff --git a/src/synth/square.rs b/src/synth/square.rs
index 9b4374f..4b01e07 100644
--- a/src/synth/square.rs
+++ b/src/synth/square.rs
@@ -35,7 +35,7 @@ impl GeneratorFactory for SquareFactory {
fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> {
Ok(Box::new(Square {
freq: params.remove_param("freq", 0)?.into_gen()?,
- phase: params.get_param("phase", 1, &ParamValue::Float(0.0)).as_f32()?,
+ phase: params.get_param("phase", 1, &mut ParamValue::Float(0.0)).as_f32()?,
buf: SampleBuffer::new(params.env.default_buffer_size),
}))
}
diff --git a/src/synth/triangle.rs b/src/synth/triangle.rs
index 19a2296..944c539 100644
--- a/src/synth/triangle.rs
+++ b/src/synth/triangle.rs
@@ -39,7 +39,7 @@ impl GeneratorFactory for TriangleFactory {
fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> {
Ok(Box::new(Triangle {
freq: params.remove_param("freq", 0)?.into_gen()?,
- phase: params.get_param("phase", 1, &ParamValue::Float(0.0)).as_f32()?,
+ phase: params.get_param("phase", 1, &mut ParamValue::Float(0.0)).as_f32()?,
buf: SampleBuffer::new(params.env.default_buffer_size),
}))
}
diff --git a/src/synth/util.rs b/src/synth/util.rs
new file mode 100644
index 0000000..5bde721
--- /dev/null
+++ b/src/synth/util.rs
@@ -0,0 +1,60 @@
+use super::*;
+
+#[derive(Debug)]
+pub struct ControlRate {
+ pub value: GenBox,
+ pub buf: SampleBuffer,
+}
+
+impl ControlRate {
+ pub fn new(mut gen: GenBox) -> ControlRate {
+ gen.set_buffer(SampleBuffer::new(1));
+ ControlRate { value: gen, buf: SampleBuffer::new(1) }
+ }
+}
+
+impl Generator for ControlRate {
+ fn eval<'a>(&'a mut self, params: &Parameters) -> &'a SampleBuffer {
+ self.buf.rate = Rate::Control;
+ self.buf.update_from(self.value.eval(params));
+ &self.buf
+ }
+ fn buffer(&self) -> &SampleBuffer { &self.buf }
+ fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer { mem::replace(&mut self.buf, buf) }
+}
+
+pub struct ControlRateFactory;
+
+impl GeneratorFactory for ControlRateFactory {
+ fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> {
+ Ok(Box::new(ControlRate::new(params.remove_param("gen", 0)?.into_gen()?)))
+ }
+}
+
+pub static FactoryControlRate: ControlRateFactory = ControlRateFactory;
+
+#[derive(Debug)]
+pub struct SampleRate {
+ pub buf: SampleBuffer,
+}
+
+impl Generator for SampleRate {
+ fn eval<'a>(&'a mut self, params: &Parameters) -> &'a SampleBuffer {
+ self.buf.set(params.env.sample_rate);
+ &self.buf
+ }
+ fn buffer(&self) -> &SampleBuffer { &self.buf }
+ fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {
+ mem::replace(&mut self.buf, buf)
+ }
+}
+
+pub struct SampleRateFactory;
+
+impl GeneratorFactory for SampleRateFactory {
+ fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> {
+ Ok(Box::new(SampleRate { buf: SampleBuffer::new(1) }))
+ }
+}
+
+pub static FactorySampleRate: SampleRateFactory = SampleRateFactory;