基于炬芯ATS3089X的蓝牙A2DP之SBC编码算法音频数据导出实现

44.1KHZ, 立体声

44.1KHZ, 立体声

A2DP 蓝牙音乐 SBC / PCM / WAV 同时导出说明

1. 本次功能

手机通过经典蓝牙 A2DP 向开发板播放 **SBC 音乐** 时,使用一条启动指令,同时采集:

  1. **解码前**:设备实际收到、成功写入解码器输入流的原始 SBC 压缩帧。

  2. **解码后**:炬芯原厂 DSP 的 `DECODE_OUT1` 节点输出的 PCM 样本。

上位机按最后确认的需求,同时保存 **3 个音频文件**:

| 文件 | 内容 | 试听方式 |

| --- | --- | --- |

| `a2dp_received.sbc` | 原始 SBC 完整帧,已去掉 SDK 包头和对齐填充 | 使用支持原始 SBC 的解码器,例如 FFmpeg |

| `a2dp_decoded.pcm` | 原厂 DSP 解码后的裸 PCM | 在 Audacity 等工具中按实际参数导入 |

| `a2dp_decoded.wav` | 与上述 PCM 完全相同的样本,加上标准 WAV 文件头 | 直接打开试听 |

另有 `metadata.json` 和中文 `试听说明.txt`,记录采样率、声道、时长、CRC32、异常状态等。WAV 不再次压缩、不调音量、不重采样;其数据区与 PCM 文件逐字节一致。

本功能独立于原厂通话上下行/AEC dump,只有执行启动命令才复制音频。采集期间先存内存,不写 NAND,不通过 USB 实时推送音频;结束后统一导出到电脑。

2. v3 推荐流程:普通串口启动,PC 仅导出

本次错误的原因和修复

`log_26_10_12.txt` 的 15:26:02 明确出现 `A2DP dump input observer unavailable`,15:26:09 的状态为:

```text

A2DPDUMP,SOURCE,1,1,0,1,1,2,44100,1

```

这说明播放器和输入流存在,但 `observer=0`,SBC 采集观察接口没有挂上。后续截图即使已经 `codec=SBC` 仍为 `observer=0`,并返回 `-16`,对应旧的 `stream_set_observer()` 注册失败。它的两个通用观察槽没有空闲位置时返回 `-EBUSY`;v2 反复重试同一接口无法解决。这个位置的 `-16` 不能直接解释为用户启动了其他录音。

另一次直接读取 COM14 原始数据得到:

```text

A2DPDUMP,STATUS,0,0,0,0spinand power off ...

```

USB 普通日志镜像使用 4096 字节队列,允许在队列满时丢字节,而且不同线程的打印可以交错。旧版把 SOURCE/STATUS 等协议回复也当普通日志发送,造成状态字段截断、混入日志,PC 因此报"协议版本或字段数量错误"。这类错误不表示 SBC 解码出错,也不能直接判定为固件版本不匹配。

v3 做了两处修复:

  1. 在 `bt_manager_a2dp.c` 已有的接收处理里,原包成功写入解码输入流后调用独立的只读回调,不再占用通用 stream 观察槽。未采集时回调立即返回,不改变播放数据。

  2. A2DP 命令的 SOURCE/STATUS/QUEUED/CODEC/CLEARED/同步 ERROR 回复使用独占 CDC 发送,等待队列空间,并在结尾等待发送完成。期间正常 UART 仍能打印,CDC 不插入普通日志。PC 对损坏的状态查询最多重试 3 次,仍损坏时指出具体帧和原始内容。

操作步骤

烧录本文末尾的 **v3 固件**,使用更新后的 `a2dp_dump.py`。普通串口助手连接 UART 口,例如 COM11;PC 导出使用开发板 USB CDC,例如 COM14,二者可以同时使用,只要不要同时占用 COM14。

若已确认 `codec=SBC`,直接开始录制。若仍为 AAC,先在普通串口发送 `app a2dp_dump codec sbc`,重启开发板、重新连接手机并播放音乐。策略设置只有重启后才影响端点注册;它不是当前连接实时改编码的指令。

在手机音乐持续从开发板喇叭播放时,在**普通串口**发送:

```text

app a2dp_dump status

app a2dp_dump start 10

```

v3 正常应看到 `SOURCE` 的 `player/input/observer=1/1/1`、`codec=0`。等待:

