summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGraham Northup <grissess@nexusg.org>2017-09-24 03:41:45 -0400
committerGraham Northup <grissess@nexusg.org>2017-09-24 03:41:45 -0400
commit7eef21b3b90898f4ef05fa4220fde608cf55c6ab (patch)
treedb09a752bef57a5b6eb6040048ed1fdf66ab5043
parent3d370b9a980d88f884ddd87b62bc785c3b963e1d (diff)
parser appears to work (oh my)
-rw-r--r--src/lang/mod.rs32
-rw-r--r--src/lang/parser.rs175
-rw-r--r--src/lang/tokenizer.rs15
-rw-r--r--src/lib.rs1
-rw-r--r--src/main.rs22
-rw-r--r--src/synth/logic.rs19
-rw-r--r--src/synth/math.rs60
-rw-r--r--src/synth/mod.rs202
-rw-r--r--src/synth/noise.rs27
-rw-r--r--src/synth/param.rs15
-rw-r--r--src/synth/rel.rs62
-rw-r--r--src/synth/saw.rs15
-rw-r--r--src/synth/sine.rs15
-rw-r--r--src/synth/square.rs15
-rw-r--r--src/synth/triangle.rs15
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 {
diff --git a/src/lib.rs b/src/lib.rs
index c0bd79c..e4ddf70 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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;