这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【EVALBOARDFORNRF54L15】采集MIC声音通过auracast广

共2条 1/1 1 跳转至

【EVALBOARDFORNRF54L15】采集MIC声音通过auracast广播、电脑端实现音频接收

助工
2026-04-21 01:07:04     打赏
本次目标通过INMP441全向麦克风模块,将其中采集到的音频,通过auracast广播出去,然后其中nrf52840 dongle接收到音频从电脑上播放出来采集到的声音。方案流程图
1.png
  • 硬件平台与外设

  • 本项目包含发射端(广播)和接收端(监听)两个主要硬件实体:
    • 广播端 (Broadcaster):
      • 主控芯片: Nordic nRF54L15-DK(负责 I2S 驱动、LC3 编码与蓝牙 LE Audio 广播)。

      • 音频采集模块: INMP441 全向 I2S 硅麦克风(高信噪比,支持 24/32-bit I2S 输出)。

    • 接收端 (Receiver/Sink):
      • 主控芯片: Nordic nRF52840 Dongle(负责蓝牙周期性广播同步、LC3 解码与 USB UAC2 音频类传输)。

      • 播放终端: 个人电脑(PC),通过 USB 识别 Dongle 为标准音频输入设备。

  • 系统架构与数据流向

  • 整个系统的端到端(End-to-End)数据流向呈现“漏斗状”的生产-消费模型,主要分为以下几个阶段:
  • 声学采集 (I2S): 环境声音 -> INMP441->(I2S I2S_RX)->nRF54L15 内存池。

  • 编码与广播 (ISO Tx): nRF54L15 (PCM 数据 16kHz)-> LC3 编码器 -> 蓝牙底层的 BIG/BIS (广播等时流) -> 天线。

  • 同步与解码 (ISO Rx): 天线-> nRF52840 Dongle 扫描并同步 PA/BIG ->获取 LC3 载荷 -> LC3 解码器->还原出 PCM 数据。

  • PC 端播放 (USB UAC2): Dongle 内部 PCM 数据->USB Audio Class 2.0 驱动-> 电脑 USB 接口 -> 操作系统识别为“USB 麦克风”->电脑扬声器播放。

  • 主要代码实现

  • 麦克风采集我们使用16k采样率和16位,这样可以降低我们的设备的资源消耗在LC3编码中,其中支持帧长7.5ms和10ms,,这里我们选择帧长10ms
    #define I2S_NODE DT_NODELABEL(i2s20)   
    #define MIC_SAMPLE_RATE 16000          /* 麦克风采样率:16kHz */
    #define MIC_WORD_SIZE 16               /* 采样位宽:16 bit */
    #define MIC_CHANNELS 1                 /* 通道数:单声道 */
    #define MIC_FRAME_SAMPLES 160          /* 10ms数据(16000 * 0.01) = 160个采样点 */
    #define MIC_FRAME_BYTES    (MIC_FRAME_SAMPLES * sizeof(int16_t)) /* 160 * 2 = 320 字节 */
    之后我们创建线程,来接收我们的麦克风音频数据
    static void mic_i2s_thread(void *a, void *b, void *c)
    {
        const struct device *i2s_dev = DEVICE_DT_GET(I2S_NODE); // 获取设备实例
        int ret;
        struct i2s_config cfg = {
            .word_size = MIC_WORD_SIZE,
            .channels = MIC_CHANNELS,
            .format = I2S_FMT_DATA_FORMAT_I2S,
            .options = I2S_OPT_BIT_CLK_MASTER | I2S_OPT_FRAME_CLK_MASTER, 
            .frame_clk_freq = MIC_SAMPLE_RATE, // 16000 Hz
            .mem_slab = &mic_rx_slab,          
            .block_size = MIC_FRAME_BYTES,     /
            .timeout = 1000,                   // 读写超时时间
        };
        if (!device_is_ready(i2s_dev)) { return; } 
        ret = i2s_configure(i2s_dev, I2S_DIR_RX, &cfg); 
        ret = i2s_trigger(i2s_dev, I2S_DIR_RX, I2S_TRIGGER_START);
    数据传输,这里我们将其中采集到的数据消息队列传入到LC3编码中
    while (1) {
            void *mem_block;
            size_t block_size_out;
            int16_t frame[MIC_FRAME_SAMPLES];
            ret = i2s_read(i2s_dev, &mem_block, &block_size_out);
            if (ret < 0) {
                k_msleep(10); 
                continue;
            }
            memcpy(frame, mem_block, MIN(block_size_out, sizeof(frame)));
            ret = k_msgq_put(&mic_frame_q, frame, K_NO_WAIT);
            if (ret != 0) {
                printk("mic_frame_q full, drop one frame\n"); 
            }
            k_mem_slab_free(&mic_rx_slab, mem_block);
        }
    }

    最后就是调用ISO接口将我们的编码好的LC3数据传输,接下来是本次项目的演示视频

  • 总结

  • 本次比较匆忙的完成此次链路的测评,给大家带来自己实现auracast的一些实现方法,其中有写关于auracast的相关概念没有讲清楚,等下次遇到带有auracast的功能,将详细的给大家带来其中仔细讲解--立flag

此次测评的所有代码NRF_Code.zip




关键词: INMP441     auracast    

院士
2026-04-21 15:25:39     打赏
2楼

学习了,谢谢分享。

请问楼主:这个是作为实用的方案吗?如果是的,建议对MIC做一些频点控制,因为MIC引起的啸叫(视频里1分25秒处开始出现)会影响使用效果,供参考。


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]