· 6 min read
How to Create Custom MIDI Rules in MIDIHub
Master MIDIHub's powerful custom rules system. Learn byte-level MIDI manipulation to create complex conditions, transformations, and new messages.

Custom rules are MIDIHub’s most powerful feature, giving you complete control over MIDI messages at the byte level. While this requires understanding MIDI’s structure, it enables transformations impossible with simple remapping - from velocity curves to generating entirely new messages.
Understanding MIDI Messages
Before diving into custom rules, you need to understand that MIDI messages consist of bytes:
Status Byte: Tells what kind of message (Note On, CC, etc.) and channel Data Bytes: The values (note number, velocity, CC value, etc.)
For example, a Note On message:
- Status: 144 (Note On channel 1)
- Data 1: 60 (Middle C)
- Data 2: 100 (velocity)
Note: Channels in status bytes are 0-15, but displayed as 1-16 in the UI
The Custom Rules Interface
The custom rules dialog with condition builder and actions
The custom rules dialog has three main sections:
- Conditions (IF): When should this rule trigger?
- Actions (THEN): What should happen?
- Byte Tables: Quick reference for values
Basic Rule Structure
Every custom rule follows this pattern:
IF [conditions] THEN [actions]
You can have multiple conditions (using AND) and multiple actions.
Creating Your First Custom Rule
Let’s start with a simple example: limiting velocity to 100.
Step 1: Add a Custom Rule
- Open a port’s Rulebook
- Tap “Add Rule”
- Select “Custom Rule”
Step 2: Set the Condition
We want to catch notes with velocity over 100:
IF status >= 144 AND status <= 159 AND byte2 > 100
This catches all Note On messages (144-159 covers all channels) with velocity over 100.
Step 3: Set the Action
THEN EDIT byte2 = 100
This edits the velocity (byte2) to 100.
Condition Types
You can combine multiple conditions using AND logic. Each condition is evaluated, and all must be true for the rule to trigger.
Available Logic Operators
==
Equal to (exact match)!=
Not equal to (doesn’t match)<
Less than>
Greater than<=
Less than or equal to>=
Greater than or equal to
Examples:
IF byte1 == 60 // Exactly Middle C
IF byte2 != 0 // Any velocity except 0
IF byte1 < 60 // Notes below Middle C
IF byte2 > 100 // High velocity values
IF byte1 <= 72 // C5 and below
IF status >= 144 // Note On channel 1 and higher
Multiple Conditions
Chain conditions with AND:
IF
status >= 144
AND
status <= 159
AND
byte2 > 64
// Note On messages with velocity above 64
IF
status == 176
AND
byte1 == 64
AND
byte2 > 0
// Sustain pedal on (CC 64 with value > 0)
IF
status == 144
AND
byte1 >= 60
AND
byte1 <= 72
// Note On channel 1, notes C4 to C5
Status bytes range from 128-255, and data bytes (byte1 and byte2) range from 0-127. Use the lookup tables in the Custom Rules dialog to find specific values.
Action Types
EDIT - Modify the Original Message
Edit the message that matches your conditions.
Available operators:
=
Set to a value+
Add to current value-
Subtract from current value*
Multiply current value/
Divide current value
Examples:
EDIT byte1 = 60 // Set note to Middle C
EDIT byte2 = 127 // Set to maximum velocity
EDIT status = 145 // Change to channel 2
EDIT byte2 = byte2 * 0.5 // Halve velocity
EDIT byte1 = byte1 + 12 // Transpose up octave
EDIT byte2 = byte2 - 20 // Reduce velocity by 20
EDIT byte2 = byte2 / 2 // Divide velocity by 2
COPY AND EDIT - Duplicate and Modify
Keep the original message and create a modified copy. Uses the same operators as EDIT.
Examples:
COPY AND EDIT byte1 = byte1 + 12 // Octave double
COPY AND EDIT byte2 = byte2 * 0.7 // Quieter copy
COPY AND EDIT status = status + 1 // Copy to next channel
COPY AND EDIT byte1 = byte1 - 12 // Octave below
COPY AND EDIT byte2 = byte2 / 3 // One third velocity
ADD MESSAGE - Create New Messages
Add completely new messages. Available message types:
- Note Off
- Note On
- Polyphonic Aftertouch
- Control Change
- Program Change
- Channel Aftertouch
Examples:
ADD NoteOn 60 100 // Add Middle C immediately
ADD NoteOff 60 0, Delay 200ms // Add Note Off after 200ms
ADD CC 64 127 // Add sustain on
ADD CC 64 0, Delay 500ms // Release sustain after 500ms
ADD ProgramChange 5 // Change to patch 5
The delay parameter lets you schedule messages - perfect for creating automatic note-offs, timed effects, or rhythmic patterns.
DELETE ORIGINAL - Discard the Message
Remove the message that matched your conditions:
DELETE ORIGINAL // Discard the matched message
Common pattern - replace a message:
IF status == 176 AND byte1 == 1
THEN ADD CC 11 = byte2, DELETE ORIGINAL
// Converts mod wheel (CC 1) to expression (CC 11)
Practical Examples
Velocity Curve
Create a custom velocity response:
IF status >= 144 AND status <= 159 AND byte2 < 30
THEN EDIT byte2 = byte2 * 2
IF status >= 144 AND status <= 159 AND byte2 >= 100
THEN EDIT byte2 = 100 + (byte2 - 100) * 0.5
Note to CC Converter
Convert specific notes to CC messages:
IF status >= 144 AND status <= 159 AND byte1 == 36
THEN ADD CC 16 = byte2, DELETE ORIGINAL
This converts kick drum (note 36) to CC 16.
Chord Generator
Add harmony to single notes:
IF status >= 144 AND status <= 159
THEN ADD NoteOn byte1+4 byte2, ADD NoteOn byte1+7 byte2
IF status >= 128 AND status <= 143
THEN ADD NoteOff byte1+4 byte2, ADD NoteOff byte1+7 byte2
Sustain Pedal Filter
Remove sustain but keep other CCs:
IF status >= 176 AND status <= 191 AND byte1 == 64
THEN DELETE ORIGINAL
Channel Splitter
Route based on note range:
IF status == 144 AND byte1 < 60
THEN EDIT status = 145
IF status == 144 AND byte1 >= 60
THEN CONTINUE
Auto-Accompaniment
Add bass note an octave below:
IF status >= 144 AND status <= 159 AND byte1 >= 60
THEN ADD NoteOn byte1-12 byte2*0.8, Delay 10ms
Velocity Gate
Only pass notes above certain velocity:
IF status >= 144 AND status <= 159 AND byte2 < 40
THEN DELETE ORIGINAL
CC Scaler
Scale mod wheel to half range:
IF status >= 176 AND status <= 191 AND byte1 == 1
THEN EDIT byte2 = byte2 * 0.5
Tips for Writing Custom Rules
Start Simple
- Test with one condition first
- Add complexity gradually
- Use the log to verify results
Use the Reference Tables
The help button shows:
- Status byte values
- CC numbers
- Note numbers
Test Thoroughly
- Use Test Generator in rulebook
- Monitor with port logs
- Check edge cases
Optimize for Performance
- Combine related conditions
- Order rules efficiently (filters first)
- Avoid unnecessary calculations
Common Pitfalls
Channel Confusion
Remember: Channels are 0-15 in bytes but shown as 1-16 in UI
- Channel 1 in UI = 0 in status byte
- Note On Ch1 = 144, Ch2 = 145, etc.
Order Matters
Rules in a ruleset apply sequentially:
Rule 1: SET byte1 = 60
Rule 2: IF byte1 = 60 THEN... // This sees the modified value!
Message Types
Not all messages have two data bytes:
- Program Change: Only byte1
- Channel Aftertouch: Only byte1
- Pitch Bend: Both bytes form 14-bit value