home *** CD-ROM | disk | FTP | other *** search
/ Sound Sensations! / sound_sensations.iso / midifile / midily / midilyzr.pas < prev    next >
Pascal/Delphi Source File  |  1989-08-30  |  16KB  |  375 lines

  1. Program Midi_Line_Analyzer;
  2. {
  3. *****************************************************************************
  4. Programmed by: J. Sloan
  5.                AlphaOmega Computer Services
  6.                Box 1052
  7.                Devon, AB.
  8.                Canada, T0C-1E0
  9.                Compuserve 71310,2267
  10.                August 28, 1989
  11. *****************************************************************************
  12. This program is based on two articles that appeared in Electronic
  13. Musician Magazine, 'Handling MPU-401 Interrupts in with Turbo Pascal' ,
  14. William Millar, EMM, May 1989, and tables of midi values that appeared in
  15. the EMM Feb. 1988 issue.
  16. The program is designed to buffer up to 512 midi bytes in a buffer,
  17. then print the bytes surrounded by brackets ie. (F6)= followed by
  18. an English description of what the byte does.  The first byte is in Hex
  19. format whereas the following 1 or 2 bytes are in decimal.  If a Sys Ex
  20. dump is taking place all subsequent bytes are in HEX.
  21.  
  22. The program requires the Unit MPU-401 in order to operate
  23. *****************************************************************************
  24. }
  25.  
  26. Uses CRT,MPU401;
  27.  
  28. Const
  29.      Hexdigits:String[16] = '0123456789ABCDEF';
  30.      spc           = ' ';
  31.      esc           = #27;
  32.  
  33. Type
  34.      Hexbytestring = String[2];
  35.  
  36. Var
  37.    Hinib,Lonib:Byte;
  38.  
  39. Function Byte2Hex(N:Byte):HexbyteString;
  40.  
  41. {** Convert the passed variable N to Hexadecimal **}
  42.  
  43. Begin
  44.    Hinib := (n and $F0) shr 4;
  45.    Lonib := n and $0F;
  46.    Byte2Hex:=HexDigits[Hinib + 1] + hexdigits[Lonib + 1]
  47. end;
  48.  
  49. Procedure WriteByte(S2:HexByteString);
  50.  
  51. {** Write the byte S2 to the screen **}
  52.  
  53. Begin
  54.      Write(Spc,S2,Spc);
  55. End;
  56.  
  57. Procedure Main_screen;
  58. {
  59. ****************************************************************************
  60. This is the main loop.  The sequence of events are as follows:
  61.  
  62.      Install MPU-401 Interrupt system
  63.      Write sign on message
  64.      Open screen window
  65.      Repeat
  66.      If a byte is available from the MPU-401
  67.         then
  68.           If it is the 1st byte display byte and description
  69.           If it is the 2nd byte display byte and description
  70.           If there is a third byte display byte and description
  71.      Until User presses ESC key
  72.      Uninstall MPU-401 Interrupt
  73.      Exit to DOS
  74. *****************************************************************************
  75. }
  76. Type
  77.     FirstByteHiNibble = Array[8..14] of String[22];
  78.     FirstByteLoNibble = Array[0..15] of String[11];
  79.     SysexByte         = Array[$F0..$FF] of String[40];
  80.     Bytetwo           = Array[0..22] of String[36];
  81.     ByteThree         = Array[0..3] of String[19];
  82.     Notes             = Array[0..11] of String[2];
  83.     String4           = String[4];
  84. Var
  85.    SecondMidiByte,ByteCount,Midibyte,HiByte,LowByte:byte;
  86.    Ch:Char;
  87.    First:Boolean;
  88.  
  89. Const
  90.    StatNibble:FirstbyteHiNibble = ('Note Off,',
  91.                                    'Note On,',
  92.                                    'PolyPhonic Aftertch,',
  93.                                    'Control Mode Change,',
  94.                                    'Program Change,',
  95.                                    'Channel Aftertch,',
  96.                                    'Pitch Wheel Rnge,');
  97.  
  98.    ChannelNibble:FirstByteLoNibble = ('Chan. 1,',
  99.                                       'Chan. 2,',
  100.                                       'Chan. 3,',
  101.                                       'Chan. 4,',
  102.                                       'Chan. 5,',
  103.                                       'Chan. 6,',
  104.                                       'Chan. 7,',
  105.                                       'Chan. 8,',
  106.                                       'Chan. 9,',
  107.                                       'Chan. 10,',
  108.                                       'Chan. 11,',
  109.                                       'Chan. 12,',
  110.                                       'Chan. 13,',
  111.                                       'Chan. 14,',
  112.                                       'Chan. 15,',
  113.                                       'Chan. 16,');
  114.  
  115.    Sysex:SysexByte = ('System Exclusive Data Dump=',
  116.                       'Sys Common Undefined',
  117.                       'Sys Common Song Position Pointer',
  118.                       'Sys Common Song Select',
  119.                       'Sys Common Undefined',
  120.                       'Sys Common Undefined',
  121.                       'Sys Common Tune Request',
  122.                       'Sys Common end of System Exclusive (EOX)',
  123.                       'Sys Real Time Timing Clock',
  124.                       'Sys Real Time Undefined',
  125.                       'Sys Real Time Start',
  126.                       'Sys Real Time Continue',
  127.                       'Sys Real Time Stop',
  128.                       'Sys Real Time Undefined',
  129.                       'Sys Real Time Active Sensing',
  130.                       'Sys Real Time Reset');
  131.  
  132.    DataByteTwo:ByteTwo = ('Continuous Controller #0',
  133.                           'Modulation Wheel',
  134.                           'Breath Control',
  135.                           'Continuous Controller #3',
  136.                           'Foot Controller',
  137.                           'Portamento Time',
  138.                           'Data Entry',
  139.                           'Main Volume',
  140.                           'Continuous Controller #',
  141.                           'Note Number',
  142.                           'Program #',
  143.                           'AfterTouch Pressure',
  144.                           'PitchWheel LSB',
  145.                           'Sustain Pedal on/off',
  146.                           'Portamento on/off',
  147.                           'Sustenuto on/off',
  148.                           'Soft Pedal on/off',
  149.                           'Local control on/off',
  150.                           'All Notes off',
  151.                           'Omni mode off',
  152.                           'Omni mode on',
  153.                           'Mono Mode On',
  154.                           'Poly mode on');
  155.  
  156.     DataByteThree:ByteThree = ('Note Velocity',
  157.                                'AfterTch Pressure',
  158.                                'Pitch Wheel MSB',
  159.                                'Value');
  160.     MidiNote:Notes = ('C',
  161.                       'C#',
  162.                       'D',
  163.                       'D#',
  164.                       'E',
  165.                       'F',
  166.                       'F#',
  167.                       'G',
  168.                       'G#',
  169.                       'A',
  170.                       'A#',
  171.                       'B');
  172.  
  173. Function ConvertToNote(Note:Byte):String4;
  174.  
  175. {** Convert the midinote # to a standard note name including the Octave **}
  176.  
  177. Var
  178.    NoteName:Notes;
  179.    Octave,NoteNumber:Byte;
  180.    NoteNumberString:String[3];
  181.  
  182. Begin
  183.     Octave:=Note Div 12;
  184.     NoteNumber:=Octave - 1;
  185.     Str(NoteNumber:2,NotenumberString);
  186.     ConvertToNote:=MidiNote[Note mod 12]+NoteNumberString;
  187. End;
  188.  
  189. Begin
  190.      Clrscr;
  191.      Writeln('MIDI Line Analyzer -- ','Version 1.0');
  192.      Writeln('Press Esc to Exit.');
  193.      Writeln;
  194.      Writeln('Waiting for MIDI Data ...');
  195.      Writeln('_____________________','_____________________',
  196.               '_____________________','________________');
  197.  
  198.      Send_Command_to_MPU(MPU_UART_MODE);
  199.      ByteCount:=0;
  200.      First:=true;
  201.      Repeat
  202.            If (Get_Data_From_MPU(MidiByte)) then
  203.            Begin
  204.            If First then
  205.               Begin
  206.                  GotoXY(1,4);Writeln('Receiving Midi Data ...');
  207.                  First:=false;
  208.                  Window(1,6,80,25)
  209.               end;
  210.            ByteCount:=ByteCount+1;
  211.            Case ByteCount of
  212.                  1:Begin
  213.                     Hibyte:=(Midibyte And $F0)SHR 4;
  214.                     LowByte:=(Midibyte And $0F);
  215.                     Case HiByte of
  216.                     1..$E:Begin
  217.                              Write('(',Byte2Hex(MidiByte),')=',StatNibble[Hibyte],' ');
  218.                              Write(ChannelNibble[Lowbyte],' ');
  219.                            end;
  220.                        $F:Begin
  221.                             Write('(',Byte2Hex(Midibyte),')=',Sysex[Midibyte],' ');
  222.                             Case Lowbyte of
  223.                                 6..$F:Begin
  224.                                          Writeln;
  225.                                          ByteCount:=0;
  226.                                        end;
  227.                             end;{case lowbyte}
  228.                         end;{F}
  229.                      end; {Hibyte}
  230.                    end;{case1}
  231.                2:Begin
  232.                   SecondMidibyte:=Midibyte;
  233.                     Case Hibyte of
  234.                       8..$A:Begin
  235.                                Write('(',Midibyte,')=','MidiNote #,',' Note is ',
  236.                                  ConvertToNote(MidiByte),', ');
  237.                             End;
  238.                       $B   :Case Midibyte of
  239.                                      00..7:Write('(',Midibyte,')=',DataByteTwo[MidiByte],
  240.                                                         ' ');
  241.                                      8..31:Write('(',Midibyte,')=','Continuous Controller #',
  242.                                                    ' ');
  243.                                      20..27:Write('(',Midibyte,')=',DataByteTwo[(MidiByte And $F0)],
  244.                                                         ' ');
  245.                                      28..63:Write('(',Midibyte,')=','Continuous Controller #',
  246.                                                   ' ');
  247.                                      64..67:Write('(',Midibyte,')=',DataByteTwo[Midibyte-51],' ');
  248.                                      68..95:Write('(',Midibyte,')=','Undefined On/Off ');
  249.                                          96:Write('(',Midibyte,')=','Data Entry +1 ');
  250.                                          97:Write('(',Midibyte,')=','Data Entry -1 ');
  251.                                     98..121:Write('(',Midibyte,')=','Undefined ');
  252.                                    122..127:Write('(',Midibyte,')=',DataByteTwo[Midibyte-105],' ');
  253.                             end;{Case}
  254.                        $C   :Begin
  255.                                 Write('(',Midibyte,')=','Program # , ');
  256.                                 Writeln;
  257.                                 ByteCount:=0;
  258.                              end;
  259.                        $D   :Begin
  260.                                Write('(',Midibyte,')=','LSB Pressure, ');
  261.                                Writeln;
  262.                                ByteCount:=0;
  263.                              end;
  264.                        $E   :Write('(',Midibyte,')=','LSB Range, ');
  265.                        $F   :Case Lowbyte of
  266.                                   0:Begin
  267.                                         Writebyte(Byte2Hex(Midibyte));
  268.                                         Repeat
  269.                                             If Get_data_from_MPU(midibyte) then
  270.                                             WriteByte(byte2hex(midibyte));
  271.                                         Until Midibyte = 247;
  272.                                         writeln('<= EOX');
  273.                                         ByteCount:=0;
  274.                                     End;
  275.                                   1:Begin
  276.                                          Write('(',Midibyte,')=','??, ');
  277.                                     end;
  278.                                   2:Write('(',Midibyte,')=','LSB, ');
  279.                                   3:Begin
  280.                                        Write('(',Midibyte,')=','Song #');
  281.                                        Writeln;
  282.                                        ByteCount:=0;
  283.                                     end;
  284.                                 4,5:Begin
  285.                                          Write('(',Midibyte,')=','??, ');
  286.                                     end;
  287.                        end;{F}
  288.                     end;{case}
  289.                  end;{2}
  290.                3:Case Hibyte of
  291.                        8..9:Begin
  292.                                Write('(',MidiByte,')=','Note Velocity');
  293.                                Writeln;
  294.                                ByteCount:=0;
  295.                             end;
  296.                          $A:Begin
  297.                                Write('(',MidiByte,')=','MSB Pressure ');
  298.                                Writeln;
  299.                                Bytecount:=0;
  300.                             end;
  301.                           $B:Begin
  302.                                Case SecondMidibyte of
  303.                                   0..31:Begin
  304.                                         Write('(',midibyte,')=','MSB');
  305.                                         Writeln;
  306.                                         end;
  307.                                  32..63:Begin
  308.                                         Write('(',Midibyte,')=','LSB');
  309.                                         Writeln;
  310.                                         end;
  311.                              64..95,122:Case MidiByte of
  312.                                                 0:begin
  313.                                                        Write('(',Midibyte,')=','Off');
  314.                                                        Writeln;
  315.                                                   end;
  316.                                               127:Begin
  317.                                                        Write('(',Midibyte,')=','On');
  318.                                                        Writeln;
  319.                                                   end;
  320.                                         end;{Case}
  321.                                   96,97:Begin
  322.                                           Write('(',Midibyte,')');
  323.                                           Writeln;
  324.                                         end;
  325.                                 98..121:Begin
  326.                                            Write('??');
  327.                                            Writeln;
  328.                                          end;
  329.                            123..125,127:Begin
  330.                                            Write('(',Midibyte,')=','0');
  331.                                            Writeln;
  332.                                         end;
  333.                                     126:Begin
  334.                                            Write('(',Midibyte,')=','0 or # of channels');
  335.                                            Writeln;
  336.                                          end;
  337.                                end;{Case Midibyte}
  338.                              ByteCount:=0;
  339.                              end;{B}
  340.                        $E   :Begin
  341.                                 Write('(',Midibyte,')=','MSB Range');
  342.                                 Writeln;
  343.                                 ByteCount:=0;
  344.                              End;
  345.                        $F   :Case LowByte of
  346.                                1,4,5:Begin
  347.                                       Write('(',Midibyte,')=','??');
  348.                                       Writeln;
  349.                                       ByteCount:=0;
  350.                                     end;
  351.                                   2:Begin
  352.                                       Write('(',Midibyte,')=','MSB');
  353.                                       Writeln;
  354.                                       ByteCount:=0;
  355.                                     end;
  356.                              end;{Case Lowbyte}
  357.                   end;{3}
  358.  
  359.                End;{ByteCount}
  360.  
  361.             End;{Then Begin}
  362.  
  363.            If (Keypressed) then
  364.               Ch:=Readkey;
  365.      Until (Ch = esc);
  366.      Send_Command_To_MPU(MPU_Reset);
  367.      Window(1,1,80,25);
  368.      clrscr;
  369. end;
  370.  
  371. Begin
  372. Main_Screen
  373. End.
  374.  
  375.