· 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 > 100This catches all Note On messages (144-159 covers all channels) with velocity over 100.
Step 3: Set the Action
THEN EDIT byte2 = 100This 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 higherMultiple 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 C5Status 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 2COPY 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 velocityADD 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 5The 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 messageCommon 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.5Note to CC Converter
Convert specific notes to CC messages:
IF status >= 144 AND status <= 159 AND byte1 == 36
THEN ADD CC 16 = byte2, DELETE ORIGINALThis 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 byte2Sustain Pedal Filter
Remove sustain but keep other CCs:
IF status >= 176 AND status <= 191 AND byte1 == 64
THEN DELETE ORIGINALChannel Splitter
Route based on note range:
IF status == 144 AND byte1 < 60
THEN EDIT status = 145
IF status == 144 AND byte1 >= 60
THEN CONTINUEAuto-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 10msVelocity Gate
Only pass notes above certain velocity:
IF status >= 144 AND status <= 159 AND byte2 < 40
THEN DELETE ORIGINALCC Scaler
Scale mod wheel to half range:
IF status >= 176 AND status <= 191 AND byte1 == 1
THEN EDIT byte2 = byte2 * 0.5Tips 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