Waveloop: Fable留给我的
摘要
作者回顾了使用AI模型Fable 5创建Waveloop的过程,这是一款音乐可视化工具,通过半圆环展示和声与旋律结构。它利用颜色和角度来表示音高类别和音程,并支持离线模式与实时麦克风模式。
暂无内容
查看缓存全文
缓存时间: 2026/06/30 21:39
# waveloop:fable留给我的遗产
来源:https://neynt.ca/writing/waveloop/
在拥有Fable 5的那两天里,它把我变成了一个音乐可视化工具。这是我从记事起就一直梦想的事情。
你可以在这里看到:Waveloop (https://saltblock.neynt.ca/waveloop.html)
---
这个想法是:一个音乐可视化工具应该能直观地揭示音乐的和谐与旋律结构。大多数可视化工具都做不到这一点——你只能得到一种模糊的响度感,最多能区分低音和高音,仅此而已。我们怎样才能做得更好?众所周知,西方大小调音乐理论的基础是12√2,即连续半音之间的频率比。(我忽略了其他调律体系,它们都足够接近十二平均律。)十二个这样的半音带你到下一个八度,而相隔整数个八度的音符被认为属于相同的音高类别。
Waveloop在色环上捕捉了这种循环结构:每个半音30°,每旋转一周就是一个八度。音乐中的任何一个瞬间都被捕捉为一个螺旋堆叠的直方图,显示每个音高类别的能量分布。直方图的每一层使用不同颜色来表示不同八度:低音区用柔和的蓝绿色,中音区用火焰般的橙色、红色和紫色,高音区用闪亮的金色和天蓝色,沿着oklch色彩空间螺旋上升。
这种表示法有几个很好的特性:
**你可以直接通过角度来读取音程。**
以下是音程:
- **m2** 30°
- **M2** 60°
- **m3** 90°
- **M3** 120°
- **P4** 150°
- **TT** 180°
- **P5** 210°
- **m6** 240°
- **M6** 270°
- **m7** 300°
- **M7** 330°
**你可以从和弦的形状判断其性质。**
移调会旋转形状,转位则不改变它。以下是几种常见和弦性质:
- **maj** 0 · 4 · 7
- **min** 0 · 3 · 7
- **dim** 0 · 3 · 6
- **aug** 0 · 4 · 8
- **sus4** 0 · 5 · 7
- **sus2** 0 · 2 · 7
- **dom7** 0 · 4 · 7 · 10
- **maj7** 0 · 4 · 7 · 11
- **min7** 0 · 3 · 7 · 10
Waveloop主要工作在离线模式下,它会预先计算特定曲目的CQT,但Fable也给了我一个实时麦克风模式。当我打开它时,我发现它能相当快速可靠地识别我弹奏的尤克里里和弦。
---
我们失去Fable大约一周了。为了提醒自己曾经拥有的是什么,我看了看一些waveloop代码。首先让我印象深刻的是它非常**紧凑**。之前的模型写代码时就像一个FAANG里理性上进的工程师,正稳步晋升直到止步于L5级别;而这个模型的写作风格更像是我想象中Terry Davis独自在房间里写代码的样子。看看waveloop文件顶部这段注释。它毫不废话地描述了刚刚写出的代码。这些注释更像是信息密度最大化的意图记录,就像锁文件一样,从中原则上可以推导出其余代码。
```c
/* 可视化工具是一个音高类轮盘:角度 = fract(log2(f / 440)),这样每个音符的每个八度都落在同一根辐条上(A在12点钟方向,顺时针上升)。
CPU保持大约5秒的每个寄存器频段的发射历史,并在每一帧将其光栅化为在此采样的RGBA径向轨迹图(REGS垂直堆叠的块,T轴=半径;rgb = 预乘的寄存器颜色,并内置衰减,a = 衰减能量):
每一行历史记录位于其自身存储振幅所携带到的半径处,因此运动是由振幅驱动的——最响的成分会穿过整个窗口,而安静的伴奏和噪声则停留在环附近,主旋律在视觉上领先于其他所有东西(参见rasterTrails)。
颜色是连续的Oklch,在CPU端每个FFT频段计算(色相以对数刻度对绝对频率进行编码,20 Hz为红色,20 kHz为紫色;明度沿寄存器轴上升——低音暗色,中音在常见基频附近全饱和,高音淡而闪亮)。
显示能量范围在0..EMAX之间(响亮的基频会过冲1而不是在旧的AGC上限处削波);轨迹图将sqrt(v / EMAX)存储在alpha中(rgb预乘该编码后的alpha),以便u8纹理在保持低端精度的同时携带额外的动态余量。
由于频段一直保持分离直到屏幕,同时在不同八度发声的音高类会在轮缘上呈现为堆叠直方图(低音寄存器在最内侧),颜色通过寄存器斜坡连续滑动(u_rim携带每个角度的寄存器分布的逆CDF),而不是在几个频段颜色之间切换;寄存器存在于堆叠位置和色相中,而不是速度中。
场延伸到屏幕最远角落之外,半径是年龄的凹函数,因此物质从轮缘涌出,并在向外漂移时减速。
*/
```
这段文字非常技术性。这个模型毫不避讳地运用它所有的知识。它随口就提到alpha预乘和基频。它喜欢使用缩写词:CDF、FFT、AGC。我几乎跟不上。文笔也很有文学性。它将12个音高类别类比为钟面上的12个刻度。噪音会“**徘徊**”。物质从轮缘“**涌出**”。Fable不惧怕使用它的全部词汇来紧凑而生动地表达它想说的任何内容。
下面是它的和弦检测函数。看起来相当扎实,而且令人惊讶的是代码量很少。
```javascript
const NOTE_NAMES = ['A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#'];
const QUALITIES = [
{ name: '', ivs: [0, 4, 7] },
{ name: 'm', ivs: [0, 3, 7] },
{ name: 'dim', ivs: [0, 3, 6] },
{ name: 'aug', ivs: [0, 4, 8] },
{ name: 'sus4', ivs: [0, 5, 7] },
{ name: 'sus2', ivs: [0, 2, 7] },
{ name: '7', ivs: [0, 4, 7, 10] },
{ name: 'maj7', ivs: [0, 4, 7, 11] },
{ name: 'm7', ivs: [0, 3, 7, 10] },
];
function detectChord() {
let total = 0;
for (let i = 0; i < 12; i++) total += chroma[i];
chromaAgc = Math.max(chromaAgc * 0.995, total, 1e-6);
if (total < 0.15 * chromaAgc || chromaAgc < 1e-3) return null;
const c = new Array(12);
for (let i = 0; i < 12; i++) c[i] = chroma[i] / total;
let best = null, bestScore = 0;
for (let root = 0; root < 12; root++) {
for (const q of QUALITIES) {
let inS = 0;
for (let k = 0; k < q.ivs.length; k++) {
inS += c[(root + q.ivs[k]) % 12] * (k === 0 ? 1.15 : 1);
}
const score = inS / Math.pow(q.ivs.length, 0.55);
if (score > bestScore) {
bestScore = score;
best = { root, q };
}
}
}
if (!best) return null;
let frac = 0;
for (const iv of best.q.ivs) frac += c[(best.root + iv) % 12];
if (frac < 0.5) return null; // 和弦音之外能量太多
return {
name: NOTE_NAMES[best.root] + best.q.name,
root: best.root,
pcs: best.q.ivs.map((iv) => (best.root + iv) % 12),
};
}
```
---
我还让Fable制作了一个讲解视频。**这用了三条提示**。我的第一条提示是这样的:
```
好吧不管了,开干吧。我们还要制作一个基于manim的视频,解释waveloop背后的数学原理,从最基础的“第一性原理音乐理论”开始,一直讲到FFT、CQT、所有DSP、圆形堆叠直方图、oklch……我觉得应该有一个TTS插件让你给视频配音。
```
结果当然是垃圾。但在我给出以下反馈之后:
```
好吧,我们来迭代那个视频。
- 一:配音糟糕透顶。toebeans有一个使用qwen3-tts-voicedesign的TTS服务器——请用类似的东西以配置好的声音来旁白。
- 二:旁白中穿插了很多非常刺耳的噪音,不知道为什么。
- 三:更多地使用与屏幕视觉对应的生成音效。
- 四:少花时间在非常基础的内容上,多深入一些更复杂的数学细节。
- 五:让脚本更口语化。感觉就像在跟朋友聊天,或者在看3blue1brown或2swap的视频。
- 六:关键且困难的是:不要在每个点上都啰嗦地给观众灌输事实,而要让你感觉用户自己也能发现这一切。
- 七:视频中少用文字。用非常有趣且说明性的视觉来代替文字。这不是幻灯片。文字只应该作为图表的一部分出现,而不是重复旁白已经解释过的东西。
```
我们得到了上面你看到的那个视频——大体上是这样的。我又跟进了一个清理请求:
```
这好多了。让我们对数学使用正确的排版,通过生成一个VoiceDesign样本来保持一致的说话声音(或者你用qwen tts做这件事的方式),并确保我们的图表不会重叠。
```
就这样。是的,它仍然不是一个出色的视频。但在我第一次看的时候,它足够吸引人,让我看完了整整十分钟。
---
AI使用声明:我使用了Claude来生成图表的SVG。但所有文字都是我自己写的。
相似文章
@flowstated: fable 5 composer 2.5 fast
Fable 5 与 Composer 2.5 Fast 集成,以增强 AI 代码生成能力。
@ericzakariasson: https://x.com/ericzakariasson/status/2072639126034137444
Fable 已回归 Cursor。本文分享了一种模式:将 Fable 作为编排器,Composer 2.5 作为工作节点,以实现高效的 AI 辅助编程,同时提供了关于长周期云代理和模型轮换的技巧。
@FinanceYF5:第一次真正“看见”Vivaldi的《Winter》。当音符化作流动的视觉轨迹,速度、…
一段演示展示了一款 AI 工具,它将 Vivaldi 的《Winter》转化为流动的视觉轨迹,让旋律的速度、动态与层次清晰可见,证明音乐不仅可以被听到,也可以被“看见”。
我用了半天的Fable 5,发现护栏才是真正的故事
Anthropic的Fable 5模型展现了令人印象深刻的推理和上下文处理能力,但存在高延迟、高成本以及在特定领域静默回退到Opus 4.8的问题,这可能会中断工作流程。
Claude 5.5 Opus 通过代码生成一个小型2D/3D视频
由Claude 5.5 Opus创建的音乐驱动视频演示包含氛围音景和中文语音提示,展示了AI的生成能力,无需口头解释。