```text

a2dp_dump: started ... codec=SBC ...

a2dp_dump: done ... ready=1 ... error=0

```

随后在工程 `` 目录的 PowerShell 执行**仅导出**:

```powershell

python .\application\bt_watch\tools\a2dp_dump\a2dp_dump.py export --port COM14 --output-dir D:\logs\a2dp

```

`export` 只请求已有快照,不发送 `status` 或 `start`,不重新录制,也不修改手机编码。音乐可以继续播放;快照保存为原始 SBC、DSP 解码 PCM 和同样本 WAV,另有元数据和中文说明。

`export` 不自动清除板端快照,因此同一段可以反复导出。下次开始新录制前,在普通串口明确执行:

```text

app a2dp_dump clear

app a2dp_dump start 10

```

已有重要数据应先导出成功再 clear。错误 `-17` 表示还保留着快照,`-16` 在 v3 中仍可能表示真实的其他 dump/录音占用,`-134` 表示当前实际编码不是 SBC。

3. 兼容方式:一条 PowerShell 命令完成采集和保存

以下命令在工程 `` 目录执行,例如:

```powershell

Set-Location D:\Master\6project\ATS3089C_to_ATS3089P\

python -m pip install pyserial

```

准备步骤:烧录本次固件,让手机连接开发板并持续播放蓝牙音乐;确认手机当前协商的是 **SBC**。插入开发板 USB 数据线,在 Windows 设备管理器确认其 CDC 虚拟串口号,例如 `COM14`,关闭占用这个 COM 的其他串口工具。

执行下面**一条指令**,同时采集 10 秒 SBC 和 PCM,自动等待结束、导出、校验并保存 SBC/PCM/WAV:

```powershell

python .\application\bt_watch\tools\a2dp_dump\a2dp_dump.py capture --port COM14 --seconds 10 --output-dir D:\logs\a2dp

```

不填 `--seconds` 时默认 5 秒,允许 1~10 秒。示例目录:

```text

D:\logs\a2dp\a2dp_sbc_20261016_132500_123456\

a2dp_received.sbc

a2dp_decoded.pcm

a2dp_decoded.wav

metadata.json

试听说明.txt

```

每次生成带时间的独立目录,已有文件不覆盖。默认在两路 CRC32 校验、SBC 帧结构检查、PC 写文件均成功后,自动清除本次板端快照,以便下次直接再次执行 `capture`。

如需在板端保留快照,增加 `--keep`:

```powershell

python .\application\bt_watch\tools\a2dp_dump\a2dp_dump.py capture --port COM14 --seconds 10 --output-dir D:\logs\a2dp --keep

```

导出失败会保留板端快照。新一次 `capture` 如果发现已有 `ready=1` 的快照,会提示先导出或清除,不会静默覆盖。

编码及播放源诊断(v2 增加,v3 保留)

`-128` 是当前 Zephyr/Newlib SDK 的 `ENOTCONN`。旧版启动采集时,播放器/输入流不存在,或者输入观察接口未挂接,都会被归为这个错误,因此仅凭错误码无法判断是哪一环失败。v2 增加了 SOURCE 和真实注册错误提示;v3 进一步改用独立的接收回调,解决旧观察接口槽位不可用的问题。

板端 `codec_id 2`、`sample_rate 44` 表示最近协商的是 **AAC / 44100 Hz**,本次排查已读到这两个值。AAC 音乐能正常播放,但不能直接保存为原始 SBC;必须先重新协商 SBC。`STREAM_SUSPEND` 后播放器句柄会关闭,查询到空句柄只代表查询瞬间的状态,不能用它判断此前有声时的播放情况。

v2 的 PC 工具会在启动前读取实时 `SOURCE`,打印播放器、输入流、观察接口、A2DP/AVRCP、编码、采样率及当前音乐模式;若播放器尚未打开,最多等待 5 秒再判断。上位机错误表也已改为本 SDK 的编号,不套用 Linux errno。

手机不能手动选择 SBC 时

烧录 v3 固件后,在普通串口发送:

```text

app a2dp_dump codec sbc

```

或者在 PC 使用同一 CDC 口设置:

```powershell

python .\application\bt_watch\tools\a2dp_dump\a2dp_dump.py codec --port COM14 --mode sbc

```

