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
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//! [![Documentation](https://docs.rs/rotary/badge.svg)](https://docs.rs/rotary)
//! [![Crates](https://img.shields.io/crates/v/rotary.svg)](https://crates.io/crates/rotary)
//! [![Actions Status](https://github.com/udoprog/rotary/workflows/Rust/badge.svg)](https://github.com/udoprog/rotary/actions)
//!
//! A library for working with audio buffers
//!
//! The buffer is constructed similarly to a `Vec<Vec<T>>`, except the interior
//! vector has a fixed size. And the buffer makes no attempt to clear data which
//! is freed when using functions such as [Dynamic::resize].
//!
//! # Example: Playing mp3 files
//!
//! Play an mp3 file with [minimp3-rs], [cpal], and [rubato] for resampling.
//!
//! ```bash
//! cargo run --release --package rotary-examples --bin play-mp3 -- path/to/file.mp3
//! ```
//!
//! # Examples
//!
//! ```rust
//! use rand::Rng as _;
//!
//! let mut buffer = rotary::Dynamic::<f32>::new();
//!
//! buffer.resize_channels(2);
//! buffer.resize(2048);
//!
//! /// Fill both channels with random noise.
//! let mut rng = rand::thread_rng();
//! rng.fill(&mut buffer[0]);
//! rng.fill(&mut buffer[1]);
//! ```
//!
//! You can use the included [Mask] trait to separately keep track of active and
//! inactive channels in an audio buffer. This requires that you specify the
//! type of the mask. A good option for this is a [BitSet<u128>], which supports
//! up to 128 channels.
//!
//! ```rust
//! use rotary::{BitSet, Mask as _};
//!
//! let mut buffer = rotary::Dynamic::<f32>::with_topology(4, 1024);
//! let mask: rotary::BitSet<u128> = rotary::bit_set![0, 2, 3];
//!
//! for chan in mask.join(buffer.iter_mut()) {
//!     for b in chan {
//!         *b = 1.0;
//!     }
//! }
//!
//! let zeroed = vec![0.0f32; 1024];
//! let expected = vec![1.0f32; 1024];
//!
//! assert_eq!(&buffer[0], &expected[..]);
//! assert_eq!(&buffer[1], &zeroed[..]);
//! assert_eq!(&buffer[2], &expected[..]);
//! assert_eq!(&buffer[3], &expected[..]);
//! ```
//!
//! For convenience we also provide the [dynamic!] macro when constructing
//! audio buffers.
//!
//! ```rust
//! use rotary::BitSet;
//!
//! let mut buf = rotary::Dynamic::<f32>::with_topology(4, 128);
//!
//! for channel in &mut buf {
//!     for f in channel {
//!         *f = 2.0;
//!     }
//! }
//!
//! assert_eq!(buf, rotary::dynamic![[2.0; 128]; 4])
//! ```
//!
//! [play-mp3]: https://github.com/udoprog/rotary/tree/main/examples/src/bin/play-mp3.rs
//! [minimp3-rs]: https://github.com/germangb/minimp3-rs
//! [cpal]: https://github.com/RustAudio/cpal
//! [rubato]: https://github.com/HEnquist/rubato
//! [Dynamic::resize]: https://docs.rs/rotary/0/rotary/dynamic/struct.Dynamic.html#method.resize
//! [BitSet<u128>]: https://docs.rs/rotary/0/rotary/bit_set/struct.BitSet.html
//! [dynamic!]: https://docs.rs/rotary/0/rotary/macros/macro.dynamic.html

#![deny(missing_docs)]

#[macro_use]
mod macros;
pub mod bit_set;
pub mod buf;
pub mod channel;
pub mod dynamic;
pub mod interleaved;
pub mod io;
pub mod mask;
mod sample;
pub mod sequential;
#[cfg(test)]
mod tests;
mod translate;
pub mod utils;
pub mod wrap;

pub use self::bit_set::BitSet;
pub use self::buf::{Buf, BufInfo, BufMut, ResizableBuf};
pub use self::channel::{Channel, ChannelMut};
pub use self::dynamic::Dynamic;
pub use self::interleaved::Interleaved;
pub use self::io::{ReadBuf, WriteBuf};
pub use self::mask::Mask;
pub use self::sample::Sample;
pub use self::sequential::Sequential;
pub use self::translate::Translate;