oddio/
lib.rs

1//! Lightweight game audio
2//!
3//! ```no_run
4//! let (mut scene_handle, mut scene) = oddio::SpatialScene::new();
5//!
6//! // In audio callback:
7//! # let data = &mut [][..];
8//! # let output_sample_rate = 44100;
9//! let out_frames = oddio::frame_stereo(data);
10//! oddio::run(&mut scene, output_sample_rate, out_frames);
11//!
12//! // In game logic:
13//! # let frames = [];
14//! # let sample_rate = 44100;
15//! # let position = [0.0, 0.0, 0.0].into();
16//! # let velocity = [0.0, 0.0, 0.0].into();
17//! let frames = oddio::FramesSignal::from(oddio::Frames::from_slice(sample_rate, &frames));
18//! let mut handle = scene_handle
19//!     .play(frames, oddio::SpatialOptions { position, velocity, ..Default::default() });
20//!
21//! // When position/velocity changes:
22//! handle.set_motion(position, velocity, false);
23//! ```
24//!
25//! To get started, review [the `examples`
26//! subdirectory](https://github.com/Ralith/oddio/tree/main/examples) in the crate source.
27//!
28//! Key primitives:
29//! - [`Frames`] stores static audio data, which can be played with a [`FramesSignal`]
30//! - [`Mixer`] allows multiple signals to be played concurrently and controlled during playback
31//! - [`SpatialScene`] is a mixer that spatializes its signals
32//! - [`run`] writes frames from a [`Signal`] into an output buffer
33
34#![allow(unused_imports)]
35#![warn(missing_docs)]
36#![no_std]
37
38extern crate alloc;
39#[cfg(not(feature = "no_std"))]
40extern crate std;
41
42mod adapt;
43mod constant;
44mod cycle;
45mod downmix;
46mod fader;
47mod frame;
48mod frames;
49mod gain;
50mod math;
51mod mixer;
52mod reinhard;
53mod ring;
54mod set;
55mod signal;
56mod sine;
57mod smooth;
58mod spatial;
59mod speed;
60mod spsc;
61mod stream;
62mod swap;
63mod tanh;
64
65pub use adapt::{Adapt, AdaptOptions};
66pub use constant::Constant;
67pub use cycle::Cycle;
68pub use downmix::Downmix;
69pub use fader::{Fader, FaderControl};
70pub use frame::Frame;
71pub use frames::*;
72pub use gain::{FixedGain, Gain, GainControl};
73pub use mixer::*;
74pub use reinhard::Reinhard;
75use set::*;
76pub use signal::*;
77pub use sine::*;
78pub use smooth::{Interpolate, Smoothed};
79pub use spatial::*;
80pub use speed::{Speed, SpeedControl};
81pub use stream::{Stream, StreamControl};
82pub use tanh::Tanh;
83
84/// Unitless instantaneous sound wave amplitude measurement
85pub type Sample = f32;
86
87/// Populate `out` with frames from `signal` at `sample_rate`
88///
89/// Convenience wrapper for [`Signal::sample`].
90pub fn run<S: Signal + ?Sized>(signal: &mut S, sample_rate: u32, out: &mut [S::Frame]) {
91    let interval = 1.0 / sample_rate as f32;
92    signal.sample(interval, out);
93}
94
95/// Convert a slice of interleaved stereo data into a slice of stereo frames
96///
97/// Useful for adapting output buffers obtained externally.
98pub fn frame_stereo(xs: &mut [Sample]) -> &mut [[Sample; 2]] {
99    unsafe { core::slice::from_raw_parts_mut(xs.as_mut_ptr() as _, xs.len() / 2) }
100}
101
102fn flatten_stereo(xs: &mut [[Sample; 2]]) -> &mut [Sample] {
103    unsafe { core::slice::from_raw_parts_mut(xs.as_mut_ptr() as _, xs.len() * 2) }
104}