Skip to main content

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}