Wallpaper Engine

Wallpaper Engine

Not enough ratings
壁纸引擎-设计师文档:如何制作音频可视化?
By 吾之野望
Wallpaper Engine 允许您处理左右音频声道的音量电平,并将其用于可视化用户系统正在播放的音频。每个声道将音频频率分割为64个部分,每个部分代表一个音频频率范围:低频代表低音,高频代表高音声域。
利用这些音量电平可构建多种类型的音频可视化效果——既可以是完整的条形音频可视化器,也能让壁纸中的特定元素随音乐节拍律动(通过仅监测低频范围实现,因为低频通常对应音频的节拍)

搬运、翻译自官方设计师文档《Audio Visualization》[docs.wallpaperengine.io]
因Steam格式问题,可能需要在知乎查看此文章[zhuanlan.zhihu.com]
   
Award
Favorite
Favorited
Unfavorite
创建音频监视器
要开始创建音频可视化效果,您需要在JavaScript中注册一个监听器函数,该函数将向您提供音频音量电平。Wallpaper Engine为此提供了window.wallpaperRegisterAudioListener函数,此函数需要接收一个您自行创建的回调函数。

wallpaperRegisterAudioListener函数仅需调用一次。请注意:切勿在window.onload事件(或任何类似事件)中注册音频监听器,此类方式不可靠且可能导致Wallpaper Engine错过某些事件。若不确定,请将此函数置于body标签的末尾调用。

以下示例中,我们同时创建了一个空的wallpaperAudioListener(audioArray)函数作为回调参数传递给wallpaperRegisterAudioListener。该函数后续将包含您处理音频的自定义逻辑。函数名称可自定义,但必须包含将音频音量电平作为数组接收的参数。

function wallpaperAudioListener(audioArray) { // 在此处理音频输入 } window.wallpaperRegisterAudioListener(wallpaperAudioListener);

当新的音频样本到达时(每秒约触发30次),wallpaperAudioListener函数将会被调用。
处理音频样本
实际的音频数据包含于我们之前作为参数创建的audioArray数组中,该数组具有固定的128长度。

数组元素0至63包含左声道音量电平,元素64至127包含右声道音量电平。

每个通道中较低的数组元素代表低音频率:数组索引0处为左声道最低低音,索引64处为右声道低音。数组索引值越大,对应的音频频率就越高。因此最接近索引64的数组元素包含左声道高音频段的音量电平,最接近索引127的元素则包含右声道高音频段的音量电平。

每个数组元素通常包含0.00至1.00范围内的浮点数值。0.00表示该特定频率当前未播放任何声音,1.00表示该频率正在以最大音量播放。但由于技术实现原因,在极少数情况下数值可能远大于1.0。因此建议通过Math.min()函数将音量值限制在1.00以内,具体示例可参考下文示例项目。
音频可视化示例
相关视频[docs.wallpaperengine.io]
以下将提供一个完整的音频可视化基础实现示例(对应上文演示效果)。您可直接将代码复制到空的.html文件中,导入Wallpaper Engine即可立即运行。通常我们不建议将所有脚本、样式和HTML内容放在单一文件中,但出于教程目的,集中展示最便于理解。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <style> body { margin:0; padding:0; } html, body { width:100%; height:100%; overflow:hidden; } canvas { height:100vh; width:100vw } </style> </head> <body> <canvas id="AudioCanvas"></canvas> <script> let audioCanvas = null; let audioCanvasCtx = null; function wallpaperAudioListener(audioArray) { // 清除画布并设置为黑色背景 audioCanvasCtx.fillStyle = 'rgb(0,0,0)'; audioCanvasCtx.fillRect(0, 0, audioCanvas.width, audioCanvas.height); // 沿画布全宽度渲染音频条 var barWidth = Math.round(1.0 / 128.0 * audioCanvas.width); var halfCount = audioArray.length / 2; // 首先以红色绘制左声道 audioCanvasCtx.fillStyle = 'rgb(255,0,0)'; // 遍历前64个数组元素(0-63)处理左声道音频数据 for (var i = 0; i < halfCount; ++i) { // 根据当前频率的音量电平创建不同高度的音频条 var height = audioCanvas.height * Math.min(audioArray, 1);
audioCanvasCtx.fillRect(barWidth * i, audioCanvas.height - height, barWidth, height);
}

// 接着以蓝色绘制右声道
audioCanvasCtx.fillStyle = 'rgb(0,0,255)';
// 遍历后64个数组元素(64-127)处理右声道音频数据
for (var i = halfCount; i < audioArray.length; ++i) {
// 根据音量电平创建音频条
// 使用audioArray[191 - i]反转右声道数据以实现视觉对称
var height = audioCanvas.height * Math.min(audioArray[191 - i], 1);
audioCanvasCtx.fillRect(barWidth * i, audioCanvas.height - height, barWidth, height);
}
}

