项目:智能音箱

嵌入式 AI 典型场景:音频采集 + 唤醒词 + ASR + TTS + 云端对话。

一、目标

二、硬件

三、音频子系统

1. ALSA 框架

#include <alsa/asoundlib.h>

snd_pcm_t *pcm;
snd_pcm_open(&pcm, "default", SND_PCM_STREAM_CAPTURE, 0);

snd_pcm_hw_params_t *params;
snd_pcm_hw_params_alloca(&params);
snd_pcm_hw_params_any(pcm, params);
snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(pcm, params, SND_PCM_FORMAT_S16_LE);
snd_pcm_hw_params_set_channels(pcm, params, 1);
snd_pcm_hw_params_set_rate(pcm, params, 16000, 0);

snd_pcm_hw_params(pcm, params);
snd_pcm_prepare(pcm);

char buf[3200];   // 100ms @ 16kHz
while (1) {
    snd_pcm_readi(pcm, buf, 1600);  // 100ms
    process_audio(buf, 3200);
}

2. 设备树

sound: sound {
    compatible = "simple-audio-card";
    simple-audio-card,name = "myboard-audio";
    simple-audio-card,dai-link@0 {
        format = "i2s";
        cpu { sound-dai = <&i2s1>; };
        codec { sound-dai = <&codec>; };
    };
    simple-audio-card,dai-link@1 {
        format = "i2s";
        cpu { sound-dai = <&i2s1>; };
        codec { sound-dai = <&spk_amp>; };
    };
};

四、唤醒词检测

使用 Snowboy / Picovoice Porcupine:

// 伪代码
while (running) {
    snd_pcm_readi(pcm, audio_buf, 1600);

    int wake = snowboy_run(snowboy, audio_buf);
    if (wake == 1) {
        play_beep();
        start_capture();
        upload_to_cloud();
    }
}

五、ASR(云端)

// 发送录音到 ASR
void send_asr(char *wav_data, int len)
{
    cJSON *root = cJSON_CreateObject();
    cJSON_AddStringToObject(root, "format", "wav");
    cJSON_AddNumberToObject(root, "rate", 16000);
    cJSON_AddRawToObject(root, "audio", base64_encode(wav_data, len));

    http_post("https://api.asr.com/recognize", root);
}

六、TTS

// 云端 TTS → 播放
char *url = "https://api.tts.com/synthesize?text=hello";
char *mp3_data = http_get(url);
play_mp3(mp3_data);

七、本地 ASR(嵌入式 AI)

git clone https://github.com/ggml-org/whisper.cpp
cd whisper.cpp
make
./main -m models/ggml-base.bin -f input.wav

ARM 量化模型:
- ggml-tiny.bin(39 MB)
- ggml-base.bin(142 MB)

适合 RK3568 / i.MX 8M Plus(带 NPU)。

八、对话管理

// 状态机
typedef enum {
    STATE_IDLE,
    STATE_LISTENING,
    STATE_PROCESSING,
    STATE_SPEAKING,
} dialog_state_t;

// FSM
if (state == STATE_IDLE && wake_detected()) {
    state = STATE_LISTENING;
    start_record();
}
if (state == STATE_LISTENING && silence_detected()) {
    state = STATE_PROCESSING;
    upload_asr();
}
if (state == STATE_PROCESSING && asr_result_ready()) {
    state = STATE_SPEAKING;
    play_tts();
}
if (state == STATE_SPEAKING && play_finished()) {
    state = STATE_IDLE;
}

九、回声消除(AEC)

// WebRTC AEC
void *aec = WebRtcAec_Create();
WebRtcAec_Init(aec, 16000, 16000);

// 远端参考(扬声器输出)
int far_buf[1600];
// 近端(麦克风输入)
int near_buf[1600];

WebRtcAec_BufferFarend(aec, far_buf, 1600);
WebRtcAec_Process(aec, near_buf, NULL, near_buf_echo_canceled, 1600, ...);

十、典型嵌入式 SoC 选型

SoC NPU 适用
RK3568 1 TOPS 中端音箱
RK3588 6 TOPS 高端、视觉
全志 R329 0.5 TOPS 低端语音
i.MX 8M Plus 2.3 TOPS 高端
Amlogic A311D 5 TOPS 高端