home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_progs / sound / algorhyt.lha / source / MusicSerial.c < prev    next >
C/C++ Source or Header  |  1992-02-21  |  9KB  |  332 lines

  1. /* MusicSerial.c
  2.    Copyright (c) 1990,1991,1992 by Thomas E. Janzen
  3.    All Rights Reserved
  4.  
  5.    THIS SOFTWARE IS FURNISHED FREE OF CHARGE FOR STUDY AND USE AND MAY
  6.    BE COPIED ONLY FOR PERSONAL USE OR COMPLETELY AS OFFERED WITH NO
  7.    CHANGES FOR FREE DISTRIBUTION.  NO TITLE TO AND OWNERSHIP OF THE
  8.    SOFTWARE IS HEREBY TRANSFERRED.  THOMAS E. JANZEN ASSUMES NO 
  9.    RESPONSBILITY FOR THE USE OR RELIABILITY OF THIS SOFTWARE.
  10.    
  11.    Thomas E. Janzen
  12.    58A School St. Apt. 2-L
  13.    Hudson, MA 01749
  14.    (508)562-1295
  15. */
  16. /*
  17. **  FACILITY:
  18. **
  19. **    AlgoRhythms music improviser on Commodore (TM) Amiga (TM)
  20. **    compiled with SAS/C V5.10b
  21. **
  22. **  ABSTRACT:
  23. **
  24. **    MusicSerial.c manages the serial device at the MIDI bit rate.
  25. **    All sends to MIDI occur here.
  26. **
  27. **  AUTHORS: Thomas E. Janzen
  28. **
  29. **  CREATION DATE:    26-MAR-1990
  30. **
  31. **  MODIFICATION HISTORY:
  32. **    DATE    NAME    DESCRIPTION
  33. ** 7 Dec 90 T. Janzen Used SendIO rather than DoIO - didn't up performance
  34. ** 4 Nov 91 T. Janzen incorporate MIDI running status; delete SendNoteOff
  35. **    8 DEC 91 T. Janzen conform to SAS/C 5.10b remove extern from functs
  36. **  4 Jan 92 TEJ  last changes for 2.0
  37. **--
  38. */
  39.  
  40. #include    "exec/types.h"
  41. #include    "exec/nodes.h"
  42. #include    "exec/lists.h"
  43. #include    "exec/ports.h"
  44. #include    "exec/libraries.h"
  45. #include    "exec/devices.h"
  46. #include    "devices/serial.h"
  47. #include    "exec/io.h"
  48. #include    "intuition/intuition.h"
  49. #include <proto/dos.h>
  50. #include <proto/graphics.h>
  51. #include <proto/exec.h>
  52. #include <proto/mathffp.h>
  53. #include <proto/intuition.h>
  54. #ifdef CLI
  55. #include <stdio.h>
  56. #endif
  57. #include "Window.h"
  58. #include "AlgoRhythms.h"
  59. #include "MusicSerial.h"
  60. #include "Record.h"
  61.  
  62. #define NOTEON       (0x90)   /* MIDI Spec note on flag    */
  63. #define NOTEOFF      (0x80)    /* MIDI Spec note off flag    */
  64. #define NOTEONCMD    (0x90)    /* MIDI Note on byte         */
  65. #define NOTEOFFCMD   (0x80)    /* MIDI Note off byte        */
  66. #define START        (0xFA)    /* MIDI Start play byte     */
  67. #define STOP         (0xFC)    /* MIDI Stop play byte        */
  68. #define CONTINUE     (0xFB)    /* MIDI Continue play byte    */
  69. #define TIMINGCLOCK  (0xF8)    /* MIDI Timing clock byte    */
  70.  
  71. int Response;
  72.  
  73. static struct IOExtSer *IORser;    /* Amiga Devices structures for serial */
  74. static struct MsgPort *port;
  75.  
  76. extern struct IORequest *CreateExtIO();
  77. extern void DeletePort(struct MsgPort *);
  78.  
  79. /* strings for error alerts */
  80. static char QuitStr[]    = "Quit",
  81.             SerErrStr[]  = "Serial Device Error",
  82.             PrtErrStr[]  = "Port Error",
  83.             IOErrStr[]   = "Create ExtIO Error",
  84.             DevErrStr[]  = "Serial Device Error",
  85.             PrmErrStr[]  = "Set Parm Error",
  86.             WrtErrStr[]  = "Serial.device write error";
  87. #ifndef CLI
  88. struct IntuiText QuitTxt = {2, 1, JAM1, 5, 4, &font_choice, QuitStr, NULL};
  89. #endif
  90. static char    playbuffer[4];    /* MIDI note message buffer     */
  91.  
  92.  
  93. #ifdef MEASURE
  94. extern unsigned int NotesTotalMeasure = 0;
  95. #endif
  96.  
  97. int SetParams (struct IOExtSer *io, unsigned long rbuf_len,
  98.     unsigned char rlen, unsigned char wlen, unsigned long brk, 
  99.     unsigned long baud, unsigned char sf, 
  100.     unsigned long ta0, unsigned long ta1)
  101. {    
  102.    /* set parameters of serial device */
  103. #ifndef CLI
  104.     struct IntuiText SerErrTxt = {2, 1, JAM1, 5, 15, &font_choice,SerErrStr,
  105.       NULL};
  106. #endif
  107.     int error;
  108.  
  109.     io->io_ReadLen    = rlen;
  110.     io->io_BrkTime    = brk; /*length of break timej (irrelevant)*/
  111.     io->io_Baud          = baud;
  112.     io->io_WriteLen    = wlen;
  113.     io->io_StopBits    = 0x01;
  114.     io->io_RBufLen    = rbuf_len;
  115.     io->io_SerFlags    = (1 << SERB_RAD_BOOGIE);
  116.     io->IOSer.io_Command = SDCMD_SETPARAMS;
  117.     io->io_TermArray.TermArray0 = ta0;
  118.     io->io_TermArray.TermArray1 = ta1;
  119.     if ((error = DoIO (io)) != 0) 
  120.    {
  121.         quit = TRUE;
  122.         fubar = TRUE;
  123. #ifdef CLI
  124.       puts (SerErrStr);
  125. #else
  126.       Response = AutoRequest ( w, &SerErrTxt, &QuitTxt, &QuitTxt, 
  127.                                0L, 0L, 300L, 60L);
  128. #endif
  129.     }
  130.     return error;
  131. }
  132.  
  133. void Open_MIDI_Port (void)
  134. {
  135. #ifndef CLI
  136.     struct IntuiText PrtErrTxt = {2, 1, JAM1, 5, 15, 
  137.                                  &font_choice, PrtErrStr, NULL},
  138.                      IOErrTxt  = {2, 1, JAM1, 5, 15, 
  139.                                  &font_choice, IOErrStr,  NULL},
  140.                      DevErrTxt = {2, 1, JAM1, 5, 15, 
  141.                                  &font_choice, DevErrStr, NULL},
  142.                      PrmErrTxt = {2, 1, JAM1, 5, 15, 
  143.                                  &font_choice, PrmErrStr, NULL};
  144. #endif
  145.     int error;
  146.     unsigned long     rbl = 512,    /*read buffer length*/
  147.                       brk = 750000, 
  148.                           /* length of break in usec, usu. 750000 */
  149.                       baud = 31250,    /* MIDI baud rate 31.25k bits/sec*/
  150.                       t0  = 0x51040303,    /*termination characters*/
  151.                       t1  = 0x03030303;
  152.     unsigned char     rwl = 0x08, /*bits per read char */
  153.                       wwl = 0x08, /*bits per write char */
  154.                       sf  = 0x00; /*serial flags cf D-124 in libs devices*/
  155.                          /* Try to get to the serial device. */
  156.                          /* page 396 of Libraries and Devices 
  157.                            was the example*/
  158.     port = CreatePort (SERIALNAME, 0);
  159.     if (port == NULL)
  160.    {
  161.         quit = TRUE;
  162.         fubar = TRUE;
  163. #ifdef CLI
  164.       puts (PrtErrStr);
  165. #else
  166.       Response = AutoRequest (w, &PrtErrTxt, &QuitTxt, &QuitTxt, 
  167.                               0L, 0L, 300L, 60L);
  168. #endif
  169.     }
  170.     IORser = 
  171.     (struct IOExtSer *)CreateExtIO(port, sizeof(struct IOExtSer));
  172.     if (IORser == NULL) 
  173.    {
  174.         quit = TRUE;
  175.         fubar = TRUE;
  176. #ifdef CLI
  177.       puts (IOErrStr);
  178. #else
  179.       Response = AutoRequest (w, &IOErrTxt, 
  180.             &QuitTxt, &QuitTxt, 0L, 0L, 300L, 60L);
  181. #endif
  182.     }
  183.     open:
  184.     if ((error = OpenDevice(SERIALNAME, 0, IORser, 0)) != 0) 
  185.    {
  186.         quit = TRUE;
  187.         fubar = TRUE;
  188. #ifdef CLI
  189.       puts (DevErrStr);
  190. #else
  191.       Response = AutoRequest (w, &DevErrTxt, 
  192.             &QuitTxt, &QuitTxt, 0L, 0L, 300L, 60L);
  193. #endif
  194.     }
  195.  
  196.     if ((error 
  197.          = SetParams (IORser, rbl, rwl, wwl, brk, baud, sf, t0, t1)) != 0)
  198.    {
  199.         fubar = TRUE;
  200.         quit = TRUE;
  201. #ifdef CLI
  202.       puts (PrmErrStr);
  203. #else
  204.       Response = AutoRequest (w, &PrmErrTxt, 
  205.             &QuitTxt, &QuitTxt, 0L, 0L, 300L, 60L);
  206. #endif
  207.         }
  208.       return;
  209.     /* The serial device is open,  so go ahead and play music.*/
  210. }
  211.  
  212. int WriteSer (struct IOExtSer *io, char *data, int length)
  213. {
  214.     int    error;
  215. #ifndef CLI
  216.     struct IntuiText WrtErrTxt = {2, 1, JAM1, 5, 15, &font_choice, 
  217.                                  WrtErrStr, NULL};
  218. #endif
  219.     io->IOSer.io_Data = (APTR)data;
  220.     io->IOSer.io_Length = length;
  221.     io->IOSer.io_Command = CMD_WRITE;
  222.  
  223.     if((error = WaitIO(io)) != 0)
  224.    {
  225.         quit = TRUE;    /* flag to get out of program */
  226.         fubar = TRUE;    /* flag to dump out of program with error*/
  227. #ifdef CLI
  228.       puts (WrtErrStr);
  229. #else
  230.       Response = AutoRequest (w, &WrtErrTxt, 
  231.             &QuitTxt, &QuitTxt, 0L, 0L, 300L, 60L);
  232. #endif
  233.     }
  234.    SendIO (io);
  235.     return error;
  236. }
  237.  
  238. void PlayNoteOn (const NOTEEVENT *PlayEvent) 
  239.    static unsigned char Running_Status = 0X00;
  240.    
  241.    if (PlayEvent->Channel < 0)
  242.    {
  243.       Running_Status = 0;
  244.       return;
  245.    }
  246.     playbuffer[0] = (unsigned char)(PlayEvent->Channel | NOTEONCMD);
  247.     playbuffer[2] = (unsigned char)(PlayEvent->Dynamic);
  248.  
  249.    if (playbuffer[2])
  250.    {
  251.         playbuffer[1] = (unsigned char)(scale[PlayEvent->Pitch]);
  252. #ifdef MEASURE
  253. NotesTotalMeasure++;
  254. #endif
  255.    }
  256.    else
  257.    {
  258.       playbuffer[1] = (unsigned char)(PlayEvent->CurPitch);
  259.    }
  260.  
  261.    if (playbuffer[0] == Running_Status)
  262.    {
  263.        WriteSer (IORser, &playbuffer[1], 2);    /* send it out MIDI */
  264.    }
  265.    else
  266.    {
  267.        WriteSer (IORser, playbuffer, 3);    /* send it out MIDI */
  268.       Running_Status = playbuffer[0];
  269.    }
  270.    return;
  271. }
  272.  
  273. void SendFunction (int Function)
  274.     playbuffer[1] = 0;
  275.     switch (Function) 
  276.    {
  277.         case STARTFUNCT:
  278.            playbuffer[0] = (unsigned char)START;
  279.            break;
  280.         case STOPFUNCT:
  281.            playbuffer[0] = (unsigned char)STOP;
  282.            break;
  283.         case CLOCKFUNCT:
  284.            playbuffer[0] = (unsigned char)TIMINGCLOCK;
  285.            break;
  286.         case CONTFUNCT:
  287.            playbuffer[0] = (unsigned char)CONTINUE;
  288.            break;
  289.       default:
  290.          break;
  291.     }
  292.     WriteSer (IORser, playbuffer, 1);    /* send it out MIDI */
  293.    return;
  294. }
  295.  
  296. void StopAllNotes (NOTEEVENT NotestoStop[])
  297. {
  298.     int i;
  299.  
  300.     for (i = 0; i < 16; i++)
  301.     {
  302.       if (NotestoStop[i].Playing)
  303.       {
  304.          NotestoStop[i].Dynamic = 0;
  305.            PlayNoteOn (&NotestoStop[i]);
  306.          if (Recording)
  307.          {
  308.             Record_Note_Event (&NotestoStop[i]);
  309.          }
  310.          NotestoStop[i].Playing = 0;
  311.          Delay (1);
  312.            if (fubar == TRUE) 
  313.          {
  314.             break;
  315.          }
  316.       }
  317.     }
  318.     SendFunction (STOPFUNCT);
  319.    return;
  320. }
  321.  
  322. void StopMIDI (void)
  323. {    
  324.    /* close up shop */
  325.     if (port) DeletePort (port);
  326.     if (IORser) CloseDevice (IORser);
  327.    return;
  328. }
  329.  
  330.