Compare commits
2 Commits
2cdfcb72ee
...
b8910becc6
| Author | SHA1 | Date | |
|---|---|---|---|
| b8910becc6 | |||
| 0d4d92f374 |
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -205,6 +205,7 @@ dependencies = [
|
|||||||
"env_logger",
|
"env_logger",
|
||||||
"itertools 0.14.0",
|
"itertools 0.14.0",
|
||||||
"midir",
|
"midir",
|
||||||
|
"regex",
|
||||||
"rustysynth",
|
"rustysynth",
|
||||||
"tinyaudio",
|
"tinyaudio",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -8,5 +8,6 @@ clap = { version = "4.5.60", features = ["derive"] }
|
|||||||
env_logger = "0.11.9"
|
env_logger = "0.11.9"
|
||||||
itertools = "0.14.0"
|
itertools = "0.14.0"
|
||||||
midir = "0.10.3"
|
midir = "0.10.3"
|
||||||
|
regex = "1.12.3"
|
||||||
rustysynth = "1.3.6"
|
rustysynth = "1.3.6"
|
||||||
tinyaudio = "2.0.0"
|
tinyaudio = "2.0.0"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use itertools::Itertools;
|
|||||||
|
|
||||||
mod flags;
|
mod flags;
|
||||||
mod syn;
|
mod syn;
|
||||||
|
mod tone;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let flags = flags::Flags::new();
|
let flags = flags::Flags::new();
|
||||||
@@ -11,8 +12,8 @@ fn main() {
|
|||||||
flags.sound_font,
|
flags.sound_font,
|
||||||
flags.sample_rate,
|
flags.sample_rate,
|
||||||
);
|
);
|
||||||
// Play some notes (middle C, E, G). // 16 channels actually // 60=c 64=e 67=g //up to 128velocity though dont go below 50 tbh // 12 notes per octave
|
// Play some tones (middle C, E, G). // 16 channels actually // 60=c 64=e 67=g //up to 128velocity though dont go below 50 tbh // 12 tones per octave
|
||||||
syn.note_on(0, 64 + 12, 127);
|
syn.note_on(0, tone::new("c").i32(), 127);
|
||||||
|
|
||||||
play(syn, flags.sample_rate, flags.bpm, flags.smallest_note);
|
play(syn, flags.sample_rate, flags.bpm, flags.smallest_note);
|
||||||
}
|
}
|
||||||
@@ -21,7 +22,7 @@ fn play(mut s: syn::Syn, sample_rate: usize, bpm: usize, smallest_note: usize) {
|
|||||||
let params = tinyaudio::prelude::OutputDeviceParameters {
|
let params = tinyaudio::prelude::OutputDeviceParameters {
|
||||||
channels_count: 2,
|
channels_count: 2,
|
||||||
sample_rate: sample_rate,
|
sample_rate: sample_rate,
|
||||||
channel_sample_count: sample_rate / bpm * 60 / smallest_note,
|
channel_sample_count: sample_rate / bpm * 60 / smallest_note,
|
||||||
};
|
};
|
||||||
|
|
||||||
let sample_count = (params.channel_sample_count) as usize;
|
let sample_count = (params.channel_sample_count) as usize;
|
||||||
|
|||||||
71
src/tone.rs
Normal file
71
src/tone.rs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Tone(i32);
|
||||||
|
|
||||||
|
// new parses [a-g][+-]?[1-5]? to tone, sharp or flat, down 2 octave..up 1 octave
|
||||||
|
pub fn new<S: ToString>(s: S) -> Tone {
|
||||||
|
Tone::new(s.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tone {
|
||||||
|
fn new(s: String) -> Tone {
|
||||||
|
let re = regex::Regex::new(r"^((?<letter>^[a-g])(?<sharpness>[+-]?)(?<octave>[1-5]?)|(?<numeric>[0-9]+))$").unwrap();
|
||||||
|
let captures = re.captures(s.as_ref()).unwrap();
|
||||||
|
Tone (match captures.name("numeric") {
|
||||||
|
Some(number) => number.as_str().parse::<i32>().unwrap(),
|
||||||
|
None => {
|
||||||
|
let mut result = match captures.name("letter").unwrap().as_str() {
|
||||||
|
"a" => 57,
|
||||||
|
"b" => 59,
|
||||||
|
"c" => 60,
|
||||||
|
"d" => 62,
|
||||||
|
"e" => 64,
|
||||||
|
"f" => 65,
|
||||||
|
_ => 67,
|
||||||
|
} as i32;
|
||||||
|
|
||||||
|
result += match captures.name("sharpness") {
|
||||||
|
Some(sharpness) => match sharpness.as_str() {
|
||||||
|
"+" => 1,
|
||||||
|
"-" => -1,
|
||||||
|
_ => 0,
|
||||||
|
},
|
||||||
|
None => 0,
|
||||||
|
} as i32;
|
||||||
|
|
||||||
|
result += match captures.name("octave") {
|
||||||
|
Some(octave) => match octave.as_str() {
|
||||||
|
"" => 0,
|
||||||
|
_ => (octave.as_str().parse::<i32>().unwrap() - 3) * 12,
|
||||||
|
},
|
||||||
|
None => 0,
|
||||||
|
} as i32;
|
||||||
|
|
||||||
|
result
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn i32(&self) -> i32 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
#[test]
|
||||||
|
fn test_tone_new() {
|
||||||
|
assert_eq!(super::new("60").i32(), 60);
|
||||||
|
|
||||||
|
assert_eq!(super::new("c").i32(), 60);
|
||||||
|
assert_eq!(super::new("e").i32(), 64);
|
||||||
|
assert_eq!(super::new("g").i32(), 67);
|
||||||
|
|
||||||
|
assert_eq!(super::new("c+").i32(), 60+1);
|
||||||
|
assert_eq!(super::new("c-").i32(), 60-1);
|
||||||
|
|
||||||
|
assert_eq!(super::new("c3").i32(), 60);
|
||||||
|
assert_eq!(super::new("c4").i32(), 60+12);
|
||||||
|
|
||||||
|
assert_eq!(super::new("c+4").i32(), 60+12+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user