pub struct AudioFrame {
pub sample_rate: u32,
pub channels: u16,
pub samples: Arc<PooledFrameData<f32>>,
pub metadata: Option<PacketMetadata>,
}Expand description
A single frame or packet of raw audio data, using f32 as the internal standard.
Audio samples are stored in an Arc<PooledSamples> for efficient zero-copy cloning when packets
are distributed to multiple outputs (fan-out). This makes packet cloning extremely cheap
(just an atomic refcount increment) while still allowing mutation when needed via
copy-on-write semantics.
§Immutability by Default
AudioFrame follows an immutable-by-default design:
- Cloning is cheap (O(1) - just increments Arc refcount)
- Nodes can pass packets through without copying
- Nodes that need to modify samples use
make_samples_mut()for copy-on-write
§Example: Pass-through (zero-copy)
// Packet flows through pacer without any memory allocation
output_sender.send("out", packet).await?;§Example: Mutation (copy-on-write)
// Gain filter - copies only if Arc is shared, mutates in place if unique
if let Packet::Audio(mut frame) = packet {
for sample in frame.make_samples_mut() {
*sample *= gain;
}
output_sender.send("out", Packet::Audio(frame)).await?;
}Fields§
§sample_rate: u32§channels: u16§samples: Arc<PooledFrameData<f32>>The raw audio data, with samples interleaved for multi-channel audio (e.g., [L, R, L, R, …]). Stored in an Arc for efficient cloning.
metadata: Option<PacketMetadata>Optional timing metadata for pacing and synchronization
Implementations§
Source§impl AudioFrame
impl AudioFrame
Sourcepub fn from_pooled(
sample_rate: u32,
channels: u16,
samples: PooledFrameData<f32>,
metadata: Option<PacketMetadata>,
) -> AudioFrame
pub fn from_pooled( sample_rate: u32, channels: u16, samples: PooledFrameData<f32>, metadata: Option<PacketMetadata>, ) -> AudioFrame
Create a new AudioFrame from pooled storage (preferred for hot paths).
Sourcepub fn new(sample_rate: u32, channels: u16, samples: Vec<f32>) -> AudioFrame
pub fn new(sample_rate: u32, channels: u16, samples: Vec<f32>) -> AudioFrame
Create a new AudioFrame from a Vec of samples.
This is the preferred way to construct AudioFrame as it clearly wraps the samples in an Arc.
§Example
use streamkit_core::types::AudioFrame;
let samples = vec![0.5, -0.5, 0.3, -0.3]; // Stereo: L, R, L, R
let frame = AudioFrame::new(48000, 2, samples);
assert_eq!(frame.sample_rate, 48000);
assert_eq!(frame.channels, 2);Sourcepub fn with_metadata(
sample_rate: u32,
channels: u16,
samples: Vec<f32>,
metadata: Option<PacketMetadata>,
) -> AudioFrame
pub fn with_metadata( sample_rate: u32, channels: u16, samples: Vec<f32>, metadata: Option<PacketMetadata>, ) -> AudioFrame
Create a new AudioFrame with metadata.
§Example
use streamkit_core::types::{AudioFrame, PacketMetadata};
let metadata = PacketMetadata {
timestamp_us: Some(1000),
duration_us: Some(20_000),
sequence: Some(42),
};
let frame = AudioFrame::with_metadata(48000, 2, vec![0.5, -0.5], Some(metadata));
assert_eq!(frame.metadata.unwrap().sequence, Some(42));Sourcepub const fn from_arc(
sample_rate: u32,
channels: u16,
samples: Arc<PooledFrameData<f32>>,
metadata: Option<PacketMetadata>,
) -> AudioFrame
pub const fn from_arc( sample_rate: u32, channels: u16, samples: Arc<PooledFrameData<f32>>, metadata: Option<PacketMetadata>, ) -> AudioFrame
Create an AudioFrame from an already-Arc’d pooled buffer.
This is useful when you already have samples in an Arc and want to avoid any allocation or copying.
Sourcepub fn samples(&self) -> &[f32]
pub fn samples(&self) -> &[f32]
Get immutable access to samples as a slice (zero cost).
§Example
use streamkit_core::types::AudioFrame;
let frame = AudioFrame::new(48000, 2, vec![0.5, -0.3, 0.7, -0.1]);
let peak = frame.samples().iter().fold(0.0f32, |a, &b| a.max(b.abs()));
assert!((peak - 0.7).abs() < 0.001);Sourcepub fn make_samples_mut(&mut self) -> &mut [f32]
pub fn make_samples_mut(&mut self) -> &mut [f32]
Get mutable access to samples, cloning only if Arc is shared.
This implements copy-on-write semantics:
- If this is the only reference: mutates in place (zero cost)
- If shared with other clones: clones the data first (one copy)
§Example
use streamkit_core::types::AudioFrame;
let mut frame = AudioFrame::new(48000, 2, vec![0.5, -0.5, 0.25, -0.25]);
let gain = 2.0;
for sample in frame.make_samples_mut() {
*sample *= gain;
}
assert_eq!(frame.samples(), &[1.0, -1.0, 0.5, -0.5]);Sourcepub fn has_unique_samples(&self) -> bool
pub fn has_unique_samples(&self) -> bool
Check if we have exclusive ownership of the samples.
Returns true if this is the only Arc reference to the samples,
meaning make_samples_mut() will mutate in place without copying.
This is primarily useful for optimization hints and debugging.
§Example
use streamkit_core::types::AudioFrame;
let frame1 = AudioFrame::new(48000, 1, vec![0.5, 0.3]);
assert!(frame1.has_unique_samples()); // Only one owner
let frame2 = frame1.clone();
assert!(!frame1.has_unique_samples()); // Now shared
assert!(!frame2.has_unique_samples()); // Both share the ArcSourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Get the number of samples (total across all channels).
For stereo audio, this is twice the number of sample frames.
Sourcepub fn num_frames(&self) -> usize
pub fn num_frames(&self) -> usize
Get the number of sample frames (samples / channels).
For 960 stereo samples, this returns 480 frames.
Sourcepub fn duration_us(&self) -> Option<u64>
pub fn duration_us(&self) -> Option<u64>
Calculate the duration of this audio frame in microseconds.
Returns None if sample_rate is 0 (invalid).
Trait Implementations§
Source§impl Clone for AudioFrame
impl Clone for AudioFrame
Source§fn clone(&self) -> AudioFrame
fn clone(&self) -> AudioFrame
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more