Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1131
  • Last Modified:

Generating MIDI Files...

Hi all...

I need a simple Delphi app that will write a MIDI file with a single note-on, followed by a single note-off.  It needs to just open the file, dump the contents into the file using Write(File, #$xx), close the file and then I should be able to play the file in another program (which you don't have to write).

The only proviso is that I need a full explanation of what each bit of the code does and how it is formed so that I can expand from there...

Hope someone can help me ASAP...

Matt
0
mdavis1982
Asked:
mdavis1982
1 Solution
 
DragonSlayerCommented:
0
 
LukA_YJKCommented:
Fortunately I just recently worked on an utility for changing custom song format to midi, so learned out some things. Not much, but hope enough... That is it... [Red Leader]

procedure TSngFile.SaveAsMidi(note: byte; FileName: string);
const
  midHdr: array[0..13]of byte = ($4D,$54,$68,$64,
     $00,$00,$00,$06,$00,$01,$00,$01,$01,$E0);
  midTrk: array[0..7]of byte = ($4D,$54,$72,$6B,$00,$00,$00,$0E);
  midEnd: array[0..3]of byte = ($00,$FF,$2F,$00);
  midCmd: array[0..4]of byte = ($80,$00,$90,$00,$00);
  Velocity = $FF;
  Time     = $FF;
var
  midFile: TFileStream;
begin
  // Create MIDI file
  midFile := TFileStream.Create(FileName +'.mid', fmCreate);
  with midFile do try
    // Write MIDI header
    Write(midHdr, SizeOf(midHdr));
    // Write MIDI track
    Write(midTrk, SizeOf(midTrk));
    // Write Note On
    midCmd[2] := $90;
    midCmd[3] := Note;
    midCmd[4] := Velocity;
    Write(midCmd, SizeOf(midCmd));
    // Write Note Off
    midCmd[0] := $80 or (Time div 128 mod 128);
    midCmd[1] := $00 or (Time mod 128);
    midCmd[2] := $80;
    Write(midCmd, SizeOf(midCmd));
    // Write MIDI track end
    Write(midEnd, SizeOf(midEnd));
  finally
    midFile.Free;
  end;
end;

Hope it will help...
0
 
LukA_YJKCommented:
I checked my comment above and it works good (at least here) so I propose it as an Answer...
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
mdavis1982Author Commented:
I have not accepted it because nothing is explained like I asked for... If you could write a full description of the codes etc, then I would be more than happy to accept it
0
 
LukA_YJKCommented:
Is it working (there) ?
0
 
LukA_YJKCommented:
This is it:

procedure TSngFile.SaveAsMidi(note: byte; FileName: string);
const
  // MIDI file header
  midHdr: array[0..13]of byte =
   // [0..3] Always MThd
   ($4D,$54,$68,$64,
   // [4..7] Always the same
   $00,$00,$00,$06,
   // [8..9] Two bytes for file format
   // $01 = synchronous multiple tracks
   $00,$01,
   // [10..11] Two bytes for number of tracks
   $00,$01,
   // [12..13] Two bytes for ticks per quarter note
   $01,$E0);

  // MIDI track header
  midTrk: array[0..7]of byte =
   // [0..3] Always MTrk
   ($4D,$54,$72,$6B,
   // [4..7] Four bytes for track size in bytes
   $00,$00,$00,$0E);
  // MIDI track end bytes

  midEnd: array[0..3]of byte =
   // [0..3] Always the same
   ($00,$FF,$2F,$00);

  // MIDI command
  midCmd: array[0..4]of byte =
   // [0..1] Two bytes for time in ticks
   ($80,$00,
   // [2] Command:
   // $90 = Note on at channel 0
   // $80 = Note off at channel 0
   $90,
   // [3] Note and [4] velocity
   $00,$00);

  // Constant velocity
  Velocity = $FF;
  // Constant duration
  Time     = $FF;
var
  midFile: TFileStream;
begin
  // Create MIDI file
  midFile := TFileStream.Create(FileName +'.mid', fmCreate);
  with midFile do try

    // Write MIDI header
    Write(midHdr, SizeOf(midHdr));

    // Write MIDI track
    Write(midTrk, SizeOf(midTrk));

    // Write Note On
    // Play immediately = time is 0
    midCmd[2] := $90;
    midCmd[3] := Note;
    midCmd[4] := Velocity;
    Write(midCmd, SizeOf(midCmd));

    // Write Note Off
    // Separate time into two bytes
    midCmd[0] := $80 or (Time div 128 mod 128);
    midCmd[1] := $00 or (Time mod 128);
    midCmd[2] := $80;
    Write(midCmd, SizeOf(midCmd));

    // Write MIDI track end
    Write(midEnd, SizeOf(midEnd));
  finally
    midFile.Free;
  end;
end;

To learn more visit the links supposed by DragonSlayer above...
0
 
LukA_YJKCommented:
Ask what portion is not clear enough...
0
 
MindphaserCommented:
mdavis1982

LukA_YJK gave you the code AND the documentation you requested. Please accept his proposed answer now or provide feedback if you any further help.

I will give you 3 days, after that I will force-accept this question.

** Mindphaser - Community Support Moderator **
0
 
MindphaserCommented:
Force accepted

** Mindphaser - Community Support Moderator **
0

Featured Post

New feature and membership benefit!

New feature! Upgrade and increase expert visibility of your issues with Priority Questions.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now