pub struct Limit<I>(/* private fields */)
where
I: Source;
Expand description
A source filter that applies audio limiting to prevent peaks from exceeding a threshold.
This filter reduces the amplitude of audio signals that exceed the configured threshold level, helping to prevent clipping and maintain consistent output levels. The limiter automatically adapts to mono, stereo, or multi-channel audio sources by using the appropriate internal implementation.
§How It Works
The limiter detects peaks in each audio channel independently but applies gain reduction uniformly across all channels. This preserves stereo imaging while ensuring that loud peaks in any channel are controlled. The limiting uses:
- Soft-knee compression: Gradual gain reduction around the threshold
- Attack/release timing: Configurable response speed to level changes
- Peak detection: Tracks maximum levels across all channels
- Gain smoothing: Prevents audible artifacts from rapid gain changes
§Created By
Use Source::limit()
with LimitSettings
to create a Limit
source:
use rodio::source::{SineWave, Source};
use rodio::source::LimitSettings;
use std::time::Duration;
let source = SineWave::new(440.0).amplify(2.0);
let settings = LimitSettings::default()
.with_threshold(-6.0) // -6 dBFS threshold
.with_attack(Duration::from_millis(5))
.with_release(Duration::from_millis(100));
let limited = source.limit(settings);
§Performance
The limiter automatically selects the most efficient implementation based on channel count:
- Mono: Single-channel optimized processing
- Stereo: Two-channel optimized with interleaved processing
- Multi-channel: Generic implementation for 3+ channels
§Channel Count Stability
Important: The limiter is optimized for sources with fixed channel counts. Most audio files (music, podcasts, etc.) maintain constant channel counts, making this optimization safe and beneficial.
If the underlying source changes channel count mid-stream (rare), the limiter will continue to function but performance may be degraded. For such cases, recreate the limiter when the channel count changes.
§Type Parameters
I
- The input audio source type that implementsSource
Implementations§
Source§impl<I> Limit<I>where
I: Source,
impl<I> Limit<I>where
I: Source,
Sourcepub fn inner(&self) -> &I
pub fn inner(&self) -> &I
Returns a reference to the inner audio source.
This allows access to the original source’s properties and methods without consuming the limiter. Useful for inspecting source characteristics like sample rate, channels, or duration.
Useful for inspecting source properties without consuming the filter.
Sourcepub fn inner_mut(&mut self) -> &mut I
pub fn inner_mut(&mut self) -> &mut I
Returns a mutable reference to the inner audio source.
This allows modification of the original source while keeping the limiter wrapper. Essential for operations like seeking that need to modify the underlying source.
Sourcepub fn into_inner(self) -> I
pub fn into_inner(self) -> I
Consumes the limiter and returns the inner audio source.
This dismantles the limiter wrapper to extract the original source, allowing the audio pipeline to continue without limiting overhead. Useful when limiting is no longer needed but the source should continue.
Trait Implementations§
Source§impl<I> Iterator for Limit<I>where
I: Source,
impl<I> Iterator for Limit<I>where
I: Source,
Source§fn next_chunk<const N: usize>(
&mut self,
) -> Result<[Self::Item; N], IntoIter<Self::Item, N>>where
Self: Sized,
fn next_chunk<const N: usize>(
&mut self,
) -> Result<[Self::Item; N], IntoIter<Self::Item, N>>where
Self: Sized,
iter_next_chunk
)N
values. Read more1.0.0 · Source§fn count(self) -> usizewhere
Self: Sized,
fn count(self) -> usizewhere
Self: Sized,
1.0.0 · Source§fn last(self) -> Option<Self::Item>where
Self: Sized,
fn last(self) -> Option<Self::Item>where
Self: Sized,
Source§fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>>
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>>
iter_advance_by
)n
elements. Read more1.0.0 · Source§fn nth(&mut self, n: usize) -> Option<Self::Item>
fn nth(&mut self, n: usize) -> Option<Self::Item>
n
th element of the iterator. Read more1.28.0 · Source§fn step_by(self, step: usize) -> StepBy<Self>where
Self: Sized,
fn step_by(self, step: usize) -> StepBy<Self>where
Self: Sized,
1.0.0 · Source§fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter>
fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter>
1.0.0 · Source§fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter>where
Self: Sized,
U: IntoIterator,
fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter>where
Self: Sized,
U: IntoIterator,
Source§fn intersperse(self, separator: Self::Item) -> Intersperse<Self>
fn intersperse(self, separator: Self::Item) -> Intersperse<Self>
iter_intersperse
)separator
between adjacent
items of the original iterator. Read moreSource§fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>
fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>
iter_intersperse
)separator
between adjacent items of the original iterator. Read more1.0.0 · Source§fn map<B, F>(self, f: F) -> Map<Self, F>
fn map<B, F>(self, f: F) -> Map<Self, F>
1.0.0 · Source§fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ
fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ
1.0.0 · Source§fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
1.0.0 · Source§fn enumerate(self) -> Enumerate<Self>where
Self: Sized,
fn enumerate(self) -> Enumerate<Self>where
Self: Sized,
1.0.0 · Source§fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
1.0.0 · Source§fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
1.57.0 · Source§fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
1.0.0 · Source§fn skip(self, n: usize) -> Skip<Self>where
Self: Sized,
fn skip(self, n: usize) -> Skip<Self>where
Self: Sized,
n
elements. Read more1.0.0 · Source§fn take(self, n: usize) -> Take<Self>where
Self: Sized,
fn take(self, n: usize) -> Take<Self>where
Self: Sized,
n
elements, or fewer
if the underlying iterator ends sooner. Read more1.0.0 · Source§fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
1.29.0 · Source§fn flatten(self) -> Flatten<Self>
fn flatten(self) -> Flatten<Self>
Source§fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N>
fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N>
iter_map_windows
)f
for each contiguous window of size N
over
self
and returns an iterator over the outputs of f
. Like slice::windows()
,
the windows during mapping overlap as well. Read more1.0.0 · Source§fn inspect<F>(self, f: F) -> Inspect<Self, F>
fn inspect<F>(self, f: F) -> Inspect<Self, F>
1.0.0 · Source§fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
Iterator
. Read moreSource§fn try_collect<B>(
&mut self,
) -> <<Self::Item as Try>::Residual as Residual<B>>::TryType
fn try_collect<B>( &mut self, ) -> <<Self::Item as Try>::Residual as Residual<B>>::TryType
iterator_try_collect
)Source§fn collect_into<E>(self, collection: &mut E) -> &mut E
fn collect_into<E>(self, collection: &mut E) -> &mut E
iter_collect_into
)1.0.0 · Source§fn partition<B, F>(self, f: F) -> (B, B)
fn partition<B, F>(self, f: F) -> (B, B)
Source§fn is_partitioned<P>(self, predicate: P) -> bool
fn is_partitioned<P>(self, predicate: P) -> bool
iter_is_partitioned
)true
precede all those that return false
. Read more1.27.0 · Source§fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
1.27.0 · Source§fn try_for_each<F, R>(&mut self, f: F) -> R
fn try_for_each<F, R>(&mut self, f: F) -> R
1.0.0 · Source§fn fold<B, F>(self, init: B, f: F) -> B
fn fold<B, F>(self, init: B, f: F) -> B
1.51.0 · Source§fn reduce<F>(self, f: F) -> Option<Self::Item>
fn reduce<F>(self, f: F) -> Option<Self::Item>
Source§fn try_reduce<R>(
&mut self,
f: impl FnMut(Self::Item, Self::Item) -> R,
) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType
fn try_reduce<R>( &mut self, f: impl FnMut(Self::Item, Self::Item) -> R, ) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType
iterator_try_reduce
)1.0.0 · Source§fn all<F>(&mut self, f: F) -> bool
fn all<F>(&mut self, f: F) -> bool
1.0.0 · Source§fn any<F>(&mut self, f: F) -> bool
fn any<F>(&mut self, f: F) -> bool
1.0.0 · Source§fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
1.30.0 · Source§fn find_map<B, F>(&mut self, f: F) -> Option<B>
fn find_map<B, F>(&mut self, f: F) -> Option<B>
Source§fn try_find<R>(
&mut self,
f: impl FnMut(&Self::Item) -> R,
) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType
fn try_find<R>( &mut self, f: impl FnMut(&Self::Item) -> R, ) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType
try_find
)1.0.0 · Source§fn position<P>(&mut self, predicate: P) -> Option<usize>
fn position<P>(&mut self, predicate: P) -> Option<usize>
1.0.0 · Source§fn max(self) -> Option<Self::Item>
fn max(self) -> Option<Self::Item>
1.0.0 · Source§fn min(self) -> Option<Self::Item>
fn min(self) -> Option<Self::Item>
1.6.0 · Source§fn max_by_key<B, F>(self, f: F) -> Option<Self::Item>
fn max_by_key<B, F>(self, f: F) -> Option<Self::Item>
1.15.0 · Source§fn max_by<F>(self, compare: F) -> Option<Self::Item>
fn max_by<F>(self, compare: F) -> Option<Self::Item>
1.6.0 · Source§fn min_by_key<B, F>(self, f: F) -> Option<Self::Item>
fn min_by_key<B, F>(self, f: F) -> Option<Self::Item>
1.15.0 · Source§fn min_by<F>(self, compare: F) -> Option<Self::Item>
fn min_by<F>(self, compare: F) -> Option<Self::Item>
1.0.0 · Source§fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
1.36.0 · Source§fn copied<'a, T>(self) -> Copied<Self>
fn copied<'a, T>(self) -> Copied<Self>
Source§fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N>where
Self: Sized,
fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N>where
Self: Sized,
iter_array_chunks
)N
elements of the iterator at a time. Read more1.11.0 · Source§fn product<P>(self) -> P
fn product<P>(self) -> P
Source§fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering
fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering
iter_order_by
)Iterator
with those
of another with respect to the specified comparison function. Read more1.5.0 · Source§fn partial_cmp<I>(self, other: I) -> Option<Ordering>
fn partial_cmp<I>(self, other: I) -> Option<Ordering>
PartialOrd
elements of
this Iterator
with those of another. The comparison works like short-circuit
evaluation, returning a result without comparing the remaining elements.
As soon as an order can be determined, the evaluation stops and a result is returned. Read moreSource§fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering>where
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>,
fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering>where
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>,
iter_order_by
)Iterator
with those
of another with respect to the specified comparison function. Read moreSource§fn eq_by<I, F>(self, other: I, eq: F) -> bool
fn eq_by<I, F>(self, other: I, eq: F) -> bool
iter_order_by
)1.5.0 · Source§fn lt<I>(self, other: I) -> bool
fn lt<I>(self, other: I) -> bool
Iterator
are lexicographically
less than those of another. Read more1.5.0 · Source§fn le<I>(self, other: I) -> bool
fn le<I>(self, other: I) -> bool
Iterator
are lexicographically
less or equal to those of another. Read more1.5.0 · Source§fn gt<I>(self, other: I) -> bool
fn gt<I>(self, other: I) -> bool
Iterator
are lexicographically
greater than those of another. Read more1.5.0 · Source§fn ge<I>(self, other: I) -> bool
fn ge<I>(self, other: I) -> bool
Iterator
are lexicographically
greater than or equal to those of another. Read more1.82.0 · Source§fn is_sorted(self) -> bool
fn is_sorted(self) -> bool
1.82.0 · Source§fn is_sorted_by<F>(self, compare: F) -> bool
fn is_sorted_by<F>(self, compare: F) -> bool
1.82.0 · Source§fn is_sorted_by_key<F, K>(self, f: F) -> bool
fn is_sorted_by_key<F, K>(self, f: F) -> bool
Source§impl<I> Source for Limit<I>where
I: Source,
impl<I> Source for Limit<I>where
I: Source,
Source§fn current_span_len(&self) -> Option<usize>
fn current_span_len(&self) -> Option<usize>
None
means “infinite” or
“until the sound ends”.
Should never return 0 unless there’s no more data. Read moreSource§fn sample_rate(&self) -> SampleRate
fn sample_rate(&self) -> SampleRate
Source§fn channels(&self) -> ChannelCount
fn channels(&self) -> ChannelCount
Source§fn total_duration(&self) -> Option<Duration>
fn total_duration(&self) -> Option<Duration>
Source§fn try_seek(&mut self, position: Duration) -> Result<(), SeekError>
fn try_seek(&mut self, position: Duration) -> Result<(), SeekError>
Source§fn buffered(self) -> Buffered<Self> ⓘwhere
Self: Sized,
fn buffered(self) -> Buffered<Self> ⓘwhere
Self: Sized,
Source§fn repeat_infinite(self) -> Repeat<Self> ⓘwhere
Self: Sized,
fn repeat_infinite(self) -> Repeat<Self> ⓘwhere
Self: Sized,
Source§fn take_duration(self, duration: Duration) -> TakeDuration<Self> ⓘwhere
Self: Sized,
fn take_duration(self, duration: Duration) -> TakeDuration<Self> ⓘwhere
Self: Sized,
Source§fn delay(self, duration: Duration) -> Delay<Self> ⓘwhere
Self: Sized,
fn delay(self, duration: Duration) -> Delay<Self> ⓘwhere
Self: Sized,
Source§fn skip_duration(self, duration: Duration) -> SkipDuration<Self> ⓘwhere
Self: Sized,
fn skip_duration(self, duration: Duration) -> SkipDuration<Self> ⓘwhere
Self: Sized,
Source§fn amplify(self, value: f32) -> Amplify<Self> ⓘwhere
Self: Sized,
fn amplify(self, value: f32) -> Amplify<Self> ⓘwhere
Self: Sized,
Source§fn amplify_decibel(self, value: f32) -> Amplify<Self> ⓘwhere
Self: Sized,
fn amplify_decibel(self, value: f32) -> Amplify<Self> ⓘwhere
Self: Sized,
Source§fn amplify_normalized(self, value: f32) -> Amplify<Self> ⓘwhere
Self: Sized,
fn amplify_normalized(self, value: f32) -> Amplify<Self> ⓘwhere
Self: Sized,
[0.0, 1.0]
range. This method better matches the perceived
loudness of sounds in human hearing and is recommended to use when you want to change
volume in [0.0, 1.0]
range.
based on article: https://www.dr-lex.be/info-stuff/volumecontrols.html Read moreSource§fn automatic_gain_control(
self,
target_level: f32,
attack_time: f32,
release_time: f32,
absolute_max_gain: f32,
) -> AutomaticGainControl<Self> ⓘwhere
Self: Sized,
fn automatic_gain_control(
self,
target_level: f32,
attack_time: f32,
release_time: f32,
absolute_max_gain: f32,
) -> AutomaticGainControl<Self> ⓘwhere
Self: Sized,
Source§fn take_crossfade_with<S: Source>(
self,
other: S,
duration: Duration,
) -> Crossfade<Self, S>
fn take_crossfade_with<S: Source>( self, other: S, duration: Duration, ) -> Crossfade<Self, S>
Source§fn fade_out(self, duration: Duration) -> FadeOut<Self> ⓘwhere
Self: Sized,
fn fade_out(self, duration: Duration) -> FadeOut<Self> ⓘwhere
Self: Sized,
Source§fn limit(self, settings: LimitSettings) -> Limit<Self> ⓘwhere
Self: Sized,
fn limit(self, settings: LimitSettings) -> Limit<Self> ⓘwhere
Self: Sized,
Source§fn linear_gain_ramp(
self,
duration: Duration,
start_value: f32,
end_value: f32,
clamp_end: bool,
) -> LinearGainRamp<Self> ⓘwhere
Self: Sized,
fn linear_gain_ramp(
self,
duration: Duration,
start_value: f32,
end_value: f32,
clamp_end: bool,
) -> LinearGainRamp<Self> ⓘwhere
Self: Sized,
Source§fn periodic_access<F>(
self,
period: Duration,
access: F,
) -> PeriodicAccess<Self, F> ⓘ
fn periodic_access<F>( self, period: Duration, access: F, ) -> PeriodicAccess<Self, F> ⓘ
access
closure on Self
the first time the source is iterated and every
time period
elapses. Read moreSource§fn speed(self, ratio: f32) -> Speed<Self> ⓘwhere
Self: Sized,
fn speed(self, ratio: f32) -> Speed<Self> ⓘwhere
Self: Sized,
Source§fn reverb(
self,
duration: Duration,
amplitude: f32,
) -> Mix<Self, Delay<Amplify<Self>>> ⓘ
fn reverb( self, duration: Duration, amplitude: f32, ) -> Mix<Self, Delay<Amplify<Self>>> ⓘ
Source§fn pausable(self, initially_paused: bool) -> Pausable<Self> ⓘwhere
Self: Sized,
fn pausable(self, initially_paused: bool) -> Pausable<Self> ⓘwhere
Self: Sized,
Source§fn skippable(self) -> Skippable<Self> ⓘwhere
Self: Sized,
fn skippable(self) -> Skippable<Self> ⓘwhere
Self: Sized,
Skippable::skip
for skipping this source. Skipping
makes Source::next() return None. Which in turn makes the Sink skip to
the next source.