**然后重启开发板,并在手机重新连接蓝牙、重新播放音乐。** 如果手机保留旧能力导致仍选择 AAC,在手机删除此蓝牙配对后重新配对。设置命令只保存策略,不自动重启、断开音乐或清除快照;只断连重连而不重启,仍会使用原来已注册的 AAC 能力。

原理:`bt_manager_config_support_a2dp_aac()` 在蓝牙启动注册端点时读取 `A2DP_DUMP_SBC` 属性,选择 SBC 测试模式后不注册 AAC 接收端点,因此手机重新连接时只能协商已开放的 SBC。SBC 文件仍是手机发送的原始 SBC,不是把 AAC 转码得到的文件。此策略保存到非易失属性区,重新上电仍保留。

测试结束恢复正常的 SBC/AAC 能力:

```text

app a2dp_dump codec auto

```

同样需要重启并重连。PC 对应命令为 `python .\application\bt_watch\tools\a2dp_dump\a2dp_dump.py codec --port COM14 --mode auto`。默认策略为 `auto`,按照工程原配置开放编码。

查询已保存策略:`app a2dp_dump codec status`,或 `python .\application\bt_watch\tools\a2dp_dump\a2dp_dump.py codec --port COM14`。返回 `A2DPDUMP,CODEC,1` 表示下次启动仅开放 SBC,`0` 表示原配置;它不是当前正在使用的编码,当前编码以以下 SOURCE 为准。

只查询状态、不启动采集:

```powershell

python .\application\bt_watch\tools\a2dp_dump\a2dp_dump.py status --port COM14

```

普通 UART 或 CDC 仍可发送 `app a2dp_dump status`。v2/v3 先输出:

```text

A2DPDUMP,SOURCE,player,input,observer,a2dp,avrcp,codec,rate,mode

```

`player/input/observer` 正常应为 `1/1/1`;`codec=0` 为 SBC,`codec=2` 为 AAC;`rate` 是实际 Hz;`mode=1` 为蓝牙音乐,`mode=0` 为本地音乐。AAC 播放不能以 SBC 文件导出,工具会明确提示。旧版固件未提供 SOURCE 时,新工具仍可解释其 SDK 错误码。

USB 没有枚举 CDC 时

沿用工程现有 USB 自动监听配置。如当前处于 U 盘或 USB 声卡模式,或者 CDC 自动监听被关闭,在**普通 UART 串口**发送:

```text

app usbserial on

```

等待 Windows 出现 CDC COM 口后再运行 Python 命令。`--port` 必须填写开发板的 **USB CDC 虚拟串口**,不能填写普通 UART 转串口板的端口。无需进入 `app udisk on`;进入 U 盘模式会占用本功能导出所需的 USB 接口。

4. 普通串口命令与快照状态

也可以先在普通 UART 串口发送:

```text

app a2dp_dump start 10

```

这条指令同时开启 SBC 与解码 PCM 两路采集,到时自动停止,音乐继续播放。采集开始前必须已经有 SBC 蓝牙音乐在播放;该命令不会主动连接手机或开始播放歌曲。

常用命令:

| 指令 | 说明 |

| --- | --- |

| `app a2dp_dump start` | 同时采集两路,默认 5 秒 |

| `app a2dp_dump start 10` | 同时采集两路,目标 10 秒 |

| `app a2dp_dump status` | 查询状态、格式、字节数、SBC 帧数、异常情况 |

| `app a2dp_dump stop` | 提前停止当前两路采集,保留已有数据 |

| `app a2dp_dump clear` | 清除板端快照状态,允许再次采集;不删除电脑文件 |

| `app a2dp_dump export` | 请求从 USB CDC 输出二进制快照,供上位机协议接收 |

| `app a2dp_dump codec sbc` | 保存 SBC 测试策略;重启并重连手机后只开放 SBC 接收 |

| `app a2dp_dump codec auto` | 恢复工程原编码策略;重启并重连生效 |

| `app a2dp_dump codec status` | 查询已保存的策略;实际编码通过 `status` 查询 |

`start` 成功返回 `A2DPDUMP,QUEUED,10` 只表示请求已入队。播放器线程实际启动后会打印:

```text

a2dp_dump: started id=1 seconds=10 codec=SBC rate=44100 pcm_channels=2 bits=16

```

