diff --git a/src/grid.rs b/src/grid.rs index 746fc8c..395c27a 100644 --- a/src/grid.rs +++ b/src/grid.rs @@ -1,7 +1,8 @@ use std::ops::RangeInclusive; use eframe::egui; -use eframe::egui::{Color32, Context, Id, PointerButton, Pos2, Rangef, Sense, Ui, Vec2, Widget}; +use eframe::egui::{Color32, Context, Id, PointerButton, Pos2, Rangef, RichText, Sense, Ui, Vec2, Widget}; use crate::noise::NoteType; +use crate::scale::Scale; use crate::tenori::LOOP_LENGTH; impl NoteType { @@ -20,6 +21,7 @@ pub struct Grid { pub note_type: NoteType, pub volume: f32, pub length: u64, + scale: Scale, notes: Vec, id: String } @@ -30,6 +32,7 @@ impl Grid { note_type, volume: 1.0, length: 250, + scale: Scale::CMajor, notes: vec![false; (LOOP_LENGTH * LOOP_LENGTH) as usize], id: format!("Track {}", counter) } @@ -44,10 +47,19 @@ impl Grid { } ui.menu_button("Scale...", |ui| { - ui.button("C Major"); - ui.button("C Minor"); - ui.button("Chromatic"); - ui.button("Pentatonic"); + if ui.button(Scale::CMajor.label_text(self.scale)).clicked() { + self.scale = Scale::CMajor + } + if ui.button(Scale::CMinor.label_text(self.scale)).clicked() { + self.scale = Scale::CMinor + } + if ui.button(Scale::Chromatic.label_text(self.scale)).clicked() { + self.scale = Scale::Chromatic + } + if ui.button(Scale::Pentatonic.label_text(self.scale)).clicked() { + self.scale = Scale::Pentatonic + } + }) }); @@ -102,11 +114,12 @@ impl Grid { } } - pub fn notes(&self, beat: u32) -> Vec { + pub fn notes(&self, beat: u32) -> Vec { let mut notes = vec![]; for y in 0..LOOP_LENGTH { if self.notes[(y * LOOP_LENGTH + beat) as usize] { - notes.push(LOOP_LENGTH - y) + let row = LOOP_LENGTH - y - 1; + notes.push(self.scale.tone(row)) } } notes diff --git a/src/main.rs b/src/main.rs index e8ce426..382c405 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ mod gui; mod tenori; mod grid; mod noise; +mod scale; use std::time::Duration; use eframe::{App, Frame}; diff --git a/src/scale.rs b/src/scale.rs new file mode 100644 index 0000000..cc9a483 --- /dev/null +++ b/src/scale.rs @@ -0,0 +1,40 @@ +use eframe::egui::RichText; + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum Scale { + CMajor, + CMinor, + Chromatic, + Pentatonic +} + +impl Scale { + pub fn label_text(self, other: Scale) -> RichText { + let selected = other == self; + let s = match self { + Scale::CMajor => "C Major", + Scale::CMinor => "C Minor", + Scale::Chromatic => "Chromatic", + Scale::Pentatonic => "Pentatonic", + }; + + let r = RichText::new(s); + if selected { r.strong() } else { r } + } + + pub fn tone(self, row: u32) -> i32 { + let row = row as usize; + let tones = match self { + Scale::CMajor => [-9, -7, -5, -4, -2, 0, 2, 3, 5, 7, 8, 10, 12, 14, 15, 17], + Scale::CMinor => [-9, -7, -6, -4, -2, -1, 1, 3, 5, 6, 8, 10, 11, 13, 15, 17], + Scale::Chromatic => [-9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6], + Scale::Pentatonic => [-9, -7, -5, -2, 0, 3, 5, 7, 10, 12, 15, 17, 19, 22, 24, 27] + }; + + if row >= tones.len() { + 0 + } else { + tones[row] + } + } +} \ No newline at end of file diff --git a/src/tenori.rs b/src/tenori.rs index 76e23e3..4357ebb 100644 --- a/src/tenori.rs +++ b/src/tenori.rs @@ -90,8 +90,7 @@ impl Tenori { let beat = self.beat(); for grid in self.grids.iter() { - for note in grid.notes(beat).into_iter() { - let tone: i32 = note as i32 - 8; + for tone in grid.notes(beat).into_iter() { notes.push(Note { note_type: grid.note_type,