Explorar o código

Added LUTs and ControlRate; improved parser

Graham Northup %!s(int64=8) %!d(string=hai) anos
pai
achega
22cb7d7cbc

+ 4 - 0
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']
 

+ 21 - 10
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#
 ]

+ 1 - 0
gens/test_basic.gen

@@ -0,0 +1 @@
+lutgen(sine(lut_freq), 128, v_freq) * ifelse(v_frame < v_deadline, v_amp, 0)

+ 1 - 0
gens/test_lut.gen

@@ -0,0 +1 @@
+lutgen(sine(lut_freq), 256, 440)

+ 1 - 1
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

+ 180 - 46
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()),
+        }
     }
 }

+ 4 - 1
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);

+ 8 - 3
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.");

+ 8 - 8
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(),
         }
     }
 }

+ 122 - 0
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;

+ 84 - 0
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;

+ 32 - 17
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
 }

+ 1 - 1
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),
         }))
     }

+ 13 - 0
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 {

+ 1 - 1
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),
         }))
     }

+ 1 - 1
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),
         }))
     }

+ 1 - 1
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),
         }))
     }

+ 1 - 1
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),
         }))
     }

+ 60 - 0
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;