> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs-staging.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 高级音频功能

> 启用高级音频功能，包括回声消除、噪声抑制、VoIP 和多设备播放。

## **最大限度地减少回声和噪声**

回声和噪声问题是 VoIP 系统中常见的问题。语音从远端扬声器发出，并经过时延后回声，从而造成感知问题。回声消除可减少通信期间来自远端扬声器的回声。噪声抑制可减少来自麦克风通道的噪声。SMECNS 回声消除和噪声抑制（ECNS）算法可提供平稳和非平稳噪声抑制以及回声消除。

声学回声是指由于设备的扬声器和麦克风之间的声学路径（声学耦合）而产生的回声。这对免提和电话会议应用非常重要。

下图显示了声学回声路径以及扬声器和麦克风之间如何发生声学回声。

<div className="flex flex-col items-center gap-2">
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-staging/archives/2.1/zh/Technologies/Audio/media/qualcomm-linux-iot-audio-voice/ecns_overview.svg" alt="Noise and acoustic echo" />

  <p className="text-sm text-gray-700">
    噪声与声学回声
  </p>
</div>

近端语音信号远端语音信号近端扬声器环境噪声声学回声路径声学回声近端语音远端语音

噪声与声学回声

* **回声消除器** – 一种自适应滤波器，可自我调整系数以消除回声。每个回声都有一个回声路径，并由脉冲响应表征。回声消除器可以自适应网络回声路径，从而消除回声。
* **噪声抑制** – 单麦克风回声消除器和噪声抑制器（SMECNS）在嘈杂环境中使用设备时，有助于抑制周围的平稳噪声。

### **为录音启用 SMECNS**

录音时，SMECNS 通过抑制麦克风采集到的背景噪声来保持录音路径中的语音质量。

对于单麦克风录音，仅支持平稳噪声抑制。平稳噪声是指频率不随时间变化的噪声，例如道路噪声或白噪声。

下图显示了如何使用增益、SMECNS 和后处理模块来去除外部噪声和回声，从而输出清晰的语音。

<div className="flex flex-col items-center gap-2">
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-staging/archives/2.1/zh/Technologies/Audio/media/qualcomm-linux-iot-audio-voice/fluence_recording.svg" alt="SMECNS software block for recording" />

  <p className="text-sm text-gray-700">
    用于录音的 SMECNS 软件块
  </p>
</div>

用于录音的 SMECNS 软件块

要在录音路径中启用 SMECNS：

1. 使用 `wpctl status` 命令列出可用节点。
   ```text theme={null}
   systemctl stop pipewire wireplumber pipewire.socket pipewire-manager.socket
   ```
   ```text theme={null}
   chmod 777 /dev/dma_heap/system
   ```
   ```text theme={null}
   systemctl start pipewire wireplumber
   ```
   ```text theme={null}
   wpctl status
   ```
2. 运行 `wpctl set-default` 将源节点设置为手持麦克风。
   ```text theme={null}
   wpctl set-default <sink/source node ID>
   ```
3. 运行 `pw-record` 开始录音。以下示例以详细模式运行，并将录音保存到 `/opt/test.wav`。
   ```text theme={null}
   pw-record /opt/test.wav -v
   ```

### **模拟 VoIP**

要使用 PipeWire 模拟 VoIP：

| **设置录音源** | |
| :- | :- |

```text theme={null}
pw-record /opt/record_voip.wav -v --target=voip-tx0
```

| **设置播放接收端** | |
| :- | :- |

```text theme={null}
pw-play /opt/test.wav -v --target=voip-rx0
```

<Note>
  请务必将 PCM 文件（`<FileName>.wav`）推送到 `/opt/` 文件夹。
</Note>

### **启用单流多设备播放**

配置平台以同时在多个输出设备（例如内置扬声器和有线耳机）上呈现单个音频流。在此模式下，音频会被复制，同一解码音频流会同时路由到多个活动输出设备，确保所有选定端点之间的同步播放。

