Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/better mixer #50

Merged
merged 88 commits into from
Oct 12, 2024
Merged
Show file tree
Hide file tree
Changes from 82 commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
fd1586a
feat: start adding flags
nenikitov Jan 29, 2024
7472e27
wip: remake the mixer
nenikitov Feb 2, 2024
04dbb51
wip: add proper bpm
nenikitov Feb 2, 2024
eaa8d3e
wip: making sustain instruments
nenikitov Feb 2, 2024
2135955
wip: make instrument take a reference to sample
nenikitov Feb 3, 2024
642aab9
refactor: use reference instead of indexes
nenikitov Feb 3, 2024
c6a6c06
refactor: separate event
nenikitov Feb 3, 2024
7baf735
refactor: remove flags from pattern, replace by option
nenikitov Feb 3, 2024
539f75e
refactor: remove unecessary option of pattern and replace by empty pa…
nenikitov Feb 3, 2024
2e41b88
feat: make samples loop properly
nenikitov Feb 4, 2024
7dd40a9
wip: make event pitch
nenikitov Feb 5, 2024
b6adcc3
fix: proper bpm and note pitch
nenikitov Feb 6, 2024
3649f23
refactor: move all note adding and frequency ratio computations into …
nenikitov Feb 6, 2024
441ec03
feat: make audio stretching linearly interpolate
nenikitov Feb 6, 2024
70da45d
fix: clicks with linear interpolation
nenikitov Feb 6, 2024
b06854e
fix: overflow problems
nenikitov Feb 6, 2024
b395bf1
feat: make audio samples resampled to 48khz
nenikitov Feb 6, 2024
d4ee7b2
refactor: remove unecessary parameter
nenikitov Feb 6, 2024
def4072
fix: remove interpolation for now
nenikitov Feb 6, 2024
edc4a86
fix: volume of the instrument
nenikitov Feb 6, 2024
b34c4fa
format
nenikitov Feb 6, 2024
ccacd95
wip: remove interpolation and upsampling
nenikitov Feb 7, 2024
a768669
wip: experimenting with linear interpolation
nenikitov Feb 7, 2024
5ff29bb
feat: made a more faithful frequency calculator
nenikitov Feb 10, 2024
2c3362a
sync: main
nenikitov Feb 17, 2024
6761ff2
fix: clippy
nenikitov Feb 17, 2024
84aa652
refactor: volume
nenikitov Feb 17, 2024
f0a998a
refactor: volume envelope
nenikitov Feb 17, 2024
7831da2
wip: store previous note
nenikitov Feb 17, 2024
c39b9bd
wip: add volume envelope
nenikitov Feb 20, 2024
9dee522
refactor: note volume computation
nenikitov Feb 20, 2024
c3e8c8d
wip: add separate volume control
nenikitov Feb 20, 2024
a69e866
refactor: move effects
nenikitov Feb 20, 2024
efd67e7
refactor: even simpler volume
nenikitov Feb 20, 2024
e7e8ecd
wip: implement volume slide
nenikitov Feb 20, 2024
f02b597
wip: effect memory
nenikitov Mar 9, 2024
713b979
refactor: effects
nenikitov Mar 9, 2024
541a37a
feat(sample): write resampling logic
nenikitov Apr 30, 2024
287807d
feat(sample): write new wav converter
nenikitov Apr 30, 2024
dc6b947
feat(sample): integrate new sample and fix noise
nenikitov May 2, 2024
30abf62
feat(sample): move volume before stretching
nenikitov May 2, 2024
dae3928
refactor(effects): improve effect memory
nenikitov May 3, 2024
8a30cac
feat(effect): start playback direction
nenikitov May 3, 2024
0ddc5f0
perf(sample): majorly optimized audio generation
nenikitov May 5, 2024
13ce305
feat(effect): playback direction
nenikitov May 5, 2024
89f67a6
feat(effect): porta slide and bump
nenikitov May 5, 2024
830668a
feat(effect): porta tone
nenikitov May 7, 2024
5bf350b
feat(effect): global volume
nenikitov May 7, 2024
afda0a2
feat(debug): added printing to tsong
nenikitov May 12, 2024
84e400d
fix(sound): fixed default instrument volume)
nenikitov May 14, 2024
8826d18
feat(sound): add global volume
nenikitov May 14, 2024
bb58d7c
feat: remove predefined instruments, they are null
nenikitov Sep 22, 2024
0f5dea7
wip: new new mixer
nenikitov Sep 22, 2024
269d931
wip: new mixer is finally playing something :D
nenikitov Sep 23, 2024
bac2054
wip
nenikitov Sep 23, 2024
d8e08c3
wip: effects
nenikitov Sep 23, 2024
0e7aa34
fix: pattern orders
nenikitov Sep 27, 2024
a53917f
feat: made sample blending work, f*cking finally
nenikitov Sep 27, 2024
6e2a9c1
wip: small tweaks
nenikitov Sep 28, 2024
7f3ae3a
feat: more effects
nenikitov Oct 2, 2024
e833fa6
feat: implement volume envelope
nenikitov Oct 5, 2024
4aaf12b
feat(effect): note delay
nenikitov Oct 5, 2024
13b5f2a
fix(instrument): retrigger on special 255 instrument
nenikitov Oct 5, 2024
0792607
fix(instrument): retrigger on special 255 instrument
nenikitov Oct 5, 2024
9aa2cb6
fix(effects): repeated effects should only apply in the current row
nenikitov Oct 5, 2024
3c36cc8
feat: add volume ramping
nenikitov Oct 6, 2024
58cdec8
feat(effect): pattern break and wip pattern jump
nenikitov Oct 7, 2024
b88841d
feat(effect): pattern jump
nenikitov Oct 7, 2024
56aea46
feat: ramping for global volume
nenikitov Oct 7, 2024
2348563
feat(effect): note retrigger
nenikitov Oct 7, 2024
b988e8b
refactor: remove old mixer and dummy effect
nenikitov Oct 7, 2024
f5d3164
wip: removing old code
nenikitov Oct 8, 2024
869c6ef
refactor: more old code removed
nenikitov Oct 8, 2024
a41c48c
hotfix: invalid file size
nenikitov Oct 9, 2024
b75f1bf
refactor
nenikitov Oct 9, 2024
0ef415c
refactor: clippy warnings
nenikitov Oct 9, 2024
6a5e62f
refactor: loom
nenikitov Oct 9, 2024
b1182dd
refactor
nenikitov Oct 9, 2024
870f084
perf(sample): optimized normalize
nenikitov Oct 9, 2024
ff4e408
perf(sample): remove sample computations when volume envelope ended
nenikitov Oct 9, 2024
493ff22
perf(finetune): precompute all possible finetunes
nenikitov Oct 9, 2024
1554f4a
fix(effects): off by 1 error in backwards playback
nenikitov Oct 10, 2024
96ec959
chore: address comments
nenikitov Oct 11, 2024
dca4c2c
refactor: volume envelope
nenikitov Oct 11, 2024
abaa85e
chore: update readme
nenikitov Oct 11, 2024
c044cab
chore: more comments
nenikitov Oct 11, 2024
9aec4b0
chore: more comments
nenikitov Oct 11, 2024
edd08f3
chore: change `0.` to `0.0`
UserIsntAvailable Oct 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,16 @@ members = [
"ashen",
"engine",
]


