Phase continuity

This commit is contained in:
Thomas Forgione 2026-02-17 17:40:07 +01:00
parent bf8f7f397e
commit bda18d8b46
2 changed files with 27 additions and 4 deletions

View File

@ -27,6 +27,19 @@ impl Wave {
}
}
}
pub fn sample_from_phase(self, phase: f64) -> f64 {
match self {
Wave::Square => {
if phase < 0.5 {
1.0
} else {
-1.0
}
}
Wave::Triangle => 4.0 * (phase - 0.5).abs() - 1.0,
}
}
}
pub struct NoteEvent {
@ -50,6 +63,7 @@ pub struct Track {
pub amplitude: f64,
pub notes: Vec<NoteEvent>,
pub current_tick: Tick,
pub phase: f64,
}
impl Track {
@ -59,6 +73,7 @@ impl Track {
amplitude,
notes: vec![],
current_tick: Tick(0),
phase: 0.0,
}
}
@ -120,6 +135,8 @@ impl Piece {
let seconds_per_tick = 60.0 / (self.bpm as u64 * TICKS_PER_BEAT) as f64;
let params = wav::Params::new();
let mut track_phases: Vec<f64> = vec![0.0; self.tracks.len()];
let total_samples =
(self.max_beat() as f64 * seconds_per_beat * params.sampling_rate as f64).ceil() as u32;
@ -134,12 +151,18 @@ impl Piece {
for i in 0..total_samples {
let t = i as f64 / params.sampling_rate as f64;
let mut value: f64 = 0.0;
for track in &self.tracks {
for (track, phase) in self.tracks.iter().zip(track_phases.iter_mut()) {
for event in &track.notes {
let start_time = event.start.0 as f64 * seconds_per_tick;
let end_time = (event.start + event.duration).0 as f64 * seconds_per_tick;
if t >= start_time && t < end_time {
value += track.amplitude * track.wave.sample(&event.note, t);
let freq = event.note.freq();
// value += track.amplitude * track.wave.sample(&event.note, t);
value += track.amplitude * track.wave.sample_from_phase(*phase);
// Update phase
*phase += freq / params.sampling_rate as f64;
*phase %= 1.0;
}
}
}

View File

@ -14,7 +14,7 @@ pub fn technology() -> Piece {
}
pub fn bass_track() -> Track {
let mut bass_track = Track::new(Wave::Square, 0.05);
let mut bass_track = Track::new(Wave::Triangle, 0.5);
for _ in 0..4 {
bass_track.add(A1, Tick::bar());
bass_track.add(G0, Tick::beats(2));
@ -121,7 +121,7 @@ pub fn chords() -> Track {
}
pub fn main_track() -> Track {
let mut track = Track::new(Wave::Square, 0.1);
let mut track = Track::new(Wave::Square, 0.075);
track.add_silence(Tick::bars(4));
// Lick 1