### Get Configured Channels Source: https://docs.rs/ebur128/latest/ebur128/struct.EbuR128.html?search=std%3A%3Avec Retrieves the configured number of audio channels. ```rust pub fn channels(&self) -> u32 ``` -------------------------------- ### Get Rate Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Retrieves the configured audio sample rate. ```APIDOC ## rate ### Description Gets the configured sample rate. ### Method `rate(&self) -> u32` ### Returns The sample rate. ``` -------------------------------- ### Get Configured Mode Source: https://docs.rs/ebur128/latest/ebur128/struct.EbuR128.html?search=std%3A%3Avec Retrieves the currently configured loudness analysis mode. ```rust pub fn mode(&self) -> Mode ``` -------------------------------- ### Get Configured Sample Rate Source: https://docs.rs/ebur128/latest/ebur128/struct.EbuR128.html?search=std%3A%3Avec Retrieves the configured audio sample rate. ```rust pub fn rate(&self) -> u32 ``` -------------------------------- ### Initialize C History Module Source: https://docs.rs/ebur128/latest/src/ebur128/history.rs.html?search= Ensures that the C-side history module is initialized exactly once using a `Once` static. This is a common pattern for one-time setup in Rust. ```rust use std::sync::Once; static START: Once = Once::new(); START.call_once(|| unsafe { history_init_c() }); ``` -------------------------------- ### Histogram Initialization Source: https://docs.rs/ebur128/latest/src/ebur128/history.rs.html?search= Creates a new, empty histogram with 1000 bins, all initialized to zero. This is the starting point for accumulating energy measurements. ```rust fn new() -> Self { Histogram(Box::new([0; 1000])) } ``` -------------------------------- ### TruePeak Initialization and Usage Source: https://docs.rs/ebur128/latest/src/ebur128/true_peak.rs.html Demonstrates how to create a TruePeak instance and use it to check for true peaks in audio data. This is useful for ensuring audio does not exceed digital clipping limits. ```rust impl TruePeak { pub fn new(rate: u32, channels: u32) -> Option { UpsamplingScanner::new(rate, channels).map(|interp| Self { interp }) } pub fn reset(&mut self) { self.interp.reset(); } pub fn check_true_peak<'a, T: Sample + 'a, S: crate::Samples<'a, T>>( &mut self, src: S, peaks: &mut [f64], ) { self.interp.check_true_peak(src, peaks) } pub fn seed<'a, T: Sample + 'a, S: crate::Samples<'a, T>>(&mut self, src: S) { let mut true_peaks: SmallVec<[f64; 16]> = smallvec![0.0; src.channels()]; self.interp.check_true_peak(src, &mut true_peaks) } } ``` -------------------------------- ### Get number of frames in Planar data Source: https://docs.rs/ebur128/latest/src/ebur128/utils.rs.html Returns the total number of frames available in the Planar data, calculated as the difference between the end and start indices. ```rust pub fn frames(&self) -> usize { self.end - self.start } ``` -------------------------------- ### Get Gating Block Count and Energy Source: https://docs.rs/ebur128/latest/src/ebur128/history.rs.html?search= A convenience function to get the gating block count and energy for a single history entry by calling the multiple version with a slice containing only self. ```rust pub fn gating_block_count_and_energy(&self) -> Result<(u64, f64), HistoryError> { Self::gating_block_count_and_energy_multiple(&[self]) } ``` -------------------------------- ### TruePeak Initialization and Usage Source: https://docs.rs/ebur128/latest/src/ebur128/true_peak.rs.html?search=u32+-%3E+bool Demonstrates how to create a TruePeak instance with a given sample rate and number of channels, and how to check for true peaks in audio data. The `seed` method is used to prime the interpolator. ```rust pub struct TruePeak { /// Interpolator/resampler. interp: UpsamplingScanner, } impl TruePeak { pub fn new(rate: u32, channels: u32) -> Option { UpsamplingScanner::new(rate, channels).map(|interp| Self { interp }) } pub fn reset(&mut self) { self.interp.reset(); } pub fn check_true_peak<'a, T: Sample + 'a, S: crate::Samples<'a, T>>( &mut self, src: S, peaks: &mut [f64], ) { self.interp.check_true_peak(src, peaks) } pub fn seed<'a, T: Sample + 'a, S: crate::Samples<'a, T>>(&mut self, src: S) { let mut true_peaks: SmallVec<[f64; 16]> = smallvec![0.0; src.channels()]; self.interp.check_true_peak(src, &mut true_peaks) } } ``` -------------------------------- ### Get Channel Map Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Retrieves the configured channel mapping. ```APIDOC ## channel_map ### Description Gets the configured channel map. ### Method `channel_map(&self) -> &[Channel]` ### Returns A slice representing the channel map. ``` -------------------------------- ### EbuR128 Initialization and Basic Measurements (f32) Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html Demonstrates initializing EbuR128 for stereo audio with f32 sample data and performing basic loudness measurements after processing. ```rust let mut data = vec![0.0f32; 48_000 * 5 * 2]; let mut accumulator = 0.0; let step = 2.0 * std::f32::consts::PI * 440.0 / 48_000.0; for out in data.chunks_exact_mut(2) { let val = f32::sin(accumulator); out[0] = val; out[1] = val; accumulator += step; } let mut ebu = EbuR128::new(2, 48_000, Mode::all()).unwrap(); ebu.add_frames_f32(&data).unwrap(); assert_float_eq!( ebu.loudness_global().unwrap(), -0.6500000000000054, abs <= 0.000001 ); ``` -------------------------------- ### C API: Create TruePeak instance Source: https://docs.rs/ebur128/latest/src/ebur128/true_peak.rs.html?search=std%3A%3Avec Creates a C-compatible TruePeak instance. Requires a sample rate and number of channels. Returns a raw pointer to the created instance. ```rust #[cfg(feature = "c-tests")] extern "C" { pub fn true_peak_create_c(rate: u32, channels: u32) -> *mut c_void; } ``` -------------------------------- ### Compare Rust and C Relative Threshold Implementations Source: https://docs.rs/ebur128/latest/src/ebur128/history.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E This `quickcheck` test compares the `relative_threshold` calculation between the Rust implementation and its C-compatible counterpart. The snippet is truncated, showing only the setup phase. ```Rust #[quickcheck] fn compare_c_impl_relative_threshold( energy: Vec, use_histogram: bool, max: NonZeroU16, ) -> Result<(), String> { init(); let mut hist = History::new(use_histogram, max.get() as usize); for e in &energy { hist.add(e.0); } let val = hist.relative_threshold(); let val_c = unsafe { let hist_c = history_create_c(i32::from(use_histogram), max.get() as usize); for e in &energy { ``` -------------------------------- ### Get Mode Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Retrieves the configured operating mode of the Ebur128 instance. ```APIDOC ## mode ### Description Gets the configured mode. ### Method `mode(&self) -> Mode` ### Returns The current `Mode` setting. ``` -------------------------------- ### prev_sample_peak Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search= Get the maximum sample peak from the last call to add_frames. ```APIDOC ## prev_sample_peak ### Description Retrieves the maximum sample peak value for a specified channel that occurred during the most recent call to `add_frames`. The value is typically converted to dBFS using the formula: 20 * log10(peak_value). ### Method `get` ### Endpoint `/peak/previous_sample/{channel_number}` ### Parameters #### Path Parameters - **channel_number** (u32) - Required - The index of the channel for which to retrieve the previous sample peak. ### Returns - `f64`: The maximum sample peak from the last frame addition for the specified channel. Returns an error if the SAMPLE_PEAK mode is not enabled or the channel index is invalid. ``` -------------------------------- ### Initialize C Test Environment with `Once` Source: https://docs.rs/ebur128/latest/src/ebur128/history.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E This snippet provides an `init` function that uses `std::sync::Once` to ensure a C-side initialization function (`history_init_c`) is called exactly once, typically for setting up test fixtures. ```Rust fn init() { use std::sync::Once; static START: Once = Once::new(); START.call_once(|| unsafe { history_init_c() }); } ``` -------------------------------- ### Sample trait implementation for i32 Source: https://docs.rs/ebur128/latest/src/ebur128/utils.rs.html Provides the `Sample` trait implementation for `i32`, defining its maximum amplitude based on `i32::MIN` and a raw conversion to `f64`. ```rust impl Sample for i32 { const MAX_AMPLITUDE: f64 = -(Self::MIN as f64); #[inline(always)] fn as_f64_raw(self) -> f64 { self as f64 } } ``` -------------------------------- ### Getting number of channels Source: https://docs.rs/ebur128/latest/src/ebur128/utils.rs.html?search=std%3A%3Avec Returns the number of channels in the planar data. ```rust #[inline] fn channels(&self) -> usize { self.data.len() } ``` -------------------------------- ### Test Case: Comparing Rust and C Interpolation Implementations Source: https://docs.rs/ebur128/latest/src/ebur128/interp.rs.html?search= This test case compares the output of the Rust and C interpolation implementations using QuickCheck. It generates a signal, processes it with both implementations, and asserts that the results are approximately equal. ```rust #[quickcheck] fn compare_c_impl(signal: Signal) -> quickcheck::TestResult { let frames = signal.data.len() / signal.channels as usize; let factor = if signal.rate < 96_000 { 4 } else if signal.rate < 192_000 { 2 } else { return quickcheck::TestResult::discard(); }; let mut data_out = vec![0.0f32; signal.data.len() * factor]; let mut data_out_c = vec![0.0f32; signal.data.len() * factor]; process_rust( &signal.data, &mut data_out, factor, signal.channels as usize, ); unsafe { let interp = interp_create_c(49, factor as u32, signal.channels); interp_process_c( interp, frames, signal.data.as_ptr(), data_out_c.as_mut_ptr(), ); interp_destroy_c(interp); } for (i, (r, c)) in data_out.iter().zip(data_out_c.iter()).enumerate() { assert_float_eq!( *r, *c, // For a performance-boost, filter is defined as f32, causing slightly lower precision abs <= 0.000004, "Rust and C implementation differ at sample {}", i ); } quickcheck::TestResult::passed() } ``` -------------------------------- ### Get Mode Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search= Retrieves the current operating mode of the loudness measurement. ```APIDOC ## mode ### Description Get the configured mode. ### Method `mode()` ### Returns - `Mode`: The current operating mode. ``` -------------------------------- ### Rust Test: Comparing C and Rust Implementations for i16 Source: https://docs.rs/ebur128/latest/src/ebur128/true_peak.rs.html?search=u32+-%3E+bool This quickcheck test compares the results of the C implementation of true peak checking against the Rust implementation for i16 audio samples. It discards tests with very high sample rates to avoid excessive test duration. ```rust #[quickcheck] fn compare_c_impl_i16(signal: Signal) -> quickcheck::TestResult { if signal.rate >= 192_000 { return quickcheck::TestResult::discard(); } // Maximum of 400ms but our input is up to 5000ms, so distribute it evenly // by shrinking accordingly. let len = signal.data.len() / signal.channels as usize; let len = std::cmp::min(2 * len / 25, 4 * ((signal.rate as usize + 5) / 10)); let mut peaks = vec![0.0f64; signal.channels as usize]; let mut peaks_c = vec![0.0f64; signal.channels as usize]; { let mut tp = TruePeak::new(signal.rate, signal.channels).unwrap(); tp.check_true_peak( crate::Interleaved::new( &signal.data[0..(len * signal.channels as usize)], signal.channels as usize, ) .unwrap(), &mut peaks, ); } } ``` -------------------------------- ### Verify Loudness Metrics with i32 Audio Data Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search=u32+-%3E+bool This snippet demonstrates how to process stereo i32 audio data and assert various loudness metrics, including global, momentary, short-term, windowed loudness, and loudness range. It also verifies sample and true peak values. ```rust let mut data = vec![0i32; 48_000 * 5 * 2]; let mut accumulator = 0.0; let step = 2.0 * std::f32::consts::PI * 440.0 / 48_000.0; for out in data.chunks_exact_mut(2) { let val = f32::sin(accumulator) * (i32::MAX - 1) as f32; out[0] = val as i32; out[1] = val as i32; accumulator += step; } let mut ebu = EbuR128::new(2, 48_000, Mode::all()).unwrap(); ebu.add_frames_i32(&data).unwrap(); assert_float_eq!( ebu.loudness_global().unwrap(), -0.6500000000000054, abs <= 0.000001 ); assert_float_eq!( ebu.loudness_momentary().unwrap(), -0.6813325598274425, abs <= 0.000001 ); assert_float_eq!( ebu.loudness_shortterm().unwrap(), -0.6827591715105212, abs <= 0.000001 ); assert_float_eq!( ebu.loudness_window(1).unwrap(), -0.8742956620040943, abs <= 0.000001 ); assert_float_eq!(ebu.loudness_range().unwrap(), 0.0, abs <= 0.000001); assert_float_eq!(ebu.sample_peak(0).unwrap(), 1.0, abs <= 0.000001); assert_float_eq!(ebu.sample_peak(1).unwrap(), 1.0, abs <= 0.000001); assert_float_eq!(ebu.prev_sample_peak(0).unwrap(), 1.0, abs <= 0.000001); assert_float_eq!(ebu.prev_sample_peak(1).unwrap(), 1.0, abs <= 0.000001); assert_float_eq!( ebu.true_peak(0).unwrap(), 1.0008491277694702, abs <= 0.000001 ); assert_float_eq!( ebu.true_peak(1).unwrap(), 1.0008491277694702, abs <= 0.000001 ); assert_float_eq!( ebu.prev_true_peak(0).unwrap(), 1.0008491277694702, abs <= 0.000001 ); assert_float_eq!( ebu.prev_true_peak(1).unwrap(), 1.0008491277694702, abs <= 0.000001 ); assert_float_eq!( ebu.relative_threshold().unwrap(), -10.650000000000006, abs <= 0.000001 ); } ``` -------------------------------- ### Get Max History Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Retrieves the configured maximum history duration in milliseconds. ```APIDOC ## max_history ### Description Gets the configured maximum history in milliseconds. ### Method `max_history(&self) -> usize` ### Returns The maximum history duration in milliseconds. ``` -------------------------------- ### Initialize Ebur128 with Default Parameters Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search=std%3A%3Avec Creates a new Ebur128 instance with default settings for audio processing. This is the primary constructor for the library. ```rust pub fn new(mode: Mode, rate: u32, channels: u32) -> Result { let sample_peak = vec![0.0; channels as usize]; let true_peak = vec![0.0; channels as usize]; let history = usize::MAX; let samples_in_100ms = (rate as usize + 5) / 10; let window = if mode.contains(Mode::S) { 3000 } else if mode.contains(Mode::M) { 400 } else { return Err(Error::InvalidMode); }; let audio_data = Self::allocate_audio_data(channels, rate, window)?; // start at the beginning of the buffer let audio_data_index = 0; let block_energy_history = crate::history::History::new(mode.contains(Mode::HISTOGRAM), history / 100); let short_term_block_energy_history = crate::history::History::new(mode.contains(Mode::HISTOGRAM), history / 3000); let short_term_frame_counter = 0; let filter = crate::filter::Filter::new( rate, channels, mode.contains(Mode::SAMPLE_PEAK), mode.contains(Mode::TRUE_PEAK), ); let channel_map = default_channel_map(channels); // the first block needs 400ms of audio data let needed_frames = samples_in_100ms * 4; Ok(Self { mode, rate, channels, audio_data, audio_data_index, needed_frames, channel_map: channel_map.into_boxed_slice(), samples_in_100ms, filter, block_energy_history, short_term_block_energy_history, short_term_frame_counter, sample_peak: sample_peak.into_boxed_slice(), true_peak: true_peak.into_boxed_slice(), window, history, }) } ``` -------------------------------- ### Get Max Window Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Retrieves the configured maximum window duration in milliseconds. ```APIDOC ## max_window ### Description Gets the configured maximum window duration in milliseconds. ### Method `max_window(&self) -> usize` ### Returns The maximum window duration in milliseconds. ``` -------------------------------- ### true_peak Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search= Get the maximum true peak for a specific channel from all processed frames. ```APIDOC ## true_peak ### Description Retrieves the maximum true peak value for a specified channel across all frames processed by the EBU R128 instance. The true peak is calculated using an implementation-defined algorithm (e.g., polyphase FIR interpolator) and converted to dBTP using the formula: 20 * log10(true_peak_value). ### Method `get` ### Endpoint `/peak/true/{channel_number}` ### Parameters #### Path Parameters - **channel_number** (u32) - Required - The index of the channel for which to retrieve the true peak. ### Returns - `f64`: The maximum true peak for the specified channel. Returns an error if the TRUE_PEAK mode is not enabled or the channel index is invalid. ``` -------------------------------- ### TruePeak::new Source: https://docs.rs/ebur128/latest/src/ebur128/true_peak.rs.html?search= Creates a new TruePeak instance. It initializes the internal UpsamplingScanner with the specified sample rate and number of channels. ```APIDOC ## Method TruePeak::new ### Description Creates a new TruePeak instance. It initializes the internal UpsamplingScanner with the specified sample rate and number of channels. ### Signature `pub fn new(rate: u32, channels: u32) -> Option` ### Parameters * `rate` (u32) - The sample rate of the audio signal. * `channels` (u32) - The number of audio channels. ### Returns * `Option` - Returns `Some(TruePeak)` if initialization is successful, otherwise `None`. ``` -------------------------------- ### sample_peak Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search= Get the maximum sample peak for a specific channel from all processed frames. ```APIDOC ## sample_peak ### Description Retrieves the maximum sample peak value for a specified channel across all frames processed by the EBU R128 instance. The value is typically converted to dBFS using the formula: 20 * log10(peak_value). ### Method `get` ### Endpoint `/peak/sample/{channel_number}` ### Parameters #### Path Parameters - **channel_number** (u32) - Required - The index of the channel for which to retrieve the sample peak. ### Returns - `f64`: The maximum sample peak for the specified channel. Returns an error if the SAMPLE_PEAK mode is not enabled or the channel index is invalid. ``` -------------------------------- ### Compare Rust and C Gated Loudness Implementations Source: https://docs.rs/ebur128/latest/src/ebur128/history.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E This `quickcheck` test compares the `gated_loudness` calculation between the Rust implementation and its C-compatible counterpart, asserting their floating-point equality within a small tolerance. ```Rust #[quickcheck] fn compare_c_impl_gated_loudness( energy: Vec, use_histogram: bool, max: NonZeroU16, ) -> Result<(), String> { init(); let mut hist = History::new(use_histogram, max.get() as usize); for e in &energy { hist.add(e.0); } let val = hist.gated_loudness(); let val_c = unsafe { let hist_c = history_create_c(i32::from(use_histogram), max.get() as usize); for e in &energy { history_add_c(hist_c, e.0); } let val = history_gated_loudness_c(hist_c); history_destroy_c(hist_c); val }; if !float_eq!(val, val_c, ulps <= 2) { Err(format!("{val} != {val_c}")) } else { Ok(()) } } ``` -------------------------------- ### Sample trait implementation for i16 Source: https://docs.rs/ebur128/latest/src/ebur128/utils.rs.html Provides the `Sample` trait implementation for `i16`, defining its maximum amplitude based on `i16::MIN` and a raw conversion to `f64`. ```rust impl Sample for i16 { const MAX_AMPLITUDE: f64 = -(Self::MIN as f64); #[inline(always)] fn as_f64_raw(self) -> f64 { self as f64 } } ``` -------------------------------- ### loudness_window Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search= Get the loudness of a specified window in LUFS. The window size is in seconds. ```APIDOC ## loudness_window ### Description Calculates and returns the loudness for a specified time window in LUFS. The window size cannot exceed the maximum window size set for the instance. ### Method `get` ### Endpoint `/loudness/window/{window_seconds}` ### Parameters #### Path Parameters - **window_seconds** (u32) - Required - The duration of the window in seconds for which to calculate loudness. ``` -------------------------------- ### Sample trait implementation for f64 Source: https://docs.rs/ebur128/latest/src/ebur128/utils.rs.html Provides the `Sample` trait implementation for `f64`, defining its maximum amplitude and a raw conversion to `f64`. ```rust impl Sample for f64 { const MAX_AMPLITUDE: f64 = 1.0; #[inline(always)] fn as_f64_raw(self) -> f64 { self } } ``` -------------------------------- ### loudness_momentary Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search= Get the momentary loudness, which is the loudness of the last 400ms of audio, in LUFS. ```APIDOC ## loudness_momentary ### Description Calculates and returns the momentary loudness of the audio processed so far, specifically the last 400 milliseconds, in LUFS. ### Method `get` ### Endpoint `/loudness/momentary` ### Returns - `f64`: The momentary loudness in LUFS. Returns -infinity if the energy is non-positive. ``` -------------------------------- ### loudness_global Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html Gets the global integrated loudness in LUFS. Requires the 'I' mode to be enabled. ```APIDOC ## loudness_global ### Description Gets the global integrated loudness in LUFS. Requires the 'I' mode to be enabled. ### Method `pub fn loudness_global(&self) -> Result` ### Response #### Success Response (200) * `f64`: The global integrated loudness in LUFS. ``` -------------------------------- ### Sample trait implementation for f32 Source: https://docs.rs/ebur128/latest/src/ebur128/utils.rs.html Provides the `Sample` trait implementation for `f32`, defining its maximum amplitude and a raw conversion to `f64`. ```rust impl Sample for f32 { const MAX_AMPLITUDE: f64 = 1.0; #[inline(always)] fn as_f64_raw(self) -> f64 { self as f64 } } ``` -------------------------------- ### Get Channels Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search= Retrieves the number of audio channels the library is configured to process. ```APIDOC ## channels ### Description Get the configured number of channels. ### Method `channels()` ### Returns - `u32`: The number of audio channels. ``` -------------------------------- ### EbuR128 Configuration and Initialization Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search=u32+-%3E+bool This snippet shows the internal logic for allocating audio data and updating channel-specific parameters when the audio configuration changes. It ensures that internal buffers and settings are correctly adjusted based on the new channel count and sample rate. ```rust self.audio_data = Self::allocate_audio_data(channels, rate, self.window)?; if self.channels != channels { self.channels = channels; self.channel_map = default_channel_map(channels).into_boxed_slice(); self.sample_peak = vec![0.0; channels as usize].into_boxed_slice(); self.true_peak = vec![0.0; channels as usize].into_boxed_slice(); } if self.rate != rate { self.rate = rate; self.samples_in_100ms = (rate as usize + 5) / 10; } self.filter = crate::filter::Filter::new( rate, channels, self.mode.contains(Mode::SAMPLE_PEAK), self.mode.contains(Mode::TRUE_PEAK), ); // the first block needs 400ms of audio data self.needed_frames = self.samples_in_100ms * 4; // start at the beginning of the buffer self.audio_data_index = 0; // reset short term frame counter self.short_term_frame_counter = 0; Ok(()) } ``` -------------------------------- ### Calculate Loudness Metrics for Planar i32 Audio Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search=u32+-%3E+bool This snippet shows how to generate a sine wave, process it using planar i32 data with EbuR128, and verify loudness measurements. It's similar to the i16 example but uses 32-bit integers for audio samples. ```rust let mut data = vec![0i32; 48_000 * 5 * 2]; let mut accumulator = 0.0; let step = 2.0 * std::f32::consts::PI * 440.0 / 48_000.0; let (fst, snd) = data.split_at_mut(48_000 * 5); for (fst, snd) in Iterator::zip(fst.iter_mut(), snd.iter_mut()) { let val = f32::sin(accumulator) * (i32::MAX - 1) as f32; *fst = val as i32; *snd = val as i32; accumulator += step; } let mut ebu = EbuR128::new(2, 48_000, Mode::all() & !Mode::HISTOGRAM).unwrap(); ebu.add_frames_planar_i32(&[fst, snd]).unwrap(); assert_float_eq!( ebu.loudness_global().unwrap(), -0.6826039914171368, abs <= 0.000001 ); assert_float_eq!( ebu.loudness_momentary().unwrap(), -0.6813325598274425, abs <= 0.000001 ); assert_float_eq!( ebu.loudness_shortterm().unwrap(), -0.6827591715105212, abs <= 0.000001 ); assert_float_eq!( ebu.loudness_window(1).unwrap(), -0.8742956620040943, abs <= 0.000001 ); assert_float_eq!( ebu.loudness_range().unwrap(), 0.00006921150165073442, abs <= 0.000001 ); assert_float_eq!(ebu.sample_peak(0).unwrap(), 1.0, abs <= 0.000001); assert_float_eq!(ebu.sample_peak(1).unwrap(), 1.0, abs <= 0.000001); assert_float_eq!(ebu.prev_sample_peak(0).unwrap(), 1.0, abs <= 0.000001); assert_float_eq!(ebu.prev_sample_peak(1).unwrap(), 1.0, abs <= 0.000001); assert_float_eq!( ebu.true_peak(0).unwrap(), 1.0008491277694702, abs <= 0.000001 ); ``` -------------------------------- ### Compare Rust and C Implementations of Gated Loudness Source: https://docs.rs/ebur128/latest/src/ebur128/history.rs.html A quickcheck test that compares the gated loudness calculation between the Rust implementation and its C counterpart. It initializes the C side, adds energy data to both, and asserts equality within a tolerance. ```rust #[quickcheck] fn compare_c_impl_gated_loudness( energy: Vec, use_histogram: bool, max: NonZeroU16, ) -> Result<(), String> { init(); let mut hist = History::new(use_histogram, max.get() as usize); for e in &energy { hist.add(e.0); } let val = hist.gated_loudness(); let val_c = unsafe { let hist_c = history_create_c(i32::from(use_histogram), max.get() as usize); for e in &energy { history_add_c(hist_c, e.0); } let val = history_gated_loudness_c(hist_c); history_destroy_c(hist_c); val }; if !float_eq!(val, val_c, ulps <= 2) { Err(format!("{val} != {val_c}")) } else { Ok(()) } } ``` -------------------------------- ### Get Max History Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search=std%3A%3Avec Retrieves the maximum history duration in milliseconds configured for the library. ```APIDOC ## Get Max History ### Description Retrieves the maximum history duration in milliseconds. ### Method `GET` ### Endpoint `/max_history` ### Response #### Success Response (200) - **history** (usize) - The maximum history duration in milliseconds. ``` -------------------------------- ### Seeding Filter State with Audio Samples Source: https://docs.rs/ebur128/latest/src/ebur128/filter.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Initializes the filter's state by processing a source of audio samples without producing output. This is useful for setting up the filter's internal state before starting actual loudness measurements. It iterates through channels and applies the filter's coefficients to the input samples. ```rust pub fn seed<'a, T: Sample + 'a, S: crate::Samples<'a, T>>( &mut self, src: S, channel_map: &[crate::ebur128::Channel], ) { assert!(channel_map.len() == self.channels as usize); assert!(src.channels() == self.channels as usize); assert!(self.filter_state.len() == self.channels as usize); ftz::with_ftz(|ftz| { for (c, channel_map) in channel_map.iter().enumerate() { if *channel_map == crate::ebur128::Channel::Unused { continue; } assert!(c < src.channels()); let Filter { ref mut filter_state, ref a, .. } = *self; let filter_state = &mut filter_state[c]; src.foreach_sample(c, |src| { ``` -------------------------------- ### Get Rate Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search=std%3A%3Avec Retrieves the audio sample rate (in Hz) the library is configured to process. ```APIDOC ## Get Rate ### Description Retrieves the audio sample rate. ### Method `GET` ### Endpoint `/rate` ### Response #### Success Response (200) - **rate** (u32) - The sample rate in Hz. ``` -------------------------------- ### Process Audio in Chunks and Verify Aggregated Loudness Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html This snippet demonstrates how to process audio data in chunks and then verify that the aggregated loudness measurements (sample peak, true peak, and global loudness) match the results obtained by processing the entire audio data at once. ```rust let mut data = vec![0.0f32; 48_000 * 3]; let mut accumulator = 0.0; let step = 2.0 * std::f32::consts::PI * 440.0 / 48_000.0; for out in data.chunks_exact_mut(1) { let val = f32::sin(accumulator); out[0] = val; accumulator += step; } let mut ebu1 = EbuR128::new(1, 48_000, Mode::all() | Mode::HISTOGRAM).unwrap(); ebu1.add_frames_f32(&data).unwrap(); let mut ebu_chunks = Vec::new(); for i in 0..3usize { let mut ebu_chunk = EbuR128::new(1, 48_000, Mode::all() | Mode::HISTOGRAM & !Mode::HISTOGRAM).unwrap(); let start_index = std::cmp::max(i as isize * 48_000, 0) as usize; let stop_index = std::cmp::min(start_index + 48_000 + (48_00 * 3), data.len()); if start_index > 0 { ebu_chunk .seed_frames_f32(&data[start_index - 48_00..start_index]) .unwrap(); } ebu_chunk .add_frames_f32(&data[start_index..stop_index]) .unwrap(); ebu_chunks.push(ebu_chunk); } assert_float_eq!( ebu1.sample_peak(0).unwrap(), f64_max(ebu_chunks.iter().map(|meter| meter.sample_peak(0).unwrap())).unwrap(), abs <= 0.000001 ); assert_float_eq!( ebu1.true_peak(0).unwrap(), f64_max(ebu_chunks.iter().map(|meter| meter.true_peak(0).unwrap())).unwrap(), abs <= 0.000001 ); assert_float_eq!( ebu1.loudness_global().unwrap(), EbuR128::loudness_global_multiple(ebu_chunks.iter()).unwrap(), abs <= 0.000001 ); ``` -------------------------------- ### loudness_range_multiple Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search= Get the loudness range (LRA) of a program across multiple EbuR128 instances. ```APIDOC ## loudness_range_multiple ### Description Calculates the Loudness Range (LRA) across multiple `EbuR128` instances, according to the EBU 3342 standard. This is useful for analyzing LRA over segments or different files. ### Method `post` ### Endpoint `/loudness/range/multiple` ### Request Body - **instances** (array of EbuR128) - Required - An array of `EbuR128` instances to calculate the combined loudness range from. ### Returns - `f64`: The loudness range in LU. Returns an error if LRA mode is not enabled for any instance. ``` -------------------------------- ### loudness_shortterm Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search= Get the short-term loudness, which is the loudness of the last 3 seconds of audio, in LUFS. ```APIDOC ## loudness_shortterm ### Description Calculates and returns the short-term loudness of the audio processed so far, specifically the last 3 seconds, in LUFS. ### Method `get` ### Endpoint `/loudness/shortterm` ### Returns - `f64`: The short-term loudness in LUFS. Returns -infinity if the energy is non-positive. ``` -------------------------------- ### Queue Implementation for Energy History Source: https://docs.rs/ebur128/latest/src/ebur128/history.rs.html A fixed-size queue to store recent audio energy measurements. Useful for calculating loudness ranges and dynamic thresholds. ```rust pub struct Queue { queue: VecDeque, max: usize, } impl Queue { fn new(max: usize) -> Self { Queue { queue: VecDeque::with_capacity(std::cmp::min(max, 5000)), max, } } fn add(&mut self, energy: f64) { // Remove last element to keep the size if self.max == self.queue.len() { self.queue.pop_front(); } self.queue.push_back(energy); } fn set_max_size(&mut self, max: usize) { if self.queue.len() < max { // FIXME: Use shrink() once stabilized self.queue.resize(max, 0.0); self.queue.shrink_to_fit(); } self.max = max; } fn reset(&mut self) { self.queue.clear(); } fn calc_relative_threshold(&self) -> (u64, f64) { (self.queue.len() as u64, self.queue.iter().sum::()) } fn loudness_range(q: &[f64]) -> f64 { if q.is_empty() { return 0.0; } let power = q.iter().sum::() / q.len() as f64; let minus_twenty_decibels = f64::powf(10.0, -20.0 / 10.0); let integrated = minus_twenty_decibels * power; let relgated = q.iter().take_while(|&v| *v < integrated).count(); let relgated_size = q.len() - relgated; if let Some(relgated_size) = relgated_size.checked_sub(1) { let relgated_size = relgated_size as f64; let h_en = q[relgated + (relgated_size * 0.95 + 0.5) as usize]; let l_en = q[relgated + (relgated_size * 0.1 + 0.5) as usize]; energy_to_loudness(h_en) - energy_to_loudness(l_en) } else { 0.0 } } } ``` -------------------------------- ### Get Sample Rate Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search= Retrieves the audio sample rate the library is configured to process. ```APIDOC ## rate ### Description Get the configured sample rate. ### Method `rate()` ### Returns - `u32`: The sample rate in Hz. ``` -------------------------------- ### QuickCheck Test for i16 Input with C Implementation Comparison Source: https://docs.rs/ebur128/latest/src/ebur128/filter.rs.html?search=std%3A%3Avec This test uses QuickCheck to generate random i16 audio signals and compares the results of the Rust implementation against the C implementation for processing. ```rust #[quickcheck] fn compare_c_impl_i16( signal: Signal, calculate_sample_peak: bool, calculate_true_peak: bool, ) { // Maximum of 400ms but our input is up to 5000ms, so distribute it evenly // by shrinking accordingly. let frames = signal.data.len() / signal.channels as usize; let frames = std::cmp::min(2 * frames / 25, 4 * ((signal.rate as usize + 5) / 10)); let mut data_out = vec![0.0f64; frames * signal.channels as usize]; let mut data_out_c = vec![0.0f64; frames * signal.channels as usize]; let channel_map_c = vec![1; signal.channels as usize]; let channel_map = vec![Channel::Left; signal.channels as usize]; let (sp, tp) = { let mut f = Filter::new( signal.rate, signal.channels, calculate_sample_peak, calculate_true_peak, ); let mut data_out_tmp = vec![0.0f64; frames * signal.channels as usize]; f.process( crate::Interleaved::new( &signal.data[..(frames * signal.channels as usize)], signal.channels as usize, ) .unwrap(), &mut data_out_tmp, 0, &channel_map, ); for (c, src) in data_out_tmp.chunks_exact(frames).enumerate() { for (i, src) in src.iter().enumerate() { data_out[i * signal.channels as usize + c] = *src; } } (Vec::from(f.sample_peak()), Vec::from(f.true_peak())) }; } ``` -------------------------------- ### Initialize ebur128 with default parameters Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E This snippet shows the initialization of the ebur128 struct with default settings for audio processing. It allocates necessary buffers and sets up internal filters and history tracking based on the provided mode, channels, and sample rate. ```rust let sample_peak = vec![0.0; channels as usize]; let true_peak = vec![0.0; channels as usize]; let history = usize::MAX; let samples_in_100ms = (rate as usize + 5) / 10; let window = if mode.contains(Mode::S) { 3000 } else if mode.contains(Mode::M) { 400 } else { return Err(Error::InvalidMode); }; let audio_data = Self::allocate_audio_data(channels, rate, window)?; // start at the beginning of the buffer let audio_data_index = 0; let block_energy_history = crate::history::History::new(mode.contains(Mode::HISTOGRAM), history / 100); let short_term_block_energy_history = crate::history::History::new(mode.contains(Mode::HISTOGRAM), history / 3000); let short_term_frame_counter = 0; let filter = crate::filter::Filter::new( rate, channels, mode.contains(Mode::SAMPLE_PEAK), mode.contains(Mode::TRUE_PEAK), ); let channel_map = default_channel_map(channels); // the first block needs 400ms of audio data let needed_frames = samples_in_100ms * 4; Ok(Self { mode, rate, channels, audio_data, audio_data_index, needed_frames, channel_map: channel_map.into_boxed_slice(), samples_in_100ms, filter, block_energy_history, short_term_block_energy_history, short_term_frame_counter, sample_peak: sample_peak.into_boxed_slice(), true_peak: true_peak.into_boxed_slice(), window, history, }) ``` -------------------------------- ### Get Configured Channel Map Source: https://docs.rs/ebur128/latest/ebur128/struct.EbuR128.html?search=std%3A%3Avec Retrieves the slice representing the configured channel types. ```rust pub fn channel_map(&self) -> &[Channel] ``` -------------------------------- ### EbuR128::new Source: https://docs.rs/ebur128/latest/ebur128/struct.EbuR128.html?search=u32+-%3E+bool Creates a new instance of the EbuR128 loudness analyzer with the specified configuration. ```APIDOC ## EbuR128::new ### Description Create a new instance with the given configuration. ### Method `new(channels: u32, rate: u32, mode: Mode) -> Result` ### Parameters * `channels` (u32) - The number of audio channels. * `rate` (u32) - The sample rate of the audio. * `mode` (Mode) - The loudness measurement mode. ### Returns A `Result` containing a new `EbuR128` instance on success, or an `Error` on failure. ``` -------------------------------- ### Get Max Window Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search=std%3A%3Avec Retrieves the maximum window duration in milliseconds configured for audio processing. ```APIDOC ## Get Max Window ### Description Retrieves the maximum window duration in milliseconds. ### Method `GET` ### Endpoint `/max_window` ### Response #### Success Response (200) - **window** (usize) - The maximum window duration in milliseconds. ``` -------------------------------- ### Get Mode Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search=std%3A%3Avec Retrieves the configured audio mode (e.g., standard, mixed, or true peak). ```APIDOC ## Get Mode ### Description Retrieves the configured audio mode. ### Method `GET` ### Endpoint `/mode` ### Response #### Success Response (200) - **mode** (Mode) - The current audio mode configuration. ``` -------------------------------- ### EbuR128::new Source: https://docs.rs/ebur128/latest/ebur128/struct.EbuR128.html?search= Creates a new instance of the EbuR128 loudness analyzer with the specified configuration. ```APIDOC ## EbuR128::new ### Description Creates a new instance with the given configuration. ### Signature `pub fn new(channels: u32, rate: u32, mode: Mode) -> Result` ### Parameters * `channels` (u32) - The number of audio channels. * `rate` (u32) - The sample rate of the audio. * `mode` (Mode) - The analysis mode to use. ### Returns A `Result` containing a new `EbuR128` instance on success, or an `Error` on failure. ``` -------------------------------- ### Sample trait implementations for f32 and f64 Source: https://docs.rs/ebur128/latest/src/ebur128/utils.rs.html?search=std%3A%3Avec Provides implementations for the Sample trait for f32 and f64 types, defining MAX_AMPLITUDE and a raw conversion to f64. ```rust impl Sample for f32 { const MAX_AMPLITUDE: f64 = 1.0; #[inline(always)] fn as_f64_raw(self) -> f64 { self as f64 } } impl Sample for f64 { const MAX_AMPLITUDE: f64 = 1.0; #[inline(always)] fn as_f64_raw(self) -> f64 { self } } ``` -------------------------------- ### Getting number of frames Source: https://docs.rs/ebur128/latest/src/ebur128/utils.rs.html?search=std%3A%3Avec Returns the total number of frames available in the planar data slice. ```rust #[inline] fn frames(&self) -> usize { self.end - self.start } ``` -------------------------------- ### loudness_range Source: https://docs.rs/ebur128/latest/src/ebur128/ebur128.rs.html?search= Get the loudness range (LRA) of the program in LU, calculated according to EBU 3342. ```APIDOC ## loudness_range ### Description Calculates and returns the Loudness Range (LRA) of the audio program in LU, adhering to the EBU 3342 standard. This measurement requires the LRA mode to be enabled. ### Method `get` ### Endpoint `/loudness/range` ### Returns - `f64`: The loudness range in LU. Returns an error if LRA mode is not enabled. ```