- 音视频
- 图形学
- 桌面应用
【免费下载链接】t3
TiXL is an open source software to create realtime motion graphics.
本指南围绕 TiXL(开源实时动态图形软件,代号 t3)中Lib.io.midi运算符库的MidiPitchbendOutput节点展开,讲解如何向指定 MIDI 输出设备发送 14-bit 弯音(Pitchbend)事件,涵盖整数与归一化浮点两种取值方式、连续发送与触发发送两种工作模式,以及如何结合 [AnimValue] 与同库的 Note/Control/Trigger 输出节点搭建生成式音乐或硬件控制链路。读完本文,你将掌握该节点全部 8 个输入参数的语义与默认值、底层实现的值钳制与边沿检测机制,并能据此写出可实际运行的 TiXL 图(Graph)配置。
节点概述:它做什么
MidiPitchbendOutput 位于 TiXL 的 Lib.io.midi 运算符库中,职责是:向所选 MIDI 输出设备(Device)的指定通道(ChannelNumber)发送 14-bit 弯音轮事件。
MIDI 弯音消息使用 14 位分辨率(0~16383,共 16384 级),远比 7-bit 的 ControlChange(0~127)精细,因此适合表达连续的滑音、颤音、音高微调(transpose/detune)等需要平滑变化的控制量。该节点在 TiXL 内部的搜索别名(AKA)为:pitch、pitchbend、transpose、detune,在运算符搜索框中输入这些关键词即可快速定位。
节点接受两种等价的取值形式:
- 整数形式:范围
-8192到8191(对应弯音轮的负向到底到正向到顶); - 归一化浮点形式:范围
-1.0到1.0,更适合直接连接来自动画曲线、数学表达式或 Audio 分析节点的连续信号。
两种形式由布尔开关UsePitchFloat切换,详见下文输入参数表。
输入参数详解
下表完整列出该节点的 8 个输入参数(名称、相关性与类型来自节点定义,默认值来自 MidiPitchbendOutput.t3 的DefaultValue):
| 名称(相关性 & 类型) | 描述 | 默认值 | 取值范围 / 说明 |
|---|---|---|---|
| SendMode(Int32) | 发送模式 | 0 | 枚举型下拉框:0 = SendContinuously(每帧连续发送),1 = SendWhenTriggered(仅在触发时发送)。见 源码枚举定义 |
| TriggerSend(Boolean) | 触发发送信号 | false | 仅在SendMode = SendWhenTriggered时生效;收到临时true时发送一次事件 |
| Device(String) | 目标 MIDI 输出设备 | ""(空) | 下拉列表自动枚举系统当前可用的 MIDI 输出设备(见下文“设备下拉列表”) |
| ChannelNumber(Int32) | MIDI 通道号 | 1 | 有效范围 1~16,源码中通过.Clamp(1, 16)强制约束,超出会自动收敛到边界 |
| Pitch(Int32) | 弯音值(整数形式) | 0 | 有效范围-8192~8191,源码通过.Clamp(-8192, 8191)约束 |
| UsePitchFloat(Boolean) | 是否使用浮点形式 | false | 为true时改用 PitchFloat 输入,忽略 Pitch |
| PitchFloat(Single) | 弯音值(归一化浮点形式) | 0.0 | 有效范围-1.0~1.0,源码通过.Clamp(-1, 1)约束后再换算为 14-bit 整数 |
| Result(输出) | — | — | 见下方“输出”小节 |
说明:参数表以文档 MidiPitchbendOutput.md 的输入列表为骨架,
默认值一列补充自同目录运算符的序列化配置 MidiPitchbendOutput.t3,范围与钳制行为补充自 MidiPitchbendOutput.cs 的Update方法。
输出
| 名称 | 类型 |
|---|---|
| Result | T3.Core.DataTypes.Command |
Result是 TiXL 的通用 Command 槽(Slot),用于把本次 MIDI 发送动作接入渲染命令链或作为执行完成的标记,其类型定义位于 Command.cs 所在的数据类型层。
14-bit 弯音值是如何编码的
MIDI 弯音消息本身携带 14 位数据(2^14 = 16384 个步进),中心位置(无弯音)对应数值 8192。源码 MidiPitchbendOutput.cs 展示了两种输入形式到 14-bit 值的换算:
var useFloat = UsePitchFloat.GetValue(context); int intPitch; if (!useFloat) { intPitch = Pitch.GetValue(context).Clamp(-8192, 8191) + 8192; } else { intPitch = (int)((PitchFloat.GetValue(context).Clamp(-1, 1) * 8192.0).Clamp(-8192, 8191) + 8192); }关键换算逻辑:
- 整数
-8192~8191直接加上偏移量+8192,映射到 0~16383 的 14-bit 范围; - 浮点
-1.0~1.0先乘以8192.0得到-8192.0~8192.0,再经过一次钳制并取整,最后同样+8192; - 最终值被包装进 NAudio 的
PitchWheelChangeEvent并通过GetAsShortMessage()编码为 MIDI 短消息发送:
midiEvent = new PitchWheelChangeEvent(0, channel, intPitch); // ... m.Send(midiEvent.GetAsShortMessage());因此无论用户输入哪种形式,底层都会统一为 0~16383 的 14-bit 弯音码,保证中心点(0 / 0.0)恰好落在 8192 的中立位置。
两种发送模式与设备洪泛问题
文档明确警告:值可以每帧连续发送,也可以仅在触发输入收到(临时的)布尔true时发送;连续发送可能导致接收设备被消息洪泛(flooding),因此只要条件允许,应优先使用触发选项。
对应到源码,SendMode被映射到枚举 SendModes:
private enum SendModes { SendContinuously, // = 0 SendWhenTriggered // = 1 }SendContinuously(模式 0,默认)
每个求值帧都无条件构造并发送一次PitchWheelChangeEvent。该模式适合需要高频平滑滑音的场合,但代价是 MIDI 总线上的消息吞吐量与帧率成正比——若节点在 60 FPS 下运行,接收设备每秒将收到约 60 条弯音消息,文档建议尽量避免这种“无脑连续”用法。
SendWhenTriggered(模式 1)
只有TriggerSend输入发生false → true 的边沿跳变时才发送一次。源码通过成员变量_triggered实现边沿检测:
if (triggerActive != _triggered) { if (triggerActive) triggerJustActivated = true; _triggered = triggerActive; } // 仅当 triggerJustActivated 为 true 时才构造并发送 PitchWheelChangeEvent也就是说,触发后即使TriggerSend一直保持true,也只会发送一次事件,避免了重复消息的洪泛。
用 AnimValue 的 WasHit 平滑降载
文档给出了一个实用技巧:可以将某个 [AnimValue](TiXL 的动画值节点)的WasHit输出接到TriggerSend,并把 AnimValue 的频率设置到“对你当前用途而言足够平滑”的档位,从而以较低的消息频率实现接近连续的弯音效果,显著降低接收设备与 MIDI 总线的负载。这属于“以触发替代连续”思路的典型落地:频率即采样率,频率越高弯音越平滑、负载越大,需要按实际音色与硬件能力折中。
与其他 MIDI 运算符组合
该节点可与同库的多个输出节点协同工作,构建生成式音乐或硬件控制链路,文档中点名的组合对象包括:
- MidiNoteOutput:发送音符开/关事件(NoteOn/NoteOff),支持
NoteWhileTriggered与NoteFixedDuration两种触发语义; - MidiControlOutput:发送 7-bit ControlChange 或 ChannelPressure 事件(0~127 或 0.0~1.0);
- MidiTriggerOutput:发送 ProgramChange 或 Sequencer 命令(0~127);
- MidiNoteOutputExample:位于
Operators/examples中的可运行示例图,展示了此类 MIDI 输出节点的接线方式。
典型链路:用 [MidiNoteOutput] 驱动音高与门限、用 [MidiPitchbendOutput] 叠加滑音/颤音、用 [MidiControlOutput] 控制滤波器或音量、用 [MidiTriggerOutput] 切换音色程序号,从而把 TiXL 的动画、随机、音频分析能力转化为真实的 MIDI 演奏数据。所有输出节点都要求先正确选择Device与ChannelNumber才能生效。
底层实现:设备枚举、注册与状态反馈
通过 MidiConnectionManager 管理 MIDI 输出
节点实现了MidiConnectionManager.IMidiConsumer接口并在首次求值时调用MidiConnectionManager.RegisterConsumer(this)完成注册(源码)。虽然该节点本身并不接收 MIDI 输入(MessageReceivedHandler等为空实现,源码注释说明“只是想保持 MIDI 连接线程存活”),但注册机制保证了 TiXL 的 MIDI 子系统在节点激活时被正确初始化。
设备匹配逻辑遍历 MidiConnectionManager.MidiOutsWithDevices(NAudioMidiOut与设备信息的映射表),按device.ProductName与Device输入精确比对,命中后发送并break:
foreach (var (m, device) in MidiConnectionManager.MidiOutsWithDevices) { if (device.ProductName != deviceName) continue; // ...构造并发送 PitchWheelChangeEvent foundDevice = true; break; }值得注意:设备捕获行为还受CoreSettings.Config.LimitMidiDeviceCapture配置影响(见 MidiConnectionManager.cs),用户可以在设置中用换行分隔的设备名关键字限制 TiXL 占用哪些 MIDI 设备,避免与 DAW(如 Ableton)等宿主程序冲突。
设备下拉列表(ICustomDropdownHolder)
节点实现ICustomDropdownHolder,为Device输入提供动态下拉选项——选项实时来自MidiConnectionManager.MidiOutsWithDevices中每个输出设备的ProductName(源码),选中后通过Device.SetTypedInputValue(selected)写回输入。这意味着在属性面板中可直接从系统当前可用的 MIDI 输出设备列表中选择目标,无需手敲设备名。
状态反馈(IStatusProvider)
节点还实现了IStatusProvider,当发生错误时会在节点上显示错误状态:
- 遍历完所有设备仍未匹配到
deviceName时,错误信息为$"Can't find MidiDevice {deviceName}"; - 发送过程中抛出异常时,错误信息为
$"Failed to send midi to {deviceName}: {e.Message}",并同时写入日志(Log.Warning)。
正常无错误时状态为Success,便于在大型图中快速定位“设备未找到/设备被占用”之类的接线问题。
生命周期与资源释放
节点重写Dispose(bool),在已初始化的情况下调用MidiConnectionManager.UnregisterConsumer(this)反注册,配合管理器在消费者清空时自动CloseMidiDevices()(MidiConnectionManager.cs),确保图销毁或切换时不会残留 MIDI 设备句柄。
默认值与首次上手配置
根据运算符序列化配置 MidiPitchbendOutput.t3,节点默认状态为:UsePitchFloat = false、SendMode = 0(连续发送)、Device = ""、ChannelNumber = 1、Pitch = 0、TriggerSend = false、PitchFloat = 0.0。
一个推荐的稳健启动配置:
- 在
Device下拉框中选择目标 MIDI 输出设备(如虚拟 MIDI 端口、合成器或 DAW 的 MIDI Loopback); - 将
SendMode切换为SendWhenTriggered(1),并在TriggerSend上接入动画/逻辑信号(例如 [AnimValue] 的 WasHit),避免连续模式洪泛; - 保持
UsePitchFloat = false、Pitch = 0验证中心位置输出,再接入 -8192~8191 的整数信号;若希望直接使用归一化曲线,则勾选UsePitchFloat并把PitchFloat接到 -1.0~1.0 的信号源; - 确认通道号
ChannelNumber与接收端(合成器/DAW 音轨)一致(1~16)。
小结与注意事项
- 取值边界:整数
-8192~8191、浮点-1.0~1.0,越界输入会被源码强制钳制;14-bit 编码中心点为 8192(即 0 / 0.0)。 - 发送模式:连续发送(默认)简单直接但易洪泛接收设备,触发发送只响应
TriggerSend的 false→true 边沿,是文档推荐的省带宽做法。 - 组合能力:与 [MidiNoteOutput]、[MidiControlOutput]、[MidiTriggerOutput] 组合可覆盖音符、控制器、程序切换与弯音四大类 MIDI 消息,配合 MidiNoteOutputExample 可快速上手生成式音乐与硬件控制场景。
- 可观测性:借助
IStatusProvider,设备未找到与发送失败都会直接在节点上呈现错误状态,便于调试。 - 所有结论均来自本仓库文档 MidiPitchbendOutput.md、实现源码 MidiPitchbendOutput.cs、配置 MidiPitchbendOutput.t3 与 MidiConnectionManager.cs,读者可打开对应文件对照验证。
- 音视频
- 图形学
- 桌面应用
【免费下载链接】t3
TiXL is an open source software to create realtime motion graphics.
相关推荐
TiXL 中 MidiOutput 运算器完全指南:向 MIDI 设备发送音符与控制器事件
TiXL 中 MidiOutput 运算器完全指南:向 MIDI 设备发送音符与控制器事件 MidiOutput 是 TiXL(实时动态图形创作软件) Lib.
音视频图形学桌面应用MoE专家混合架构:Kimi-K2.7-Code-NVFP4模型结构技术解析
MoE专家混合架构:Kimi K2.7 Code NVFP4模型结构技术解析 在当今人工智能快速发展的时代, MoE专家混合架构 正在成为大型语言模型的核心技术
音视频图形学桌面应用TiXL 符号库 Reveal in Explorer 使用指南:在文件管理器中一键定位运算符符号
TiXL 符号库 Reveal in Explorer 使用指南:在文件管理器中一键定位运算符符号 TiXL(实时动态图形创作软件)的 Symbol Libra
音视频图形学桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考