トップへ(mam-mam.net/)

Playing MIDI Sounds in Delphi — A Practical Guide to midiOutShortMsg

Japanese

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)
C60 ($3C) C#61 ($3D) D62 ($3E) D#63 ($3F)
E64 ($40) F65 ($41) F#66 ($42) G67 ($43)
G#68 ($44) A69 ($45) B♭70 ($46) B71 ($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
0Acoustic Grand Piano
1Bright Acoustic Piano
2Electric Grand Piano
3Honky-tonk Piano
4Electric Piano 1
5Electric Piano 2
6Harpsichord
7Clavinet
8Celesta
9Glockenspiel
10Music Box
11Vibraphone
12Marimba
13Xylophone
14Tubular Bells
15Dulcimer
16Drawbar Organ
17Percussive Organ
18Rock Organ
19Church Organ
20Reed Organ
21Accordion
22Harmonica
23Tango Accordion
24Acoustic Guitar (Nylon)
25Acoustic Guitar (Steel)
26Jazz Guitar
27Clean Electric Guitar
28Muted Electric Guitar
29Overdriven Guitar
30Distortion Guitar
31Guitar Harmonics
32Acoustic Bass
33Fingered Bass
34Picked Bass
35Fretless Bass
36Slap Bass 1
37Slap Bass 2
38Synth Bass 1
39Synth Bass 2
40Violin
41Viola
42Cello
43Contrabass
44Tremolo Strings
45Pizzicato Strings
46Harp
47Timpani
48String Ensemble 1
49String Ensemble 2
50Synth Strings 1
51Synth Strings 2
52Choir Aahs
53Voice Oohs
54Synth Voice
55Orchestra Hit
56Trumpet
57Trombone
58Tuba
59Muted Trumpet
60French Horn
61Brass Section
62Synth Brass 1
63Synth Brass 2
64Soprano Sax
65Alto Sax
66Tenor Sax
67Baritone Sax
68Oboe
69English Horn
70Bassoon
71Clarinet
72Piccolo
73Flute
74Recorder
75Pan Flute
76Bottle Blow
77Shakuhachi
78Whistle
79Ocarina
80Square Wave
81Sawtooth Wave
82Calliope
83Chiff
84Charango
85Voice
86Fifths
87Bass + Lead
88Fantasia
89Warm Pad
90Poly Synth
91Choir Pad
92Bowed Pad
93Metallic Pad
94Halo Pad
95Sweep Pad
96Rain
97Soundtrack
98Crystal
99Atmosphere
100Brightness
101Goblin
102Echo Drops
103Sci-Fi
104Sitar
105Banjo
106Shamisen
107Koto
108Kalimba
109Bagpipe
110Fiddle
111Shanai
112Tinkle Bell
113Agogo
114Steel Drums
115Woodblock
116Taiko Drum
117Melodic Tom
118Synth Drum
119Reverse Cymbal
120Guitar Fret Noise
121Breath Noise
122Seashore
123Bird Tweet
124Telephone Ring
125Helicopter
126Applause
127Gunshot

Creating the Project and Designing the Form

Create a new project (VCL Application).
Drag and drop a TButton component onto the form (Form1).

Designing the form in the Delphi IDE

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.