Skip to content

Commit

Permalink
add back csv1d
Browse files Browse the repository at this point in the history
  • Loading branch information
xasopheno committed Mar 8, 2023
1 parent 889ac84 commit 1ae51d4
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 97 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ If you want to learn how to make cool sounds using WereSoCool, you'll find cool
at [weresocool.org](https://www.weresocool.org/).


My recommend following the tutorials in order and writing your own composition after completing each one. Additional documentation is currently being worked on, as well as a record featuring a great band, so stay tuned.
I recommend following the tutorials in order and writing your own composition after completing each one. Additional documentation is currently being worked on, as well as a record featuring a great band, so stay tuned.

On mobile, you can still view the tutorials, but you won't be able to hear anything.

Expand Down
93 changes: 93 additions & 0 deletions ast/src/datagen/csv1d_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#[cfg(test)]
mod eeg_test {
use num_rational::Rational64;

use crate::{
datagen::mod_1d::{
csv_to_normalform, eeg_data_to_normal_form, eeg_datum_to_point_op, CsvData,
},
NameSet, NormalForm, PointOp,
};
#[test]
fn test_eeg_datum_to_point_op() {
let mut names = NameSet::new();
names.insert("data.csv".to_string());
let result = eeg_datum_to_point_op(1.0e-14, None, 2.0e14, "data.csv");
let expected = PointOp {
fa: Rational64::new(2, 1),
l: Rational64::new(1, 50),
names,
..PointOp::default()
};
assert_eq!(result, expected);
}

#[test]
fn test_eeg_datum_to_normal_form() {
let eeg_data = CsvData {
data: vec![0.5e-14, 1.0e-14, 1.5e-14],
};
let mut names = NameSet::new();
names.insert("data.csv".to_string());
let result = eeg_data_to_normal_form(&eeg_data, 2.0e14, "data.csv");
let expected = NormalForm {
operations: vec![vec![
PointOp {
fa: Rational64::new(1, 1),
l: Rational64::new(1, 50),
names: names.clone(),
..PointOp::default()
},
PointOp {
fa: Rational64::new(3, 2),
l: Rational64::new(1, 50),
names: names.clone(),
..PointOp::default()
},
PointOp {
fa: Rational64::new(2, 1),
l: Rational64::new(1, 50),
names,
..PointOp::default()
},
]],
length_ratio: Rational64::new(3, 50),
};
assert_eq!(result, expected);
}
#[test]
fn test_csv_to_normalform() {
let result = csv_to_normalform(
"./src/datagen/test_data.csv",
Some(Rational64::new(200_000_000_000_000, 1)),
)
.unwrap();

let mut names = NameSet::new();
names.insert("test_data.csv".to_string());
let expected = NormalForm {
operations: vec![vec![
PointOp {
fa: Rational64::new(1, 1),
l: Rational64::new(1, 50),
names: names.clone(),
..PointOp::default()
},
PointOp {
fa: Rational64::new(3, 2),
l: Rational64::new(1, 50),
names: names.clone(),
..PointOp::default()
},
PointOp {
fa: Rational64::new(2, 1),
l: Rational64::new(1, 50),
names,
..PointOp::default()
},
]],
length_ratio: Rational64::new(3, 50),
};
assert_eq!(result, expected);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ mod csv2d_tests {
assert_that!(&result, contains(expected).exactly());
}

//TODO: Fix these
#[test]
fn test_point_to_point_op() {
let mut names = NameSet::new();
Expand Down
7 changes: 3 additions & 4 deletions ast/src/datagen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ use std::{fs::File, path::Path};
use weresocool_error::Error;
use weresocool_ring_buffer::RingBuffer;
use weresocool_shared::helpers::r_to_f32;
mod csv_test;
mod test;
mod csv1d_test;
mod csv2d_test;
mod mod_1d;

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Copy)]
pub struct Point {
Expand Down Expand Up @@ -145,9 +146,7 @@ fn get_data1d(filename: String, length: Rational64) -> Result<Vec<Vec<f32>>, Err
.deserialize::<Vec<f32>>()
.map(|datum| datum.expect("Error deserializing datum"))
.collect();
dbg!(&deserialized);
let result: Vec<Vec<f32>> = deserialized[0].iter().map(|v| vec![*v, length]).collect();
dbg!(&result);

Ok(result)
}
Expand Down
140 changes: 140 additions & 0 deletions ast/src/datagen/mod_1d.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
use crate::{NameSet, NormalForm, Normalize, Op, OscType, PointOp, Term, ASR};
use num_rational::{Ratio, Rational64};
use scop::Defs;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use std::{fs::File, path::Path};
use weresocool_error::Error;
use weresocool_ring_buffer::RingBuffer;
use weresocool_shared::helpers::r_to_f32;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CsvData {
pub data: Vec<f32>,
}

pub fn csv_to_normalform(filename: &str, scale: Option<Rational64>) -> Result<NormalForm, Error> {
let data = get_data(filename.into())?;
let path = Path::new(&filename);
Ok(vec_eeg_data_to_normal_form(
data,
if let Some(s) = scale {
r_to_f32(s)
} else {
1.0
},
path.file_name()
.unwrap()
.to_string_lossy()
.to_string()
.as_str(),
))
}

fn vec_eeg_data_to_normal_form(data: Vec<CsvData>, scale: f32, filename: &str) -> NormalForm {
let mut nfs: Vec<NormalForm> = data
.iter()
.map(|stream| eeg_data_to_normal_form(stream, scale, filename))
.collect();

let overlay = Op::Overlay {
operations: nfs.iter_mut().map(|nf| Term::Nf(nf.to_owned())).collect(),
};

let mut nf = NormalForm::init();
overlay
.apply_to_normal_form(&mut nf, &mut Defs::new())
.expect("unable to normalize");
nf
}

pub fn eeg_data_to_normal_form(data: &CsvData, scale: f32, filename: &str) -> NormalForm {
let mut length_ratio = Rational64::new(0, 1);

let mut buffer = RingBuffer::<f32>::new(50);

let point_ops: Vec<PointOp> = data
.data
.iter()
.map(|value| {
let op = eeg_datum_to_point_op(*value, Some(&mut buffer), scale, filename);
length_ratio += op.l;
op
})
.collect();

NormalForm {
length_ratio,
operations: vec![point_ops],
}
}

pub fn f32_to_rational(mut float: f32) -> Rational64 {
if !float.is_finite() || float > 100_000_000.0 {
float = 0.0
}
let float_string = format!("{:.8}", float);
let decimal = float_string.split('.').collect::<Vec<&str>>()[1];
let den = i64::pow(10, decimal.len() as u32);
let num = i64::from_str(&float_string.replace('.', ""))
.unwrap_or_else(|_| panic!("error converting {} to i64", float_string));

Ratio::new(num, den)
}

pub fn eeg_datum_to_point_op(
datum: f32,
buffer: Option<&mut RingBuffer<f32>>,
scale: f32,
filename: &str,
) -> PointOp {
let mut nameset = NameSet::new();
nameset.insert(filename.to_string());
let mut datum = datum.abs() * scale;
if let Some(b) = buffer {
b.push(datum);

let b_vec = b.to_vec();
let sum: f32 = b_vec.iter().sum();
datum = sum / b_vec.len() as f32;
}

let fa = f32_to_rational(datum);
PointOp {
// fm,
fm: Rational64::new(1, 1),
fa,
l: Rational64::new(2, 100),
g: Rational64::new(1, 1),
pm: Rational64::new(1, 1),
pa: Rational64::new(0, 1),
asr: ASR::Long,
portamento: Rational64::new(1, 1),
attack: Rational64::new(1, 1),
decay: Rational64::new(1, 1),
reverb: None,
osc_type: OscType::None,
names: nameset,
}
}

fn get_data(filename: String) -> Result<Vec<CsvData>, Error> {
let path = Path::new(&filename);
let cwd = std::env::current_dir()?;
let file = File::open(path).unwrap_or_else(|_| {
panic!(
"unable to read file: {}. current working directory is: {}",
path.display(),
cwd.display()
)
});
let mut rdr = csv::ReaderBuilder::new()
.has_headers(false)
.delimiter(b',')
.from_reader(file);

Ok(rdr
.deserialize::<CsvData>()
.map(|datum| datum.expect("Error deserializing datum"))
.collect())
}
91 changes: 0 additions & 91 deletions ast/src/datagen/test.rs

This file was deleted.

0 comments on commit 1ae51d4

Please sign in to comment.