TiXL 音频系统完全指南:时间线音频剪辑、路由混音图与音频反应式视觉
【免费下载链接】t3TiXL is an open source software to create realtime motion graphics.项目地址: https://gitcode.com/GitHub_Trending/t3/t3
本篇技术指南围绕 TiXL(开源实时动态图形工具)的音频子系统展开,系统讲解时间线音频剪辑的操作模型、主音轨(Main Soundtrack)机制、基于算子(Operator)的音频路由与混音图、效果器与侧链闪避(Ducking)、音频反应式视觉(Audio-Reactive)以及导出时音频的确定性混缩行为。阅读后你将掌握 TiXL 中"以普通算子搭建整套音频链路"的核心思路,并能独立完成从多剪辑并行播放、分组混音、添加混响/回声/压缩效果,到用节拍驱动参数动画的完整实战方案。
自 TiXL 4.3 起,整个音频系统不再有独立的音频配置面板,而是完全由普通算子构建:拖入时间线的音频文件会变成AudioClip算子,混音、编组、效果与电平测量都发生在可见、可编辑的算子图中。本文所有操作与原理均可对照仓库源码验证,例如音频算子实现位于 Operators/Lib/Symbols/io/audio,底层 BASS 引擎架构说明见 Core/Audio/AUDIO_ARCHITECTURE.md。
时间线上的音频剪辑(AudioClip)
从资源库(Asset Library)或系统文件管理器中将音频文件(mp3、wav、ogg)拖入时间线,它就成为一个AudioClip算子 —— 与任何其他时间线剪辑一样,可以移动、修剪、拆分、循环、静音和删除。一个项目可以在任意多的层上并行播放多个音频剪辑。
从源码结构看,AudioClip同时实现了IAudioClipProvider、IContentTimeClip与IStatusProvider接口(见 AudioClip.cs),它通过TimeSlot获得标准算子剪辑的全部交互能力(拖拽/修剪/拆分/吸附/删除),并在播放头处于其TimeRange内时通过AudioEngine播放。
核心参数
- AutoPlay(默认开启):播放头进入剪辑范围内即自动播放,无需任何连线。关闭后需要
AudioClipPlayer驱动,否则算子的状态栏会给出提示:"Not played — enable AutoPlay or add an [AudioClipPlayer] that collects this clip."。 - Trimming(修剪):只播放文件的局部。把剪辑起点拖到文件开头之前,多出的部分保持静音。源码中修剪通过
SourceOffsetSecs与SourceDurationSecs实现:TimeClip.SourceRange是文件时间(秒),而TimeRange是时间线的节拍(bars)位置(见 AudioClip.cs)。 - Loop(循环):在剪辑长度内重复"已修剪的源窗口"。重复边界在剪辑体上以细线显示。
- Mute(静音):静音的剪辑在时间线上显示为淡化样式。
- Style(样式):选择剪辑体内绘制的内容 —— 频率Spectrum(频谱)、峰值Waveform(波形)或平滑的Volume Level(音量电平)。
- 重命名算子:新名字以引号形式显示在剪辑上,原始文件名保留在悬浮提示中。
在播放头处按Shift+X拆分剪辑,两半会无缝衔接播放,并且新拆分出的剪辑会自动重连到原剪辑所接入的所有连线。
底层播放模型
值得注意的实现细节:AudioClip本身从不直接启动或停止音频流 —— 注册(心跳机制)就是引擎的启停信号。当剪辑被接入混音图或由 AutoPlay 注册时,AudioClipCollector.RegisterIfActive会在播放头位于剪辑时间范围内时触发,由引擎按帧创建、同步位置并回收过期的流(见 AudioClip.cs 与 AudioClipCollector.cs)。若剪辑从未被评估(无连线且关闭 AutoPlay),其状态栏会显示 Warning 级别的"未播放"提示。
主音轨(Main Soundtrack)
一个剪辑可以被指定为主音轨(Main Soundtrack),它承担三项职责:
- 渲染为时间线背后的通栏背景图像;
- 驱动音频反应式算子(FFT 分析源);
- 定义导出可执行文件的播放时长。
指定方式有两种:右键音频剪辑选择Set as Main Soundtrack,或在Project Settings → Audio中使用Create Soundtrack。技术上,主音轨的指定仅仅是剪辑的Display参数被设为Background Image—— 因此它跟随算子(随项目文件保存),而不是藏在某个隐藏的项目状态里。这一设计在源码中得到印证:_clip.IsMainSoundtrack = _clip.Display == AudioClipDisplay.BackgroundImage(见 AudioClip.cs),CompositionSettings.TryGetMainSoundtrack也是通过查找 op-clip 联合中的主音轨标志来工作的(见 CompositionSettings.cs)。
主音轨总是横跨其完整源内容,其剪辑块在时间线图层中被隐藏 —— 背景图像就是它的表现形式。若要在时间线上重新摆放它或将其变回普通剪辑,把算子的Display参数改回Clip即可。Project Settings → Audio → Select and focus Main Soundtrack可以快速跳转到该算子。
路由与混音(Routing and Mixing)
默认情况下,每个剪辑各自播放,你永远看不到一根连线。要做混音、编组和加效果,使用音频图:
- 每个
AudioClip都有一个AudioReference输出。把它接入AudioBus,总线就接管该剪辑的播放电平与混音。总线是图的汇聚端(sink)——它拥有一个主Volume,并输出一个可测量的Level。源码中AudioBus的Result(Command 输出)与Level(float 输出)均为Always触发(见 AudioBus.cs)。 CombineAudio在信号到达总线之前,把多个源归入一个共享的编组音量下。编组可以嵌套。- 效果器 ——
AudioReverb、AudioEcho、AudioCompressor—— 是插入式(inserts):所有流经它们的内容都会被处理。将一个效果器的输出接到下一个效果器的输入即可串联成链。
从源码看,效果器在总线内部被实现为"嵌套子混音"(nested submixes):AudioBus为每个声明了 FX 的节点建立一个独立的 BASS mixer submix,父级效果组的 submix 会成为内层效果组的父混音器(见 AudioBus.cs 与 AudioReverb.cs)。当效果器节点从图中移除时,总线会用 400ms 的增益渐隐(fade)让混响/回声的尾音自然收束,而不是被生硬截断(见 AudioBus.cs)。
AudioToneGenerator直接在图中产生测试音与合成持续音(drone)。源码确认其波形类型包括 Sine / Square / Sawtooth / Triangle / WhiteNoise / PinkNoise,频率被限制在 20–20000 Hz,并内置采样级精度的 ADSR 包络(Envelope 的 X=Attack、Y=Decay、Z=Sustain、W=Release),触发模式支持 Pulse(0→1 沿触发,播放Duration秒)与 Gate(保持触发期间持续发声)(见 AudioToneGenerator.cs 与 AudioToneGenerator.cs)。与AudioClip不同,它不实现IAudioSource,因此未连线时不会自动发声 —— 断开连线会立即静音。PlayAudioSample用于触发一次性采样(one-shot samples)。
AutoCollectClips:隐式汇入
在总线或编组上开启AutoCollectClips后,同一 composition 中未连线的兄弟音频剪辑会隐式加入其中——当你希望整段合成的剪辑共享同一个音量、电平表或效果,又不想逐个连线时非常有用。每个 composition 只应使用一个自动汇入算子(两个会自动汇入的算子会争抢同一批声道)。源码中AudioBus与CombineAudio都通过LooseAudioClipScanner.GetLooseClipOutputs收集这些"游离"剪辑,评估它们的 AudioReference 输出同时充当播放心跳(见 AudioBus.cs 与 CombineAudio.cs)。
总线的求值前提
总线必须被求值才会发声——把它接入你的渲染命令链,或固定(pin)到某个输出视图上。源码中总线每帧注册到AudioExportSourceRegistry,并以"心跳"机制维持活跃:如果总线停止被求值,引擎会暂停其 submix,而不是让它保持播放一个冻结的最后状态(见 AudioBus.cs)。
视频音频(Video Audio)
视频会播放自己的声音:PlayVideo和时间线上的VideoClip都会解码其文件的音轨并与画面同步播放。Volume参数控制缩放;当 Volume 为 0 时,音轨完全不会被解码—— 纯粹当作纹理使用的视频不会产生额外开销。与所有音频源一样,两个算子都有AudioReference输出:把它接入AudioBus或CombineAudio,即可为视频声音提供编组音量、效果或闪避;保持不连线则直接播放。
声音跟随画面,具体规则:
- 没有被渲染的
PlayVideo是静音的;VideoClip只在它的 cut 范围内可闻,修剪或滑动剪辑会让声音随帧一起移动。 - 音频在正常正向播放时发声。拖拽(scrubbing)、反向与变速播放是静音的—— 为这些模式提供变调修正(pitch-corrected)音频已在计划中。
- 预览代理(preview proxies)不携带音轨,所以声音始终来自原始文件,无论是否使用代理预览。
- 视频音频目前不会被包含进渲染的视频文件或可执行文件(见下文 导出)。
电平测量与闪避(Metering and Ducking)
AudioLevel是一个电平测量抽头(tap),测量它所在链路位置的信号。关键要求是串联接入(source → tap → bus),而不是作为旁路分支,这样才能测量时间线剪辑。源码解释了这一原因:测量通过"effect-less insert"实现,路由总线会把它落实为独立的 submix——正是这一点让包括引擎自持的AudioClip声道在内的所有源类型都能被可靠测量;而旁路分支直接测量叶子声道,引擎自持声道(不可缓冲)会静默读到 0(见 AudioLevel.cs)。若接成旁路,算子会给出 Warning 提示。测量值滞后可闻信号约一帧,这对闪避与反应式用途完全足够。
其 level 输出可以驱动任何东西:灯光亮度、缩放,或DuckAudioLevel。闪避的经典场景——人声压音乐(voice-over-over-music):
- 让音乐通过一个
DuckAudioLevel。 - 用
AudioLevel测量人声编组,把它的 level 接入 duck 的控制输入(Level)。 - 调整 Threshold 与 Amount,直到音乐随人声"呼吸"。
从源码看,DuckAudioLevel的核心是把 level 信号转换为平滑的闪避增益:当电平超过Threshold时,增益以 Attack 斜坡压向1 − Amount;低于阈值时以 Release 斜坡恢复。GainAndBias(Vector2)用于塑形响应曲线(knee),Attack/Release通过指数平滑(k = 1 − exp(−dt/τ))实现,且跟随实时音频信号而非时间线(见 DuckAudioLevel.cs)。将Gain输出接入CombineAudio或AudioBus的 Volume 即可(需要与既有音量相乘时可通过数学算子处理)。
音频反应式视觉(Audio-Reactive Visuals)
AudioReaction对项目的音频分析作出反应——节拍(beats)、低频(bass)、高频(highs)——并输出数值驱动参数。它监听什么取决于项目设置(Project Settings → Timing):
- Animation(动画)项目分析主音轨,逐帧精确——渲染视频时同样生效,因此导出的反应式效果与播放时一致。
- Live / Interactive(现场/交互)项目分析Project Settings → Audio中配置的音频输入设备,并提供Gain调节变化不定的输入电平、Decay塑造反应回落的快慢。
AudioReaction的输出包括Level、WasHit(bool)与HitCount(int),输入参数包括Threshold(触发阈值)、MinTimeBetweenHits(相邻命中最小间隔)、WindowCenter/WindowWidth/WindowEdge(频谱窗的选择与边缘衰减,均被钳制在 0..1)、Amplitude、Bias与Reset。其InputBand可选输入模式包括 RawFft、NormalizedFft、FrequencyBands、FrequencyBandsPeaks、FrequencyBandsAttacks;Output可选输出模式包括 Pulse、TimeSinceHit、Count、Level、AccumulatedLevel(见 AudioReaction.cs 与 AudioReaction.cs)。
只对单一音源作出反应
要只对某一个源(而不是整个混音)作出反应,把AudioReaction插入图中:把源的AudioReference接入它的Source输入,再把它的Result继续接到总线上。这样串联接入时,它只分析流经自身的内容——例如在音乐同时播放时只分析某段视频的声音。如果接成死端旁路,它无法分析时间线剪辑或视频音频;算子会在这种接法下发出 Warning(见 AudioReaction.cs)。
导出(Export)
听到即所得(What you hear is what you get):时间线剪辑以及所有经过音频图路由的内容——包括编组音量、效果与闪避——都会渲染进导出的视频与可执行文件。主音轨定义可执行文件的播放时长。从底层实现看,导出使用一个独立的 BASS export mixer,AudioRendering.PrepareRecording会暂停全局混音器、把音轨流从 SoundtrackMixer 临时移入导出混音器,由 BASS 自动完成各剪辑原生采样率到混音器频率的重采样,GetFullMixDownBuffer逐帧读取混缩缓冲(见 Core/Audio/AUDIO_ARCHITECTURE.md 与 AudioRendering.cs)。AudioBus还实现了IAudioExportSource:导出的算子链被求值时,总线会持续注册求值,避免渲染期间因心跳中断而静音,并在每次导出前通过Bass.FXReset清空效果器内部状态,确保同一区间的两次渲染结果一致(见 AudioBus.cs)。
当前唯一的例外是视频音频:它在编辑器中实时播放,但尚未进入确定性的导出混缩,因此渲染出的文件和可执行文件不携带它。
相关阅读
- Timeline —— 剪辑、关键帧与时间扭曲。
- TiXL for VJ and live performances —— 点按测速、节拍锁定与实时输入。
- Exporting videos 与 Exporting executables。
附:深入仓库的线索
若想进一步研究音频系统底层,仓库提供了完整的架构文档与实现:
- 音频系统整体架构(混音器层级、信号流、导出路径、陈旧检测机制):Core/Audio/AUDIO_ARCHITECTURE.md
- 混音器管理与 BASS 初始化(Global/Operator/Soundtrack 三路混音器、设备采样率探测、FLAC 插件):AudioMixerManager.cs
- 音频配置(低频延迟参数、FFT 缓冲、3D 音频因子、日志开关):AudioConfig.cs
- 项目音频相关设置(AudioSource 枚举、音频输入设备名、主音轨查询):CompositionSettings.cs
- 音频算子全集(Bus、Combine、效果器、反应式、闪避、采样触发):Operators/Lib/Symbols/io/audio
【免费下载链接】t3TiXL is an open source software to create realtime motion graphics.项目地址: https://gitcode.com/GitHub_Trending/t3/t3
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考