Skip to content

Commit

Permalink
chore: address comments
Browse files Browse the repository at this point in the history
  • Loading branch information
nenikitov committed Oct 11, 2024
1 parent 1554f4a commit 96ec959
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 51 deletions.
3 changes: 1 addition & 2 deletions engine/src/asset/sound/dat/finetune.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ static PITCH_FACTORS: LazyLock<[f64; FineTune::MAX]> = LazyLock::new(|| {
// And it's very magic.
// Maybe simplify it or at least name constants.
(0..FineTune::MAX)
.map(|i| i as f64)
.map(|cents| {
1.0 / (2f64.powf(cents / (12.0 * FineTune::CENTS_PER_NOTE as f64))
1.0 / (2f64.powf(cents as f64 / (12.0 * FineTune::CENTS_PER_NOTE as f64))
* 8363.0
// TODO(nenikitov): This is `2^20`, which is divided by `2048` and `8192` results in `1/16`
* 1048576.0
Expand Down
85 changes: 38 additions & 47 deletions engine/src/asset/sound/dat/mixer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,18 @@ struct PlayerChannel {
}

impl PlayerChannel {
// Length of a transition between the current and the next sample in seconds
// Too large of a time and samples will audibly blend and play 2 notes at the same time, which sounds weird.
// Too little and transitions between notes will click.
// Chosen value is a bit of an arbitrary value that I found sounds nice.
// It amounts to:
// - 13 samples at 16000
// - 35 samples at 44100
// - 38 samples at 48000
/// Length of a transition between the current and the next sample in seconds
/// Too large of a time and samples will audibly blend and play 2 notes at the same time, which sounds weird.
/// Too little and transitions between notes will click.
/// Chosen value is a bit of an arbitrary value that I found sounds nice.
/// It amounts to:
/// - 13 samples at 16000
/// - 35 samples at 44100
/// - 38 samples at 48000
const SAMPLE_BLEND: f64 = Duration::from_micros(800).as_secs_f64();
// Maximum difference in volume between 2 audio samples
// Volume as in channels volume, does not account for samples
// A bit of an arbitrary amount too
/// Maximum difference in volume between 2 audio samples
/// Volume as in channels volume, does not account for samples
/// A bit of an arbitrary amount too
const MAX_VOLUME_CHANGE: f32 = 1. / 128.;

fn note_cut(&mut self) {
Expand All @@ -69,19 +69,17 @@ impl PlayerChannel {
self.instrument.as_ref().and_then(|i| match &i.volume {
TInstrumentVolume::Envelope(envelope) => {
if self.note.on {
Some(
envelope
.volume_beginning()
.get(self.pos_volume_envelope)
.copied()
.unwrap_or(envelope.volume_loop()),
)
envelope
.volume_start()
.get(self.pos_volume_envelope)
.copied()
.or_else(|| Some(envelope.volume_loop()))
} else {
envelope
.volume_end()
.get(
self.pos_volume_envelope
.saturating_sub(envelope.volume_beginning().len()),
.saturating_sub(envelope.volume_start().len()),
)
.copied()
}
Expand Down Expand Up @@ -130,7 +128,7 @@ impl PlayerChannel {
self.previous = None;
}

previous_sample + factor * (current_sample - previous_sample)
factor.mul_add(current_sample - previous_sample, previous_sample)
} else {
current_sample
}
Expand Down Expand Up @@ -164,9 +162,7 @@ impl PlayerChannel {
fn change_note(&mut self, note: PatternEventNote) {
if let Some(instrument) = &self.instrument {
match note {
PatternEventNote::Off => {
self.note.on = false;
}
PatternEventNote::Off => self.note.on = false,
PatternEventNote::On(note) => {
self.note.finetune = Some(note);
self.note.finetune_initial = Some(note);
Expand Down Expand Up @@ -226,35 +222,30 @@ impl PlayerChannel {
}
}

trait MinMax {
fn generic_min(a: Self, b: Self) -> Self;
fn generic_max(a: Self, b: Self) -> Self;
}

macro_rules! impl_min_max {
($($ty:tt),*) => {
$(impl MinMax for $ty {
fn generic_min(a: Self, b: Self) -> Self {
$ty::min(a, b)
}

fn generic_max(a: Self, b: Self) -> Self {
$ty::max(a, b)
}
})*
};
}

impl_min_max!(f32, FineTune);

fn advance_to<T>(from: T, to: T, step: T) -> T
where
T: PartialOrd + Add<Output = T> + Sub<Output = T> + MinMax,
T: PartialOrd + Add<Output = T> + Sub<Output = T>,
{
use std::cmp::Ordering;
fn partial_min<T: PartialOrd>(input: T, min: T) -> T {
if input < min {
min
} else {
input
}
}
fn partial_max<T: PartialOrd>(input: T, max: T) -> T {
if input > max {
max
} else {
input
}
}
match from.partial_cmp(&to) {
Some(Ordering::Less) => T::generic_min(from + step, to),
Some(Ordering::Greater) => T::generic_max(from - step, to),
Some(Ordering::Less) => partial_max(from + step, to),
Some(Ordering::Greater) => partial_min(from - step, to),
// Calling `clamp_max` and `clamp_min` with `f32` or `f64` is "safe", because
// `from.partial_cmp(&to)` would return `None` if either of the values are `NAN`.
Some(Ordering::Equal) | None => from,
}
}
Expand Down
2 changes: 1 addition & 1 deletion engine/src/asset/sound/dat/t_instrument.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub struct TInstrumentVolumeEnvelope {
}

impl TInstrumentVolumeEnvelope {
pub fn volume_beginning(&self) -> &[f32] {
pub fn volume_start(&self) -> &[f32] {
if let Some(sustain) = self.sustain {
&self.data[0..sustain]
} else {
Expand Down
2 changes: 1 addition & 1 deletion engine/src/asset/sound/sample.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{fmt::Debug, mem::size_of, ops::Index};
use std::{fmt::Debug, ops::Index};

pub enum AudioSamplePointFormat {
Int,
Expand Down

0 comments on commit 96ec959

Please sign in to comment.