1. 列出可用的音频节点。

   ```text theme={null}
   wpctl status
   ```

<div className="flex flex-col items-center gap-2">
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-staging/archives/2.1/zh/Technologies/Audio/media/qualcomm-linux-iot-audio-voice/wpctl_status.png" alt="wpctl status output showing available PAL sink and source nodes" />

  <p className="text-sm text-gray-700">
    wpctl status 输出显示了可用的 PAL 接收端和源节点
  </p>
</div>

2. 设置默认节点。

   ```text theme={null}
   wpctl set-default <NUMBER for low-latency>
   ```

   * 对于低延迟，选择带有 `pal sink combined speaker and headset ll` 的节点。
   * 对于深度缓冲，选择带有 `pal sink combined speaker and headset db` 的节点。

3. 开始播放。

   ```text theme={null}
   pw-play /tmp/yesterday_48KHz.wav -v
   ```

### **启用多流多设备播放**

配置平台以同时在不同的输出设备（例如内置扬声器和有线耳机）上呈现多个独立的音频流。在此模式下，每个音频流都是独立管理和路由的，允许不同的流同时传送到不同的输出设备而不会互相干扰。这样可实现例如跨多个端点的并行媒体播放和通知路由等用例。

1. 列出可用的音频节点。

   ```text theme={null}
   pw-cli ls Node
   ```

2. 选择要在其上播放多个流的音频节点，并使用 `--target` 命令行选项指定这些节点名称。

3. 启动低延迟播放。

   ```text theme={null}
   pw-play --target=pal_sink_speaker_ll /opt/clip1.wav -v
   ```

   ```text theme={null}
   pw-play --target=pal_sink_headset_ll /opt/clip2.wav -v
   ```

### **使用 PipeWire 进行动态设备切换**

使用 `wpctl` 在音频活动时触发动态设备切换。

1. 列出所有可用的音频节点。

   ```text theme={null}
   wpctl status
   ```

2. 在默认设备（例如扬声器）上开始播放。

   ```text theme={null}
   pw-play /opt/test.wav -v
   ```

3. 在播放期间，通过设置新的默认接收端切换到不同的输出设备（例如耳机）。

   ```text theme={null}
   wpctl set-default <headset sink node ID>
   ```

   WirePlumber 会重新路由流，PAL 会无缝执行设备切换。

## **启用 DP 和 HDMI 音频**

本节适用于 QCS6490 (Kodiak) 和 IQ-9075 (Lemans) 平台（config1）。

### **设置 QCS6490 (rb3-gen2-core-kit)**

1. 将拓扑二进制文件复制到固件路径。

   ```text theme={null}
   cp \\sphere\CasaBuilds\QLI\Topology\QCS6490\QCS6490-RB3Gen2-tplg.bin /lib/firmware/qcom/qcs6490/
   ```

2. 复制 HiFi 配置文件。

   ```text theme={null}
   cp \\sphere\CasaBuilds\QLI\Topology\QCS6490\HiFi.conf.kodiak /usr/share/alsa/ucm2/Qualcomm/qcs6490/QCS6490-RB3Gen2/HiFi.conf
   ```

3. 复制 HDMI 格式配置文件。

   ```text theme={null}
   cp \\sphere\CasaBuilds\QLI\Topology\QCS6490\51-hdmi-format.conf /usr/share/wireplumber.conf.d/51-hdmi-format.conf
   ```

4. 重启设备。启动时，确保 DP 已连接（typeC 转 HDMI 母头 + HDMI 转 HDMI 线缆）。

   ```text theme={null}
   reboot
   ```

**HDMI 和 DP 音频播放 (QCS6490)**

