Skip to content

Commit

Permalink
update oddio to 0.7.4
Browse files Browse the repository at this point in the history
+ clippy pass
  • Loading branch information
Uriopass committed Dec 20, 2023
1 parent fd906ba commit b31594b
Show file tree
Hide file tree
Showing 26 changed files with 269 additions and 188 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ flat_spatial = "0.6"
egui_extras = { git = "https://github.com/emilk/egui" }
egui_plot = { git = "https://github.com/emilk/egui" }
ordered-float = { version = "4.2.0", default-features = false }
oddio = "0.6.2"
oddio = "0.7.4"
derive_more = "0.99.17"

# Set the settings for build scripts and proc-macros.
Expand Down
1 change: 1 addition & 0 deletions assets_gui/src/orbit_camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ impl OrbitCamera {
self.update(ctx);
}

#[allow(clippy::redundant_closure_call)]
pub fn camera_movement(&mut self, ctx: &mut Context) {
if !self.camera.pos.is_finite() {
self.camera.pos = Vec3::ZERO;
Expand Down
9 changes: 4 additions & 5 deletions assets_gui/src/yakui_gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,8 @@ impl State {
l.cross_axis_alignment = CrossAxisAlignment::Stretch;
l.show(|| {
label("Companies");
if self.gui.companies.changed {
if button("Save").clicked {
self.gui.companies.save();
}
if self.gui.companies.changed && button("Save").clicked {
self.gui.companies.save();
}
for (i, comp) in self.gui.companies.companies.iter().enumerate() {
let b = Button::styled(comp.name.to_string());
Expand Down Expand Up @@ -250,7 +248,7 @@ impl State {
recipe.consumption.iter().zip(consumption.iter())
{
let amount = amount.clone();
props.add(&*name, move || inspect_v(&mut *amount.borrow_mut()));
props.add(name, move || inspect_v(&mut *amount.borrow_mut()));
}

props.add("production", || {
Expand Down Expand Up @@ -335,6 +333,7 @@ fn on_changed<T: Copy + PartialEq + 'static>(v: T, f: impl FnOnce()) {
}
}

#[allow(clippy::type_complexity)]
struct PropertiesBuilder<'a> {
props: Vec<(&'a str, Box<dyn FnOnce() + 'a>)>,
}
Expand Down
159 changes: 124 additions & 35 deletions engine/src/audio.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use common::{AudioKind, FastMap, FastSet};
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use oddio::{Filter, Frames, FramesSignal, Gain, Handle, Mixer, Sample, Signal, Smoothed, Stop};
use oddio::{
FixedGain, Frame, Frames, FramesSignal, Mixed, Mixer, MixerControl, Sample, Signal, Smoothed,
};
use std::cell::RefCell;
use std::fmt::Debug;
use std::sync::atomic::{AtomicU32, Ordering};
Expand All @@ -13,7 +15,7 @@ type StoredAudio = Arc<Frames<[Sample; 2]>>;
#[allow(dead_code)]
pub struct AudioContext {
stream: Option<cpal::Stream>,
scene_handle: Option<Handle<Mixer<[Sample; 2]>>>,
scene_handle: Option<MixerControl<[Sample; 2]>>,
cache: Arc<RwLock<FastMap<String, StoredAudio>>>,
preloading: FastSet<String>,
}
Expand All @@ -23,7 +25,6 @@ static MUSIC_SHARED: AtomicU32 = AtomicU32::new(0);
static EFFECT_SHARED: AtomicU32 = AtomicU32::new(0);
static UI_SHARED: AtomicU32 = AtomicU32::new(0);

pub type ControlHandle<T> = Handle<Stop<GlobalGain<T>>>;
pub type Stereo = [Sample; 2];
pub type BaseSignal = FramesSignal<Stereo>;

Expand Down Expand Up @@ -55,13 +56,13 @@ impl AudioContext {
buffer_size: cpal::BufferSize::Fixed(4096), // Using BufferSize::Default causes 100% cpu usage with ALSA on linux
};

let (scene_handle, scene) = oddio::split(Mixer::new());
let (scene_handle, mut scene) = Mixer::new();

let stream = match device.build_output_stream(
&config,
move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
let frames = oddio::frame_stereo(data);
oddio::run(&scene, sample_rate.0, frames);
oddio::run(&mut scene, sample_rate.0, frames);
},
move |err| {
eprintln!("{err:?}");
Expand Down Expand Up @@ -195,10 +196,11 @@ impl AudioContext {
if let AudioKind::Music = kind {
log::error!("shouldn't play music with base play as it's not affected by global volume changes");
}
log::info!("playing {}", name);
let mut g = Gain::new(FramesSignal::new(x, 0.0));
g.set_amplitude_ratio(vol);
h.control().play(g);
if vol <= 0.001 {
return;
}
let g = FixedGain::new(FramesSignal::new(x, 0.0).1, vol.log10() * 20.0);
h.play(g);
}
}
}
Expand All @@ -207,24 +209,25 @@ impl AudioContext {
self.cache.read().unwrap().len() >= self.preloading.len()
}

pub fn play_with_control<S: 'static>(
pub fn play_with_control<S: 'static, Control>(
&mut self,
name: &'static str,
transform: impl FnOnce(StoredAudio) -> S,
transform: impl FnOnce(StoredAudio) -> (Control, S),
kind: AudioKind,
) -> Option<ControlHandle<S>>
) -> Option<(Control, Mixed)>
where
S: Signal<Frame = [Sample; 2]> + Send,
{
if let Some(ref mut h) = self.scene_handle {
if let Some(x) = Self::get(&self.preloading, &self.cache, name) {
let (control, signal) = transform(x);
let test = GlobalGain {
volume: RefCell::new(Smoothed::new(1.0)),
kind,
inner: transform(x),
inner: signal,
};
let hand = h.control().play(test);
return Some(hand);
let mixed = h.play(test);
return Some((control, mixed));
}
}
None
Expand Down Expand Up @@ -274,7 +277,7 @@ pub struct GlobalGain<T: ?Sized> {
impl<T: Signal<Frame = [Sample; 2]>> Signal for GlobalGain<T> {
type Frame = [Sample; 2];

fn sample(&self, interval: f32, out: &mut [Self::Frame]) {
fn sample(&mut self, interval: f32, out: &mut [Self::Frame]) {
fn upd(x: &AtomicU32, gain: &mut std::cell::RefMut<Smoothed<f32>>) {
let master = f32::from_bits(MASTER_SHARED.load(Ordering::Relaxed));
let shared = master * f32::from_bits(x.load(Ordering::Relaxed));
Expand Down Expand Up @@ -309,18 +312,6 @@ impl<T: Signal<Frame = [Sample; 2]>> Signal for GlobalGain<T> {
gain.advance(interval * 30.0);
}
}

fn handle_dropped(&self) {
self.inner.handle_dropped()
}
}

impl<T> Filter for GlobalGain<T> {
type Inner = T;

fn inner(&self) -> &Self::Inner {
&self.inner
}
}

pub struct FadeIn<T: ?Sized> {
Expand All @@ -342,7 +333,7 @@ impl<T> FadeIn<T> {
impl<T: Signal<Frame = [Sample; 2]>> Signal for FadeIn<T> {
type Frame = [Sample; 2];

fn sample(&self, interval: f32, out: &mut [Self::Frame]) {
fn sample(&mut self, interval: f32, out: &mut [Self::Frame]) {
self.inner.sample(interval, out);

let mut advance = self.advance.borrow_mut();
Expand All @@ -356,16 +347,114 @@ impl<T: Signal<Frame = [Sample; 2]>> Signal for FadeIn<T> {
*advance += interval / self.fadetime;
}
}
}

/// Amplifies a signal dynamically
///
/// To implement a volume control, place a gain combinator near the end of your pipeline where the
/// input amplitude is initially in the range [0, 1] and pass decibels to [`oddio::GainControl::set_gain`],
/// mapping the maximum volume to 0 decibels, and the minimum to e.g. -60.
///
/// Forked from oddio to allow directly setting the volume to avoid pops at zero volume
/// due to Ordering::Relaxed being too relaxed
pub struct Gain<T: ?Sized> {
shared: Arc<AtomicU32>,
gain: Smoothed<f32>,
inner: T,
}

fn handle_dropped(&self) {
self.inner.handle_dropped()
impl<T> Gain<T> {
/// Apply dynamic amplification to `signal`
pub fn new(signal: T, vol: f32) -> (GainControl, Self) {
let signal = Gain {
shared: Arc::new(AtomicU32::new(vol.to_bits())),
gain: Smoothed::new(vol),
inner: signal,
};
let handle = GainControl(signal.shared.clone());
(handle, signal)
}
}

impl<T> Filter for FadeIn<T> {
type Inner = T;
impl<T: Signal> Signal for Gain<T>
where
T::Frame: Frame,
{
type Frame = T::Frame;

fn inner(&self) -> &Self::Inner {
&self.inner
#[allow(clippy::float_cmp)]
fn sample(&mut self, interval: f32, out: &mut [T::Frame]) {
self.inner.sample(interval, out);
let shared = f32::from_bits(self.shared.load(Ordering::Relaxed));
if self.gain.target() != &shared {
self.gain.set(shared);
}
if self.gain.progress() == 1.0 {
let g = self.gain.get();
if g != 1.0 {
for x in out {
*x = scale(x, g);
}
}
return;
}
for x in out {
*x = scale(x, self.gain.get());
self.gain.advance(interval / SMOOTHING_PERIOD);
}
}

fn is_finished(&self) -> bool {
self.inner.is_finished()
}
}

#[inline]
fn scale<T: Frame>(x: &T, factor: f32) -> T {
map(x, |x| x * factor)
}

#[inline]
fn map<T: Frame>(x: &T, mut f: impl FnMut(Sample) -> Sample) -> T {
let mut out = T::ZERO;
for (&x, o) in x.channels().iter().zip(out.channels_mut()) {
*o = f(x);
}
out
}

/// Thread-safe control for a [`Gain`] filter
pub struct GainControl(Arc<AtomicU32>);

impl GainControl {
/// Get the current amplification in decibels
pub fn gain(&self) -> f32 {
20.0 * self.amplitude_ratio().log10()
}

/// Amplify the signal by `db` decibels
///
/// Perceptually linear. Negative values make the signal quieter.
///
/// Equivalent to `self.set_amplitude_ratio(10.0f32.powf(db / 20.0))`.
pub fn set_gain(&mut self, db: f32) {
self.set_amplitude_ratio(10.0f32.powf(db / 20.0));
}

/// Get the current amplitude scaling factor
pub fn amplitude_ratio(&self) -> f32 {
f32::from_bits(self.0.load(Ordering::Relaxed))
}

/// Scale the amplitude of the signal directly
///
/// This is nonlinear in terms of both perception and power. Most users should prefer
/// `set_gain`. Unlike `set_gain`, this method allows a signal to be completely zeroed out if
/// needed, or even have its phase inverted with a negative factor.
pub fn set_amplitude_ratio(&mut self, factor: f32) {
self.0.store(factor.to_bits(), Ordering::Relaxed);
}
}

/// Number of seconds over which to smooth a change in gain
const SMOOTHING_PERIOD: f32 = 0.1;
28 changes: 13 additions & 15 deletions engine/src/drawables/terrain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,15 @@ impl<const CSIZE: usize, const CRESOLUTION: usize> TerrainRender<CSIZE, CRESOLUT

defer!(log::info!("finished init of terrain render"));
Self {
normal_pipeline: normal_pipeline(&gfx, &normals_tex),
normal_pipeline: normal_pipeline(gfx, &normals_tex),
normal_unis: collect_arrlod((0..LOD).map(|lod| {
Uniform::new(
(CSIZE << lod) as f32 / Self::LOD0_RESOLUTION as f32,
&gfx.device,
)
})),
downsample_pipeline: resample_pipeline(&gfx, &terrain_tex, "downsample"),
upsample_pipeline: resample_pipeline(&gfx, &terrain_tex, "upsample"),
downsample_pipeline: resample_pipeline(gfx, &terrain_tex, "downsample"),
upsample_pipeline: resample_pipeline(gfx, &terrain_tex, "upsample"),

bgs: Arc::new(collect_arrlod(bgs)),
terrain_tex: Arc::new(terrain_tex),
Expand All @@ -169,11 +169,9 @@ impl<const CSIZE: usize, const CRESOLUTION: usize> TerrainRender<CSIZE, CRESOLUT

let mut contents = Vec::with_capacity(CRESOLUTION * CRESOLUTION * 2);

for i in 0..CRESOLUTION {
let ys: &[f32; CRESOLUTION] = &chunk[i];

for j in 0..CRESOLUTION {
contents.extend(pack(ys[j]));
for ys in chunk.iter() {
for &v in ys {
contents.extend(pack(v));
}
}

Expand Down Expand Up @@ -436,10 +434,10 @@ fn normal_pipeline(gfx: &GfxContext, normals_tex: &Texture) -> RenderPipeline {
})
}

fn normal_update<'a>(
fn normal_update(
gfx: &GfxContext,
normal_pipeline: &RenderPipeline,
encoder: &'a mut CommandEncoder,
encoder: &mut CommandEncoder,
height_tex: &TextureView,
normal_view: &TextureView,
uni: &Uniform<f32>,
Expand All @@ -448,15 +446,15 @@ fn normal_update<'a>(
layout: &normal_pipeline.get_bind_group_layout(0),
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::TextureView(&height_tex),
resource: wgpu::BindingResource::TextureView(height_tex),
}],
label: None,
});

let mut rp = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("terrain normals render pass"),
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: &normal_view,
view: normal_view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Load,
Expand All @@ -467,7 +465,7 @@ fn normal_update<'a>(
timestamp_writes: None,
occlusion_query_set: None,
});
rp.set_pipeline(&normal_pipeline);
rp.set_pipeline(normal_pipeline);
rp.set_bind_group(0, &bg, &[]);
rp.set_bind_group(1, &uni.bindgroup, &[]);
rp.draw(0..4, 0..1);
Expand Down Expand Up @@ -556,7 +554,7 @@ fn downsample_update(
timestamp_writes: None,
occlusion_query_set: None,
});
rp.set_pipeline(&downsample_pipeline);
rp.set_pipeline(downsample_pipeline);
rp.set_bind_group(0, &bg, &[]);
rp.draw(0..4, 0..1);
drop(rp);
Expand Down Expand Up @@ -594,7 +592,7 @@ fn upsample_update(
timestamp_writes: None,
occlusion_query_set: None,
});
rp.set_pipeline(&upsample_pipeline);
rp.set_pipeline(upsample_pipeline);
rp.set_bind_group(0, &bg, &[]);
rp.draw(0..4, 0..1);
drop(rp);
Expand Down
Loading

0 comments on commit b31594b

Please sign in to comment.