Skip to content

Commit cb551c1

Browse files
committed
documentation and cleanup
1 parent 5ec5097 commit cb551c1

File tree

19 files changed

+288
-137
lines changed

19 files changed

+288
-137
lines changed

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
name = "scamble"
33
version = "0.1.0"
44
edition = "2024"
5+
license = "MIT"
6+
description = "Library for building FMOD DSPs"
7+
repository = "https://github.com/l-Luna/scamble"
8+
keywords = ["fmod", "dsp"]
9+
categories = ["multimedia::audio"]
510

611
[workspace]
712
members = ["tcp_effects", "cassette_player"]

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
a rust library for writing FMOD DSPs
2+
3+
a simple example:
4+
```rs
5+
#![feature(macro_metavar_expr)]
6+
#![feature(macro_metavar_expr_concat)]
7+
8+
use scamble::expose_dsp;
9+
use scamble::dsp::*;
10+
use scamble::dsp::signal::*;
11+
12+
pub struct Invert;
13+
14+
impl Dsp for Invert{
15+
fn name() -> &'static str { "Invert" }
16+
fn version() -> u32 { 1 }
17+
fn ty() -> DspType { DspType::Effect }
18+
fn create() -> Self { Invert }
19+
20+
fn read(&mut self, input: SignalConst, mut output: SignalMut) {
21+
let in_data = input.samples();
22+
let out_data = output.samples_mut();
23+
for i in 0..in_data.len() {
24+
out_data[i] = -in_data[i];
25+
}
26+
}
27+
}
28+
29+
expose_dsp!(Invert);
30+
```

build.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
use bindgen::EnumVariation;
2-
use std::{env, fs};
2+
use std::env;
33
use std::path::PathBuf;
44