| HDMI 音频播放 | DP 音频播放 |
| :- | :- |
| `amixer -c 0 cset iface=MIXER,name='SECONDARY_MI2S_RX Audio Mixer MultiMedia3' 1` | `amixer -c 0 cset iface=MIXER,name='DISPLAY_PORT_RX_0 Audio Mixer MultiMedia4' 1` |
| `aplay -D plughw:0,2 /home/test.wav` | `aplay -D plughw:0,3 /home/test.wav` |
| `wpctl set-default <node>` | `wpctl set-default <node>` |
| `pw-play -v /home/test.wav` | `pw-play -v /home/test.wav` |

### **设置 IQ-9075 (iq-9075-evk)**

1. 将拓扑二进制文件复制到固件路径。

   ```text theme={null}
   cp \\sphere\CasaBuilds\QLI\Topology\IQ-9075\LEMANS-EVK-tplg.bin /lib/firmware/qcom/sa8775p/
   ```

2. 复制 HiFi 配置文件。

   ```text theme={null}
   cp \\sphere\CasaBuilds\QLI\Topology\IQ-9075\HiFi.conf.lemans /usr/share/alsa/ucm2/Qualcomm/sa8775p/lemans-evk/HiFi.conf
   ```

3. 重启设备。启动时，确保 DP 已连接（eDP 转 DP 线缆）。

   ```text theme={null}
   reboot
   ```

**DP 音频播放 (IQ-9075)**

| DP 音频播放 |
| :- |
| `amixer -c 0 cset iface=MIXER,name='DISPLAY_PORT_RX_0 Audio Mixer MultiMedia3' 1` |
| `aplay -D plughw:0,2 /home/test.wav` |
| `wpctl set-default <node>` |
| `pw-play -v /home/test.wav` |

## **设置并验证 Shikra 音频（Config 1 和 Config 2）**

本节介绍 Config 1 和 Config 2 下 CQS、CQM 和 IQS 外形规格的 Shikra 音频验证流程。

<Note>
  请将 `<SHIKRA_IP>` 和 `<audio-file>.wav` 等占位符替换为适用于你的设置的值。
</Note>

### **Config 1 验证**

Config 1 使用拓扑二进制文件和混音器命令，进行基于 ALSA 的播放和录音验证。

#### **外形规格映射**

| **外形规格** | **拓扑二进制文件** | **播放设备** | **录音设备** |
| :- | :- | :- | :- |
| CQS | `shikra-cqs-evk-tplg.bin` | `plughw:0,0` | `plughw:0,2` |
| CQM | 无需复制拓扑 | `plughw:0,2` | `plughw:0,3` |
| IQS | `shikra-iqs-evk-tplg.bin` | `plughw:0,0` | `plughw:0,2` |

#### **主机准备**

```text theme={null}
sudo apt update
sudo apt install -y wget
wget https://raw.githubusercontent.com/AudioReach/audioreach-conf/master/qcom/qli/SHIKRA_CQS/shikra-cqs-evk-tplg.bin
wget https://raw.githubusercontent.com/AudioReach/audioreach-conf/master/qcom/qli/SHIKRA_IQS/shikra-iqs-evk-tplg.bin
```

#### **CQS 验证**

对 CQS 外形规格使用此流程，包括拓扑传输、音频文件复制、目标验证、重启、播放和录音验证。

**设置和文件传输**

```text theme={null}
scp shikra-cqs-evk-tplg.bin root@<SHIKRA_IP>:/lib/firmware/qcom/shikra/
scp <audio-file>.wav root@<SHIKRA_IP>:/usr/
ls -l /lib/firmware/qcom/shikra/
reboot
```

**播放**

```text theme={null}
amixer -c 0 cset name='SECONDARY_TDM_RX_0 Audio Mixer MultiMedia1' 1
amixer -c 0 cset name='Rx Slot Mask' 3
amixer -c 0 cset name='Speaker Volume' 72
amixer -c 0 cset name='Usage Mode' 3
aplay -D plughw:0,0 -r 48000 -f S16_LE -c 2 /usr/<audio-file>.wav -vv
```

**录音**

