From 9219b6c4756588e519970e496fbe1ced70862e24 Mon Sep 17 00:00:00 2001 From: Alex Page Date: Mon, 31 Jan 2022 18:10:39 -0500 Subject: [PATCH] Use FunDSP crate for beepboops --- Cargo.lock | 139 ++++++++++++++++++++++++++------- Cargo.toml | 4 +- src/resources/sound_effects.rs | 18 ++--- src/resources/sound_output.rs | 57 ++++++-------- 4 files changed, 142 insertions(+), 76 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e668a7..4fbd2e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -778,12 +778,37 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +[[package]] +name = "fundsp" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e44dcde4aedad5675c131b5114d431b4d7c739dc32dd599bf0460f36413d247e" +dependencies = [ + "generic-array", + "lazy_static", + "num-complex", + "numeric-array", + "rsor", + "rustfft", + "tinyvec", +] + [[package]] name = "futures" version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" +[[package]] +name = "generic-array" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.3" @@ -1024,11 +1049,11 @@ version = "0.1.0" dependencies = [ "bracket-lib", "cpal", + "fundsp", "oddio", - "rand", "specs", "specs-derive", - "spin_sleep", + "typenum", "winres", ] @@ -1413,6 +1438,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "num-complex" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26873667bbbb7c5182d4a37c1add32cdf09f841af72da53318fdb81543c15085" +dependencies = [ + "num-traits", +] + [[package]] name = "num-derive" version = "0.3.3" @@ -1520,6 +1554,16 @@ dependencies = [ "syn", ] +[[package]] +name = "numeric-array" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c59a9b227913a685ed84aa0de5ded58274e8bcfa55760faae07bc82aee64ccf" +dependencies = [ + "generic-array", + "num-traits", +] + [[package]] name = "objc" version = "0.2.7" @@ -1650,10 +1694,13 @@ dependencies = [ ] [[package]] -name = "ppv-lite86" -version = "0.2.15" +name = "primal-check" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" +checksum = "01419cee72c1a1ca944554e23d83e483e1bccf378753344e881de28b5487511d" +dependencies = [ + "num-integer", +] [[package]] name = "proc-macro-crate" @@ -1698,19 +1745,6 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" dependencies = [ - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", "rand_core", ] @@ -1719,18 +1753,6 @@ name = "rand_core" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] [[package]] name = "rand_xorshift" @@ -1786,12 +1808,32 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +[[package]] +name = "rsor" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b57e3964dc31a38416366d2e8f7675755402a10832d5cf4e4112d66ac77cdda" + [[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustfft" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d089e5c57521629a59f5f39bca7434849ff89bd6873b521afe389c1c602543" +dependencies = [ + "num-complex", + "num-integer", + "num-traits", + "primal-check", + "strength_reduce", + "transpose", +] + [[package]] name = "rusttype" version = "0.9.2" @@ -1961,6 +2003,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" +[[package]] +name = "strength_reduce" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3ff2f71c82567c565ba4b3009a9350a96a7269eaa4001ebedae926230bc2254" + [[package]] name = "strsim" version = "0.9.3" @@ -1998,6 +2046,21 @@ dependencies = [ "syn", ] +[[package]] +name = "tinyvec" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + [[package]] name = "tokio-executor" version = "0.1.10" @@ -2029,6 +2092,16 @@ dependencies = [ "serde", ] +[[package]] +name = "transpose" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95f9c900aa98b6ea43aee227fd680550cdec726526aab8ac801549eadb25e39f" +dependencies = [ + "num-integer", + "strength_reduce", +] + [[package]] name = "ttf-parser" version = "0.6.2" @@ -2050,6 +2123,12 @@ dependencies = [ "nom 5.1.2", ] +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + [[package]] name = "ultraviolet" version = "0.8.1" diff --git a/Cargo.toml b/Cargo.toml index 6fb9185..374353b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,8 +11,8 @@ specs = { version = "0.16.1", default-features = false } specs-derive = "0.4.1" cpal = "0.13" oddio = "0.5" -rand = "0.8" -spin_sleep = "1.0" +fundsp = "0.1.0" +typenum = "1.15.0" [target.'cfg(windows)'.build-dependencies] winres = "0.1" diff --git a/src/resources/sound_effects.rs b/src/resources/sound_effects.rs index e3f3259..d9a9286 100644 --- a/src/resources/sound_effects.rs +++ b/src/resources/sound_effects.rs @@ -5,12 +5,15 @@ use bracket_lib::random::RandomNumberGenerator; use crate::resources::sound_output::{SoundOutput, SoundSamples}; type Frequency = u32; +type StartFrequency = u32; +type EndFrequency = u32; type MinFrequency = u32; type MaxFrequency = u32; pub enum SoundType { Silence, Tone(Frequency), + Sweep(StartFrequency, EndFrequency), Noise(MinFrequency, MaxFrequency), } @@ -38,13 +41,10 @@ impl SoundEffects { pub fn new(ss: &SoundOutput) -> Self { Self { startup: ss.render_sound_effect(&SoundEffect { - sounds: (30..400) - .step_by(8) - .map(|x| Sound { - sound_type: SoundType::Tone(x), - duration: Duration::from_millis(24), - }) - .collect(), + sounds: vec![Sound { + sound_type: SoundType::Sweep(1, 350), + duration: Duration::from_secs(1), + }], }), step: ss.render_sound_effect(&SoundEffect { sounds: vec![ @@ -80,8 +80,8 @@ impl SoundEffects { }), bad_key: ss.render_sound_effect(&SoundEffect { sounds: iter::once(Sound { - sound_type: SoundType::Tone(400), - duration: Duration::from_millis(20), + sound_type: SoundType::Tone(540), + duration: Duration::from_millis(40), }) .chain((0..4).flat_map(|_| { array::IntoIter::new([ diff --git a/src/resources/sound_output.rs b/src/resources/sound_output.rs index 2dba98a..96f800e 100644 --- a/src/resources/sound_output.rs +++ b/src/resources/sound_output.rs @@ -1,11 +1,11 @@ -use std::{f32::consts::PI, sync::Arc}; +use std::sync::Arc; use cpal::{ traits::{DeviceTrait, HostTrait, StreamTrait}, SampleRate, Stream, }; +use fundsp::prelude::*; use oddio::{Frames, FramesSignal, Gain, Handle, Mixer, MonoToStereo, Stop}; -use rand::Rng; use super::sound_effects::{SoundEffect, SoundType}; @@ -70,43 +70,30 @@ impl SoundOutput { .map(|_| 0f32) .collect::>(), SoundType::Tone(freq) => { - if freq == 0 { - return (0..(self.sample_rate.0 as f32 * sound.duration.as_secs_f32()) - as usize) - .map(|_| 0f32) - .collect::>(); - } - let num_harmonics = self.sample_rate.0 / (freq as u32 * 2); - let coefficients = (0..=num_harmonics) - .map(|i| { - if i == 0 { - return 0.0; - } - (i as f32 * 0.5 * PI).sin() * 2.0 / (i as f32 * PI) - }) - .collect::>(); - let scaler = freq as f32 * PI * 2.0 / self.sample_rate.0 as f32; + let mut c = square_hz(freq as f32); + c.reset(Some(self.sample_rate.0 as f64)); (0..(self.sample_rate.0 as f32 * sound.duration.as_secs_f32()) as usize) - .map(|i| { - let temp = scaler * i as f32; - coefficients - .iter() - .enumerate() - .map(|(j, coef)| coef * (j as f32 * temp).cos()) - .sum::() - }) + .map(|_| c.get_mono()) + .collect::>() + } + SoundType::Sweep(start_freq, end_freq) => { + let mut c = lfo(|t| { + lerp( + start_freq as f32, + end_freq as f32, + t * sound.duration.as_secs_f32(), + ) + }) >> square(); + c.reset(Some(self.sample_rate.0 as f64)); + (0..(self.sample_rate.0 as f32 * sound.duration.as_secs_f32()) as usize) + .map(|_| c.get_mono()) .collect::>() } SoundType::Noise(min, max) => { + let mut c = + (((white() + dc(1.0)) * dc(max as f32 / 2.0)) + dc(min as f32)) >> square(); (0..(self.sample_rate.0 as f32 * sound.duration.as_secs_f32()) as usize) - .map(|i| { - let t = i as f32 / self.sample_rate.0 as f32; - (t * (rand::thread_rng().gen_range(min as f32..max as f32)) - * 2.0 - * std::f32::consts::PI) - .sin() - .signum() - }) + .map(|_| c.get_mono()) .collect::>() } }) @@ -120,7 +107,7 @@ impl SoundOutput { .control::, _>() .play(oddio::MonoToStereo::new(oddio::Gain::new( oddio::FramesSignal::from(samples), - 0.20, + 0.50, ))) } }