跳到正文
Hacker News· smig0·· 10 天前AI 评分12

Pebble Time 2 手表 64k 演示 demo 发布

64k demo for the Pebble Time 2

AI 导读

开发者发布了一款运行在 Pebble Time 2 手表上的 64k demo,使用 Mad Tea Synth 插件在 DAW 中制作,代码语言为 Tea++。

正文 · AI 翻译

为 Pebble Time 2 Watch 和 MicroW8 制作的 64k demo

如果你有这款手表,可以从官方 pebble 网站安装

Mad Tea Synth

这个 demo 是用 Mad Tea Synth 制作的,它是 Reaper 或 Bitwig 等音乐软件/DAW 中使用的插件。它基本上是一个事件列表,比如底鼓、主音合成器或视觉效果。

每个事件都映射到一个 MIDI 音符范围,然后它只是一个代码框(对于同时包含声音和视觉效果的事件,则是两个代码框)

在每个代码框中,你可以访问诸如 MIDI 力度 vel、以拍为单位的歌曲位置 beat、自音符开启以来的秒数 t 和相对采样率 rate 等内容

然后还有一些基本函数用于绘制圆形、线条、矩形和文本。在音频方面,支持每个事件一个采样槽,使用函数 smp 进行流式传输。

代码框使用一种自定义语言(Tea++)。它是命令式的,具有推断类型。我努力让它感觉像随意的脚本编写(但支持编译为 C 并输出定点数学运算)

音乐 / 概念

有一个著名的语音采样来自 1950 年代儿童电视节目 Howdy Doody 的开场,后来在 80/90 年代嘻哈/舞曲场景中被采样。整个内容是“Say kids, what time is it”,最后那部分似乎很有用……

我能在脑海中听到旋律,并相应地剪切和调整了这些词。对于其他采样,我重复使用了 Daydreamer 中的一个 stab 和 RE-FORM 中的脏电贝斯

然后还有很多与时间相关的概念可以借鉴,不过我不确定自己是否选得好……

合成器里没有合成器?

计划是有一个用于声音设计的 API,部分源自 RE-FORM Synth。但这从未实现,所以除了播放单声道采样外,没有包含任何内容。

我求助于 2013 年的一个实验。想法是:

  • 脉冲宽度波形只是将单个位翻转从 0 到 1 线性动画化——如果我们使用异或组合多个动画符号翻转会怎样?

当时我尝试了许多替代方案,我非常喜欢其中一个听起来像带有大量相位器效果的贝斯:

pw = (x, pw) => {  // normal pw, for reference
  x -= floor(x)    
  return x < pw ? -1 : 1         
}

phaserpw = (x, pw) => {
  x -= floor(x)
  return ( (x < 1/8 - pw * 1/8) 
         ^ (x < 2/8 - pw * 2/8) 
         ^ (x < 5/8 - pw * 2/8) 
         ^ (x < 6/8 + pw * 2/8) 
         ^ (x < 7/8 + pw * 1/8)
    ) ? -1 : 1  
} 

所以在这个 demo 中,我用 boxcar 滤波器重写了它,然后几乎用于 demo 中所有的合成器声音。在 Mad Tea Lab 中试玩 / 聆听。

ASCII 渲染

类似于 PRINT 中的一些场景,但规模要小得多……

实现首先渲染到一个小的灰度缓冲区。它垂直采样 3 个灰度像素,然后两个外部样本的差异决定中间点应使用两个查找表中的哪一个。(双 LUT 使边缘更平滑)

upper_heavy_lut = "  '`:""--**!^+)<?vcYCFos35EH90BNW" 
lower_heavy_lut = "  ..,:;-__*!!+(>=Jc7lnIaedK$6Q&MW" 

注意:demo 中实际的 LUT 长度为 255 个字符

问候文本根据(插值的)灰度像素值改变每个字符的笔画粗细,而不是交换字形。

灰度源图像大多是单色且边缘抗锯齿,所以为了使其更有趣,我应用了晕影,这也在动画时为填充区域提供了一些良好的稳定性。大多数 ASCII 渲染场景也使用 2 个尺寸级别,因此较大的字形与 2x2 的一半大小的字形交替出现。

