Rust音频响度分析库ebur128的使用,实现EBU R128标准的音频电平测量和响度归一化
Rust音频响度分析库ebur128的使用,实现EBU R128标准的音频电平测量和响度归一化
简介
ebur128是一个实现EBU R128响度标准的Rust库。欧洲广播联盟响度建议(EBU R128)为广播公司提供了分析和归一化音频的方法,使每段音频对人耳来说具有大致相同的音量。
该库提供API来分析音频并输出感知响度,结果可用于在播放期间归一化音量。
特性
- 实现M、S和I模式
- 实现响度范围测量
- 真峰值扫描
- 通过重新计算滤波器系数支持所有采样率
完整示例代码
以下是使用ebur128库进行音频响度分析和归一化的完整示例:
use ebur128::{EbuR128, Mode, Error};
fn main() -> Result<(), Error> {
// 假设我们有一个44100Hz采样率、立体声的音频数据
let sample_rate = 44100;
let channels = 2;
// 创建一个EBU R128分析器实例
// 这里使用M模式(响度测量)和I模式(综合响度测量)
let mut analyzer = EbuR128::new(
sample_rate,
channels,
Mode::M | Mode::I
)?;
// 模拟音频数据 - 实际应用中应该从音频文件或流中读取
// 这里生成1秒的静音音频(0.0值)
let num_samples = sample_rate * channels as u32;
let audio_data = vec![0.0f32; num_samples as usize];
// 添加音频帧进行分析
analyzer.add_frames_f32(&audio_data)?;
// 获取瞬时响度(Loudness Momentary)
let momentary_loudness = analyzer.loudness_momentary()?;
println!("瞬时响度: {:.1} LUFS", momentary_loudness);
// 获取短期响度(Loudness Short-term)
let short_term_loudness = analyzer.loudness_short_term()?;
println!("短期响度: {:.1} LUFS", short_term_loudness);
// 获取综合响度(Loudness Integrated)
let integrated_loudness = analyzer.loudness_integrated()?;
println!("综合响度: {:.1} LUFS", integrated_loudness);
// 获取响度范围(Loudness Range)
let loudness_range = analyzer.loudness_range()?;
println!("响度范围: {:.1} LU", loudness_range);
// 获取真峰值(True Peak)
let true_peak = analyzer.true_peak()?;
println!("真峰值: {:.1} dBTP", true_peak);
// 计算归一化增益
// EBU R128标准目标响度为-23 LUFS
let target_loudness = -23.0;
let normalization_gain = target_loudness - integrated_loudness;
println!("归一化增益: {:.1} dB", normalization_gain);
Ok(())
}
扩展示例代码
以下是一个更完整的示例,演示如何从WAV文件读取音频并进行分析:
use ebur128::{EbuR128, Mode, Error};
use hound::{WavReader, SampleFormat};
use std::path::Path;
fn analyze_wav_file(path: &Path) -> Result<(), Error> {
// 读取WAV文件
let reader = WavReader::open(path)?;
let spec = reader.spec();
// 创建EBU R128分析器
let mut analyzer = EbuR128::new(
spec.sample_rate,
spec.channels as usize,
Mode::M | Mode::I | Mode::S | Mode::TRUE_PEAK
)?;
match spec.sample_format {
SampleFormat::Int => {
// 处理整数格式的音频数据
let samples: Vec<i32> = reader.into_samples::<i32>().collect::<Result<_, _>>()?;
let max_sample = 1 << (spec.bits_per_sample - 1);
let float_samples: Vec<f32> = samples.iter()
.map(|&s| s as f32 / max_sample as f32)
.collect();
analyzer.add_frames_f32(&float_samples)?;
}
SampleFormat::Float => {
// 处理浮点格式的音频数据
let samples: Vec<f32> = reader.into_samples::<f32>().collect::<Result<_, _>>()?;
analyzer.add_frames_f32(&samples)?;
}
}
// 打印分析结果
println!("综合响度: {:.1} LUFS", analyzer.loudness_integrated()?);
println!("瞬时响度: {:.1} LUFS", analyzer.loudness_momentary()?);
println!("短期响度: {:.1} LUFS", analyzer.loudness_short_term()?);
println!("响度范围: {:.1} LU", analyzer.loudness_range()?);
println!("真峰值: {:.1} dBTP", analyzer.true_peak()?);
Ok(())
}
fn main() -> Result<(), Error> {
let path = Path::new("example.wav");
analyze_wav_file(path)
}
安装
在您的项目中添加ebur128依赖:
[dependencies]
ebur128 = "0.1.10"
hound = "3.4.0" # 用于WAV文件读取
或者运行以下命令:
cargo add ebur128 hound
许可证
ebur128采用MIT许可证授权。
1 回复
Rust音频响度分析库ebur128的使用指南
概述
ebur128是一个Rust实现的音频响度分析库,用于实现EBU R128标准的音频电平测量和响度归一化。该标准广泛应用于广播、流媒体和音频制作领域,用于确保不同音频内容之间的响度一致性。
主要功能
- 计算瞬时响度、短期响度和综合响度
- 支持多种音频格式和采样率
- 实现响度归一化
- 符合EBU R128和ITU-R BS.1770标准
使用方法
添加依赖
首先在Cargo.toml中添加依赖:
[dependencies]
ebur128 = "0.2"
基本使用示例
use ebur128::{EbuR128, Mode};
fn main() {
// 创建分析器实例
// 参数: 声道数, 采样率, 模式(这里使用所有模式)
let mut analyzer = EbuR128::new(2, 44100, Mode::I | Mode::S | Mode::L).unwrap();
// 假设我们有一些PCM音频数据(这里用静音数据示例)
let samples = vec![0.0f32; 44100 * 2]; // 1秒立体声
// 添加音频数据进行分析
analyzer.add_frames_f32(&samples).unwrap();
// 获取响度测量结果
let momentary = analyzer.loudness_momentary().unwrap();
let short_term = analyzer.loudness_short_term().unwrap();
let integrated = analyzer.loudness_integrated().unwrap();
println!("瞬时响度: {:.1} LUFS", momentary);
println!("短期响度: {:.1} LUFS", short_term);
println!("综合响度: {:.1} LUFS", integrated);
// 获取真实峰值
let true_peak = analyzer.true_peak().unwrap();
println!("真实峰值: {:.1} dBTP", true_peak[0]); // 第一个声道
}
实际音频文件处理示例
以下是一个更完整的示例,展示如何处理实际音频文件:
use ebur128::{EbuR128, Mode};
use std::fs::File;
use std::io::BufReader;
use hound::{WavReader, SampleFormat};
fn analyze_wav_file(path: &str) -> Result<(), Box<dyn std::error::Error>> {
// 打开WAV文件
let reader = WavReader::open(path)?;
let spec = reader.spec();
// 创建响度分析器
let mut analyzer = EbuR128::new(
spec.channels as usize,
spec.sample_rate,
Mode::I | Mode::S | Mode::L
)?;
// 根据样本格式处理音频数据
match spec.sample_format {
SampleFormat::Float => {
for sample in reader.into_samples::<f32>() {
analyzer.add_frames_f32(&[sample?])?;
}
}
SampleFormat::Int => {
// 需要将整数样本转换为浮点数
let max_val = (1 << (spec.bits_per_sample - 1)) as f32;
for sample in reader.into_samples::<i32>() {
let s = sample? as f32 / max_val;
analyzer.add_frames_f32(&[s])?;
}
}
}
// 获取并打印结果
println!("文件: {}", path);
println!("综合响度: {:.1} LUFS", analyzer.loudness_integrated()?);
println!("短期最大响度: {:.1} LUFS", analyzer.loudness_short_term()?);
println!("真实峰值: {:.1} dBTP", analyzer.true_peak()?[0]);
Ok(())
}
fn main() {
if let Err(e) = analyze_wav_file("example.wav") {
eprintln!("分析错误: {}", e);
}
}
响度归一化示例
use ebur128::{EbuR128, Mode};
fn normalize_audio(samples: &mut [f32], target_lufs: f64) -> Result<(), Box<dyn std::error::Error>> {
// 创建分析器
let mut analyzer = EbuR128::new(2, 44100, Mode::I)?;
// 分析原始响度
analyzer.add_frames_f32(samples)?;
let current_lufs = analyzer.loudness_integrated()?;
// 计算增益调整值
let gain = (target_lufs - current_lufs).exp2() as f32;
// 应用增益
for sample in samples.iter_mut() {
*sample *= gain;
}
println!("已将音频从 {:.1} LUFS 归一化到 {:.1} LUFS", current_lufs, target_lufs);
Ok(())
}
注意事项
- 采样率支持:库支持常见的音频采样率(44.1kHz, 48kHz等)
- 声道数:支持单声道、立体声和多声道音频
- 性能考虑:对于长音频文件,可能需要分块处理以避免内存问题
- 精度:EBU R128标准要求至少测量3秒音频才能获得有效结果
高级功能
自定义测量间隔
use ebur128::{EbuR128, Mode};
fn custom_interval_analysis() {
let mut analyzer = EbuR128::new(2, 44100, Mode::I).unwrap();
// 自定义测量间隔(默认为100ms)
analyzer.set_max_window(500); // 设置为500ms
// ...处理音频数据...
}
多线程处理
对于大型音频文件,可以考虑分块并行处理:
use ebur128::{EbuR128, Mode};
use rayon::prelude::*;
fn parallel_analysis(samples: &[f32], chunk_size: usize) -> f64 {
let mut analyzer = EbuR128::new(2, 44100, Mode::I).unwrap();
samples
.par_chunks(chunk_size)
.for_each(|chunk| {
analyzer.add_frames_f32(chunk).unwrap();
});
analyzer.loudness_integrated().unwrap()
}
完整示例代码
以下是一个完整的音频处理示例,结合了文件读取、响度分析和归一化功能:
use ebur128::{EbuR128, Mode};
use hound::{WavReader, SampleFormat};
use std::path::Path;
// 音频处理结构体
struct AudioProcessor {
analyzer: EbuR128,
sample_rate: u32,
channels: usize,
}
impl AudioProcessor {
// 创建新的音频处理器
fn new(channels: usize, sample_rate: u32) -> Result<Self, Box<dyn std::error::Error>> {
Ok(Self {
analyzer: EbuR128::new(channels, sample_rate, Mode::all())?,
sample_rate,
channels,
})
}
// 分析WAV文件
fn analyze_wav(&mut self, path: &Path) -> Result<(), Box<dyn std::error::Error>> {
let reader = WavReader::open(path)?;
let spec = reader.spec();
// 检查音频参数是否匹配
if spec.channels as usize != self.channels || spec.sample_rate != self.sample_rate {
return Err("音频参数不匹配".into());
}
match spec.sample_format {
SampleFormat::Float => {
for sample in reader.into_samples::<f32>() {
self.analyzer.add_frames_f32(&[sample?])?;
}
}
SampleFormat::Int => {
let max_val = (1 << (spec.bits_per_sample - 1)) as f32;
for sample in reader.into_samples::<i32>() {
let s = sample? as f32 / max_val;
self.analyzer.add_frames_f32(&[s])?;
}
}
}
Ok(())
}
// 获取分析结果
fn get_results(&self) -> Result<(f64, f64, f64, Vec<f64>), Box<dyn std::error::Error>> {
Ok((
self.analyzer.loudness_momentary()?,
self.analyzer.loudness_short_term()?,
self.analyzer.loudness_integrated()?,
self.analyzer.true_peak()?,
))
}
// 归一化音频数据
fn normalize_audio(samples: &mut [f32], target_lufs: f64) -> Result<f32, Box<dyn std::error::Error>> {
let mut analyzer = EbuR128::new(2, 44100, Mode::I)?;
analyzer.add_frames_f32(samples)?;
let current_lufs = analyzer.loudness_integrated()?;
let gain = (target_lufs - current_lufs).exp2() as f32;
for sample in samples.iter_mut() {
*sample *= gain;
}
Ok(gain)
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 初始化音频处理器 (立体声,44.1kHz)
let mut processor = AudioProcessor::new(2, 44100)?;
// 分析音频文件
let audio_path = Path::new("audio.wav");
processor.analyze_wav(audio_path)?;
// 获取并打印结果
let (momentary, short_term, integrated, true_peak) = processor.get_results()?;
println!("音频分析结果:");
println!("瞬时响度: {:.1} LUFS", momentary);
println!("短期响度: {:.1} LUFS", short_term);
println!("综合响度: {:.1} LUFS", integrated);
println!("真实峰值: {:.1} dBTP", true_peak[0]);
// 示例:归一化音频数据
let target_lufs = -23.0; // EBU R128推荐值
let mut samples = vec![0.5f32; 44100 * 2]; // 示例音频数据
let gain = AudioProcessor::normalize_audio(&mut samples, target_lufs)?;
println!("应用增益: {:.2}x 将音频归一化到 {:.1} LUFS", gain, target_lufs);
Ok(())
}
总结
ebur128库为Rust开发者提供了完整的EBU R128标准实现,可以方便地集成到音频处理工具链中。通过上述示例,您可以快速开始进行音频响度分析和归一化处理。