home *** CD-ROM | disk | FTP | other *** search
/ Audio 4.94 - Over 11,000 Files / audio-11000.iso / msdos / midi / mpusr2 / midi.doc < prev    next >
Encoding:
Text File  |  1993-07-06  |  18.2 KB  |  598 lines

  1.  
  2.  
  3. MPU-401 MIDI Interface Module v1.0
  4.  
  5. Copyright (c) 1991, Robin Davies.
  6.  
  7. DESCRIPTION
  8.  
  9. This module provides basic MIDI message handling for IBM-PC systems
  10. equipped with a Roland MPU-401 or compatible MIDI interface card.
  11.  
  12. It provides interrupt driven Recording and playing and directly supports
  13. most of the MPU-401 message filtering options.
  14.  
  15. Up to four MPU-401's can be driven simultaneously.
  16.  
  17. This module allows MIDI messages to be received and transmitted.
  18.  
  19. Received messages are automatically timestamped.
  20.  
  21. Transmitted messages may either be sent as scheduled messages (i.e. sent
  22. at a specified time), or sent immediately.
  23.  
  24. Scheduled messages must be sent at least 240 ticks before they are 
  25. scheduled to be sent. There is no mechanism to slow down the transmission
  26. process, so client applications must be careful to throttle themselves to 
  27. prevent all free memory from being used for midi messages. The best way 
  28. to do this is something like the following:
  29.  
  30.     if (MidiMessagesPending(midiChannel) < 300) // or some arbitrary #
  31.         SendNextMidiMessage(channel);
  32.  
  33. This module has been compiled and tested under Turbo-Pascal 2.0. with 
  34. a variety of different programs, although it is far from completely 
  35. tested.
  36.  
  37. Three test programs, READTEST.C, WRITETST.C, and DELAYTST.C,
  38. are included as sample programs.
  39.  
  40.  
  41. FUNCTION SUMMARY
  42.     
  43.     CreateMidiChannel -- Create a channel for sending and receiving 
  44.                 midi messages.
  45.     DestroyMidiChannel -- Destory the channel, and all resources used by
  46.                 the channel (i.e. pending midi messages, turns off the MPU-401,
  47.                 removes interrupt handlers, etc).
  48.     SetMidiOperatingMode -- Change the operating mode of a midi channel 
  49.                 (to record, play, record/play, or stop).
  50.  
  51.     MidiStatus -- Returns the current error status of a midi channel.
  52.     MidiErrorString -- Returns an ASCII string describing the meaning of
  53.                 an error code returned by MidiStatus.
  54.  
  55.     AllocMidiMessage -- Allocate a midi message block (in preparation for
  56.                 filling it in and sending it).
  57.     FreeMidiMessage -- Return a midi message block to the midi message
  58.                 pool.
  59.     SetMidiMessage -- Fill a midi message block with data.
  60.     GetMidiMessageData -- Get a copy of the data in a message block.
  61.  
  62.     SendMidiMessage -- Send a midi message immediately.
  63.     ScheduleMidiMessage -- Schedule a midi message for sending at a future
  64.                     time.
  65.     ReceiveMidiMessage -- Get the next received midi message (or returns 
  66.                     NULL if no messages are waiting).
  67.     
  68.     MidiMessagePending -- Returns the number of scheduled midi messages which
  69.                 have not yet been sent.
  70.  
  71.  
  72. DATA TYPES
  73.  
  74. The philosophy of this module is vaguely object oriented. The actual 
  75. contents of data structures are considered private to this module. 
  76. Client routines should have no need to access struture members directly
  77. since access routines are provided to do so where appropriate. If you
  78. really need to access a structure member, write an access routine in 
  79. this module to do so. This will minimize problems whith future versions
  80. of this module.
  81.  
  82.  
  83.     MidiTimeT -- Time in ticks after playing or recording started.
  84.                     Currently a long integer.
  85.  
  86.     MidiMessageT -- The object which contains all data associated with 
  87.                 a midi message.
  88.  
  89.     MidiChannelT -- Midi channel control block. Contains all information
  90.                 associated with a midi communications channel.
  91.  
  92.         
  93.  
  94. HOW TO USE THIS MODULE
  95.  
  96. MIDI.H contains all typedefs, defines and function prototypes required 
  97. by clients of MIDI.C.
  98.  
  99. MIDI.C must be linked with the module MPU.C. The module MPU.C must be 
  100. compiled with register optimization disabled, and stack checking 
  101. disabled.
  102.  
  103. This module was compiled using Turbo C++ v1.0. It should work without 
  104. modification with Turbo C 2.0. It should work with Microsoft C equally 
  105. well, with minor tweaking, but I don't have a copy of MSC handy to do 
  106. the actual port. Feel free to chip in.
  107.  
  108. Three sample applications have been included: READTEST.EXE and WRITETST.EXE.
  109. They may be built with the supplied MAKEFILE.MAK and Turbo MAKE.EXE.
  110.  
  111.  
  112. ABOUT THE DOCUMENTATION
  113.  
  114. The documentation for this project was written using a simplified version
  115. of Donald Knuth's literate programming style. The documentation was 
  116. written in the source code, and stripped out afterward using the utility
  117. CDOC.EXE (included in this arc file).
  118.  
  119. Documentation is interwoven between actual source code by using enclosing
  120. documentation in "ifdef DOC" and "endif" tag lines. The program CDOC.EXE
  121. will filter out the documentation in a source file as follows:
  122.         
  123.     CDOC.EXE <infile >outfile
  124.  
  125. The reason why this is done is to ensure that documentation accurately
  126. reflects the current status of the code. If you are going to modify this
  127. code, I would ask you to update the documentation in the source code(!) 
  128. when you do so. The HISTORY section of this document (below in the source
  129. code) provides a good place for you to record the changes you made to 
  130. the sources.
  131.  
  132. If you follow this practice, then you will be able to generate up-to-date
  133. documentation quickly and easily. 
  134.  
  135. The MPU module also uses a more advanced form of literate programming 
  136. style which automatically inserts function prototypes into the 
  137. documentation, but I am unfortunately not able to distribute the program
  138. which supports this, and am not willing to manually insert the 
  139. prototypes.
  140.  
  141. RELATED FILES
  142.  
  143.     MIDI.H -- Contains defines and prototypes for clients of this module.
  144.  
  145.     MPU.C -- This module must be linked with MPU.C.
  146.  
  147.     MIDINAME.C .H -- Module which provides ascii translations of 
  148.                 midi messages.
  149.  
  150.     READTEST.C -- A sample program which demonstrates usage of 
  151.             the MIDI.C module. It provides an ASCII dump of all 
  152.             messages read from the MIDI-IN port of the MPU-401.
  153.  
  154.     WRITETST.C    -- A sample program which demonstrates usage of the 
  155.             MIDI.C module. It sends random notes to the MIDI-OUT port of 
  156.             the MPU-401. Sounds kinda nice with bell-like patches.
  157.  
  158. RELATED DOCUMENTS
  159.  
  160. 1)    Midi Processing Unit MPU-401 Technical Reference Manual, version 1.5
  161.     (5/29/85), Roland Corporation, 1985. (Available directly from Roland for
  162.     a nominal fee).
  163.  
  164. BUGS
  165.  
  166. SYSEX messages, and Common messages  may be sent as immediate messages 
  167. only. They may NOT be sent using SendScheduledMessage.
  168.  
  169. Due to the way that the MPU-401 works, System Common messages may or may 
  170. not work reliably. The MPU-401 handles most Common messages other than 
  171. SYSEX messages itself as part of the Record/Play sequence.
  172.  
  173. The parser looks like it needs some work. In particular, it will not
  174. correctly parse MPU measure end marks.
  175.  
  176.  
  177.  
  178. STATEMENT OF COPYRIGHT 
  179.  
  180. Copyright (c) 1991, Robin Davies. All Rights Reserved.
  181.  
  182. You may use or modify this source code freely as long as the following
  183. conditions are met:
  184.  
  185. (1) You may distribute object code derived from this work without
  186. displaying copyright notices of any kind. However, if this work or
  187. derivatives of this work are distributed in source form, this
  188. copyright notice must be left intact.
  189.  
  190. If you wish to express your gratitute in any way (such as sending me
  191. a complimentary copy of *your* work), you may reach me at:
  192.  
  193.     Robin Davies
  194.     224 3rd Avenue
  195.     Ottawa, Ontario
  196.     Canada. K1S 2K3.
  197.  
  198.  
  199. DISCLAIMER OF LIABILITY
  200.  
  201. If these programs, or programs based on this source code get up and
  202. burn your house down in the middle of the night, I accept no 
  203. responsibility. 
  204.  
  205. This source has not been fully tested. It may in fact have terrible bugs 
  206. in it still. It is provided "as-is", and without warranty, either express 
  207. or implied, and no representations are made as to its fitness for a 
  208. particular purpose. You have been warned, so don't come crying to me. 
  209.  
  210. However, if you do find any bugs, do let me know, and I'll see what *we*
  211. can do to fix them.
  212.  
  213. HISTORY
  214.  
  215. 1/5/91 - Version 1.0 Posted on Compuserve for the first time.    
  216.  
  217. 5/6/92 - Larry Troxler
  218.             Compuserve: 73520,1736
  219.             Bix:  ltroxler
  220.             Internet: 73520.1736@compuserve.com
  221.  
  222.             I did some work on the scheduler. Also I
  223.             had to increase the timeout constants (see MPU.C), and it
  224.             appears the incoming time-stamps were missing.
  225.  
  226.             - lt
  227.  
  228.  
  229. PROTOTYPE
  230.  
  231. MidiMessageT *AllocMidiMessage(void);
  232.  
  233. DESCRIPTION
  234.  
  235. Allocates a Midi Message block.
  236.  
  237. Returns NULL if no more memory.
  238.  
  239.  
  240. PROTOTYPE
  241.  
  242. MidiMessageT *ReceiveMidiMessage(MidiChannelT *channel) {
  243.  
  244. DESCRIPTION
  245.  
  246. Returns the next midi message.
  247.  
  248. RETURNS
  249.  
  250. Returns NULL if no message is ready to read.
  251. Returns (MidiMessageT *)(-1) if error.
  252.  
  253. REVISIONS
  254.  
  255. 5/6/92 by Larry Troxler
  256.  - Set time-stamp of message being returned.
  257.  - When an timer overflow was received, the time was not being advanced
  258.     by the correct amount.
  259.  - Do not send and overflow response to track requests from this routine.
  260.     Track requests are handled in the track request handler.
  261.  
  262. PROTOTYPE
  263.  
  264. void ScheduleMidiMessage(
  265.     MidiChannelT *channel,
  266.     int track,                
  267.     MidiTimeT time,        // Elapsed time in ticks since playback started
  268.     MidiMessageT *msg
  269. );
  270.  
  271. DESCRIPTION 
  272.  
  273. Sends a scheduled midi VOICE message. The supplied time is in ticks after the
  274. start of playback.
  275.  
  276. Events may be scheduled BEFORE playback has actually started in order to 
  277. get ahead of the MPU.
  278.  
  279. Also note there is no throttling mechanism for the event queue. If you 
  280. call this routine too fast you will eventually run out of free memory 
  281. (used to allocate MidiMessageT blocks). You may want to hold off a bit
  282. by checking to how far ahead of the Track time counter you are.
  283.  
  284. Messages are freed once they are transmitted. Once the message has been
  285. scheduled, you may not access it again!
  286.  
  287. BUGS
  288.  
  289. Sysex messages and common messages may not be scheduled! Sysex messages 
  290. may only be sent directly.
  291.  
  292.  
  293. PROTOTYPE
  294.  
  295. BOOL SendMidiMessage(MidiChannelT *channel,MidiMessageT *msg);
  296.  
  297. DESCRIPTION 
  298.  
  299. Sends a message immediately. The message is freed before returning(!). Once
  300. the message has been sent, you may not access it again.
  301.  
  302. RETURNS
  303.     YES if success.
  304.     NO if failure.
  305.     Call GetMidiStatus to receive error code.
  306.  
  307.  
  308. PROTOTYPE
  309.  
  310. void SetMidiOperatingMode(
  311.     MidiChannelT *channel,
  312.     MpuOperatingModeT operating_mode
  313. );
  314.  
  315. DESCRIPTION
  316.  
  317. Set current midi channel operating mode.
  318.  
  319. One of:
  320.  
  321. RECORD_MODE,PLAY_MODE,RECORDPLAY_MODE, STOP_MODE
  322.  
  323. RECORD_MODE: Allows receiving of timestamped midi messages and 
  324.     sending of immediate midi messages.
  325.  
  326. PLAY_MODE: Allows sending of scheduled and immediate midi messages.
  327.  
  328. RECORDPLAY_MODE: Allows sending of scheduled and unscheduled midi messages,
  329.     and receiving of timestamped midi messages.
  330.  
  331. STOP_MODE: Stops sending and receiving of messages.
  332.  
  333. BUGS
  334.  
  335. CONTINUE should probably also be supported here, but isn't at the 
  336. present time.
  337.  
  338.  
  339. PROTOTYPE
  340.  
  341. MidiChannelT *CreateMidiChannel(
  342.     int mpu_base_address, // Mpu base address (default 0x330)
  343.     int mpu_interrupt,      // Mpu interrupt number (default 2)
  344.     int rx_buffersize,      // Size of receive buffer (default 1024)
  345.     enum MpuOperatingModeT operating_mode,      // RECORD_MODE, PLAY_MODE,RECORDPLAY_MODE,STOP_MODE
  346.     enum MpuClockT mpu_clock_source, // MPU_INTERNAL_CLOCK, MPU_MIDI_CLOCK
  347.                                      // or MPU_FSK_CLOCK
  348.     int tempo,              // Beats per minute
  349.     enum MpuTimebaseT timebase,     // Ticks per beat (see MpuTimebaseT in MPU.H)
  350.     int metronome_measure_length, // beats per measure, 0 -> metronome off
  351.     int mode,              // See description
  352.     int midi_channel_mask, // bit n controls midi channel n+1
  353.                            // bit = 0 -> pass trough without host intervention
  354.                            // bit = 1 -> record/filter this midi channel    
  355.     int tracks,               // number of tracks (0 to 7) for scheduled midi messages
  356.     int *result               // retcode placed here
  357. );
  358.  
  359. DESCRIPTION
  360.  
  361. Create a MIDI channel.
  362.  
  363. mpu_base_address, mpu_interrupt, and rx_buffersize will default to 
  364. appropriate values if zero.
  365.  
  366. If you plan to send scheduled midi messages, it would probably be wise
  367. to initially set the operating mode to STOP_MODE, schedule some messages,
  368. and then set the MidiOperatingMode to PLAY_MODE once messages are ready to
  369. be scheduled.
  370.  
  371. The mode parameter allows selection of messages to be received and and
  372. passed through. Any of the following values (ORed together) may be specified:
  373.  
  374.     MPU_VOICES_THRU -- pass all non-common messages directly from 
  375.                              MIDI-IN to MIDI-OUT. Note that voice messages 
  376.                              on channels which are masked are passed through
  377.                              whether this mode option is specified or not.
  378.     MPU_EXCLUSIVE_THRU -- Pass through Sysex messages 
  379.     MPU_REALTIME_THRU  -- Pass through realtime (FA,FB,FC) messages
  380.     MPU_COMMON_THRU    -- Pass through other Common (F2,F3,F6) messages
  381.  
  382.     MPU_DEFAULT_THRU   -- (MPU_VOICES_THRU)
  383.  
  384.     MPU_RX_EXCLUSIVE     -- Receive Sysex messages
  385.     MPU_RX_REALTIME    -- Receive realtime (FA,FB,FC) messages
  386.     MPU_RX_BENDER      -- Receive bender messages
  387.     MPU_RX_MODE        -- receive mode messages
  388.     MPU_RX_COMMON      -- Receive common (F2,F3,F6) messages
  389.  
  390.     MPU_RX_DEFAULT         -- 0. (Voice messages only).
  391.     MPU_RX_ALL               -- Receive ALL messages.
  392.  
  393. midi_channel_mask selects midi channels for which messages should be 
  394. received. Note that if a channel is masked, messages are passed trough to 
  395. MIDI-OUT automatically. This is a problem with the MPU-401. There is no 
  396. way to prevent ALL messages from being passed through without actually
  397. receiving them.
  398.  
  399. The MPU-401 supports up to 8 tracks for playback. The 8th track is 
  400. reserved for sending immediate midi messages. Scheduled messages may
  401. be placed into any of these tracks. The maximum number of tracks which 
  402. will be used for playback should be set at create time. To be 
  403. perfectly honest, I can't think of a compelling reason to use more than
  404. one track.
  405.  
  406. If an error occurs, the error code is placed into *result. This error 
  407. message may originate from either the MIDI module or the MPU module.
  408. The MidiErrorString() routine will return an appropriate ASCII error message
  409. for either class of error messages.
  410.  
  411. NOTES
  412.  
  413. You must call DestroyMidiChannel before exiting your program, since 
  414. interrupt handlers for the MPU-401 are dropped at Create time.
  415.  
  416. RETURNS
  417.  
  418. NULL if error, *retval <= error code.
  419.  
  420. BUGS
  421.  
  422. There are currently no provisions for count-in measures during record or 
  423. playback. This will (may) be remedied in future versions of this module.
  424.  
  425.  
  426. PROTOTYPE
  427.  
  428. int DestroyMidiChannel(MidiChannelT *channel);
  429.  
  430. DESCRIPTION
  431.  
  432. Closes a midi channel, and deallocates all memory and resources used
  433. by that channel. Removes the MPU-401 interrupt handler.
  434.  
  435. RETURNS
  436.  
  437. 0 -> Success
  438. non-zero = MidiErrorT error code.
  439.  
  440.  
  441. PROTOTYPE
  442.  
  443. BOOL SetMidiMessage(
  444.     MidiMessageT *msg,
  445.     UCHAR midi_command, 
  446.     UCHAR data1, 
  447.     UCHAR data2,
  448.     unsigned int sysex_length,    // Must be zero for non-SYSEX commands!
  449.     UCHAR *sysex_data            
  450. );
  451.  
  452.  
  453. DESCRIPTION
  454.  
  455. Set the data of the supplied midi message.
  456.  
  457. Note that sysex data (if supplied) is copied into an in internal
  458. memory block allocated from free store. The caller is responsible 
  459. for deallocating the SUPPLIED sysex data (if applicable).
  460.  
  461. For sysex messages, data1 and data2 are unused. sysex_data must 
  462. point to the first byte of sysex data following the sysex command.
  463.  
  464. The sequence of operations for sending a midi message:
  465.  
  466.     msg = AllocMidiMessage();
  467.     SetMidiMessage(msg,cmd,data1,data2,0,NULL);
  468.                 
  469.     SendMidiMessage(midiChannel,msg);
  470.         or
  471.     SendScheduleMidiMessage(midiChannel,time,msg);
  472.  
  473. Note that a copy of the sysex data is made in heap memory, that will
  474. be deallocated when the message is freed (or sent). This may pose a 
  475. problem for large sysex messages.
  476.  
  477. RETURNS
  478.  
  479. No -> insufficient memory for copy of sysex data.
  480.  
  481.  
  482.  
  483. PROTOTYPE
  484.  
  485. void GetMidiMessageData(
  486.     MidiMessageT *msg,
  487.     UCHAR *midi_cmd, // Receives midi command
  488.     UCHAR *data1,     // Receives data1 (if not NULL)
  489.     UCHAR *data2     // Receives data2 (if not NULL)
  490. );
  491.  
  492. DESCRIPTION
  493.  
  494. Get data for current midi message.
  495.  
  496. The sequence for reading a midi message:
  497.     
  498.     msg = ReceiveMessage(channel);
  499.     if (msg == (MidiMessageT *)(-1)) {
  500.         handleMidiError(MidiStatus(channel));
  501.         return;
  502.     }
  503.     if (msg != NULL) {
  504.         GetMidiMessageData(msg,&cmd,&data1,&data2);
  505.     }
  506.  
  507.  
  508. PROTOTYPE
  509.  
  510. int MidiStatus(MidiChannelT *channel);
  511.  
  512. DESCRIPTION
  513.  
  514. Returns the error status code of the specified Midi channel.
  515.  
  516. The only way to clear the error status is to Destroy the channel 
  517. and recreate it.
  518.  
  519. RETURNS
  520.  
  521. 0 -> No error
  522. non-zero = enum MidiErrorT.
  523.  
  524.  
  525. PROTOTYPE
  526.  
  527. char *MidiErrorString(int error_code);
  528.  
  529. DESCRIPTION
  530.  
  531. Returns a string error message corresponding to the specified
  532. (enum MidiErrorT or enum MpuErrorT) error code as returned by
  533. either MidiStatus or CreateMidiChannel. Error codes originating
  534. from either the MIDI module, or the MPU module are handled correctly.
  535.  
  536.  
  537. PROTOTYPE
  538.  
  539. int MidiMessagesPending(MidiChannelT *channel);
  540.  
  541. DESCRIPTION
  542.  
  543. Returns the number of scheduled messages which have not been sent
  544. to the MPU-401.
  545.  
  546. This function provides a useful technique for controlling the amount
  547. of memory used by the midi messages queue:
  548.  
  549.     if (MidiMessagesPending(channel) < 300) // or some arbitrary #
  550.             sendNextMidiMessage();
  551.  
  552.  
  553. PROTOTYPE
  554.  
  555. void GetMidiMessageSysexData(
  556.     MidiMessageT *msg,
  557.     int *sysexLength,
  558.     UCHAR **sysexData    // Filled if not null
  559. );
  560.  
  561. DESCRIPTION
  562.  
  563. This routine returns the length and a pointer to the extra data
  564. bytes sent or received with a sysex message.
  565.  
  566. The pointer remains valid until the message is sent or freed. (Clients
  567. should NOT free the pointer themselves).
  568.  
  569. The first byte of sysex data is the byte which immediately follows the 
  570. Sysex (FF) midi command. The last byte of sysex data must be EOX_MSG (0xF7).
  571. The contents of data1 and data2 as returned by GetMidiMessageData are 
  572. unspecified when a sysex command is sent or recieved.
  573.  
  574. sysexLength includes the EOX_MSG byte at the end of the sysex message.
  575.  
  576. BUGS
  577.  
  578. In truth, midi sysex messages may be terminated by ANY Midi status byte.
  579. The current code only handles MIDI sysex messages terminated by EOX_MSG.
  580. This is probably a fairly major ommission, although I have been 
  581. lucky enough not to have run into a machine which doesn't terminate 
  582. sysex messages with EOX_MSG. You have been warned.
  583.  
  584.  
  585.  
  586. PROTOTYPE
  587.  
  588. MidiTimeT GetMidiMessageReceiveTime(
  589.     MidiMessageT *msg
  590. );
  591.  
  592. DESCRIPTION
  593.  
  594. Returns the time that the message was received by the MPU-401 in ticks
  595. since recording started. Results are unspecified for messages which 
  596. haven't been obtained through ReceiveMidiMessage().
  597.  
  598.