Use FunDSP crate for beepboops

This commit is contained in:
Alex Page 2022-01-31 18:10:39 -05:00
parent 784e205357
commit 9219b6c475
4 changed files with 142 additions and 76 deletions

View file

@ -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([

View file

@ -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,
)))
}
}