55
fn main() {
6-
// println!("cargo:rustc-link-search=./libs/");
7-
// println!("cargo:rustc-link-lib= fmod");
8-
96
let bindings = bindgen::Builder::default()
107
.header("libs/wrapper.h")
118
.default_enum_style(EnumVariation::Rust {
@@ -20,12 +17,4 @@ fn main() {
2017
bindings
2118
.write_to_file(target)
2219
.expect("Couldn't write bindings!");
23-
24-
// slightly hacky way to append the right link mode for windows
25-
/*let mut st = fs::read_to_string(target).expect("Couldn't update bindings!");
26-
st = st.replace(
27-
"unsafe extern \"C\" {",
28-
"#[cfg_attr(windows, link(name = \"fmod\", kind = \"raw-dylib\"))]\nunsafe extern \"C\" {"
29-
);
30-
fs::write(target, st).expect("Couldn't update bindings!");*/
3120
}

plot.png

-990 KB
Binary file not shown.

src/data.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1+
//! Data types used as DSP parameters.
2+
3+
/// A 3D vector. Part of DSP parameter types.
14
#[derive(Copy, Clone, Debug, PartialEq)]
25
pub struct Vec3 {
36
pub x: f32,
47
pub y: f32,
58
pub z: f32
69
}
710

11+
/// A perspective in 3D. Part of DSP parameter types.
812
#[derive(Copy, Clone, Debug, PartialEq)]
913
pub struct _3DAttributes {
1014
pub position: Vec3,
@@ -13,38 +17,60 @@ pub struct _3DAttributes {
1317
pub up: Vec3
1418
}
1519

20+
/// Multi-channel spectra, for use with [dsp::ParameterType::Fft].
1621
#[derive(Clone, Debug, PartialEq)]
1722
pub struct FftData {
23+
/// Per-channel spectra, as a vector of per-channel data.
1824
pub data: Vec<Vec<f32>>
1925
}
2026

27+
/// Dynamic response, for use with [dsp::ParameterType::DynamicResponse].
2128
#[derive(Clone, Debug, PartialEq)]
2229
pub struct DynamicResponseData {
30+
/// Per-channel average (RMS) gain factor.
2331
pub rms: Vec<f32>
2432
}
2533

34+
/// Overall gain, for use with [dsp::ParameterType::OverallGain]. FMOD reads this parameter type
35+
/// to determine when to virtualize voices.
2636
#[derive(Copy, Clone, Debug, PartialEq)]
2737
pub struct OverallGainData {
38+
/// Overall linear gain applied to the signal.
2839
pub linear_gain: f32,
40+
/// Overall additive gain applied to the signal.
2941
pub linear_gain_additive: f32
3042
}
3143

44+
/// Listener attributes, for use with [dsp::ParameterType::ListenerAttributes]. FMOD sets this
45+
/// parameter type based on the listener's and event's locations automatically.
3246
#[derive(Copy, Clone, Debug, PartialEq)]
3347
pub struct ListenerAttributesData {
48+
/// Relative position of the sound to the listener.
3449
pub relative: _3DAttributes,
50+
/// Absolute position of the sound in the world.
3551
pub absolute: _3DAttributes
3652
}
3753

54+
/// Listener attributes when multiple listeners exist, for use with [dsp::ParameterType::ListenerAttributesList].
55+
/// FMOD sets this parameter type based on the listeners' and event's locations automatically.
3856
#[derive(Clone, Debug, PartialEq)]
3957
pub struct ListenerAttributesListData {
58+
/// The number of listeners, equal to the length of the `relative` and `weights` fields.
4059
pub count: usize,
60+
/// Relative position of the sound to each listener.
4161
pub relative: Vec<_3DAttributes>,
62+
/// Weight of each listener to the sound output, in the range 0..1.
4263
pub weights: Vec<f32>,
64+
/// Absolute position of the sound in the world.
4365
pub absolute: _3DAttributes
4466
}
4567

68+
/// Attenuation range of an event, for use with [dsp::ParameterType::AttenuationRange]. FMOD Studio
69+
/// sets and updates this parameter type based on the event's minimum and maximum distance.
4670
#[derive(Copy, Clone, Debug, PartialEq)]
4771
pub struct AttenuationRangeData {
72+
/// Minimum distance for attenuation.
4873
pub min: f32,
74+
/// Maximum distance for attenuation.
4975
pub max: f32
5076
}

src/dsp/decode.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! Utilities for decoding samples from a plugin, for data inputs.
2+
13
use hound::{SampleFormat, WavReader};
24

35
/// Decode a data buffer into mono samples, guessing the correct format.

src/dsp/interop.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
//! Wraps `scamble`'s DSP API into FMOD's API. Use `expose_dsp` or `expose_dsp_list` to create a
2+
//! standalone plugin binary, or use [into_desc] to pass a value directly to FMOD Core's API.
3+
14
use crate::raw_bindings::*;
25
use crate::raw_bindings::FMOD_DSP_PARAMETER_DATA_TYPE::*;
36
use crate::raw_bindings::FMOD_RESULT::{FMOD_ERR_DSP_DONTPROCESS, FMOD_ERR_DSP_SILENCE, FMOD_ERR_INVALID_PARAM, FMOD_ERR_PLUGIN, FMOD_OK};
4-
pub use crate::dsp::{Dsp, DspType, ParameterType, ProcessResult};
7+
use crate::dsp::{Dsp, DspType, ParameterType, ProcessResult};
58
use crate::dsp::signal::{SignalConst, SignalMut};
69
use std::{alloc, panic, ptr};
710
use std::alloc::Layout;
@@ -11,6 +14,7 @@ use std::str::FromStr;
1114

1215
// wrapping DSPs into FMOD's format
1316

17+
/// Expose a DSP type to FMOD to be loaded as a dynamic library.
1418
#[macro_export]
1519
macro_rules! expose_dsp {
1620
($t:tt) => {
@@ -41,6 +45,7 @@ macro_rules! expose_dsp {
4145
};
4246
}
4347

48+
/// Expose multiple DSP types to FMOD to be loaded as a dynamic library.
4449
#[macro_export]
4550
macro_rules! expose_dsp_list {
4651
($($t:ident $(,)?)*) => {
@@ -89,10 +94,9 @@ macro_rules! expose_dsp_list {
8994
};
9095
}
9196

92-
pub(crate) use expose_dsp;
93-
pub(crate) use expose_dsp_list;
94-
97+
/// Convert a DSP type into an FMOD DSP description, to be passed to the FMOD Core API.
9598
pub fn into_desc<D: Dsp>() -> FMOD_DSP_DESCRIPTION {
99+
// TODO: set the hook in FMODGetPluginDescription[List] so it only applies for standalones
96100
panic::set_hook(Box::new(|it| {
97101
let mut desc = String::new();
98102
desc.push_str("Panic");
@@ -272,6 +276,8 @@ static DBGSTR: &'static str = "Rust DSP\0";
272276
static mut CUR_STATE: *mut FMOD_DSP_STATE = ptr::null_mut();
273277
static mut IN_LENGTH: usize = 0;
274278

279+
/// Read a sidechain input from a DSP. Should only be called from [Dsp::read], only if a
280+
/// [ParameterType::Sidechain] is present and enabled, otherwise [None] will always be provided.
275281
pub fn with_sidechain<T>(f: impl FnOnce(Option<SignalConst>) -> T) -> T{
276282
let cur_state = unsafe { CUR_STATE };
277283
if cur_state.is_null() {

0 commit comments

Comments
 (0)