// 在页面加载后获取音频画布
audioCanvas = document.getElementById('AudioCanvas');
// 将画布内部分辨率设置为用户屏幕分辨率
// (CSS画布尺寸与实际内部分辨率不同)
audioCanvas.height = window.innerHeight;
audioCanvas.width = window.innerWidth;
// 获取画布的2D绘图上下文供wallpaperAudioListener使用
audioCanvasCtx = audioCanvas.getContext('2d');

// 注册Wallpaper Engine提供的音频监听器
window.wallpaperRegisterAudioListener(wallpaperAudioListener);
</script>
</body>
</html>[/code]

上述HTML与JavaScript示例包含详细注释以帮助理解。以下特别说明几个关键细节:
(此处code无法正常结束,内容移动到下一章)
音频可视化示例详解
浏览器样式标准化

首先,<style>代码块中的CSS规则使画布能够适应任何分辨率和宽高比。务必确保您的壁纸适用于所有类型的屏幕分辨率和宽高比——仅针对单一分辨率进行设计是不良实践,通常只需稍作调整即可兼容所有用户设备。

本示例中,我们将body元素的默认边距和内边距重置为0,并隐藏溢出内容(虽然并非必要,但能有效防止某些极端情况下出现滚动条)。接着将画布尺寸设置为用户视口的完整宽度和高度。

基于JavaScript的标准化与初始化

在JavaScript代码中,必须避免使用window.onload函数及类似窗口事件(至少涉及Wallpaper Engine特定代码时),否则可能引发事件系统问题。由于未使用onload事件调用,需确保JavaScript代码在HTML body渲染完成后加载——因为代码直接操作画布元素。将JavaScript置于body标签末尾是完全有效的做法,我们推荐此方式。

若您未曾使用过canvas元素,需注意其采用内部渲染分辨率与HTML/CSS尺寸分离的机制。因此最好通过JavaScript明确将画布宽高设置为窗口宽高,如下列代码所示:

audioCanvas.height = window.innerHeight; audioCanvas.width = window.innerWidth;

在JavaScript示例末尾,我们调用wallpaperRegisterAudioListener函数,使wallpaperAudioListener在每次收到新音频数据时执行。如前所述,此调用绝不能置于任何窗口事件(如window.onload)内部,应通过将JavaScript置于HTML末尾来确保正确加载。

该函数将以红色绘制左声道,蓝色绘制右声道(仅为视觉效果反转顺序)。

音频条高度由for循环当前遍历频率的音量电平决定。假设用户屏幕分辨率为1920x1080:若窗口高度为1080,当前频率音量电平(存储于audioArray)为0.50,则该频率对应的音频条高度将为540像素(1080 * 0.50)。此逻辑会对所有音频频率重复执行,每次Wallpaper Engine提供新音频数据时都会触发。

值得注意的是,我们使用Math.min(audioArray, 1)对音频值进行封装。这是为了确保音频电平峰值不超过1.00。虽然大多数值永远不会超过1.00,但由于实现机制的特性,极少数情况下可能出现超过1.0的峰值,导致壁纸渲染异常。

当然,这只是一个基础示例。您完全可以彻底改变可视化形式——利用这些数据能实现的远不止简单音频条。还可以尝试在wallpaperAudioListener函数调用之间添加插值计算以平滑音频条运动,但此类情况下建议为壁纸添加FPS限制[docs.wallpaperengine.io]

核心代码逻辑如下:

for (var i = 0; i < halfCount; ++i) { // 根据当前频率的音量电平创建对应高度的音频条 var height = audioCanvas.height * Math.min(audioArray, 1);
audioCanvasCtx.fillRect(barWidth * i, audioCanvas.height - height, barWidth, height);
}
音频可视化问题排查
为节省性能,Wallpaper Engine仅在检测到壁纸代码中加载了wallpaperAudioListener时才会向壁纸发送音频数据。当编辑器预览模式检测到正确注册的音频监听器后,会自动在项目生成的project.json中添加以下配置项:

"supportsaudioprocessing" : true,

此过程通常在导入包含JavaScript的主HTML文件后自动完成。但若您实时编辑文件,可能需要通过编辑器中的"保存"功能强制Wallpaper Engine更新project.json文件。

作为最终手段,您也可以手动将此配置项添加到project.json中(若代码配置正确则无需此操作)。可通过点击编辑器顶部的"编辑"菜单,选择"在资源管理器中打开"来访问project.json文件。

若可视化效果仍存在问题,建议根据后续教程为Wallpaper Engine设置调试器连接。通过这种方式可更有效地调试JavaScript代码,并检测接收到的音频电平数据:

Web Wallpaper Debugging[docs.wallpaperengine.io]