· 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.

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

Custom Rules Dialog The custom rules dialog with condition builder and actions

The custom rules dialog has three main sections:

  1. Conditions (IF): When should this rule trigger?
  2. Actions (THEN): What should happen?
  3. 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

  1. Open a port’s Rulebook
  2. Tap “Add Rule”
  3. 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

  1. Test with one condition first
  2. Add complexity gradually
  3. 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
Back to How‑to

Related Posts

View All Posts