完成后打印 `a2dp_dump: done ... ready=1 ... error=0`。状态行格式:

```text

A2DPDUMP,STATUS,id,pending,attached,capturing,ready,exporting,seconds,rate,channels,sbc_bytes,pcm_bytes,error,export_error

```

其中 `pending` 是等待播放器线程执行,`attached` 是 DSP dump 仍然挂接,`capturing` 是正在采样,`ready` 是已有两路数据,`exporting` 是正在发送 USB。应等 `attached=0`、`ready=1` 后导出。

在电脑执行**仅导出**命令:

```powershell

python .\application\bt_watch\tools\a2dp_dump\a2dp_dump.py export --port COM14 --output-dir D:\logs\a2dp

```

`export` 不重新采集,也不自动清除,可对同一快照重复导出。下一次手动启动前执行 `app a2dp_dump clear`。二进制导出请交给 Python 接收,普通文本串口保存不能替代本协议的分帧和 CRC 校验。

5. 音频格式与试听

PCM 固定为 **16 bit、有符号、小端 S16LE**。采样率和声道跟随当前蓝牙音乐播放器,不能固定按通话的 16 kHz 单声道打开。

例如协商为 `rate=44100 channels=2` 时,在 Audacity 导入 `a2dp_decoded.pcm` 应选择:

```text

编码:Signed 16-bit PCM

字节序:Little-endian

声道:2(立体声交织,L0 R0 L1 R1 ...)

采样率:44100 Hz

偏移:0

```

若状态为 48000 Hz,则选择 48000 Hz。优先打开 `a2dp_decoded.wav`,播放器会自动读取参数。44.1 kHz 双声道 PCM 每秒为 176400 字节,10 秒为 1764000 字节;48 kHz 双声道每秒为 192000 字节。

SBC 的 `source_channels` 表示收到的压缩帧声道数,PCM 的 `channels` 表示解码输出布局。单声道 SBC 在配置为立体声输出的播放器中,可能输出两声道 PCM;两者分别记录,不能混为一谈。

电脑已有 FFmpeg 时,可以另行解码原始 SBC 来分析:

```powershell

ffmpeg -f sbc -i .\a2dp_received.sbc .\sbc_pc_decode.wav

```

该额外命令产生的文件是 PC 独立解码结果;默认导出的 `a2dp_decoded.pcm/.wav` 始终来自**板端原厂 DSP**,不是 PC 将 SBC 再解码后冒充的结果。运行日常导出工具只需要 `pyserial`,不依赖 FFmpeg。

6. 数据来源与实现原理

```text

手机 SBC 编码

↓ 蓝牙 A2DP 接收、SDK 处理 RTP

SDK 8 字节包头 + SBC 帧 + 对齐填充

↓ 成功写入 bt_player 输入流

├─ 蓝牙管理器成功写入后的只读回调 → 校验包/帧长度 → 去掉包头及填充 → SBC 快照

↓

原厂 DSP SBC 解码器

├─ DECODE_OUT1 → 2 KB 共享 ring → CPU 每 2 ms 搬运 → PCM 快照

↓

原有播放链路 / DAC / 喇叭

采集结束:撤销 DSP dump → USB CDC 双路数据 + CRC32 → PC 保存 SBC / PCM / WAV

```

SBC 从 `bt_manager_a2dp.c` 的 `BTSRV_A2DP_DATA_INDICATED` 分支、`stream_write()` 成功后调用独立只读回调复制,保留 SDK 原有观察者,不消耗或改写解码器输入。注册和回调均由已有 stream pool 锁保护,目标流不匹配或未采集时不保存数据,部分写入和失败写入不计入文件。这里抓取的是设备收到且成功提交给解码输入流的 SBC;空口没有收到、或者 SDK 未成功提交的数据无法包含在文件中。

SDK 的包头定义在 `framework/bluetooth/bt_service/profile/btsrv_a2dp.c`:4 个小端 16 位字段依次为 `frame_cnt`、`seq_no`、`frame_len`、`padding_len`,共 8 字节。代码逐包验证有效帧数、载荷长度、填充,按 SBC 帧头计算每帧长度,仅保存完整 SBC 帧。原始 SBC 中不包含这些 SDK 包头,不包含 RTP 包头,也不包含填充。

