1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//! Fixed-point primitives for the xmrs ecosystem.
//!
//! Substrate on which `xmrs` and `xmrsplayer` run without `f32`
//! arithmetic, so they ship to processors without an FPU
//! (Cortex-M0, classic 68000, eventually Z80 / 6502 with the
//! right toolchain).
//!
//! The module is split into four layers:
//!
//! * [`crate::fixed::fixed`] — generic `Q<T, FRAC>` types. All arithmetic
//! primitives, rounding rules and saturation rules live here.
//! No domain knowledge.
//!
//! * [`crate::fixed::units`] — newtypes for the player's domain concepts:
//! [`Volume`](crate::fixed::units::Volume), [`Panning`](crate::fixed::units::Panning),
//! [`Pitch`](crate::fixed::units::Pitch), [`Frequency`](crate::fixed::units::Frequency),
//! etc. These wrap the [`crate::fixed::fixed`] types and only expose
//! operations that make musical sense, so mixing them up
//! is a compile error.
//!
//! * [`crate::fixed::tables`] — compile-time lookup tables built with
//! `const fn` (sine, equal-power-pan sqrt, period→frequency,
//! Amiga period). These replace `sin`, `sqrt`, `powf`, `exp`,
//! `log2` calls; the module has no dependency on `libm`,
//! `micromath`, or any soft-float runtime.
//!
//! * [`crate::fixed::from_tracker`] — a small helper module that converts
//! the raw bytes / nibbles found in `.mod` / `.xm` / `.s3m` /
//! `.it` files directly into the domain newtypes, without
//! ever constructing an intermediate `f32`.
//!
//! Plus the optional `float_helpers` module, gated behind the
//! `float-helpers` cargo feature: `f32 ↔ Q` conversions for the
//! editor / desktop side. Never enabled on embedded builds.
//!
//! ## Discipline
//!
//! Outside the [`crate::fixed::fixed`] submodule, code should never write
//! `as i16`, `>> 15`, `<< 9` and similar bit hacks against
//! Q-formatted values. If you find yourself wanting to, the
//! corresponding method is missing from [`crate::fixed::units`] and should
//! be added there. This is what keeps the rest of the player
//! readable.
//!
//! Outside [`crate::fixed::from_tracker`] (load-time only), code should
//! never see an `f32` either. The audio hot path is integer-only.
// `crate::fixed::fixed::*` holds the raw Q-format newtypes (Q15,
// Q8_8, etc.); the outer `fixed` module groups them with the
// domain newtypes in `units`, the LUTs in `tables`, and the
// load-time converters in `from_tracker`. Renaming would churn
// 28 import sites for no functional gain.
// Convenience prelude — pull this into a player file and you
// have everything in one go.