audio_blocks/lib.rs
1//! # audio-blocks
2//!
3//! Real-time safe abstractions over audio data with support for all common layouts.
4//!
5//! ## Quick Start
6//!
7//! Install:
8//! ```sh
9//! cargo add audio-blocks
10//! ```
11//!
12//! Basic planar usage (most common for DSP):
13//! ```
14//! use audio_blocks::*;
15//!
16//! // Create a planar block - each channel gets its own buffer
17//! let mut block = Planar::<f32>::new(2, 512); // 2 channels, 512 frames
18//!
19//! // Process per channel
20//! for channel in block.channels_mut() {
21//! for sample in channel {
22//! *sample *= 0.5;
23//! }
24//! }
25//! ```
26//!
27//! Generic function that accepts any layout:
28//! ```
29//! # use audio_blocks::*;
30//! fn process(block: &mut impl AudioBlockMut<f32>) {
31//! for channel in block.channels_iter_mut() {
32//! for sample in channel {
33//! *sample *= 0.5;
34//! }
35//! }
36//! }
37//! ```
38//!
39//! ## Block Types
40//!
41//! Three multi-channel layouts supported:
42//!
43//! **Planar** - `[[ch0, ch0, ch0], [ch1, ch1, ch1]]`
44//! Each channel has its own separate buffer. Standard for real-time DSP. Optimal for SIMD/vectorization.
45//!
46//! **Sequential** - `[ch0, ch0, ch0, ch1, ch1, ch1]`
47//! Single contiguous buffer with all samples for channel 0, then all samples for channel 1. Channel-contiguous in one allocation.
48//!
49//! **Interleaved** - `[ch0, ch1, ch0, ch1, ch0, ch1]`
50//! Channels alternate sample-by-sample. Common in audio APIs and hardware interfaces.
51//!
52//! Plus a dedicated mono type:
53//!
54//! **Mono** - `[sample0, sample1, sample2, ...]`
55//! Simplified single-channel block with a streamlined API that doesn't require channel indexing.
56//!
57//! ## Core Traits
58//!
59//! Write functions that accept any layout:
60//!
61//! ```
62//! # use audio_blocks::*;
63//! fn process(block: &mut impl AudioBlockMut<f32>) {
64//! // Works with planar, sequential, or interleaved
65//! }
66//! ```
67//!
68//! Generic across float types:
69//!
70//! ```
71//! # use audio_blocks::*;
72//! fn process<F: Copy + 'static + std::ops::MulAssign>(block: &mut impl AudioBlockMut<F>) {
73//! let gain: F = todo!();
74//! for channel in block.channels_iter_mut() {
75//! for sample in channel {
76//! *sample *= gain;
77//! }
78//! }
79//! }
80//! ```
81//!
82//! ## Creating Blocks
83//!
84//! ### Owned Blocks
85//!
86//! ```
87//! use audio_blocks::*;
88//!
89//! // Allocate with default values (zero)
90//! let mut block = Planar::<f32>::new(2, 512); // 2 channels, 512 frames
91//! let mut block = Sequential::<f32>::new(2, 512); // 2 channels, 512 frames
92//! let mut block = Interleaved::<f32>::new(2, 512); // 2 channels, 512 frames
93//! let mut block = Mono::<f32>::new(512); // 512 frames
94//!
95//! // Copy from existing data
96//! let channel_data = vec![[0.0f32; 512], [0.0f32; 512]];
97//! let data = vec![0.0f32; 1024];
98//! let mut block = Planar::from_slice(&channel_data); // channels derived from slice
99//! let mut block = Sequential::from_slice(&data, 2); // 2 channels
100//! let mut block = Interleaved::from_slice(&data, 2); // 2 channels
101//! let mut block = Mono::from_slice(&data);
102//! ```
103//!
104//! Allocation only happens when creating owned blocks. Never do that in real-time contexts.
105//!
106//! ### Views (zero-allocation, borrows data)
107//!
108//! ```
109//! use audio_blocks::*;
110//!
111//! let channel_data = vec![[0.0f32; 512], [0.0f32; 512]];
112//! let data = vec![0.0f32; 1024];
113//!
114//! let block = PlanarView::from_slice(&channel_data); // channels derived from slice
115//! let block = SequentialView::from_slice(&data, 2); // 2 channels
116//! let block = InterleavedView::from_slice(&data, 2); // 2 channels
117//! let block = MonoView::from_slice(&data);
118//! ```
119//!
120//! From raw pointers:
121//! ```
122//! # use audio_blocks::*;
123//! let data = vec![0.0f32; 1024];
124//! # let ptr = data.as_ptr();
125//! let block = unsafe { InterleavedView::from_ptr(ptr, 2, 512) }; // 2 channels, 512 frames
126//! ```
127//!
128//! Planar requires adapter:
129//! ```
130//! # use audio_blocks::*;
131//! # let ch0 = vec![0.0f32; 512];
132//! # let ch1 = vec![0.0f32; 512];
133//! # let ptrs = [ch0.as_ptr(), ch1.as_ptr()];
134//! # let data = ptrs.as_ptr();
135//! let mut adapter = unsafe { PlanarPtrAdapter::<_, 16>::from_ptr(data, 2, 512) }; // 2 channels, 512 frames
136//! let block = adapter.planar_view();
137//! ```
138//!
139//! ## Common Operations
140//!
141//! Import the extension traits for additional operations:
142//!
143//! ```
144//! use audio_blocks::{AudioBlockOps, AudioBlockOpsMut};
145//! ```
146//!
147//! ### Copying and Clearing
148//!
149//! ```
150//! # use audio_blocks::*;
151//! let other_block = Planar::<f32>::new(2, 512);
152//! let mut block = Planar::<f32>::new(2, 512);
153//!
154//! // Copy from another block (flexible - copies min of both sizes)
155//! let result = block.copy_from_block(&other_block);
156//! // Returns None if exact match, Some((channels, frames)) if partial
157//!
158//! // Copy with exact size requirement (panics on mismatch)
159//! block.copy_from_block_exact(&other_block);
160//!
161//! // Fill all samples with a value
162//! block.fill_with(0.5);
163//!
164//! // Clear to zero
165//! block.clear();
166//! ```
167//!
168//! ### Per-Sample Processing
169//!
170//! ```
171//! # use audio_blocks::*;
172//! let mut block = Planar::<f32>::new(2, 512);
173//!
174//! // Process each sample
175//! block.for_each(|sample| *sample *= 0.5);
176//!
177//! // Process with channel/frame indices
178//! block.enumerate(|channel, frame, sample| {
179//! *sample *= 0.5;
180//! });
181//!
182//! // Apply gain to all samples
183//! block.gain(0.5);
184//! ```
185//!
186//! ### Mono Conversions
187//!
188//! ```
189//! # use audio_blocks::*;
190//! let mut block = Planar::<f32>::new(2, 512);
191//! let mut mono_data = vec![0.0f32; 512];
192//! let mut mono_view = MonoViewMut::from_slice(&mut mono_data);
193//!
194//! // Mix all channels to mono (averages channels)
195//! let result = block.mix_to_mono(&mut mono_view);
196//! // Returns None if exact match, Some(frames_processed) if partial
197//!
198//! // Or with exact size requirement
199//! block.mix_to_mono_exact(&mut mono_view);
200//!
201//! // Copy a specific channel to mono
202//! block.copy_channel_to_mono(&mut mono_view, 0); // channel 0
203//!
204//! // Copy mono to all channels of a block
205//! let mono_ro = MonoView::from_slice(&mono_data);
206//! block.copy_mono_to_all_channels(&mono_ro);
207//! ```
208//!
209//! ## Working with Slices
210//!
211//! Convert generic blocks to concrete types for slice access:
212//!
213//! ```
214//! # use audio_blocks::*;
215//! fn process(block: &mut impl AudioBlockMut<f32>) {
216//! if block.layout() == BlockLayout::Planar {
217//! let mut view = block.as_planar_view_mut().unwrap();
218//! let ch0: &mut [f32] = view.channel_mut(0);
219//! let ch1: &mut [f32] = view.channel_mut(1);
220//! }
221//! }
222//! ```
223//!
224//! Direct slice access on concrete types:
225//!
226//! ```
227//! # use audio_blocks::*;
228//! let mut block = Planar::<f32>::new(2, 512); // 2 channels, 512 frames
229//! let channel: &[f32] = block.channel(0);
230//! let raw_data: &[Box<[f32]>] = block.raw_data();
231//!
232//! let mut block = Interleaved::<f32>::new(2, 512); // 2 channels, 512 frames
233//! let frame: &[f32] = block.frame(0);
234//! let raw_data: &[f32] = block.raw_data();
235//! ```
236//!
237//! ## Trait API Reference
238//!
239//! ### `AudioBlock`
240//!
241//! Size and layout:
242//! ```
243//! # use audio_blocks::*;
244//! # fn example(audio: &impl AudioBlock<f32>) {
245//! let channels: u16 = audio.num_channels();
246//! let frames: usize = audio.num_frames();
247//! let layout: BlockLayout = audio.layout();
248//! # }
249//! ```
250//!
251//! Sample access:
252//! ```
253//! # use audio_blocks::*;
254//! # fn example(audio: &impl AudioBlock<f32>) {
255//! let s: f32 = audio.sample(0, 0);
256//! # }
257//! ```
258//!
259//! Iteration:
260//! ```
261//! # use audio_blocks::*;
262//! # fn example(audio: &impl AudioBlock<f32>) {
263//! for s in audio.channel_iter(0) { let _: &f32 = s; }
264//! for ch in audio.channels_iter() { for s in ch { let _: &f32 = s; } }
265//! for s in audio.frame_iter(0) { let _: &f32 = s; }
266//! for fr in audio.frames_iter() { for s in fr { let _: &f32 = s; } }
267//! # }
268//! ```
269//!
270//! Generic view (zero-allocation):
271//! ```
272//! # use audio_blocks::*;
273//! # fn example(audio: &impl AudioBlock<f32>) {
274//! let view = audio.as_view();
275//! # }
276//! ```
277//!
278//! Downcast to concrete type:
279//! ```
280//! # use audio_blocks::*;
281//! # fn example(audio: &impl AudioBlock<f32>) {
282//! let interleaved: Option<InterleavedView<f32>> = audio.as_interleaved_view();
283//! let sequential: Option<SequentialView<f32>> = audio.as_sequential_view();
284//! # }
285//! ```
286//!
287//! ### `AudioBlockMut`
288//!
289//! Everything from `AudioBlock` plus:
290//!
291//! Resizing:
292//! ```
293//! # use audio_blocks::*;
294//! # fn example(audio: &mut impl AudioBlockMut<f32>) {
295//! audio.set_visible(2, 1024);
296//! audio.set_num_channels_visible(2);
297//! audio.set_num_frames_visible(1024);
298//! # }
299//! ```
300//!
301//! Mutable access:
302//! ```
303//! # use audio_blocks::*;
304//! # fn example(audio: &mut impl AudioBlockMut<f32>) {
305//! let s: &mut f32 = audio.sample_mut(0, 0);
306//! for s in audio.channel_iter_mut(0) { let _: &mut f32 = s; }
307//! for ch in audio.channels_iter_mut() { for s in ch { let _: &mut f32 = s; } }
308//! for s in audio.frame_iter_mut(0) { let _: &mut f32 = s; }
309//! for fr in audio.frames_iter_mut() { for s in fr { let _: &mut f32 = s; } }
310//! # }
311//! ```
312//!
313//! Generic view (zero-allocation):
314//! ```
315//! # use audio_blocks::*;
316//! # fn example(audio: &mut impl AudioBlockMut<f32>) {
317//! let view = audio.as_view_mut();
318//! # }
319//! ```
320//!
321//! Downcast to concrete type:
322//! ```
323//! # use audio_blocks::*;
324//! # fn example(audio: &mut impl AudioBlockMut<f32>) {
325//! let interleaved: Option<InterleavedViewMut<f32>> = audio.as_interleaved_view_mut();
326//! let sequential: Option<SequentialViewMut<f32>> = audio.as_sequential_view_mut();
327//! # }
328//! ```
329//!
330//! ### `AudioBlockOps` (extension trait)
331//!
332//! Read-only operations on audio blocks:
333//! ```
334//! # use audio_blocks::*;
335//! # fn example(block: &impl AudioBlock<f32>, dest: &mut MonoViewMut<f32>) {
336//! let _: Option<usize> = block.mix_to_mono(dest);
337//! block.mix_to_mono_exact(dest);
338//! let _: Option<usize> = block.copy_channel_to_mono(dest, 0);
339//! block.copy_channel_to_mono_exact(dest, 0);
340//! # }
341//! ```
342//!
343//! ### `AudioBlockOpsMut` (extension trait)
344//!
345//! Mutable operations on audio blocks:
346//! ```
347//! # use audio_blocks::*;
348//! # fn example(block: &mut impl AudioBlockMut<f32>, other: &impl AudioBlock<f32>, mono: &MonoView<f32>) {
349//! let _: Option<(u16, usize)> = block.copy_from_block(other);
350//! block.copy_from_block_exact(other);
351//! let _: Option<usize> = block.copy_mono_to_all_channels(mono);
352//! block.copy_mono_to_all_channels_exact(mono);
353//! block.for_each(|sample| *sample *= 0.5);
354//! block.enumerate(|_ch, _fr, sample| { *sample *= 0.5; });
355//! block.for_each_allocated(|sample| *sample *= 0.5);
356//! block.fill_with(0.5);
357//! block.clear();
358//! block.gain(0.5);
359//! # }
360//! ```
361//!
362//! ## Advanced: Variable Buffer Sizes
363//!
364//! Blocks separate allocated capacity from visible size. Resize visible portion without reallocation:
365//!
366//! ```
367//! # use audio_blocks::*;
368//! let mut block = Planar::<f32>::new(2, 512); // 2 channels, 512 frames
369//! block.set_num_frames_visible(256); // use only 256 frames
370//! ```
371//!
372//! Create views with limited visibility:
373//! ```
374//! # use audio_blocks::*;
375//! # let data = vec![0.0f32; 1024];
376//! let block = InterleavedView::from_slice_limited(
377//! &data,
378//! 2, // num_channels_visible
379//! 256, // num_frames_visible
380//! 2, // num_channels_allocated
381//! 512 // num_frames_allocated
382//! );
383//! ```
384//!
385//! Query allocation:
386//! ```
387//! # use audio_blocks::*;
388//! # let block = Planar::<f32>::new(2, 512);
389//! let _ = block.num_channels_allocated();
390//! let _ = block.num_frames_allocated();
391//! ```
392//!
393//! ## Advanced: Access Allocated Samples
394//!
395//! For operations that process all allocated memory (including non-visible samples):
396//!
397//! ```
398//! use audio_blocks::AudioBlockOpsMut;
399//! # use audio_blocks::*;
400//! # let mut block = Planar::<f32>::new(2, 512);
401//!
402//! block.for_each_allocated(|sample| *sample *= 0.5);
403//! block.enumerate_allocated(|_ch, _frame, sample| {
404//! // Process including allocated but non-visible samples
405//! let _ = sample;
406//! });
407//! ```
408//!
409//! Note: `fill_with`, `clear`, and `gain` also operate on the entire allocated buffer for efficiency.
410//!
411//! Direct memory access:
412//! ```
413//! # use audio_blocks::*;
414//! let block = Sequential::<f32>::new(2, 512);
415//! let data: &[f32] = block.raw_data(); // Includes non-visible samples
416//! ```
417//!
418//! ## Performance
419//!
420//! Iterator performance varies by layout:
421//! - Sequential/Planar: Channel iteration faster
422//! - Interleaved (many channels): Frame iteration faster
423//!
424//! `raw_data()` access is fastest but exposes non-visible samples. For simple operations like gain, processing all samples (including non-visible) can be more efficient.
425//!
426//! Check layout before optimization:
427//! ```
428//! # use audio_blocks::*;
429//! # fn example(block: &impl AudioBlock<f32>) {
430//! match block.layout() {
431//! BlockLayout::Planar => { /* channel-wise processing */ }
432//! BlockLayout::Interleaved => { /* frame-wise processing */ }
433//! BlockLayout::Sequential => { /* channel-wise processing */ }
434//! }
435//! # }
436//! ```
437//!
438//! ## `no_std` Support
439//!
440//! Disable default features. Owned blocks require `alloc` or `std` feature.
441#![cfg_attr(all(not(test), not(feature = "std")), no_std)] // enable std library when feature std is provided
442
443#[cfg(all(feature = "alloc", not(feature = "std")))]
444extern crate alloc;
445
446#[cfg(not(feature = "std"))]
447extern crate core as std;
448
449#[cfg(feature = "std")]
450extern crate std;
451
452pub use ops::AudioBlockOps;
453pub use ops::AudioBlockOpsMut;
454
455#[cfg(any(feature = "std", feature = "alloc"))]
456pub use interleaved::Interleaved;
457pub use interleaved::InterleavedView;
458pub use interleaved::InterleavedViewMut;
459
460#[cfg(any(feature = "std", feature = "alloc"))]
461pub use sequential::Sequential;
462pub use sequential::SequentialView;
463pub use sequential::SequentialViewMut;
464
465#[cfg(any(feature = "std", feature = "alloc"))]
466pub use planar::Planar;
467pub use planar::PlanarPtrAdapter;
468pub use planar::PlanarPtrAdapterMut;
469pub use planar::PlanarView;
470pub use planar::PlanarViewMut;
471
472#[cfg(any(feature = "std", feature = "alloc"))]
473pub use mono::Mono;
474pub use mono::MonoView;
475pub use mono::MonoViewMut;
476
477pub mod interleaved;
478mod iter;
479pub mod mono;
480pub mod ops;
481pub mod planar;
482pub mod sequential;
483
484/// Represents the memory layout of audio data returned by [`AudioBlock::layout`].
485///
486/// This enum allows consumers to determine the underlying data layout, which is essential for:
487/// - Direct raw data access
488/// - Performance optimizations
489/// - Efficient interfacing with external audio APIs
490///
491/// # Examples of layouts
492///
493/// Each variant represents a common pattern used in audio processing.
494#[derive(PartialEq, Debug)]
495pub enum BlockLayout {
496 /// Samples from different channels alternate in sequence.
497 ///
498 /// Format: `[ch0, ch1, ..., ch0, ch1, ..., ch0, ch1, ...]`
499 ///
500 /// This layout is common in consumer audio formats and some APIs.
501 Interleaved,
502
503 /// Channels are separated into discrete chunks of memory.
504 ///
505 /// Format: `[[ch0, ch0, ch0, ...], [ch1, ch1, ch1, ...]]`
506 ///
507 /// Useful for operations that work on one channel at a time.
508 Planar,
509
510 /// All samples from one channel appear consecutively before the next channel.
511 ///
512 /// Format: `[ch0, ch0, ch0, ..., ch1, ch1, ch1, ...]`
513 ///
514 /// Note: Unlike `Planar`, this uses a single contiguous buffer rather than separate buffers per channel.
515 Sequential,
516}
517
518/// Represents a sample type that can be stored and processed in audio blocks.
519///
520/// This trait is automatically implemented for any type that meets the following requirements:
521/// - `Copy`: The type can be copied by value efficiently
522/// - `Zero`: The type has a zero value
523/// - `'static`: The type doesn't contain any non-static references
524///
525/// All numeric types (f32, f64, i16, i32, etc.) automatically implement this trait,
526/// as well as any custom types that satisfy these bounds.
527pub trait Sample: Copy + 'static {}
528impl<T> Sample for T where T: Copy + 'static {}
529
530/// Core trait for audio data access operations across various memory layouts.
531///
532/// [`AudioBlock`] provides a unified interface for interacting with audio data regardless of its
533/// underlying memory representation ([`BlockLayout::Interleaved`], [`BlockLayout::Sequential`], or [`BlockLayout::Planar`]). It supports operations
534/// on both owned audio blocks and temporary views.
535///
536/// # Usage
537///
538/// This trait gives you multiple ways to access audio data:
539/// - Direct sample access via indices
540/// - Channel and frame iterators for processing data streams
541/// - Raw data access for optimized operations
542/// - Layout information for specialized handling
543///
544/// # Example
545///
546/// ```
547/// use audio_blocks::AudioBlock;
548///
549/// fn example(audio: &impl AudioBlock<f32>) {
550/// // Get number of channels and frames
551/// let channels = audio.num_channels();
552/// let frames = audio.num_frames();
553///
554/// // Access individual samples
555/// let first_sample = audio.sample(0, 0);
556///
557/// // Process one channel
558/// for sample in audio.channel_iter(0) {
559/// // work with each sample
560/// }
561///
562/// // Process all channels
563/// for channel in audio.channels_iter() {
564/// for sample in channel {
565/// // work with each sample
566/// }
567/// }
568/// }
569/// ```
570pub trait AudioBlock<S: Sample> {
571 type PlanarView: AsRef<[S]>;
572
573 /// Returns the number of active audio channels.
574 fn num_channels(&self) -> u16;
575
576 /// Returns the number of audio frames (samples per channel).
577 fn num_frames(&self) -> usize;
578
579 /// Returns the total number of channels allocated in memory.
580 ///
581 /// This may be greater than `num_channels()` if the buffer has reserved capacity.
582 fn num_channels_allocated(&self) -> u16;
583
584 /// Returns the total number of frames allocated in memory.
585 ///
586 /// This may be greater than `num_frames()` if the buffer has reserved capacity.
587 fn num_frames_allocated(&self) -> usize;
588
589 /// Returns the memory layout of this audio block (interleaved, sequential, or planar).
590 fn layout(&self) -> BlockLayout;
591
592 /// Returns the sample value at the specified channel and frame position.
593 ///
594 /// # Panics
595 ///
596 /// Panics if channel or frame indices are out of bounds.
597 fn sample(&self, channel: u16, frame: usize) -> S;
598
599 /// Returns an iterator over all samples in the specified channel.
600 ///
601 /// # Panics
602 ///
603 /// Panics if channel index is out of bounds.
604 fn channel_iter(&self, channel: u16) -> impl ExactSizeIterator<Item = &S>;
605
606 /// Returns an iterator that yields an iterator for each channel.
607 fn channels_iter(&self) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &S>>;
608
609 /// Returns an iterator over all samples in the specified frame (across all channels).
610 ///
611 /// # Panics
612 ///
613 /// Panics if frame index is out of bounds.
614 fn frame_iter(&self, frame: usize) -> impl ExactSizeIterator<Item = &S>;
615
616 /// Returns an iterator that yields an iterator for each frame.
617 fn frames_iter(&self) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &S>>;
618
619 /// Creates a non-owning view of this audio block.
620 ///
621 /// This operation is real-time safe, as it returns a lightweight
622 /// wrapper around the original data.
623 fn as_view(&self) -> impl AudioBlock<S>;
624
625 /// Attempts to downcast this generic audio block to a concrete interleaved view.
626 /// This enables access to frame slices and the underlying raw data.
627 ///
628 /// Returns `Some` if the underlying data is stored in interleaved format,
629 /// otherwise returns `None`.
630 fn as_interleaved_view(&self) -> Option<InterleavedView<'_, S>> {
631 None
632 }
633
634 /// Attempts to downcast this generic audio block to a concrete planar view.
635 /// This enables access to frame slices and the underlying raw data.
636 ///
637 /// Returns `Some` if the underlying data is stored in planar format,
638 /// otherwise returns `None`.
639 fn as_planar_view(&self) -> Option<PlanarView<'_, S, Self::PlanarView>> {
640 None
641 }
642
643 /// Attempts to downcast this generic audio block to a concrete sequential view.
644 /// This enables access to frame slices and the underlying raw data.
645 ///
646 /// Returns `Some` if the underlying data is stored in sequential format,
647 /// otherwise returns `None`.
648 fn as_sequential_view(&self) -> Option<SequentialView<'_, S>> {
649 None
650 }
651}
652
653/// Extends the [`AudioBlock`] trait with mutable access operations.
654///
655/// [`AudioBlockMut`] provides methods for modifying audio data across different memory layouts.
656/// It enables in-place processing, buffer resizing, and direct mutable access to the underlying data.
657///
658/// # Usage
659///
660/// This trait gives you multiple ways to modify audio data:
661/// - Change individual samples at specific positions
662/// - Iterate through and modify channels or frames
663/// - Resize the buffer to accommodate different audio requirements
664/// - Access raw data for optimized processing
665///
666/// # Example
667///
668/// ```
669/// use audio_blocks::{AudioBlock, AudioBlockMut};
670///
671/// fn process_audio(audio: &mut impl AudioBlockMut<f32>) {
672/// // Resize to 2 channels, 1024 frames
673/// audio.set_visible(2, 1024);
674///
675/// // Modify individual samples
676/// *audio.sample_mut(0, 0) = 0.5;
677///
678/// // Process one channel with mutable access
679/// for sample in audio.channel_iter_mut(0) {
680/// *sample *= 0.8; // Apply gain reduction
681/// }
682///
683/// // Process all channels
684/// for mut channel in audio.channels_iter_mut() {
685/// for sample in channel {
686/// // Apply processing to each sample
687/// }
688/// }
689/// }
690/// ```
691pub trait AudioBlockMut<S: Sample>: AudioBlock<S> {
692 type PlanarViewMut: AsRef<[S]> + AsMut<[S]>;
693
694 /// Sets the visible size of the audio block to the specified number of channels and frames.
695 ///
696 /// # Panics
697 ///
698 /// When `num_channels` exceeds [`AudioBlock::num_channels_allocated`] or `num_frames` exceeds [`AudioBlock::num_frames_allocated`].
699 fn set_visible(&mut self, num_channels: u16, num_frames: usize) {
700 self.set_num_channels_visible(num_channels);
701 self.set_num_frames_visible(num_frames);
702 }
703
704 /// Sets the visible size of the audio block to the specified number of channels.
705 ///
706 /// This operation is real-time safe but only works up to [`AudioBlock::num_channels_allocated`].
707 ///
708 /// # Panics
709 ///
710 /// When `num_channels` exceeds [`AudioBlock::num_channels_allocated`].
711 fn set_num_channels_visible(&mut self, num_channels: u16);
712
713 /// Sets the visible size of the audio block to the specified number of frames.
714 ///
715 /// # Panics
716 ///
717 /// When `num_frames` exceeds [`AudioBlock::num_frames_allocated`].
718 fn set_num_frames_visible(&mut self, num_frames: usize);
719
720 /// Returns a mutable reference to the sample at the specified channel and frame position.
721 ///
722 /// # Panics
723 ///
724 /// Panics if channel or frame indices are out of bounds.
725 fn sample_mut(&mut self, channel: u16, frame: usize) -> &mut S;
726
727 /// Returns a mutable iterator over all samples in the specified channel.
728 ///
729 /// # Panics
730 ///
731 /// Panics if channel index is out of bounds.
732 fn channel_iter_mut(&mut self, channel: u16) -> impl ExactSizeIterator<Item = &mut S>;
733
734 /// Returns a mutable iterator that yields mutable iterators for each channel.
735 fn channels_iter_mut(
736 &mut self,
737 ) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &mut S>>;
738
739 /// Returns a mutable iterator over all samples in the specified frame (across all channels).
740 ///
741 /// # Panics
742 ///
743 /// Panics if frame index is out of bounds.
744 fn frame_iter_mut(&mut self, frame: usize) -> impl ExactSizeIterator<Item = &mut S>;
745
746 /// Returns a mutable iterator that yields mutable iterators for each frame.
747 fn frames_iter_mut(
748 &mut self,
749 ) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &mut S>>;
750
751 /// Creates a non-owning mutable view of this audio block.
752 ///
753 /// This operation is real-time safe, as it returns a lightweight
754 /// wrapper around the original data.
755 fn as_view_mut(&mut self) -> impl AudioBlockMut<S>;
756
757 /// Attempts to downcast this generic audio block to a concrete interleaved view.
758 /// This enables access to frame slices and the underlying raw data.
759 ///
760 /// Returns `Some` if the underlying data is stored in interleaved format,
761 /// otherwise returns `None`.
762 fn as_interleaved_view_mut(&mut self) -> Option<InterleavedViewMut<'_, S>> {
763 None
764 }
765
766 /// Attempts to downcast this generic audio block to a concrete planar view.
767 /// This enables access to frame slices and the underlying raw data.
768 ///
769 /// Returns `Some` if the underlying data is stored in planar format,
770 /// otherwise returns `None`.
771 fn as_planar_view_mut(&mut self) -> Option<PlanarViewMut<'_, S, Self::PlanarViewMut>> {
772 None
773 }
774
775 /// Attempts to downcast this generic audio block to a concrete sequential view.
776 /// This enables access to frame slices and the underlying raw data.
777 ///
778 /// Returns `Some` if the underlying data is stored in sequential format,
779 /// otherwise returns `None`.
780 fn as_sequential_view_mut(&mut self) -> Option<SequentialViewMut<'_, S>> {
781 None
782 }
783}