You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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类型的样本,需要通过Sample trait的to_f32()方法转换为DTMF解码器所需的f32格式。
  • 批次处理:使用固定大小的缓冲区分批处理样本,避免一次性加载大量数据,保证实时性。
  • 设备选择:如果需要指定非默认麦克风,可以用rodio::input_devices()枚举所有设备,手动选择目标设备。
  • 采样率匹配:解码器的采样率必须和麦克风输入的采样率一致,代码中直接复用了输入设备的采样率,避免不兼容问题。

内容的提问来源于stack exchange,提问作者denizsincar29

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 22:05:27