PCM 从 SDK 已有 `media_player_dump_data()` 接口挂接 `MEDIA_DATA_TAG_DECODE_OUT1`,由原厂 DSP 写共享 ring,CPU 搬入 PSRAM。整个过程复用当前 SBC 解码器,新增代码没有实现或替换 SBC 解码算法。

**两路由同一个请求启动,但不承诺第一帧/第一个样本完全对齐**:开始时输入队列已有缓存,DSP 又有解码延迟,因此两个文件内容可能有固定时间偏移。需要逐样本对比时,应先在电脑按相关性对齐;不能直接把两个文件的第 0 个样本当成同一播放时刻。SBC 按完整帧结束,其时长最多比目标多一个 SBC 帧。

7. 时长、互斥与完整性

  • 目标时长 1~10 秒,默认 5 秒。PCM 预留 1920000 字节,SBC 预留 512 KiB,均在 PSRAM。常见手机 SBC 码率可覆盖 10 秒;异常高码率达到 SBC 容量上限时会提前停止并报告 `-28`,已采集数据仍可导出。

  • 复用 SDK 音乐 dump 的 2 KiB 共享内存,不扩大已接近上限的 SHARE_RAM。采集线程优先级 9,每 2 ms 读取一次,采集阶段不写文件、不卡 USB 发送。

  • 与 `music_rec`、`call_rec`、`call_dump` 共享 dump 所有权,避免同时挂接覆盖共享区。资源忙返回 `-16`,先结束另一项录制再启动。TWS 混音和 SDK 调试 TOOL 同时使用此区域不属于本功能支持的采集场景;当前配置 `CONFIG_TOOL` 为关闭。

  • 采集中暂停音乐、蓝牙断连或通话抢占会先撤销 DSP dump,再释放 ring,保留已经获取的两路数据,报告 `-140`。如果其中一路完全没有数据,`ready=0`,不会伪造空音频成功。

  • 如果音频停止提供而播放器尚未关闭,目标时长加 2 秒后超时结束,报告 `-116`。

  • 导出失败不清除快照,USB 恢复后可重新运行 `export`。快照在内存中,关机/重启会丢失。

`metadata.json` 和板端 `status` 里的关键诊断:

| 字段 | 含义 |

| --- | --- |

| `sbc_frames` / `sbc_samples` | 完整 SBC 帧数 / 每声道音频样本数 |

| `packets` / `sequence_gaps` | 采集到的 SDK 包数 / RTP 序号不连续次数,包括丢包、重复或乱序 |

| `peak_poll_ms` | PCM 搬运线程的最大实际轮询间隔 |

| `ring_risk` | 共享 ring 曾接近满,可能存在 DSP 丢样风险 |

| `capture_error` / `export_error` | 板端采集 / USB 导出错误码(`export_error` 从 status 查询) |

| `sbc_crc32` / `pcm_crc32` | 验证 USB 传输的两个 CRC32 |

| `length_complete` | 两路是否达到请求的音频时长 |

| `complete` | 长度满足,且未报告采集错误、序号不连续或 ring 风险 |

CRC32 验证 USB 传输是否一致;它不能证明蓝牙空口没有丢包,或者 DSP 共享 ring 绝无丢样。当前 SDK 没有提供这个节点的精确丢样计数,因此 `complete=true` 也只表示本工具的现有检查均通过。

8. 常见问题

| 现象/错误码 | 处理 |

| --- | --- |

| `app unknown parameter: a2dp_dump` | 确认烧录本次带 `a2dp_sbc_dump` 名称的固件 |

| `-134` | 当前协商 AAC 等其他编码;在手机选择 SBC,或执行 `app a2dp_dump codec sbc` 后重启板子、重新连接手机 |

| `-128` | 启动时没有 A2DP 播放器/输入流,确认手机媒体输出选择开发板、开发板处于蓝牙音乐模式;通过 SOURCE 确认;若在 export 阶段出现则检查 CDC 模式 |

| `-17` | 已有快照,先 `export` 保存,或明确执行 `clear` 放弃 |

| `-16` | v2 若 `observer=0`,表示旧观察接口注册失败,更新 v3;v3 检查是否另一项 dump/录音或本次导出正在进行 |

| 控制帧不完整/混入日志 | 更新 v3 固件及工具;v3 回复独占 CDC,不走允许丢字节的普通日志镜像 |

| `-77` | 收到的帧结构或格式变化,不会把无效数据拼成 SBC;保留日志与 metadata 给研发 |

| `-88` | 输入流尚未打开,或观察接口不可用;结合 SOURCE 及普通串口日志检查 |

| `COM14 拒绝访问` | 关闭占用同一个 CDC 端口的串口助手/其他 Python 导出进程 |

| PCM 播放低沉、速度不对 | 使用实际 44100/48000 Hz 和正确声道,或直接打开 WAV |

| 中文显示异常 | 工具源码为 UTF-8,文本说明为 UTF-8 BOM;旧 PowerShell 可设置 `Console::OutputEncoding = System.Text.UTF8Encoding::new()` |

以上错误码取自本 SDK 的 `zephyr/lib/libc/minimal/include/errno.h` 和工具链 Newlib 头文件。旧版说明及工具错误地套用了 Linux 编号(例如 `-107/-95`),v2 已修正。

9. 代码文件与职责

下表路径以 `` 为根目录:

| 文件 | 职责 |

| --- | --- |

| `application/bt_watch/src/main/a2dp_dump.c` | SBC 包剥离与帧检查、PCM 快照、状态机、互斥、停止清理、USB 二进制导出 |

| `application/bt_watch/src/main/a2dp_dump.h` | 模块 API、最大时长/容量、状态结构 |

| `application/bt_watch/src/bt_player/bt_player.c` | 注册蓝牙管理器的专用只读输入回调,在播放器所属线程启动采集,播放器关闭前撤销 dump |

| `application/bt_watch/src/bt_player/bt_player.h` | 新增播放器采集消息,追加在原有消息末尾 |

| `application/bt_watch/src/main/system_app_shell.c` | `app a2dp_dump` 命令;`shell_a2dp_reply()` 完整格式化并通过可靠 CDC 回复,普通 UART 保留打印 |

| `framework/bluetooth/bt_manager/bt_manager_a2dp.c` | 独立接收回调的注册与成功写入后的调用,不占用通用 stream 观察槽 |

| `framework/bluetooth/bt_manager/bt_manager_config.c` | 可恢复的 SBC 测试策略、属性保存与开机 AAC 接收能力选择;默认沿用原配置 |

| `framework/bluetooth/include/bt_manager.h` | 独立接收回调及编码策略接口声明,仅在 A2DP dump 功能开启时编译 |

| `application/bt_watch/src/main/stock_call_dump.h` | 为新模块和已有音乐录制增加共享 dump owner 编号 |

| `application/bt_watch/src/main/music_rec.c` | 已有音乐录制的共享资源申请/释放,防止与新采集同时占用 ring |

| `application/bt_watch/Kconfig` | `CONFIG_APP_A2DP_DUMP` 开关;当前开发板满足依赖时默认开启 |

| `application/bt_watch/src/main/CMakeLists.txt` | 条件编译模块 |

| `application/bt_watch/tools/a2dp_dump/a2dp_dump.py` | **上位机源码**:`capture` 自动流程、`export` 接收、`status` 实时诊断、`codec` 策略设置、SDK 错误提示、字段/双 CRC/SBC 检查、PCM/WAV/中文说明保存 |

| `application/bt_watch/tests/a2dp_dump/run_tests.py` | FFmpeg 生成真实 SBC,ARM 仿真运行生产 C 代码并导出真实协议测试数据 |

| `application/bt_watch/tests/a2dp_dump/test_capture.c` | 原始字节、包头剥离、序号回绕、生命周期、资源互斥、编码策略与存储异常测试 |

| `application/bt_watch/tests/a2dp_dump/mock_platform.h` | 测试平台模拟,不参与固件编译 |

| `application/bt_watch/tests/a2dp_dump/test_pc_tool.py` | 上位机协议、分片、CRC/截断失败、自动流程、真实 SBC 解码以及 PCM/WAV 一致性测试 |

重要新增及修改处均使用 `//zk+` / `//zk+-` 和中文说明,Python/Kconfig/CMake 使用 `#zk+` / `#zk+-`。

USB 复用已有 `application/bt_watch/src/main/usb_serial_runtime.c` 和驱动接口,不需要额外串口板。GUI 未参与本功能,直接运行 Python/PowerShell 即可。

