基于Waveshare ESP32-S3-Touch-AMOLED-2.06的吉他放大器与效果器
摘要
CoyoPedal 是一款基于Waveshare ESP32-S3-Touch-AMOLED-2.06的独立吉他放大器和效果器,具备实时神经放大器建模和触摸屏UI。
查看缓存全文
缓存时间: 2026/09/28 01:42
dashersw/coyopedal
来源:https://github.com/dashersw/coyopedal
CoyoPedal CI (https://github.com/dashersw/coyopedal/actions/workflows/ci.yml)
许可证:GPL v3
[赞助 (https://github.com/dashersw/coyopedal?sponsor=1)]
一款基于微雪 ESP32-S3-Touch-AMOLED-2.06 构建的独立吉他音箱与效果器单块。它在 ESP32-S3 上实时运行全尺寸 Neural Amp Modeler (https://www.neuralampmodeler.com/) A2 音色捕捉,作为 USB 主机驱动符合类规范的 USB 音频接口,并拥有一个用 TSX 编写、编译为原生 C++ 的触摸屏用户界面——设备上没有 JavaScript 引擎。
屏幕是这块板子的一部分,而非单块本身:相同的固件也适用于完全没有面板的裸 ESP32-S3 模块,其中音箱、效果器和预设都是相同的,BOOT 按钮则充当脚踏开关。
在你的浏览器中试玩 → (https://coyopedal.playtaurus.com/)
这是固件编译为 WebAssembly 的版本:相同的用户界面、相同的数字信号处理、相同的神经网络音箱模型,通过音频接口播放你的吉他。无需板子即可尝试,无需安装任何东西。
- 全尺寸 NAM A2 模型,48 kHz 采样率。 23 层、8 通道的 WaveNet 以块浮点方式运行,使用手写 Xtensa 内核,分布在两个核心上,以 64 帧为一块进行处理。
- 加载你自己的音色捕捉。 将原始的
.nam文件复制到 microSD 卡,或将浏览器构建版指向一个文件夹。单块在设备上解析、验证并准备这些文件;无需桌面转换器。 - 围绕音箱的效果链: 前置有噪声门、压缩、合唱和过载;后置有数字延迟和立体声弹簧混响。
- 预设 用于音箱、控制和效果器,存储在单块中,并带有屏幕键盘用于命名。
- 调音器 在同一屏幕上,调音时输出静音。
- 维护模式 支持经身份验证的 Wi-Fi OTA 更新、远程诊断和 BLE 发现。演奏时无线电完全关闭。
硬件
支持的板子
| 板子 | 别名 | 闪存 | 具备什么 | 如何控制它 |
|---|---|---|---|---|
| 微雪 ESP32-S3-Touch-AMOLED-2.06 | amoled | 32 MB | ESP32-S3R8、8 MB PSRAM、410 × 502 AMOLED、触摸屏、AXP2101 电源管理芯片、microSD 卡槽 | 触摸屏;BOOT:轻触旁通,按住 1.5 秒进入维护模式 |
| ESP32-S3-DevKitC-1 N16R8 和裸 S3R8 模块 | s3-devkit | 16 MB | ESP32-S3R8、8 MB PSRAM、无面板、无电源管理芯片、无 SD 卡槽 | BOOT:轻触启用或旁通,按住 1.5 秒进入维护模式 |
AMOLED 板是参考板。工厂预设、浏览器构建和屏幕截图都是基于它制作的,固件中特定于面板的部分也是为它而存在的。没有屏幕的板子通过相同的数字信号处理以相同的 48 kHz 采样率运行相同的音箱——在开发板上测试,两个核心分别使用了 1,333 μs 块预算的 91% 和 94%,没有错过截止时间——并通过维护 API 而不是手动进行配置。
无论哪种板子,都必须具备:一个带有 8 MB PSRAM 的 ESP32-S3,因为 A2 模型存放在此;以及一个芯片可以作为主机驱动的 USB 端口。裸模块没有电源管理芯片和电池通路,因此与 AMOLED 不同,它不能为主机端口自身供电;接口需要你自己的电源供电。
其他部分
| 部件 | 备注 |
|---|---|
| 音频 | 板子 USB 端口上的 USB 音频类 2 接口,作为 USB 主机以 48 kHz 运行 |
| 存储 | 可选 microSD 卡(在带有卡槽的板子上),用于存放你自己的音色捕捉 |
| 测试过的设备 | XTONE Pro 和 IK Multimedia iRig HD X;iRig HD 2 通过专用的 UAC1 配置文件 |
接口通过其 USB 描述符进行发现,因此任何暴露 48 kHz UAC2 输入和输出的接口都应该可以工作。有关格式和限制,请参阅 USB 音频。
使用单块
主屏幕按信号顺序显示效果链。轻点一个模块以开启或关闭它,或按住以编辑它:拖动滑块改变值,并使用 ‹ › 翻页浏览控制项。按住 音箱 模块可打开音色捕捉浏览器,其中显示工厂音色、导入的音色和 SD 卡自身的文件夹。
右上角的开关旁通整个单块,调音器 打开调音器。轻点预设名称可切换、保存、重命名、删除或创建预设。新预设从当前声音开始。
在每块板子上,BOOT 都可作为脚踏开关:短按启用或旁通单块,按住则在音频和维护模式之间切换。当按住达到 1.5 秒时切换开始,因此屏幕会告诉你何时可以松手。在维护模式下,短按无任何作用。
在没有屏幕的板子上,预设、音色捕捉和其他控制项通过 tools/esp32/amoled_remote.py 在维护模式下访问。
单块启动时处于启用状态,使用记忆的预设,或在没有保存选择时使用第一个预设 Silver Lining(清音)。
你自己的音色捕捉
支持的模型是 48 kHz、8 通道 NAM A2(“A2-Full”)WaveNet,包括 SlimmableContainer 的一个匹配成员。其他架构、采样率和层形状会被拒绝并报错。处理后的 .namb 文件也被接受。
将卡格式化为 FAT,并将 .nam 或 .namb 文件放在根目录下的 nam 文件夹中的任何位置(最深可达六层文件夹);浏览器会按原样显示该树状结构,音色捕捉以其文件命名。文件名必须适合 127 字节,文件大小不超过 2 MiB。在通电前插入卡,然后从 音箱 浏览器中选择音色捕捉。
首次选择音色捕捉时,单块在准备它时会暂停音频。这可能需要几十秒。当卡可写时,单块会在原始文件旁边存储一个经过验证的 .s3cache 文件,以便后续加载更快。原始文件永远不会被修改。
完整的 VoLum 库发布在 VoLum 仓库中 (https://github.com/guitarlum/VoLum/tree/main/rigs),以下命令将其复制到挂载的卡上作为 /nam/VoLum//:
npm run fetch:volum -- /Volumes/SDCARD
在浏览器中使用相同的音色捕捉
coyopedal.playtaurus.com (https://coyopedal.playtaurus.com/) 运行的是固件本身,它没有卡槽,因此要求提供一个文件夹来替代,并从该文件夹响应固件的 SD 卡调用。
音色捕捉出现在单块自身音箱浏览器的 SD 卡 下,名称和 ID 与在卡上时相同;原始 .nam 文件使用相同的调音器处理,并作为 .s3cache 缓存在文件旁,就像板子缓存它一样;预设被镜像到文件夹中作为 coyopedal-presets.json——这与 assets/presets.json 是相同的文档,你可以在文本编辑器中打开、保存在仓库中或复制到卡上。
在浏览器中填充一个文件夹,将其复制到卡上,板子无需再次准备即可读取。Chrome 和 Edge 会写回文件夹;Safari 和 Firefox 只允许页面读取文件夹,因此那里的写入操作保存在浏览器自身的存储中。
构建
要求
- Git 和 Node.js 22.13 或更新版本
- Python 3,并安装 Pillow 和 fontTools,用于光栅化 UI 字体。npm 脚本会通过平台使用的名称(
python3、python或 Windows 的py启动器)找到它。 - 用于主机测试的 C++20 编译器和 CMake
- Emscripten SDK (https://emscripten.org/) 在
PATH中,仅用于 Web 构建。
Gea CLI 会安装其他所有内容,包括 ESP-IDF。
设置
- 安装 Gea CLI:
npm i -g @geastack/cli
- 安装 ESP-IDF 6.0.2 及其 ESP32-S3 工具链。它会安装到
~/esp/esp-idf;~/esp或~/esp32下的现有安装,或IDF_PATH指定的路径,会被自动找到。
gea setup --esp-idf
- 克隆仓库并安装其依赖项:
git clone [email protected]:dashersw/coyopedal.git
cd coyopedal
npm ci
- 生成 Wi-Fi 配置。只有在
src/native/services/remote_config.h存在时,维护模式、OTA 更新和远程工具才会被编译进去;克隆的仓库没有此文件,没有它的构建将是一个完全没有无线电的单块。此文件被 gitignore,因为它包含凭据。
npm run remote:configure -- --ssid YOUR_WIFI
它会询问 Wi-Fi 密码;单块在维护模式下加入该网络。可以跳过此步骤:构建时会在其位置写入一个禁用的占位符,之后生成真正的文件并重新构建就足够了。
- 通过 USB 连接板子并注册它:
gea setup
选择 已知的支持板子,然后选择 微雪 ESP32-S3 Touch AMOLED 2.06,并保持别名 amoled:npm 脚本使用它。选择检测到的 USB 设备。CLI 通过 USB 序列号识别板子,因此它出现在哪个端口并不重要。OTA 主机是可选的。对于没有屏幕的板子,请参阅下面的另一块板子;本节的其余部分相同。
- 检查工具链和板子:
gea doctor
构建和烧录
gea build --board amoled
固件映像写入 build/pedalboard.bin。ESP-IDF 构建目录保留在 .gea/build/ 中;你永远不需要打开它。
第一次烧录必须通过 USB,因为它还写入分区表和工厂数据以及固件:
gea flash --board amoled
添加 --dry-run 可查看将要写入的内容而不实际烧录。npm run build:firmware 和 npm run flash:firmware 运行相同的两个命令。--board s3-devkit 为无头板构建相同的固件;npm 脚本是 amoled 的简写。
在 AMOLED 上,闪存布局为两个 8 MB 的 OTA 槽、一个工厂模型分区、一个工厂预设分区和一个用于导入模型的分区。保存的预设位于 NVS 中,烧录不会擦除它。具有不同闪存大小的板子有自己专属的布局——见下文。
另一块板子
固件不携带板子列表。它询问目标定义硬件有什么,并编译掉不存在的部分,两个问题决定了几乎所有事情。
是否有屏幕? 一个既没有 chips.display 也没有 canvas 的目标定义意味着该板子完全没有显示器,构建时会得到 GEA_EMBEDDED_NO_DISPLAY=1:没有帧缓冲区、没有应用树、没有帧调度器、没有运行时任务。这大约节省了 1 MB 的映像和 1.25 MB 的 PSRAM,这是带面板的板子才会分配而这块板子永远不会分配的。请注意,一个没有面板的 canvas 是另一回事——一个仍然进行渲染的离屏表面,用于截图和 OTA 预览——因此“无显示”意味着 两者都 缺失。不要给无头板一个空的 canvas。
是否有电源管理芯片? 一个声明没有电源芯片的定义以 GEA_BOARD_HAS_POWER=0 进行构建,src/native/drivers/power.cpp 会编译为空操作,而不是因链接不到板子上不存在的 AXP2101 而失败。
要启用一块新板子:
- 在
@geastack/targets中选择或编写其目标定义。开发板的是targets/esp32-s3-devkit-n16r8.json。 - 使用
gea setup为其注册一个别名,或在.gea/boards.json中手动注册:目标 ID、适配器(esp32-idf)、板子的 USB 序列号,以及当闪存大小不是 32 MB 时的flashSize。 - 如果闪存大小与 AMOLED 不同,请在
package.json的gea.targets.esp32.partitionsByTarget下添加该板子的分区布局,以目标 ID 为键。默认的gea.targets.esp32.partitions保持为 32 MB 的那个,没有自己条目的板子使用它。 gea flash --board --monitor。
在编译时板子行为异常时值得了解一条规则:应用程序自身的 gea.defines 优先于板子的。单块声明其显示尺寸,因此也声明了 canvas 大小的板子不能重新定义它们。
检查和测试
npm test # USB 描述符、效果器、预设和准备好的 NAM 模型
npm run check # lint、TypeScript 和格式化
GitHub Actions 在每次推送和拉取请求时运行这两项,并构建固件映像和 Web 模块。运行器没有板子,因此固件任务止于映像——这仍然是值得拥有的东西,因为音箱图、面板和驱动程序只在链接步骤相遇。
两种浏览器构建
npm run dev 是 DOM 预览:相同的 TSX 被重新编译到 Web 框架上,并由浏览器布局。它迭代速度快,且在你想要信任它的地方与板子保持一致。部署的页面是另一个。
geatsc 将相同的 TSX 降低到 C++,emcc 将其与固件运行的相同 Gea 布局和绘图引擎链接,因此页面显示的就是面板显示的内容:
npm run build:web-wasm
npm run serve:web
本地提供服务很重要:音频图在 AudioWorklet 中通过共享内存运行,浏览器只向跨源隔离的文档提供 SharedArrayBuffer,而 scripts/serve-web.mjs 和 web/_headers 文件安排了这一点。推送到 main 会发布它。GitHub Actions 构建模块并将其上传到提供服务的 R2 存储桶,因此页面及其命名的模块总是同时打上时间戳并一起上传。该工作流运行 scripts/deploy-web.sh,它会暂存 build/site 并上传;你自己运行它可以在没有推送的情况下发布,它需要在环境或仓库永不跟踪的 .env 文件中设置 CLOUDFLARE_ACCOUNT_ID 和 CLOUDFLARE_API_TOKEN。--stage 在暂存后停止。
该令牌是一个 R2 API 令牌,仅对此一个存储桶具有对象读写权限,没有其他权限。上传通过 R2 的 S3 API 进行,而不是通过 Wrangler,因为 Wrangler 的 r2 object 命令使用 REST 端点,该端点仅接受帐户范围的 R2 管理令牌,并对如此狭义范围的令牌返回 403。该令牌是唯一需要的秘密:scripts/r2-credentials.sh 从中派生出 S3 密钥对。存储桶通过自定义域提供服务,web/_headers 中的两个跨源隔离头部由区域上的响应头部转换规则设置:R2 只提供对象作为元数据携带的头部,这两个头部不在其中。Cache-Control 是按对象设置的,脚本会设置它。
维护模式和 OTA 更新
维护模式卸载音频图并启动 Wi-Fi 和 BLE。通过轻点预设名称,然后 设置,然后 维护模式,或使用板子的 BOOT 按钮进入——在任意一块板子上按住直到屏幕显示“请稍候”,大约 1.5 秒。
再次按住它,或选择 返回效果器板,会重新启动进入音频模式并关闭无线电。
除非上次启动崩溃,否则单块总是以音频模式启动。Wi-Fi 凭据和身份验证令牌从 src/native/services/remote_config.h 编译到固件中,该文件被 gitignore。没有该文件,整个服务,以及其中的 Wi-Fi、BLE 和 HTTP 服务器,都将从映像中剔除,大约节省 400 KB 闪存,并且单块无法进入维护模式。在构建前生成它:
npm run remote:configure -- --ssid YOUR_WIFI
单块在维护模式下加入该网络,amoled_remote.py discover 可在此处找到它。remote_config.h.example 显示了生成的格式。
当单块处于维护模式时,tools/esp32/amoled_remote.py 会找到它,读取其日志并更新它:
npm run remote -- discover
npm run remote -- --host PEDAL_IP ota
除非你传递另一个映像,否则 ota 上传 build/pedalboard.bin。在从维护模式启动 OTA 更新后,单块会以音频模式启动新映像一次,然后返回维护模式,以便你可以检查日志。运行脚本时添加 --help 可查看诊断命令。
仓库布局
src/
ui/
触摸屏应用(TSX、CSS、状态管理)用于面板
相似文章
Teenage Engineering 推出了一款内置大量效果器的乐器音箱
Teenage Engineering 推出了 EP-35,这是一款电池供电的多乐器音箱,内置适用于吉他和人声的风格化效果,支持蓝牙 Auracast 配对,并配有 amptenna FM 收音机和 EP-127 KO 无线 MIDI 踏板等配件,售价为 399 美元。
Endless AI吉他踏板潜力巨大
文章评测了Polyend的Endless AI吉他踏板,该设备利用多个AI智能体根据文本提示生成自定义效果,为吉他效果器带来独特的设计思路。
固件自由
文章倡导在吉他效果器硬件中实现固件自由,强调用户对固件的控制,以增强定制化和所有权,并以CoyoPedal和ESP32-S3等设备的实现为例。
这个小巧的吉他音箱是我用过最狂野的失真效果器
Death By Audio 的 Amp Crash 是一款小巧的吉他音箱,兼具失真效果器功能,内置麦克风和效果器,通过扬声器-麦克风交互创造独特、强烈的声音。
JAMtime.ai
JAMtime.ai 是一款AI产品,吉他手只需描述想要的音色,即可控制踏板声音。