[profile.perf]
inherits = "release"
codegen-units = 1
incremental = false
lto = "fat"
opt-level = 3
panic = "abort"

[profile.release]
debug = true
overflow-checks = true
2 changes: 2 additions & 0 deletions engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
bitflags = "2.4.2"
const_format = "0.2.32"
fixed = "1.24.0"
flate2 = "1.0.28"
Expand All @@ -16,6 +17,7 @@ sealed = "0.5.0"
thiserror = "1.0.56"

[dev-dependencies]
assert_approx_eq = "1.1.0"
eyre = "0.6.8"
image = "0.24.8"

Expand Down
6 changes: 4 additions & 2 deletions engine/src/asset/color_map.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{mem, ops::Deref};

use super::{extension::*, AssetParser};
use crate::{error, utils::nom::*};
use std::{mem, ops::Deref};

const COLORS_COUNT: usize = 256;
const SHADES_COUNT: usize = 32;
Expand All @@ -14,7 +15,7 @@
}

impl Color {
pub fn from_12_bit(color: u16) -> Self {

Check warning on line 18 in engine/src/asset/color_map.rs

View workflow job for this annotation

GitHub Actions / clippy

docs for function which may panic missing `# Panics` section

warning: docs for function which may panic missing `# Panics` section --> engine/src/asset/color_map.rs:18:5 | 18 | pub fn from_12_bit(color: u16) -> Self { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here --> engine/src/asset/color_map.rs:20:9 | 20 | assert!(color <= 0xFFF, "12 bit color is smaller than 0xFFF"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc note: the lint level is defined here --> engine/src/lib.rs:1:9 | 1 | #![warn(clippy::pedantic)] | ^^^^^^^^^^^^^^^^ = note: `#[warn(clippy::missing_panics_doc)]` implied by `#[warn(clippy::pedantic)]`
// TODO(nenikitov): return result.
assert!(color <= 0xFFF, "12 bit color is smaller than 0xFFF");

Expand Down Expand Up @@ -90,9 +91,10 @@

#[cfg(test)]
mod tests {
use std::cell::LazyCell;

use super::*;
use crate::utils::{format::*, test::*};
use std::cell::LazyCell;

#[test]
fn shade_works() -> eyre::Result<()> {
Expand Down
6 changes: 4 additions & 2 deletions engine/src/asset/gamma_table.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::mem;

use super::{extension::*, AssetParser};
use crate::{error, utils::nom::*};
use std::mem;

const ROWS_COUNT: usize = 256;
const COLS_COUNT: usize = 101;
Expand Down Expand Up @@ -47,12 +48,13 @@ impl AssetParser<Pack> for GammaTable {

#[cfg(test)]
mod tests {
use std::cell::LazyCell;

use super::*;
use crate::{
asset::color_map::Color,
utils::{format::*, test::*},
};
use std::cell::LazyCell;

const GAMMA_TABLE_DATA: LazyCell<Vec<u8>> = deflated_file!("00.dat");

Expand Down
25 changes: 15 additions & 10 deletions engine/src/asset/model/mod.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
mod dat;

use dat::{
frame::{ModelFrame, ModelSpecs},
header::ModelHeader,
sequence::ModelSequence,
triangle::{ModelTriangle, TextureDimensions},
};

use super::{
extension::*,
texture::{Texture, TextureSize},
AssetParser,
};
use crate::utils::nom::*;
use dat::{
frame::ModelFrame, frame::ModelSpecs, header::ModelHeader, sequence::ModelSequence,
triangle::ModelTriangle, triangle::TextureDimensions,
};

pub struct Model {
pub texture: Texture,
Expand Down Expand Up @@ -69,6 +72,14 @@ impl AssetParser<Pack> for Model {

#[cfg(test)]
mod tests {
use std::{
cell::LazyCell,
fmt::{Display, Formatter},
path::PathBuf,
};

use itertools::Itertools;

use super::{
dat::{frame::ModelVertex, triangle::ModelPoint},
*,
Expand All @@ -77,12 +88,6 @@ mod tests {
asset::color_map::{Color, ColorMap, PaletteTexture},
utils::test::*,
};
use itertools::Itertools;
use std::{
cell::LazyCell,
fmt::{Display, Formatter},
path::PathBuf,
};

const COLOR_MAP_DATA: LazyCell<Vec<u8>> = deflated_file!("01.dat");
const MODEL_DATA: LazyCell<Vec<u8>> = deflated_file!("0E-deflated.dat");
Expand Down
3 changes: 2 additions & 1 deletion engine/src/asset/pack_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
const HEADER: &'static str = "PMAN";
const COPYRIGHT_LENGTH: usize = 56;

pub fn new(input: &[u8]) -> Result<Self> {

Check warning on line 26 in engine/src/asset/pack_file.rs

View workflow job for this annotation

GitHub Actions / clippy

docs for function returning `Result` missing `# Errors` section

warning: docs for function returning `Result` missing `# Errors` section --> engine/src/asset/pack_file.rs:26:5 | 26 | pub fn new(input: &[u8]) -> Result<Self> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc = note: `#[warn(clippy::missing_errors_doc)]` implied by `#[warn(clippy::pedantic)]`
let (copyright, entries) = {
let (input, (copyright, total_entries)) = Self::header(input)?;
let (input, (headers)) = Self::entry_headers(input, total_entries)?;
Expand Down Expand Up @@ -86,9 +86,10 @@

#[cfg(test)]
mod tests {
use std::{cell::LazyCell, io, path::PathBuf};

use super::*;
use crate::utils::{compression::decompress, test::*};
use std::{cell::LazyCell, io, path::PathBuf};

#[test]
fn header_works() -> eyre::Result<()> {
Expand Down
3 changes: 2 additions & 1 deletion engine/src/asset/pack_info.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::ops::Index;

use super::{extension::*, AssetParser};
use crate::utils::nom::*;
use std::ops::Index;

#[derive(Debug)]
pub struct PackInfo {
Expand Down
3 changes: 2 additions & 1 deletion engine/src/asset/skybox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,13 @@ impl AssetParser<Pack> for Skybox {

#[cfg(test)]
mod tests {
use std::cell::LazyCell;

use super::*;
use crate::{
asset::color_map::PaletteTexture,
utils::{format::*, test::*},
};
use std::cell::LazyCell;

const SKYBOX_DATA: LazyCell<Vec<u8>> = deflated_file!("3C.dat");

Expand Down
124 changes: 124 additions & 0 deletions engine/src/asset/sound/dat/finetune.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
use std::{
ops::{Add, AddAssign, Neg, Sub},
sync::LazyLock,
};

use crate::utils::iterator::CollectArray;

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct FineTune {
cents: i32,
}

static PITCH_FACTORS: LazyLock<[f64; FineTune::MAX]> = LazyLock::new(|| {
// TODO(nenikitov): This formula is from the game
// And it's very magic.
// Maybe simplify it or at least name constants.
(0..FineTune::MAX)
.map(|i| i as f64)
nenikitov marked this conversation as resolved.
Show resolved Hide resolved
.map(|cents| {
1.0 / (2f64.powf(cents / (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
/ 16000.0
/ 2048.0
/ 8192.0)
})
.collect_array()
});

impl FineTune {
const CENTS_PER_NOTE: i32 = 128;
const MAX: usize = 15488;

pub const fn new(cents: i32) -> Self {
Self { cents }
}

pub const fn from_note(note: i32) -> Self {
FineTune::new(note * Self::CENTS_PER_NOTE)
}

pub fn pitch_factor(self) -> f64 {
PITCH_FACTORS[(self.cents as usize).clamp(0, Self::MAX)]
}

pub fn cents(self) -> i32 {
self.cents
}

pub fn note(self) -> i32 {
self.cents / Self::CENTS_PER_NOTE
}
}

impl Add for FineTune {
type Output = FineTune;

fn add(self, rhs: Self) -> Self::Output {
FineTune::new(self.cents.saturating_add(rhs.cents))
}
}

impl AddAssign for FineTune {
fn add_assign(&mut self, rhs: Self) {
self.cents = self.cents.saturating_add(rhs.cents);
}
}

impl Sub for FineTune {
type Output = FineTune;

fn sub(self, rhs: Self) -> Self::Output {
FineTune::new(self.cents.saturating_sub(rhs.cents))
}
}

impl Neg for FineTune {
type Output = FineTune;

fn neg(self) -> Self::Output {
FineTune::new(-self.cents)
}
}

#[cfg(test)]
mod tests {
use assert_approx_eq::assert_approx_eq;

use super::*;

#[test]
fn from_note_works() {
assert_eq!(
FineTune {
cents: 30 * FineTune::CENTS_PER_NOTE
},
FineTune::from_note(30)
);
}

#[test]
fn pitch_factor_works() {
assert_approx_eq!(2.0, FineTune::from_note(47).pitch_factor(), 0.030);
assert_approx_eq!(1.0, FineTune::from_note(59).pitch_factor(), 0.015);
assert_approx_eq!(0.5, FineTune::from_note(71).pitch_factor(), 0.008);
}

#[test]
fn add_works() {
assert_eq!(
FineTune::from_note(54),
FineTune::from_note(49) + FineTune::from_note(5),
);
}

#[test]
fn sub_works() {
assert_eq!(
FineTune::from_note(32),
FineTune::from_note(40) - FineTune::from_note(8),
);
}
}
Loading
Loading