Use FunDSP crate for beepboops
This commit is contained in:
parent
784e205357
commit
9219b6c475
4 changed files with 142 additions and 76 deletions
|
@ -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([
|
||||
|
|
|
@ -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::<Vec<f32>>(),
|
||||
SoundType::Tone(freq) => {
|
||||
if freq == 0 {
|
||||
return (0..(self.sample_rate.0 as f32 * sound.duration.as_secs_f32())
|
||||
as usize)
|
||||
.map(|_| 0f32)
|
||||
.collect::<Vec<f32>>();
|
||||
}
|
||||
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::<Vec<f32>>();
|
||||
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::<f32>()
|
||||
})
|
||||
.map(|_| c.get_mono())
|
||||
.collect::<Vec<f32>>()
|
||||
}
|
||||
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::<Vec<f32>>()
|
||||
}
|
||||
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::<Vec<f32>>()
|
||||
}
|
||||
})
|
||||
|
@ -120,7 +107,7 @@ impl SoundOutput {
|
|||
.control::<oddio::Mixer<_>, _>()
|
||||
.play(oddio::MonoToStereo::new(oddio::Gain::new(
|
||||
oddio::FramesSignal::from(samples),
|
||||
0.20,
|
||||
0.50,
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue