Playing MIDI Sounds in Delphi — A Practical Guide to midiOutShortMsg
This page explains how to play MIDI sounds in Delphi using the midiOutShortMsg function.
It covers the essential operations such as Note On/Off, program (instrument) changes, and chord playback, with practical sample code included.
Recommended for anyone interested in controlling MIDI output in a VCL application.
Reference: Software keyboard created in Delphi
https://mam-mam.net/download/skbd.html
To open a MIDI device, use the following function:
var hMidi: HMIDIOUT; // MIDI handle
midiOutOpen(@hMidi, MIDI_MAPPER, 0, 0, CALLBACK_NULL);
To play or stop notes, or to change instruments, use:
midiOutShortMsg(hMidi, dwMsg);
To close the MIDI device, use:
midiOutClose(hMidi);
About the midiOutShortMsg Function
midiOutShortMsg(hMidi, dwMsg);
The first parameter hMidi is the handle of the opened MIDI device.
The second parameter dwMsg is a 4‑byte value, and the meaning of the message changes depending on the value you pass.
Because Windows uses little-endian format, the bytes are arranged as: 3rd byte, 2nd byte, 1st byte.
| Main Message Types | 1st Byte | 2nd Byte | 3rd Byte | Example |
|---|---|---|---|---|
| Note Off (stop sound) | $8n | Note number | - | $0080 |
| Note On (play sound) | $9n | Note number | Velocity (volume) | $7F3C90 |
| Expression (volume control) | $Bn | $0B (11) | Volume value 0–127 ($00–$7F) | $7F0BB0 |
| Reverb Depth | $Bn | $5D (93) | Value 0–127 ($00–$7F) | $7F5DB0 |
| Chorus Depth | $Bn | $5B (91) | Value 0–127 ($00–$7F) | $7F5BB0 |
| Program Change (instrument change) | $Cn | Program number 0–127 ($00–$7F) | - | $04C0 |
- The n in the table above
- Represents the MIDI channel number (0–15, or $0–$F in hexadecimal). Up to 16 different instruments can be used simultaneously.
- The note number in the table above
-
Pitch value from 0–127 ($00–$7F in hexadecimal)
C 60 ($3C) C# 61 ($3D) D 62 ($3E) D# 63 ($3F) E 64 ($40) F 65 ($41) F# 66 ($42) G 67 ($43) G# 68 ($44) A 69 ($45) B♭ 70 ($46) B 71 ($47) C↑ 72 ($48) C↑# 73 ($49) D↑ 74 ($4A) D↑# 75 ($4B) - Velocity (volume)
- Volume value from 0–127 ($00–$7F in hexadecimal)
- Program (instrument) numbers
-
Program No. Instrument 0 Acoustic Grand Piano 1 Bright Acoustic Piano 2 Electric Grand Piano 3 Honky-tonk Piano 4 Electric Piano 1 5 Electric Piano 2 6 Harpsichord 7 Clavinet 8 Celesta 9 Glockenspiel 10 Music Box 11 Vibraphone 12 Marimba 13 Xylophone 14 Tubular Bells 15 Dulcimer 16 Drawbar Organ 17 Percussive Organ 18 Rock Organ 19 Church Organ 20 Reed Organ 21 Accordion 22 Harmonica 23 Tango Accordion 24 Acoustic Guitar (Nylon) 25 Acoustic Guitar (Steel) 26 Jazz Guitar 27 Clean Electric Guitar 28 Muted Electric Guitar 29 Overdriven Guitar 30 Distortion Guitar 31 Guitar Harmonics 32 Acoustic Bass 33 Fingered Bass 34 Picked Bass 35 Fretless Bass 36 Slap Bass 1 37 Slap Bass 2 38 Synth Bass 1 39 Synth Bass 2 40 Violin 41 Viola 42 Cello 43 Contrabass 44 Tremolo Strings 45 Pizzicato Strings 46 Harp 47 Timpani 48 String Ensemble 1 49 String Ensemble 2 50 Synth Strings 1 51 Synth Strings 2 52 Choir Aahs 53 Voice Oohs 54 Synth Voice 55 Orchestra Hit 56 Trumpet 57 Trombone 58 Tuba 59 Muted Trumpet 60 French Horn 61 Brass Section 62 Synth Brass 1 63 Synth Brass 2 64 Soprano Sax 65 Alto Sax 66 Tenor Sax 67 Baritone Sax 68 Oboe 69 English Horn 70 Bassoon 71 Clarinet 72 Piccolo 73 Flute 74 Recorder 75 Pan Flute 76 Bottle Blow 77 Shakuhachi 78 Whistle 79 Ocarina 80 Square Wave 81 Sawtooth Wave 82 Calliope 83 Chiff 84 Charango 85 Voice 86 Fifths 87 Bass + Lead 88 Fantasia 89 Warm Pad 90 Poly Synth 91 Choir Pad 92 Bowed Pad 93 Metallic Pad 94 Halo Pad 95 Sweep Pad 96 Rain 97 Soundtrack 98 Crystal 99 Atmosphere 100 Brightness 101 Goblin 102 Echo Drops 103 Sci-Fi 104 Sitar 105 Banjo 106 Shamisen 107 Koto 108 Kalimba 109 Bagpipe 110 Fiddle 111 Shanai 112 Tinkle Bell 113 Agogo 114 Steel Drums 115 Woodblock 116 Taiko Drum 117 Melodic Tom 118 Synth Drum 119 Reverse Cymbal 120 Guitar Fret Noise 121 Breath Noise 122 Seashore 123 Bird Tweet 124 Telephone Ring 125 Helicopter 126 Applause 127 Gunshot
Creating the Project and Designing the Form
Create a new project (VCL Application).
Drag and drop a TButton component onto the form (Form1).
Writing the Source Code
Double‑click Button1 and enter the following source code.
The code below plays the note “C” for one second and then stops it.
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Winapi.MMSystem;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
hMidi: HMIDIOUT; // MIDI handle
dwMsg: Cardinal;
vol, tone, ch: Byte;
begin
// Volume
vol := $40; // $00–$7F
// Instrument (program number)
tone := $7C; // Telephone ($00–$7F)
// Channel
ch := $00; // $00–$0F
// Open the MIDI device (enables MIDI output)
midiOutOpen(@hMidi, MIDI_MAPPER, 0, 0, CALLBACK_NULL);
try
// Change instrument (Program Change)
dwMsg := ($C0 + ch) + (tone shl 8);
midiOutShortMsg(hMidi, dwMsg);
// Play note: C4 (60) volume
dwMsg := ($90 + ch) + ($3C shl 8) + (vol shl 16);
midiOutShortMsg(hMidi, dwMsg);
// Wait 1 second
Sleep(1000);
// Stop the C4 note
dwMsg := ($80 + ch) + ($3C shl 8);
midiOutShortMsg(hMidi, dwMsg);
finally
// Close the MIDI device
midiOutClose(hMidi);
end;
end;
end.
Reference
The following source code plays a C–E–G chord for one second and then stops all notes.
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Winapi.MMSystem;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
hMidi: HMIDIOUT; // MIDI handle
dwMsg: Cardinal;
vol, tone, ch: Byte;
begin
// Volume
vol := $40; // $00–$7F
// Instrument (program number)
tone := $10; // $00–$7F
// Channel
ch := $00; // $00–$0F
// Open the MIDI device (enable MIDI output)
midiOutOpen(@hMidi, MIDI_MAPPER, 0, 0, CALLBACK_NULL);
try
// Change instrument (Program Change)
dwMsg := ($C0 + ch) + (tone shl 8);
midiOutShortMsg(hMidi, dwMsg);
// Play C4 (60) with volume
dwMsg := ($90 + ch) + ($3C shl 8) + (vol shl 16);
midiOutShortMsg(hMidi, dwMsg);
// Play E4 (64) with volume
dwMsg := ($90 + ch) + ($40 shl 8) + (vol shl 16);
midiOutShortMsg(hMidi, dwMsg);
// Play G4 (67) with volume
dwMsg := ($90 + ch) + ($43 shl 8) + (vol shl 16);
midiOutShortMsg(hMidi, dwMsg);
// Wait 1 second
Sleep(1000);
// Stop C4
dwMsg := ($80 + ch) + ($3C shl 8);
midiOutShortMsg(hMidi, dwMsg);
// Stop E4
dwMsg := ($80 + ch) + ($40 shl 8);
midiOutShortMsg(hMidi, dwMsg);
// Stop G4
dwMsg := ($80 + ch) + ($43 shl 8);
midiOutShortMsg(hMidi, dwMsg);
finally
// Close the MIDI device
midiOutClose(hMidi);
end;
end;
end.
Reference
The following source code plays a short melody.
This melody is a public‑domain German folk song ("Frog Round").
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Winapi.MMSystem;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
const
notes: array[0..42] of Byte =
(
$3C,$3E,$40,$41,$40,$3E,$3C,$00,
$40,$41,$43,$45,$43,$41,$40,$00,
$3C,$00,$3C,$00,$3C,$00,$3C,$00,
$3C,$00,$3C,$00,$3E,$00,$3E,$00,$40,$00,$40,$00,$41,$00,$41,$00,
$40,$3E,$3C
);
times: array[0..42] of Integer =
(
400,400,400,400,400,400,400,400,
400,400,400,400,400,400,400,400,
400,400,400,400,400,400,400,400,
100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
400,400,400
);
procedure TForm1.Button1Click(Sender: TObject);
var
hMidi: HMIDIOUT; // MIDI handle
dwMsg: Cardinal;
vol, tone, ch: Byte;
i: Integer;
begin
// Volume
vol := $40; // $00–$7F
// Instrument (voice “A”)
tone := 52; // $00–$7F
// Channel
ch := $00; // $00–$0F
// Open the MIDI device (enable MIDI output)
midiOutOpen(@hMidi, MIDI_MAPPER, 0, 0, CALLBACK_NULL);
try
// Change instrument (Program Change)
dwMsg := ($C0 + ch) + (tone shl 8);
midiOutShortMsg(hMidi, dwMsg);
for i := Low(notes) to High(notes) do
begin
if notes[i] <> 0 then
begin
// Note on
dwMsg := ($90 + ch) + (notes[i] shl 8) + (vol shl 16);
midiOutShortMsg(hMidi, dwMsg);
end;
Sleep(times[i]);
if notes[i] <> 0 then
begin
// Note off
dwMsg := ($80 + ch) + (notes[i] shl 8);
midiOutShortMsg(hMidi, dwMsg);
end;
end;
finally
// Close the MIDI device
midiOutClose(hMidi);
end;
end;
end.