10. 导出协议与编译验证

协议版本 1:

```text

A2DPDUMP,BEGIN,1,id,start_ms,seconds,rate,channels,bits,sbc_bytes,pcm_bytes,sbc_frames,sbc_samples,source_channels,packets,sequence_gaps,ring_risk,peak_poll_ms,elapsed_ms,error\n

<sbc_bytes 字节 SBC 二进制>

<pcm_bytes 字节 PCM 二进制>

A2DPDUMP,END,id,SBC_CRC32,PCM_CRC32\n

```

两段数据之间没有分隔符,只能按头帧长度读取。两个 CRC 为各自数据的 IEEE CRC32,结束帧以 8 位大写十六进制表示。上位机保存 WAV 后额外增加的文件头不计入 PCM CRC32。

当前环境运行测试:

```powershell

python .\application\bt_watch\tests\a2dp_dump\run_tests.py

python .\application\bt_watch\tests\a2dp_dump\test_pc_tool.py

python .\application\bt_watch\tests\stock_call_dump\run_tests.py

python .\application\bt_watch\tests\stock_call_dump\test_pc_tool.py

```

ARM 仿真测试依赖 SDK 的 `arm-none-eabi-gcc`、工程测试目录中现有的 Unicorn/pyelftools,以及 `imageio-ffmpeg`。上位机测试覆盖 16/32/44.1/48 kHz、单/双声道的实际编码帧。日常用户采集只需要 Python 和 pyserial。

编译打包:

```powershell

Push-Location .\zephyr

python build.py -n -b ats3089p_dev_watch -a bt_watch

Pop-Location

```

本次带功能名的固件位于:

```text

application\bt_watch\outdir\ats3089p_dev_watch\_firmware\ats3089p_dev_watch_261016_a2dp_sbc_dump_v3.fw

application\bt_watch\outdir\ats3089p_dev_watch\_firmware\ats3089p_dev_watch_261016_a2dp_sbc_dump_v3_debug.fw

application\bt_watch\outdir\ats3089p_dev_watch\_firmware\ats3089p_dev_watch_261016_a2dp_sbc_dump_v3_SHA256.txt

```

软件验证包括 ARM 生产代码仿真、真实 SBC 标准解码、PC 协议与文件一致性,以及既有原厂通话 dump 回归。实板蓝牙采集吞吐和实际音乐听感需烧录后检查 `ring_risk`、`sequence_gaps` 与导出文件。

v3 的针对性验证覆盖:真实生产接收回调在成功写入时复制、失败/部分写入/其他输入流不采集、回调注册幂等及资源冲突、可靠控制回复完整且不重复镜像、CDC 不在线时普通 UART 仍输出,以及按实板现象构造的 SOURCE/STATUS 截断重试。固件已编译打包,尚需用户烧录 v3 后完成真实手机蓝牙音乐采集确认。

相关推荐
是店小二呀1 小时前
想用自己的音色给视频配音?我用Index-TTS跑通参考音频、语音生成和远程访问
人工智能·音视频·语音识别
揽秀亭长1 小时前
提取视频文案的工程选型|五类转写方案对比、可复现脚本与报错排查表
人工智能·音视频
quaer2 小时前
FFmpeg环境搭建10.16
音视频
Likeadust4 小时前
门店客流少、曝光弱?视频直播点播EasyDSS音视频平台解锁门店线上拓客新模式
网络·音视频·easydss
voipmaker4 小时前
融合通信调度录音的困局:基于 MediaX 网关实现对讲语音 AI 事件萃取
人工智能·ai·音视频·语音识别·实时音视频·信息与通信·iot
Sayai13 小时前
ComfyUI+混元视频实战:12G 显存跑 13G 模型,5 分钟出片(国产开源,附模型与工作流)
人工智能·aigc·音视频·comfyui·hunyuanvideo·混元视频
ACP广源盛1392462567315 小时前
项目评估记录:4K 视频墙方案调研,GSV9001E @ACP参数与工程问题记录
硬件架构·音视频·硬件工程·视频·国产芯片
AI视频工具指南21 小时前
怎么用 AI 做一两分钟的小故事视频?从结尾倒推故事
人工智能·aigc·音视频
AI视频工具指南1 天前
AI短剧怎么做?一个矛盾怎样接着讲三集
人工智能·aigc·音视频