This commit is contained in:
2025-10-05 14:14:47 -05:00
parent 0da8fd9cb2
commit 47802ba782
5 changed files with 10 additions and 67 deletions
-37
View File
@@ -1,10 +1,6 @@
use std::ops::RangeInclusive;
use std::time::Duration; use std::time::Duration;
use eframe::egui;
use eframe::egui::{Context, Id, Label, Slider, Window};
use rodio::{ChannelCount, SampleRate, Source}; use rodio::{ChannelCount, SampleRate, Source};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::gui::Showable;
#[derive(Copy, Clone, PartialEq, Debug, Deserialize, Serialize)] #[derive(Copy, Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct Envelope { pub struct Envelope {
@@ -107,39 +103,6 @@ impl<S: Source> Source for EnvelopeSource<S> {
} }
} }
impl Showable<(Id, String)> for (&mut Envelope, &mut bool) {
fn show(&mut self, ctx: &Context, (id, title): &(Id, String)) {
let mut open = true;
let window = Window::new(title)
.id(*id)
.open(&mut open)
.resizable([false, false])
.scroll([false, false]);
window.show(ctx, |ui| {
egui::Grid::new(id).show(ui, |ui| {
ui.add(Label::new("Attack"));
ui.add(Slider::new(&mut self.0.attack, RangeInclusive::new(0.0, 1.0)));
ui.end_row();
ui.add(Label::new("Decay"));
ui.add(Slider::new(&mut self.0.decay, RangeInclusive::new(0.0, 1.0)));
ui.end_row();
ui.add(Label::new("Sustain"));
ui.add(Slider::new(&mut self.0.sustain, RangeInclusive::new(0.0, 1.0)));
ui.end_row();
ui.add(Label::new("Hold"));
ui.add(Slider::new(&mut self.0.hold, RangeInclusive::new(0.0, 2.0)));
ui.end_row();
ui.add(Label::new("Release"));
ui.add(Slider::new(&mut self.0.release, RangeInclusive::new(0.0, 1.0)));
ui.end_row();
});
});
*self.1 = open;
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
+2 -4
View File
@@ -1,7 +1,6 @@
use std::ops::RangeInclusive; use std::ops::RangeInclusive;
use eframe::egui; use eframe::egui;
use eframe::egui::{Color32, Context, Id, PointerButton, Pos2, Rangef, Sense, Ui, Vec2}; use eframe::egui::{Color32, Context, Id, PointerButton, Pos2, Rangef, Sense, Ui, Vec2};
use crate::envelope::Envelope;
use crate::gui::Showable; use crate::gui::Showable;
use crate::noise::NoteType; use crate::noise::NoteType;
use crate::scale::Scale; use crate::scale::Scale;
@@ -82,14 +81,13 @@ impl Grid {
if response.contains_pointer() { if response.contains_pointer() {
ui.input(|input| { ui.input(|input| {
if input.pointer.button_clicked(PointerButton::Primary) { if input.pointer.button_clicked(PointerButton::Primary) &&
if let Some(pos) = input.pointer.latest_pos() { let Some(pos) = input.pointer.latest_pos() {
let x = ((pos.x - rect.left()) / 20.0).floor() as usize; let x = ((pos.x - rect.left()) / 20.0).floor() as usize;
let y = ((pos.y - rect.top()) / 20.0).floor() as usize; let y = ((pos.y - rect.top()) / 20.0).floor() as usize;
let n = x + y * LOOP_LENGTH as usize; let n = x + y * LOOP_LENGTH as usize;
self.notes[n] = !self.notes[n] self.notes[n] = !self.notes[n]
} }
}
}) })
} }
} }
+2 -4
View File
@@ -55,9 +55,7 @@ impl Tenori {
ui.add(egui::Slider::new(&mut self.tempo, RangeInclusive::new(20, 180))); ui.add(egui::Slider::new(&mut self.tempo, RangeInclusive::new(20, 180)));
if self.playing { if self.playing {
if ui.button("||").clicked() { self.playing = false } if ui.button("||").clicked() { self.playing = false }
} else { } else if ui.button(">").clicked() { self.playing = true }
if ui.button(">").clicked() { self.playing = true }
}
}); });
}) })
}); });
@@ -80,7 +78,7 @@ impl Tenori {
} }
fn save_to_file<P: AsRef<Path>>(&self, filename: P) -> Result<(), String> { fn save_to_file<P: AsRef<Path>>(&self, filename: P) -> Result<(), String> {
let serialized = toml::to_string(&PersistedTenori::from(&*self)).map_err(|e| e.to_string())?; let serialized = toml::to_string(&PersistedTenori::from(self)).map_err(|e| e.to_string())?;
fs::write(filename, serialized).map_err(|e| e.to_string()) fs::write(filename, serialized).map_err(|e| e.to_string())
} }
-16
View File
@@ -1,7 +1,6 @@
use rodio::mixer::Mixer; use rodio::mixer::Mixer;
use rodio::Source; use rodio::Source;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::envelope::Envelope;
use crate::timbre::Timbre; use crate::timbre::Timbre;
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@@ -36,21 +35,6 @@ fn freq(tone: i32) -> f32 {
440.0 * 1.0595f32.powf(tone as f32) 440.0 * 1.0595f32.powf(tone as f32)
} }
impl NoteType {
fn source(self, tone: i32) -> Box<dyn Source + Send> {
let freq = freq(tone);
let source: Box<dyn Source + Send> = match self {
NoteType::Sine => Box::new(rodio::source::SineWave::new(freq)),
NoteType::Triangle => Box::new(rodio::source::TriangleWave::new(freq)),
NoteType::Sawtooth => Box::new(rodio::source::SawtoothWave::new(freq)),
NoteType::Square => Box::new(rodio::source::SquareWave::new(freq)),
NoteType::Noise => Box::new(rodio::source::noise::WhiteUniform::new(44100)
.low_pass_with_q(freq as u32, 2.0))
};
source
}
}
impl Note { impl Note {
pub fn play(self, mixer: &Mixer) { pub fn play(self, mixer: &Mixer) {
let freq = freq(self.tone); let freq = freq(self.tone);
+6 -6
View File
@@ -33,21 +33,21 @@ impl Default for Timbre {
impl Timbre { impl Timbre {
pub fn source(&self, frequency: f32) -> EnvelopeSource<MixerSource> { pub fn source(&self, frequency: f32) -> EnvelopeSource<MixerSource> {
let (mut mixer, source) = rodio::mixer::mixer(1, 44100); let (mixer, source) = rodio::mixer::mixer(1, 44100);
if self.sine > 0.0 { if self.sine > 0.0 {
mixer.add(SineWave::new(frequency).amplify_normalized(self.sine)) mixer.add(SineWave::new(frequency).amplify(self.sine))
} }
if self.triangle > 0.0 { if self.triangle > 0.0 {
mixer.add(TriangleWave::new(frequency).amplify_normalized(self.triangle)) mixer.add(TriangleWave::new(frequency).amplify(self.triangle))
} }
if self.square > 0.0 { if self.square > 0.0 {
mixer.add(SquareWave::new(frequency).amplify_normalized(self.square)) mixer.add(SquareWave::new(frequency).amplify(self.square))
} }
if self.sawtooth > 0.0 { if self.sawtooth > 0.0 {
mixer.add(SawtoothWave::new(frequency).amplify_normalized(self.sawtooth)) mixer.add(SawtoothWave::new(frequency).amplify(self.sawtooth))
} }
if self.noise > 0.0 { if self.noise > 0.0 {
mixer.add(WhiteUniform::new(44100).amplify_normalized(self.noise)) mixer.add(WhiteUniform::new(44100).amplify(self.noise))
} }
self.envelope.modulate(source) self.envelope.modulate(source)
} }