如何用Rust的cpal库从麦克风读取f32音频样本并实时解码DTMF信号?
实时DTMF解码:从麦克风获取音频数据
首先确保Cargo.toml中添加依赖:
[dependencies] dtmf = "0.1.5" rodio = "0.17.1"
以下是从麦克风实时读取音频并解码DTMF的完整代码:
use dtmf::decoder::Decoder; use rodio::{InputStream, Sample}; use std::error::Error; fn main() -> Result<(), Box<dyn Error>> { // 获取默认音频输入设备(麦克风) let (stream, handle) = InputStream::try_default()?; let sample_rate = handle.sample_rate(); println!("使用采样率: {} Hz", sample_rate); // 初始化DTMF解码器,传入采样率和回调函数 let mut decoder = Decoder::new(sample_rate, |tone, state| { println!("检测到DTMF信号: {:?} | 状态: {:?}", tone, state); }); // 定义每次处理的样本批次大小(可根据需求调整,1024是常用值) const BATCH_SIZE: usize = 1024; let mut sample_buffer = Vec::with_capacity(BATCH_SIZE); // 开始监听麦克风输入,流式处理样本 handle.stream_raw(move |data: &[i16], _| { // 将i16格式的样本转换为f32(DTMF解码器需要f32类型) for &sample in data { let f32_sample = sample.to_f32(); sample_buffer.push(f32_sample); // 当缓冲区达到批次大小时,传给解码器处理 if sample_buffer.len() == BATCH_SIZE { decoder.process(&sample_buffer); sample_buffer.clear(); } } Ok(()) })?; // 保持程序运行,直到用户按下回车 println!("正在监听麦克风输入,按回车键退出..."); std::io::stdin().read_line(&mut String::new())?; drop(stream); // 关闭音频流 Ok(()) }
关键说明:
- 音频格式转换:rodio默认从麦克风获取的是
i16类型的样本,需要通过Sampletrait的to_f32()方法转换为DTMF解码器所需的f32格式。 - 批次处理:使用固定大小的缓冲区分批处理样本,避免一次性加载大量数据,保证实时性。
- 设备选择:如果需要指定非默认麦克风,可以用
rodio::input_devices()枚举所有设备,手动选择目标设备。 - 采样率匹配:解码器的采样率必须和麦克风输入的采样率一致,代码中直接复用了输入设备的采样率,避免不兼容问题。
内容的提问来源于stack exchange,提问作者denizsincar29
相关产品推荐
相关产品推荐