```text theme={null}
amixer -c 0 cset iface=MIXER,name='VA DEC0 MUX' 'VA_DMIC'
amixer -c 0 cset iface=MIXER,name='VA DMIC MUX0' 'DMIC0'
amixer -c 0 cset iface=MIXER,name='VA_AIF1_CAP Mixer DEC0' 1
amixer -c 0 cset iface=MIXER,name='VA_DEC0 Volume' 100
amixer -c 0 cset name='MultiMedia3 Mixer VA_CODEC_DMA_TX_0' 1
arecord -D plughw:0,2 -c 1 -d 10 -f S16_LE -r 48000 /tmp/rec.wav
```

#### **CQM 验证**

对 CQM 外形规格使用此流程。此路径需要复制音频文件，但不包括拓扑二进制文件传输。

**设置和文件传输**

```text theme={null}
scp <audio-file>.wav root@<SHIKRA_IP>:/usr/
```

**播放**

```text theme={null}
amixer -c 0 cset name='Rx Slot Mask' 3
amixer -c 0 cset name='Speaker Volume' 72
amixer -c 0 cset name='Usage Mode' 3
aplay -D plughw:0,2 -r 48000 -f S16_LE -c 2 /usr/<audio-file>.wav
```

**录音**

```text theme={null}
amixer -c 0 cset iface=MIXER,name='VA DEC0 MUX' 'VA_DMIC'
amixer -c 0 cset iface=MIXER,name='VA DMIC MUX0' 'DMIC0'
amixer -c 0 cset iface=MIXER,name='VA_AIF1_CAP Mixer DEC0' 1
amixer -c 0 cset iface=MIXER,name='VA_DEC0 Volume' 100
arecord -D plughw:0,3 -c 1 -d 10 -f S16_LE -r 48000 /tmp/rec.wav
```

#### **IQS 验证**

对 IQS 外形规格使用此流程，包括拓扑传输、音频文件复制、目标验证、重启、启动 remoteproc、播放和录音验证。

**设置和文件传输**

```text theme={null}
scp shikra-iqs-evk-tplg.bin root@<SHIKRA_IP>:/lib/firmware/qcom/shikra/
scp <audio-file>.wav root@<SHIKRA_IP>:/usr/
ls -l /lib/firmware/qcom/shikra/
reboot
echo start > /sys/class/remoteproc/remoteproc0/state
```

**播放**

```text theme={null}
amixer -c 0 cset iface=MIXER,name='Left Speaker Mixer Left DAC Switch' on
amixer -c 0 cset iface=MIXER,name='Right Speaker Mixer Right DAC Switch' on
amixer -c 0 cset name='Speaker Left Switch' on
amixer -c 0 cset name='Speaker Right Switch' on
amixer -c 0 cset name='Speaker Switch' on
amixer -c 0 cset iface=MIXER,name='Speaker Volume' '10'
amixer -c 0 cset iface=MIXER,name='Speaker Left Mixer Volume' '3'
amixer -c 0 cset iface=MIXER,name='Speaker Right Mixer Volume' '3'
amixer -c 0 cset iface=MIXER,name='Speaker Switch' 1
amixer -c 0 cset iface=MIXER,name='Playback Path DC Blocking' 1
amixer -c 0 cset iface=MIXER,name='PRIMARY_MI2S_RX Audio Mixer MultiMedia1' 1
aplay -D plughw:0,0 -r 48000 -f S16_LE -c 2 /usr/<audio-file>.wav
```

**录音**

```text theme={null}
amixer -c 0 cset iface=MIXER,name='VA DEC0 MUX' 'VA_DMIC'
amixer -c 0 cset iface=MIXER,name='VA DMIC MUX0' 'DMIC0'
amixer -c 0 cset iface=MIXER,name='VA_AIF1_CAP Mixer DEC0' 1
amixer -c 0 cset iface=MIXER,name='VA_DEC0 Volume' 100
amixer -c 0 cset name='MultiMedia3 Mixer VA_CODEC_DMA_TX_0' 1
arecord -D plughw:0,2 -c 1 -d 10 -f S16_LE -r 48000 /tmp/rec.wav
```

