N64 放不出好音乐?他把一款小众编解码器搬上老主机,44.1kHz 只占 4% CPU

作者:陈一帆

独立开发者 phoboslab 发文讲了他把超低复杂度编解码器 ULC 移植到 N64 的过程:44.1kHz 立体声、码率接近 Opus,约占用 4% CPU 和 5% RSP 时间。解码器已并入开源工具链 libdragon 的预览分支,前几天发布的《半条命》N64 移植版用它装下了全部语音和音乐。

GitHub - ToxyCola/Half-Life-Nintendo-64-Port

发生了什么

独立开发者 phoboslab 在 11 月 3 日的博客里,讲了他把 ULC(Ultra Low Complexity Codec)解码器移植到 N64 的全过程:44.1kHz 立体声、码率接近 Opus,代价大约是 4% 的 CPU 时间和 5% 的 RSP 时间 。这套解码器已经并入开源 N64 工具链 libdragon 的预览分支 ,而几天前发布的《半条命》N64 移植版,正是靠它把所有语音和音乐塞进了一张 64MB 卡带 。

为什么老游戏机的音乐像是按时拼起来的

PS 可以直接从 CD 上流式播未压缩的 redbook 音频,N64 没有这条路:卡带空间贵,93MHz CPU 的时间也紧 。更麻烦的是,任天堂长期不允许第三方直接给向量协处理器 RSP 写代码,官方库 Libultra 只提供一套 ADPCM 的透明播放,由 RSP 边解压边送进输出缓冲 。ADPCM 能把采样压到四分之一,可一首 5 分钟的 44.1kHz 立体声仍要约 12MB——《马力欧 64》整个 ROM 才 8MB,史上最大的 N64 游戏也只有 64MB 。所以当年的 N64 配乐更像 tracker:把短采样安排在正确的时间点播放,再加一点有限的效果 。后期有少数开发组获准直接写 RSP,《Conker's Bad Fur Day》用它解 MP3 播语音,代价是帧率——过场里够用,连续播背景音乐就太重了 。

开源这边的情况类似。libdragon 有 RSP 版 ADPCM,phoboslab 自己的《Xibalba 64》32MB ROM 里有 31MB 给了音频,而这游戏只有 15 分钟音乐 。libdragon 也有 Giovanni Bajo 做的 RSP 加速 Opus 解码器,质量和压缩率都很好,但游戏跑起来时还是太慢 。QOA 比 ADPCM 略好,可每个采样都依赖前一个,很难向量化 。

ULC 的方案

ULC 是 Aikku93 从 2019 年开始做的自制编码器,起因是一个 GBA 演示:16MHz ARM、没有向量指令,能以 70kbps 播放录制音乐,质量可比,据说还有余量 。它和 MP3 同宗,同样把 PCM 变换到频域、同样用 MDCT;区别是不分频带(full-band),也不做霍夫曼熵编码,变换后的系数直接按 4 bit 半字节打包 。0 表示零填充(后面跟着 1–16 的游程长度),1 表示长零填充,-1 表示量化器切换,-8 表示噪声填充;全部半字节对齐,因此不需要任意位读取,也不需要熵解码 。解包一个块的系数大约 150 行 C 。那个噪声填充很实用,镲片、踩镲、军鼓都受益匪浅,而 MP3 没有对应机制 。低到 16kbps 也能出可用结果 。

塞进 4096 字节

真正的难点在 RSP:数据内存 4096 字节、指令内存 4096 字节,向量指令只做 16 位或 32 位定点,没有浮点 。要在一次变换内把数据全放进 DMEM,作者最后选了 16 位定点(Q1.14)配 1024 采样块、512 采样 lapping 缓冲,共 3072 字节——DMA 流量小、运算也快,代价是噪声底更高;他用耳朵验收,把音量拧大只听到(或想象到)极轻的白噪声 。移植靠 Max Bebök 的 RSPL(一门写 RSP 的类 C 语言)起步,用 Codex 一块块翻译再逐段验证,之后手工改汇编、调优化器减少流水线停顿,最后是约 1400 行 MIPS 汇编,勉强塞进 IMEM 。另外他在文件尾部加了每 8 帧一个偏移的稀疏表,方便跳转,每秒多约 20 字节 。

已经落地的部分

结果是:质量和码率接近 Opus,复杂度约为 ADPCM 的 4 倍,一条 44.1kHz 立体声轨约占 4% CPU、5% RSP,够做背景音乐、语音、环境声和较长的音效 。在 libdragon 里它和其他音频编码器一样透明调用 。真正把它用在项目里的是 ToxyCola 的《半条命》N64 移植版:用 Valve 的 SDK、玩家自己的游戏文件构建新引擎,需要 Expansion Pak,README 写明语音和音乐用 libdragon 的 ULC 压缩 ;phoboslab 引用的说法是 2500 个音效、27 首曲子因此装进一张 64MB 镜像 。

边界也得说清。这个移植版主要在一个周期精确的模拟器里测试,真机逐场景帧率还没实测,最忙的场景在 20 多帧 。ULC 本身也不是“音质更好”,它的目标是“够用且便宜”。

我更在意的其实是它的做法:没有发明新算法,而是把 MDCT 那条早就成熟的路重新打包,简单到能塞进一块 4KB 内存的协处理器里,用一点压缩率换解码开销。这种账,今天的耳机、手表和廉价 IoT 设备也还在算。

转载说明

本文根据以下公开资料整理,原文及配图出处见下方。

0
游速速·硬件体验官发布在 # Installation and Hardware · computerintegrated 圈 · 1 天前

评论

还没有评论,来抢沙发。

游速速 · 游戏 / 软件 / AI / 硬件一站式下载站
当前页面:帖子详情