TiXL 中 MidiNoteOutput 算子实战:MIDI 音符发送、力度映射与触发模式的完整指南
发布时间:2026/9/20 23:17:45 锦皓数字建站

TiXL 中 MidiNoteOutput 算子实战MIDI 音符发送、力度映射与触发模式的完整指南【免费下载链接】t3TiXL is an open source software to create realtime motion graphics.项目地址: https://gitcode.com/GitHub_Trending/t3/t3本篇技术指南围绕 TiXL实时动态图形创作工具中的MidiNoteOutput算子展开讲解如何将 TiXL 内的布尔触发信号转换为真实的 MIDI NoteOn / NoteOff 消息发送到指定设备的指定通道。读完本文你将掌握两种触发模式Note While Triggered 与 Note Fixed Duration的区别与选择、整数 / 归一化浮点两种力度Velocity的映射规则、各输入参数的取值范围与默认值并了解该算子底层与 NAudio、MidiConnectionManager的协作机制从而把 MidiNoteOutput 与 MidiControlOutput、MidiPitchbendOutput、MidiTriggerOutput 组合起来搭建生成式音乐或硬件控制管线。MidiNoteOutput 位于Lib.io.midi算子库是 TiXL 中向外部 MIDI 设备合成器、音源、硬件控制器、DAW 虚拟端口等发送音符事件的核心节点。该算子通过 IoServices/MidiConnectionManager.cs 管理底层 NAudio 的MidiOut设备连接并在界面上以状态提示IStatusProvider反馈发送结果。功能概述MidiNoteOutput 负责向所选设备在给定通道上发送 MIDI 音符Note。它的核心行为可以概括为通过TriggerSend布尔输入触发音符的按下NoteOn与松开NoteOff音符编号NoteNumber决定音高取值 0127力度Velocity既可以用0127 的整数提供也可以用0.01.0 的归一化浮点提供音符的持续时间由触发模式决定见下文两种模式输出ResultT3.Core.DataTypes.Command可在 TiXL 的图Graph中作为命令型数据继续参与连线。在 TiXL 中MidiNoteOutput 常与 MidiControlOutput发送 7 位 ControlChange / Channel Pressure、MidiPitchbendOutput发送 14 位弯音、MidiTriggerOutput发送 ProgramChange 与 Sequencer 命令配合使用以搭建生成式音乐或控制硬件设备。同一算子库的完整清单可查阅 Lib.io.midi README。两种触发模式SendModeSendMode决定音符何时按下、何时松开对应源码中的枚举SendModes见 Operators/Io/Symbols/lib/io/midi/MidiNoteOutput.cs枚举值名称行为0Note_FixedDuration固定时长默认当TriggerSend变为true时发送 NoteOn音符在DurationInSecs指定的时长结束后发送 NoteOff若在时长结束前又触发了一个新音符会先强制发送前一个音符的 NoteOff防止音符重叠或悬挂hanging note1Note_WhileTriggered按住即响当TriggerSend为布尔true期间持续播放音符一旦变为false立即向接收设备发送 NoteOff 命令模式选择建议需要按住才响、松开即止的交互例如用键盘按键、瞬时开关控制音色选Note_WhileTriggered需要触发一次、自动播放固定时长的音符例如配合节拍器、序列器或预设节奏生成选Note_FixedDuration此时DurationInSecs是关键参数。源码层面的实现细节在Update(EvaluationContext context)方法中MidiNoteOutput.cs算子通过比较当前帧TriggerSend的值与内部缓存状态_triggered检测刚刚激活triggerJustActivated与刚刚释放triggerJustDeactivated两种边沿事件只有边沿发生时才会真正构造并发送 MIDI 事件Note_WhileTriggered模式激活边沿构造new NoteOnEvent(0, channel, noteIndex, velocity, durationInMs)并保存其OffEvent释放边沿直接发送缓存的_offEventMidiNoteOutput.cs。Note_FixedDuration模式激活边沿先检查_offEvent是否非空若存在则立即补发上一个音符的 NoteOff这正是防止重叠或悬挂音符的实现随后记录_lastNoteOnTime每一帧比较absTime - _lastNoteOnTime与durationInMs超过即发送 NoteOffMidiNoteOutput.cs。时长DurationInSecs在源码中被乘以 1000 转为毫秒durationInMs后Clamp(1, 100000)因此有效范围是1ms100s最小 1ms、最大 100 秒超出自动截断。输入参数详解原文档列出的全部输入参数如下本节结合源码与默认配置MidiNoteOutput.t3给出取值范围、默认值与补充说明名称类型说明取值范围 / 默认值TriggerSendBoolean音符触发开关true触发按下、false触发松开默认falseSendModeInt32音符发送模式0Note_FixedDuration1Note_WhileTriggered默认0DeviceString目标 MIDI 输出设备名称ProductName在 UI 上以下拉框形式选择默认空字符串ChannelNumberInt32MIDI 通道号116默认1NoteNumberInt32音符编号音高MIDI 标准0127默认64即中央 C 附近的 EVelocityInt32整数力度值当UseVelocityFloatfalse时生效0127默认100UseVelocityFloatBoolean是否使用归一化浮点力度默认falseVelocityFloatSingle归一化浮点力度当UseVelocityFloattrue时生效0.01.0默认0.75DurationInSecsSingle固定时长模式下的音符持续时间秒默认0.5实际范围 0.001s100s参数的源码级约束从Update方法可确认以下输入被强制钳制Clamp超范围值不会被发送ChannelNumber被Clamp(1, 16)即 116 通道NoteNumber被Clamp(0, 127)即完整 MIDI 音域整数力度Velocity被Clamp(0, 127)浮点力度VelocityFloat被Clamp(0, 1)后乘以 127 再取整得到最终力度MidiNoteOutput.cs。因此两种力度输入最终都会落到 0127 的标准 MIDI 力度区间UseVelocityFloat只是一个输入方式的切换开关。Device 设备下拉框与状态提示Device输入在 TiXL 编辑器中呈现为下拉框其选项由ICustomDropdownHolder接口从MidiConnectionManager.MidiOutsWithDevices中实时枚举所有可用 MIDI 输出设备的ProductName生成MidiNoteOutput.cs。同时该算子实现了IStatusProvider当找不到名为Device的设备时节点状态会显示错误提示Cant find MidiDevice {deviceName}当发送抛出异常时显示Failed to send midi to {deviceName}: ...MidiNoteOutput.cs。排查连线问题时先观察节点状态图标是否为错误即可快速定位。输出Result名称类型ResultT3.Core.DataTypes.CommandResult是 TiXL 的 Command 类型数据可继续连接到支持该数据类型的下游输入用于记录、转发或与其他输出算子组合。需要注意MIDI 事件的实际发送发生在算子内部更新时调用m.Send(midiEvent.GetAsShortMessage())Result主要用于 TiXL 图数据流中的命令传递。底层协作与 MidiConnectionManager 的关系MidiNoteOutput 继承自InstanceMidiNoteOutput并实现MidiConnectionManager.IMidiConsumer接口其设备生命周期管理全部委托给静态类MidiConnectionManager位于 IoServices/MidiConnectionManager.cs首次执行时调用MidiConnectionManager.RegisterConsumer(this)这会触发一次ScanAndRegisterToMidiDevices()遍历 NAudio 枚举到的所有MidiOut.NumberOfDevices并建立MidiOut句柄析构时调用UnregisterConsumer释放资源MidiConnectionManager.cs。每帧更新时算子遍历MidiConnectionManager.MidiOutsWithDevices按device.ProductName deviceName匹配目标设备MidiNoteOutput.cs。IMidiConsumer的MessageReceivedHandler/ErrorReceivedHandler在该算子中是空实现源码注释说明算子并不实际接收 MIDI 输入实现该接口只是为了保持 MIDI 连接线程运行。设备是否被捕获还受全局设置CoreSettings.Config.LimitMidiDeviceCapture约束可在 TiXL 设置中限制允许捕获的设备名单若设备正被其他应用占用NAudio 会抛出MmExceptionMemoryAllocationError此时需先关闭占用该 MIDI 端口的程序。实战接线建议选设备在Device下拉框中选择目标 MIDI 输出合成器、虚拟 MIDI 端口或 DAW 回环端口并确认该端口未被其他应用独占。定通道ChannelNumber设为接收设备的音色所在通道116。定音高NoteNumber按 MIDI 音高表设置如 60C4。定力度静态力度直接填Velocity若希望用动画曲线、LFO 或音频分析驱动力度开启UseVelocityFloat并用 0.01.0 的VelocityFloat驱动。选模式交互式控制选SendMode1Note_WhileTriggered自动节奏选SendMode0Note_FixedDuration并设置DurationInSecs。驱动触发将任意布尔信号按钮、键盘、节拍同步、音频检测、随机触发等接到TriggerSend配合 MidiControlOutput、MidiPitchbendOutput、MidiTriggerOutput 可同时输出 CC、弯音与 ProgramChange实现完整的生成式音乐或硬件控制方案。需要注意的是MIDI 消息本质上是瞬时事件触发信号应以边沿短暂变为 true 再变回 false驱动避免长期保持true造成重复触发或音符悬挂Note_FixedDuration模式本身已经内置了新音符强制终止旧音符的保护逻辑。相关算子与文档MidiControlOutput发送 7 位 ControlChange 或 Channel Pressure 事件支持 0127 整数或 0.01.0 归一化浮点。MidiPitchbendOutput发送 14 位弯音事件支持 -81928191 整数或 -1.01.0 浮点。MidiTriggerOutput发送 ProgramChange 或 Start/Stop/Continue/Tempo 等 Sequencer 命令。MidiInputMIDI 输入默认将 0127 映射为 01 输出。Lib.io.midi README完整算子库索引。上述算子的源码实现均位于 Operators/Io/Symbols/lib/io/midi设备管理基础设施位于 IoServices/MidiConnectionManager.cs可据此深入理解 TiXL 的 MIDI 输入输出架构。【免费下载链接】t3TiXL is an open source software to create realtime motion graphics.项目地址: https://gitcode.com/GitHub_Trending/t3/t3创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。