diff options
| -rw-r--r-- | src/lang/mod.rs | 32 | ||||
| -rw-r--r-- | src/lang/parser.rs | 175 | ||||
| -rw-r--r-- | src/lang/tokenizer.rs | 15 | ||||
| -rw-r--r-- | src/lib.rs | 1 | ||||
| -rw-r--r-- | src/main.rs | 22 | ||||
| -rw-r--r-- | src/synth/logic.rs | 19 | ||||
| -rw-r--r-- | src/synth/math.rs | 60 | ||||
| -rw-r--r-- | src/synth/mod.rs | 202 | ||||
| -rw-r--r-- | src/synth/noise.rs | 27 | ||||
| -rw-r--r-- | src/synth/param.rs | 15 | ||||
| -rw-r--r-- | src/synth/rel.rs | 62 | ||||
| -rw-r--r-- | src/synth/saw.rs | 15 | ||||
| -rw-r--r-- | src/synth/sine.rs | 15 | ||||
| -rw-r--r-- | src/synth/square.rs | 15 | ||||
| -rw-r--r-- | src/synth/triangle.rs | 15 | 
15 files changed, 667 insertions, 23 deletions
| diff --git a/src/lang/mod.rs b/src/lang/mod.rs index 8256f34..14a9202 100644 --- a/src/lang/mod.rs +++ b/src/lang/mod.rs @@ -1,6 +1,10 @@  pub mod tokenizer;  pub use self::tokenizer::Tokenizer; +pub mod parser; +pub use self::parser::Parser; +// NB: No Eq due to embedded f32 +#[derive(Debug,PartialEq,Clone)]  pub enum Token {      Ident(String),      Integer(isize), @@ -10,3 +14,31 @@ pub enum Token {      EOF,  } +#[derive(Debug,PartialEq,Eq,Clone,Copy)] +pub enum TokType { +    Ident, +    Integer, +    Float, +    Oper, +    String, +    EOF, +} + +impl Token { +    pub fn to_type(&self) -> TokType { +        match *self { +            Token::Ident(_) => TokType::Ident, +            Token::Integer(_) => TokType::Integer, +            Token::Float(_) => TokType::Float, +            Token::Oper(_) => TokType::Oper, +            Token::String(_) => TokType::String, +            Token::EOF => TokType::EOF, +        } +    } +} + +impl<'a> From<&'a Token> for TokType { +    fn from(tok: &'a Token) -> TokType { +        tok.to_type() +    } +} diff --git a/src/lang/parser.rs b/src/lang/parser.rs new file mode 100644 index 0000000..d068b07 --- /dev/null +++ b/src/lang/parser.rs @@ -0,0 +1,175 @@ +use std::{mem, fmt}; +use std::error::Error; +use std::collections::HashMap; +use super::*; +use synth::*; + +#[derive(Debug)] +pub enum ErrorKind { +    Unexpected(TokType, TokType), +    ExpectedOp(char, TokType), +    UnknownGen(String), +} + +#[derive(Debug)] +pub struct ErrorType { +    pub kind: ErrorKind, +    desc: String, +} + +impl ErrorType { +    pub fn new(kind: ErrorKind) -> ErrorType { +        let mut ret = ErrorType { +            kind: kind, +            desc: "".to_string(), +        }; + +        ret.desc = match &ret.kind { +            &ErrorKind::Unexpected(found, expected) => format!("Found {:?}, expected {:?}", found, expected), +            &ErrorKind::ExpectedOp(c, found) => format!("Expected {:?}, found {:?}", c, found), +            &ErrorKind::UnknownGen(ref s) => format!("Unknown generator name {}", s), +        }; + +        ret +    } + +    pub fn with_description(kind: ErrorKind, desc: String) -> ErrorType { +        ErrorType { +            kind: kind, +            desc: desc, +        } +    } +} + +impl Error for ErrorType { +    fn description<'a>(&'a self) -> &'a str { +        &self.desc +    } +} + +impl fmt::Display for ErrorType { +    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { +        write!(f, "{}", self.description()) +    } +} + +pub struct Parser<T: Iterator<Item=char>> { +    tzr: Tokenizer<T>, +    token: Token, +    pushback: Option<Token>, +    factories: HashMap<String, &'static GeneratorFactory>, +} + +impl<T: Iterator<Item=char>> Parser<T> { +    pub fn new(mut tzr: Tokenizer<T>) -> Result<Parser<T>, Box<Error>> { +        let token = tzr.next_token()?; +        Ok(Parser { +            tzr: tzr, +            token: token, +            pushback: None, +            factories: all_factories(), +        }) +    } + +    pub fn push_back(&mut self, tok: Token) { +        match self.pushback { +            None => { +                self.pushback = Some(mem::replace(&mut self.token, tok)); +            }, +            Some(_) => panic!("too many pushbacks on Parser"), +        } +    } + +    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 { +            Err(ErrorType::new(ErrorKind::Unexpected(self.token.to_type(), ty)).into()) +        } +    } + +    pub fn expect_ident(&mut self) -> Result<String, Box<Error>> { +        match self.expect(TokType::Ident)? { +            Token::Ident(s) => Ok(s), +            _ => unreachable!(), +        } +    } + +    pub fn expect_op(&mut self, oper: char) -> Result<(), Box<Error>> { +        match self.token { +            Token::Oper(c) if c == oper => { self.expect(TokType::Oper)?; Ok(()) }, +            _ => Err(ErrorType::new(ErrorKind::ExpectedOp(oper, self.token.to_type())).into()), +        } +    } + +    pub fn parse(&mut self) -> Result<GenBox, Box<Error>> { +        self.parse_gen() +    } + +    pub fn parse_gen(&mut self) -> Result<GenBox, Box<Error>> { +        let name = self.expect_ident()?; + +        self.expect_op('(')?; +        let mut params: FactoryParameters = Default::default(); +        let mut ctr = 0; +        loop { +            if self.expect_op(')').is_ok() { +                break; +            } +            let (nm, vl, new_ctr) = self.parse_param(ctr)?; +            params.vars.insert(nm, vl); +            ctr = new_ctr; + +            if self.expect_op(',').is_err() { +                eprintln!("No comma: {:?}", self.token); +                self.expect_op(')')?; +                break; +            } +        } + +        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) +    } + +    pub fn parse_param(&mut self, pos: usize) -> Result<(String, ParamValue, usize), Box<Error>> { +        let mut ctr = pos; +        let name = match self.expect_ident() { +            Ok(nm) => { +                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()), +                    } +                } +            }, +            Err(_) => { +                ctr += 1; +                (ctr - 1).to_string() +            }, +        }; + +        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()), +        }; + +        let tp = self.token.to_type(); +        self.expect(tp); +        ret +    } +} diff --git a/src/lang/tokenizer.rs b/src/lang/tokenizer.rs index d1b34e0..4f2858c 100644 --- a/src/lang/tokenizer.rs +++ b/src/lang/tokenizer.rs @@ -173,13 +173,20 @@ impl<T: Iterator<Item=char>> Tokenizer<T> {          }      } -    fn next_token(&mut self) -> Result<Token, ErrorType> { +    pub fn next_token(&mut self) -> Result<Token, ErrorType> { +        let res = self._next_token(); +        eprintln!("next_token: {:?}", res); +        res +    } + +    fn _next_token(&mut self) -> Result<Token, ErrorType> {          let mut c = self.next_char();          if c == None {              return Ok(Token::EOF);          }          let mut cc = c.unwrap(); +        /* Whitespace */          while cc.is_whitespace() {              c = self.next_char();              if c == None { @@ -315,10 +322,16 @@ impl<T: Iterator<Item=char>> Tokenizer<T> {                      radix = 16;                  } else if ncc == self.lexemes.esc_oct {                      radix = 8; +                } else if ncc == self.lexemes.radix_point { +                    floating = true; +                    buffer.push(cc); +                    buffer.push(ncc);                  } else {                      buffer.push(cc);                      buffer.push(ncc);                  } +            } else { +                buffer.push(cc);              }              loop { @@ -1,5 +1,6 @@  #![feature(associated_consts)]  #![feature(unicode)] +#![feature(drop_types_in_const)]  extern crate byteorder;  extern crate rand; diff --git a/src/main.rs b/src/main.rs index c284820..7f8e14e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,32 +2,18 @@ use std::io;  use std::io::*;  extern crate rand; -use rand::{Rng, SeedableRng};  extern crate synfone;  use synfone::synth::*; +use synfone::lang::*;  const FRAMES: usize = 44100 * 2; +const GEN: &'static str = "add(mul(sine(param('freq', 440)), 0.5), mul(sine(param('freq2', 660)), 0.5))"; +  fn main() {      let mut params = Parameters::default(); -    //let mut freq: GenBox = Box::new(Param { name: "freq".to_string(), default: 440.0, buf: SampleBuffer::new(1) }); -    //let mut sg: GenBox = Box::new(Saw { freq: freq, phase: 0.0, buf: SampleBuffer::new(params.env.default_buffer_size) }); -    let mut osrng = rand::os::OsRng::new().expect("Couldn't initialize OS RNG"); -    let mut seed: [u32; 4] = Default::default(); -    for i in seed.iter_mut() { -        *i = osrng.next_u32(); -    } -    let mut sg: GenBox = Box::new(Noise { rng: rand::XorShiftRng::from_seed(seed), buf: SampleBuffer::new(params.env.default_buffer_size) }); - -    let mut freq2: GenBox = Box::new(Param { name: "freq2".to_string(), default: 660.0, buf: SampleBuffer::new(1) }); -    let mut sg2: GenBox = Box::new(Sine { freq: freq2, phase: 0.0, buf: SampleBuffer::new(params.env.default_buffer_size) }); - -    let mut half1: GenBox = Box::new(Param { name: "half".to_string(), default: 1.0, buf: SampleBuffer::new(1) }); -    let mut half2: GenBox = Box::new(Param { name: "half".to_string(), default: 0.0, buf: SampleBuffer::new(1) }); -    let mut sc1: GenBox = Box::new(Mul { factors: vec![sg, half1], buf: SampleBuffer::new(params.env.default_buffer_size) }); -    let mut sc2: GenBox = Box::new(Mul { factors: vec![sg2, half2], buf: SampleBuffer::new(params.env.default_buffer_size) }); -    let mut gen: GenBox = Box::new(Add { terms: vec![sc1, sc2], buf: SampleBuffer::new(params.env.default_buffer_size) }); +    let mut gen = Parser::new(Tokenizer::new(GEN.chars())).expect("Failed to get first token").parse().expect("Failed to compile generator");      let mut counter = 0;      let mut out = io::stdout(); diff --git a/src/synth/logic.rs b/src/synth/logic.rs index 5071d95..672cc78 100644 --- a/src/synth/logic.rs +++ b/src/synth/logic.rs @@ -15,11 +15,11 @@ impl Generator for IfElse {          let iftrue_buf = self.iftrue.eval(params);          let iffalse_buf = self.iffalse.eval(params); -        if ( +        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 { @@ -57,7 +57,22 @@ impl Generator for IfElse {          &self.buf      } +    fn buffer<'a>(&'a self) -> &'a SampleBuffer { &self.buf }      fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {          mem::replace(&mut self.buf, buf)      }  } + +pub struct IfElseFactory; + +impl GeneratorFactory for IfElseFactory { +    fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> { +        let cond = params.remove_param("cond", 0)?.as_gen()?; +        let iftrue = params.remove_param("iftrue", 1)?.as_gen()?; +        let iffalse = params.remove_param("iffalse", 2)?.as_gen()?; +        let buf = SampleBuffer::new(cmp::max(cmp::max(cond.buffer().len(), iftrue.buffer().len()), iffalse.buffer().len())); +        Ok(Box::new(IfElse { cond: cond, iftrue: iftrue, iffalse: iffalse, buf: buf })) +    } +} + +pub static Factory: IfElseFactory = IfElseFactory; diff --git a/src/synth/math.rs b/src/synth/math.rs index 8adad4b..eb1a604 100644 --- a/src/synth/math.rs +++ b/src/synth/math.rs @@ -20,11 +20,25 @@ impl Generator for Add {          }          &self.buf      } +    fn buffer<'a>(&'a self) -> &'a SampleBuffer { &self.buf }      fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {          mem::replace(&mut self.buf, buf)      }  } +pub struct AddFactory; + +impl GeneratorFactory for AddFactory { +    fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> { +        Ok(Box::new(Add { +            terms: params.get_pos_params().into_iter().map(|x| x.as_gen()).collect::<Result<Vec<_>, _>>()?, +            buf: SampleBuffer::new(params.env.default_buffer_size), +        })) +    } +} + +pub static FactoryAdd: AddFactory = AddFactory; +  #[derive(Debug)]  pub struct Mul {      pub factors: Vec<GenBox>, @@ -44,11 +58,25 @@ impl Generator for Mul {          }          &self.buf      } +    fn buffer<'a>(&'a self) -> &'a SampleBuffer { &self.buf }      fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {          mem::replace(&mut self.buf, buf)      }  } +pub struct MulFactory; + +impl GeneratorFactory for MulFactory { +    fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> { +        Ok(Box::new(Mul { +            factors: params.get_pos_params().into_iter().map(|x| x.as_gen()).collect::<Result<Vec<_>, _>>()?, +            buf: SampleBuffer::new(params.env.default_buffer_size), +        })) +    } +} + +pub static FactoryMul: MulFactory = MulFactory; +  #[derive(Debug)]  pub struct Negate {      pub value: GenBox, @@ -70,11 +98,27 @@ impl Generator for Negate {          }          &self.buf      } +    fn buffer<'a>(&'a self) -> &'a SampleBuffer { &self.buf }      fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {          mem::replace(&mut self.buf, buf)      }  } +pub struct NegateFactory; + +impl GeneratorFactory for NegateFactory { +    fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> { +        let mut gen = params.remove_param("value", 0)?.as_gen()?; +        let len = gen.buffer().len(); +        Ok(Box::new(Negate { +            value: gen, +            buf: SampleBuffer::new(len), +        })) +    } +} + +pub static FactoryNegate: NegateFactory = NegateFactory; +  #[derive(Debug)]  pub struct Reciprocate {      pub value: GenBox, @@ -96,7 +140,23 @@ impl Generator for Reciprocate {          }          &self.buf      } +    fn buffer<'a>(&'a self) -> &'a SampleBuffer { &self.buf }      fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {          mem::replace(&mut self.buf, buf)      }  } + +pub struct ReciprocateFactory; + +impl GeneratorFactory for ReciprocateFactory { +    fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> { +        let mut gen = params.remove_param("value", 0)?.as_gen()?; +        let len = gen.buffer().len(); +        Ok(Box::new(Reciprocate { +            value: gen, +            buf: SampleBuffer::new(len), +        })) +    } +} + +pub static FactoryReciprocate: ReciprocateFactory = ReciprocateFactory; diff --git a/src/synth/mod.rs b/src/synth/mod.rs index 4f23a01..b22e162 100644 --- a/src/synth/mod.rs +++ b/src/synth/mod.rs @@ -1,5 +1,6 @@ -use std::{iter, cmp, slice, mem}; +use std::{iter, cmp, slice, mem, fmt};  use std::fmt::Debug; +use std::error::Error;  use std::ops::{Index, IndexMut};  use std::collections::HashMap;  use super::*; @@ -154,11 +155,191 @@ impl IndexMut<usize> for SampleBuffer {  pub trait Generator : Debug {      fn eval<'a>(&'a mut self, params: &Parameters) -> &'a SampleBuffer; +    fn buffer<'a>(&'a self) -> &'a SampleBuffer;      fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer;  }  pub type GenBox = Box<Generator>; +#[derive(Debug)] +pub enum GenFactoryError { +    MissingRequiredParam(String, usize), +    CannotConvert(ParamKind, ParamKind), +    BadType(ParamKind), +} + +#[derive(Debug)] +pub struct GenFactoryErrorType { +    pub kind: GenFactoryError, +    desc: String +} + +impl GenFactoryErrorType { +    pub fn new(kind: GenFactoryError) -> GenFactoryErrorType { +        let mut ret = GenFactoryErrorType { +            kind: kind, +            desc: "".to_string(), +        }; + +        ret.desc = match &ret.kind { +            &GenFactoryError::MissingRequiredParam(ref name, pos) => format!("Needed a parameter named {} or at pos {}", name, pos), +            &GenFactoryError::CannotConvert(from, to) => format!("Cannot convert {:?} to {:?}", from, to), +            &GenFactoryError::BadType(ty) => format!("Bad parameter type {:?}", ty), +        }; + +        ret +    } + +    pub fn with_description(kind: GenFactoryError, desc: String) -> GenFactoryErrorType { +        GenFactoryErrorType { +            kind: kind, +            desc: desc, +        } +    } +} + +impl From<GenFactoryError> for GenFactoryErrorType { +    fn from(e: GenFactoryError) -> GenFactoryErrorType { +        GenFactoryErrorType::new(e) +    } +} + +impl Error for GenFactoryErrorType { +    fn description<'a>(&'a self) -> &'a str { +        &self.desc +    } +} + +impl fmt::Display for GenFactoryErrorType { +    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { +        write!(f, "{}", self.description()) +    } +} + +impl Into<Box<Error>> for GenFactoryError { +    fn into(self) -> Box<Error> { +        Box::new(GenFactoryErrorType::new(self)) +    } +} + +#[derive(Debug,PartialEq,Eq,Clone,Copy)] +pub enum ParamKind { +    Integer, +    Float, +    String, +    Generator, +} + +pub enum ParamValue { +    Integer(isize), +    Float(f32), +    String(String), +    Generator(GenBox), +} + +impl ParamValue { +    pub fn kind(&self) -> ParamKind { +        match *self { +            ParamValue::Integer(_) => ParamKind::Integer, +            ParamValue::Float(_) => ParamKind::Float, +            ParamValue::String(_) => ParamKind::String, +            ParamValue::Generator(_) => ParamKind::Generator, +        } +    } + +    pub fn as_isize(&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)), +        } +    } + +    pub fn as_f32(&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)), +        } +    } + +    pub fn as_string(&self) -> Result<String, GenFactoryError> { +        match *self { +            ParamValue::Integer(v) => Ok(v.to_string()), +            ParamValue::Float(v) => Ok(v.to_string()), +            ParamValue::String(ref v) => Ok(v.clone()), +            ParamValue::Generator(_) => Err(GenFactoryError::CannotConvert(ParamKind::Generator, ParamKind::String)), +        } +    } + +    pub fn as_gen(self) -> Result<GenBox, GenFactoryError> { +        match self { +            ParamValue::Integer(v) => Ok(Box::new(self::param::Param { name : "_".to_string(), default: v as f32, buf: SampleBuffer::new(1) })), +            ParamValue::Float(v) => Ok(Box::new(self::param::Param { name : "_".to_string(), default: v, buf: SampleBuffer::new(1) })), +            ParamValue::String(_) => Err(GenFactoryError::CannotConvert(ParamKind::String, ParamKind::Generator)), +            ParamValue::Generator(g) => Ok(g), +        } +    } +} + +impl<'a> From<&'a ParamValue> for ParamKind { +    fn from(val: &'a ParamValue) -> ParamKind { +        val.kind() +    } +} + +#[derive(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_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 remove_param(&mut self, name: &str, position: usize) -> Result<ParamValue, GenFactoryError> { +        match self.vars.remove(name).or_else(|| self.vars.remove(&position.to_string())) { +            Some(v) => Ok(v), +            None => Err(GenFactoryError::MissingRequiredParam(name.to_string(), position)), +        } +    } + +    pub fn get_pos_params(&mut self) -> Vec<ParamValue> { +        let mut ret = Vec::new(); + +        for i in 0.. { +            match self.vars.remove(&i.to_string()) { +                Some(v) => ret.push(v), +                None => return ret, +            } +        } + +        unreachable!() +    } +} + +pub trait GeneratorFactory { +    // NB: Like above, &self is for object safety. This should have an associated type, but that +    // would compromise object safety; for the same reason, the return of this may only be a +    // Box<Generator>, which necessitates allocation. +    fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError>; +} +  pub mod param;  pub use self::param::Param;  pub mod math; @@ -179,3 +360,22 @@ pub mod noise;  pub use self::noise::Noise;  //pub mod adsr;  //pub use self::adsr::ADSR; + +pub fn all_factories() -> HashMap<String, &'static GeneratorFactory> { +    let mut ret = HashMap::new(); + +    ret.insert("param".to_string(), &self::param::Factory as &GeneratorFactory); +    ret.insert("add".to_string(), &self::math::FactoryAdd as &GeneratorFactory); +    ret.insert("mul".to_string(), &self::math::FactoryMul as &GeneratorFactory); +    ret.insert("negate".to_string(), &self::math::FactoryNegate as &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("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 +} diff --git a/src/synth/noise.rs b/src/synth/noise.rs index 4d90f3b..68c120f 100644 --- a/src/synth/noise.rs +++ b/src/synth/noise.rs @@ -1,7 +1,8 @@  use std::mem;  use super::*; -use ::rand::{XorShiftRng, Rng}; +use ::rand::{XorShiftRng, Rng, SeedableRng}; +use ::rand::os::OsRng;  #[derive(Debug)]  pub struct Noise { @@ -19,8 +20,32 @@ impl Generator for Noise {          &self.buf      } +    fn buffer<'a>(&'a self) -> &'a SampleBuffer { &self.buf }      fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {          mem::replace(&mut self.buf, buf)      }  } +static mut _rand_gen: Option<OsRng> = None; + +pub struct NoiseFactory; + +impl GeneratorFactory for NoiseFactory { +    fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> { +        if unsafe { &_rand_gen }.is_none() { +            unsafe {_rand_gen = Some(OsRng::new().expect("Couldn't initialize OS random")); } +        } + +        let mut seed: [u32; 4] = Default::default(); +        for i in seed.iter_mut() { +            *i = unsafe { &mut _rand_gen }.as_mut().unwrap().next_u32(); +        } + +        Ok(Box::new(Noise { +            rng: XorShiftRng::from_seed(seed), +            buf: SampleBuffer::new(params.env.default_buffer_size), +        })) +    } +} + +pub static Factory: NoiseFactory = NoiseFactory; diff --git a/src/synth/param.rs b/src/synth/param.rs index f679b56..859f789 100644 --- a/src/synth/param.rs +++ b/src/synth/param.rs @@ -12,7 +12,22 @@ impl Generator for Param {          self.buf.set(*params.vars.get(&self.name).unwrap_or(&self.default));          &self.buf      } +    fn buffer<'a>(&'a self) -> &'a SampleBuffer { &self.buf }      fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {          mem::replace(&mut self.buf, buf)      }  } + +pub struct ParamFactory; + +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()?, +            buf: SampleBuffer::new(1), +        })) +    } +} + +pub static Factory: ParamFactory = ParamFactory; diff --git a/src/synth/rel.rs b/src/synth/rel.rs index 76b6c04..bb3cf1f 100644 --- a/src/synth/rel.rs +++ b/src/synth/rel.rs @@ -11,6 +11,39 @@ pub enum RelOp {      Less,  } +/* TODO +impl<T: PartialEq<isize>> From<T> for RelOp { +    fn from(i: T) -> RelOp { +        match i { +            0 => RelOp::Greater, +            1 => RelOp::GreaterEqual, +            _ => RelOp::Equal, +            3 => RelOp::NotEqual, +            4 => RelOp::LessEqual, +            5 => RelOp::Less, +        } +    } +} +*/ + +impl<'a> From<&'a str> for RelOp { +    fn from(s: &'a str) -> RelOp { +        if s == ">" { +            RelOp::Greater +        } else if s == ">=" { +            RelOp::GreaterEqual +        } else if s == "!=" { +            RelOp::NotEqual +        } else if s == "<=" { +            RelOp::LessEqual +        } else if s == "<" { +            RelOp::Less +        } else { +            RelOp::Equal +        } +    } +} +  #[derive(Debug)]  pub struct Rel {      pub left: GenBox, @@ -72,7 +105,36 @@ impl Generator for Rel {          &self.buf      } +    fn buffer<'a>(&'a self) -> &'a SampleBuffer { &self.buf }      fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {          mem::replace(&mut self.buf, buf)      }  } + +pub struct RelFactory; + +impl GeneratorFactory for RelFactory { +    fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> { +        let op = match params.get_req_param("rel", 1)? { +            /* TODO +            &ParamValue::Integer(v) => v.into(), +            &ParamValue::Float(v) => (v as isize).into(), +            */ +            &ParamValue::Integer(_) => return Err(GenFactoryError::BadType(ParamKind::Integer)), +            &ParamValue::Float(_) => return Err(GenFactoryError::BadType(ParamKind::Float)), +            &ParamValue::String(ref v) => (&*v as &str).into(), +            &ParamValue::Generator(_) => return Err(GenFactoryError::BadType(ParamKind::Generator)), +        }; +        let left = params.remove_param("left", 0)?.as_gen()?; +        let right = params.remove_param("right", 2)?.as_gen()?; +        let buf = SampleBuffer::new(cmp::max(left.buffer().len(), right.buffer().len())); +        Ok(Box::new(Rel { +            left: left, +            right: right, +            op: op, +            buf: buf, +        })) +    } +} + +pub static Factory: RelFactory = RelFactory; diff --git a/src/synth/saw.rs b/src/synth/saw.rs index bfd3cb0..b85794d 100644 --- a/src/synth/saw.rs +++ b/src/synth/saw.rs @@ -19,7 +19,22 @@ impl Generator for Saw {          self.phase = (self.phase + pvel * (self.buf.len() as f32)) % 1.0;          &self.buf      } +    fn buffer<'a>(&'a self) -> &'a SampleBuffer { &self.buf }      fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {          mem::replace(&mut self.buf, buf)      }  } + +pub struct SawFactory; + +impl GeneratorFactory for SawFactory { +    fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> { +        Ok(Box::new(Saw { +            freq: params.remove_param("freq", 0)?.as_gen()?, +            phase: params.get_param("phase", 1, &ParamValue::Float(0.0)).as_f32()?, +            buf: SampleBuffer::new(params.env.default_buffer_size), +        })) +    } +} + +pub static Factory: SawFactory = SawFactory; diff --git a/src/synth/sine.rs b/src/synth/sine.rs index 90f3200..918261c 100644 --- a/src/synth/sine.rs +++ b/src/synth/sine.rs @@ -22,7 +22,22 @@ impl Generator for Sine {          self.phase = (self.phase + pvel * (self.buf.len() as f32)) % TAU;          &self.buf      } +    fn buffer<'a>(&'a self) -> &'a SampleBuffer { &self.buf }      fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {          mem::replace(&mut self.buf, buf)      }  } + +pub struct SineFactory; + +impl GeneratorFactory for SineFactory { +    fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> { +        Ok(Box::new(Sine { +            freq: params.remove_param("freq", 0)?.as_gen()?, +            phase: params.get_param("phase", 1, &ParamValue::Float(0.0)).as_f32()?, +            buf: SampleBuffer::new(params.env.default_buffer_size), +        })) +    } +} + +pub static Factory: SineFactory = SineFactory; diff --git a/src/synth/square.rs b/src/synth/square.rs index 8197110..d207562 100644 --- a/src/synth/square.rs +++ b/src/synth/square.rs @@ -23,7 +23,22 @@ impl Generator for Square {          self.phase = (self.phase + pvel * (self.buf.len() as f32)) % 1.0;          &self.buf      } +    fn buffer<'a>(&'a self) -> &'a SampleBuffer { &self.buf }      fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {          mem::replace(&mut self.buf, buf)      }  } + +pub struct SquareFactory; + +impl GeneratorFactory for SquareFactory { +    fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> { +        Ok(Box::new(Square { +            freq: params.remove_param("freq", 0)?.as_gen()?, +            phase: params.get_param("phase", 1, &ParamValue::Float(0.0)).as_f32()?, +            buf: SampleBuffer::new(params.env.default_buffer_size), +        })) +    } +} + +pub static Factory: SquareFactory = SquareFactory; diff --git a/src/synth/triangle.rs b/src/synth/triangle.rs index 5c0c69a..4f62e4c 100644 --- a/src/synth/triangle.rs +++ b/src/synth/triangle.rs @@ -27,7 +27,22 @@ impl Generator for Triangle {          self.phase = (self.phase + pvel * (self.buf.len() as f32)) % 1.0;          &self.buf      } +    fn buffer<'a>(&'a self) -> &'a SampleBuffer { &self.buf }      fn set_buffer(&mut self, buf: SampleBuffer) -> SampleBuffer {          mem::replace(&mut self.buf, buf)      }  } + +pub struct TriangleFactory; + +impl GeneratorFactory for TriangleFactory { +    fn new(&self, params: &mut FactoryParameters) -> Result<GenBox, GenFactoryError> { +        Ok(Box::new(Triangle { +            freq: params.remove_param("freq", 0)?.as_gen()?, +            phase: params.get_param("phase", 1, &ParamValue::Float(0.0)).as_f32()?, +            buf: SampleBuffer::new(params.env.default_buffer_size), +        })) +    } +} + +pub static Factory: TriangleFactory = TriangleFactory; | 