沙漏场景

这个场景是为了与 demo 的整体单色风格形成对比并展示彩色显示而制作的。显示器支持 64 种颜色(每个 RGB 通道 4 种色调),我感觉自己评估了所有相关的 7 色从暖到冷的调色板……

电子纸显示屏在阳光和暖光下显示效果最佳,所以我在录制视频时使用了这种光线。

在 Mad Tea Labs func-plot 中制作轮廓原型,然后合并为一个单一函数

用代码做动画

对于非交互式/固定动画,我更喜欢无状态实现,以及输出归一化范围的实用函数。

运动 / 过渡 / 打击

renderman/glsl 的 smoothstep API 非常适合做动画,我使用这些函数:

linearstep   (start_time, end_time, time)
smoothstep   (start_time, end_time, time)
smootherstep (start_time, end_time, time)

积分版本(a == 曲线下面积)

linearstepa  (start_time, end_time, time)
smoothstepa  (start_time, end_time, time)
smootherstepa(start_time, end_time, time)

最后几个函数在比如做两个音符之间的插值/滑音时很方便,或者当你希望图形在静止和旋转之间过渡时;与其这样做:

cur_spin_speed = smoothstep(0, 1, t) * max_speed
rotation += cur_spin_speed

跳过状态,直接这样做:

rotation = smoothstepa(0, 1, t) * max_speed

为了在视觉上同步“打击”如底鼓、军鼓和重音,我再次使用linearstep,但带一个指数来控制曲线。

节奏时间扭曲

时间扭曲是一种将节奏同步应用到已经动画化的东西上的好方法,比如点隧道场景。我通常只是让时间通过这样一个函数:

rhythmic_time_warp = (x, amount, len = 0.18) => {
    var steps = fract(x + 0.5)
    return x + amount * (smootherstep(-len, len, steps - 0.5) - steps)
}

这个函数的设计使得时间总是在整数处运行得最快,然而,我倾向于根据上下文稍微偏移输入时间以获得正确的感觉。

节奏弹跳

简单地 4 * frac(x) * frac(-x)

工具失败

当我在为演示制作视觉效果时,我觉得通常使用 beats(全局时间)并手动偏移比使用 t 更好,因为使用 t 时你无法在事件中间开始预览。但这意味着如果我移动场景,就必须更新偏移量,所以 DAW 中视觉编辑的一个关键承诺落空了,这令人失望……

走向 64k

实际硬件似乎有能力,但为了更好的电池寿命,Pebble SDK 设置了限制:128kb RAM、256kb 闪存存储,并且不支持浮点。Pebble SDK 中还有一个 bug,将二进制文件限制在 64k。我觉得我反正没有时间好好利用闪存存储,所以我把所有东西都控制在 64k。

要真正利用硬件,你必须更改固件/操作系统。但这会让人们实际运行演示变得更加麻烦……

提高手表扬声器质量

手表支持 16 位 16 khz 的音频播放,但挑战在于微型扬声器。我猜想我可以通过应用一些频带/陷波滤波器(减少恼人的共振高频)来提高音频质量。结果这比预期更难,因为在尝试均衡频率曲线时很快就出现了失真。经过几次迭代,我最终确定了 3 个增强峰值滤波器 + 增益降低。只是凭耳朵调整,并且已经为了更好的质量牺牲了很多音量。你可以使用手表上的向下按钮来开启/关闭此功能。

表演时间!

我努力为 Evoke 2026 完成这个作品,然而我没有注意到聚会采取了强硬的反 AI 立场。所以这个演示因为工具开发过程中使用了 LLM 而被取消资格。相反,我一周后将其提交给了 Xenium,但不幸的是作为远程参赛,因为我没有精力再旅行了。取消资格也有一些好的结果,因为延迟给了我时间做一个 MicroW8 移植并改进视频剪辑。

演示范围 vs 工具范围

制作这个演示有助于推动该工具的开发,不过演示的范围相比工具本身较小。欢迎继续阅读关于Mad Tea Synth 项目的内容

来源:Hacker News · teadrinker.net