#### **Config 1 故障排除**

* **无播放音频：** 验证是否为 CQS 或 IQS 复制了正确的拓扑二进制文件，确认所选外形规格使用了正确的 `plughw` 设备，并在执行 `aplay` 之前按顺序重新运行所有混音器命令。
* **无录音输出：** 确认 VA DMIC 路由命令已成功完成，验证使用了正确的采集设备，并检查录音后是否创建了 `/tmp/rec.wav`。
* **拓扑未加载：** 确认二进制文件位于 `/lib/firmware/qcom/shikra/` 下，重启目标设备，然后再次运行 `echo start > /sys/class/remoteproc/remoteproc0/state`。

### **Config 2 验证**

Config 2 使用基于 PipeWire 的播放和录音验证。CQS 和 IQS 外形规格的设置相同。

#### **前提条件**

* 可访问目标 Shikra Config 2 设备
* 具有运行 `systemctl`、`chmod` 和 PipeWire 命令权限的 shell 访问
* 用于推送播放 WAV 文件的 ADB 访问
* 可用的测试音频文件 `yesterday_48KHz.wav`

#### **PipeWire 设置**

在目标设备上运行以下命令，以重置 PipeWire 服务并应用所需的设备权限：

```text theme={null}
echo start > /sys/class/remoteproc/remoteproc0/state
systemctl stop pipewire wireplumber pipewire-pulse
systemctl stop pipewire-manager.socket pipewire.socket pipewire-pulse.socket
chmod 777 /dev/dma_heap/qcom,audio
chmod 777 /dev/aud_pasthru_modem
systemctl start pipewire
```

#### **PipeWire 节点验证**

启动 PipeWire 后，验证音频节点是否已填充：

```text theme={null}
wpctl status
```

输出中应列出相关的音频节点。在 PipeWire 节点可用之前，请勿继续进行播放或录音验证。

#### **播放验证**

将测试文件推送到目标设备并运行播放：

```text theme={null}
adb push <audio-file>.wav /usr/
pw-play /usr/<audio-file>.wav
```

#### **录音验证**

```text theme={null}
pw-record /tmp/rec.wav -v
```

验证录音是否成功启动，并且已创建 `/tmp/rec.wav`。

#### **Config 2 快速验证摘要**

| **步骤** | **命令** | **预期结果** |
| :- | :- | :- |
| 停止服务和套接字 | `systemctl stop pipewire wireplumber pipewire-pulse` | PipeWire 相关服务已重置 |
| 应用权限 | `chmod 777 /dev/dma_heap/qcom,audio` 和 `chmod 777 /dev/aud_pasthru_modem` | 所需设备节点可访问 |
| 启动 PipeWire | `systemctl start pipewire` | PipeWire 成功启动 |
| 检查节点 | `wpctl status` | PipeWire 节点已填充 |
| 播放测试 | `pw-play /usr/<audio-file>.wav` | 音频播放正常 |
| 录音测试 | `pw-record /tmp/rec.wav -v` | 录音启动并创建文件 |

#### **Config 2 故障排除**

* **无 PipeWire 节点：** 重新检查服务启动情况和设备权限。
* **播放失败：** 确认 WAV 文件存在于目标设备上的预期路径中。
* **录音失败：** 验证输入路径，并检查 `pw-record` 的详细输出。

## **后续步骤**

* [Audio Addendum](https://dragonwingdocs.qualcomm.com/Technologies/Audio/audio-addendum-overview) — 使用 QACT 和 QXDM 进行校准和诊断
* [故障排除音频](troubleshoot-audio) — 捕获并分析音频日志以解决问题
* [自定义音频图](customize-audio-graph) — 修改音频图和 PAL 配置
