home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 2 / MECOMP-CD-II.iso / amiga / datatypes / mididt / source / handlemidi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-04  |  28.2 KB  |  909 lines

  1. /*
  2. ** $PROJECT: midi.datatype
  3. **
  4. ** $VER: handlemidi.c 40.0 (11.09.97)
  5. **
  6. ** This file is intended to hold all three subroutines to load midi data
  7. ** into memory, to save it on disk and to play it. Currently it just
  8. ** does playing the contents of a SMF file from a memory block.
  9. **
  10. ** Based on playmf created by Dan Baker.
  11. ** Bugfixed, extended (sysex,pause,repeat) and adapted by Martin Gierich.
  12. ** All Rights Reserved !
  13. **
  14. ** $HISTORY:
  15. ** 11.09.97 : 40.00 : Initial BETA release
  16. **
  17. ** $TABSIZE: 3
  18. */
  19.  
  20.  
  21. /*=======================================================================
  22. Original playmf message:
  23.  
  24. This file is a prototype score player which reads standard MIDI files,
  25. format type 0 or 1.  It conforms to the 1.0 specification for standard 
  26. MIDI files by Dave Oppenheim of Opcode Systems.  It uses both the CAMD and 
  27. RealTime libraries by Roger Dannenberg, Bill Barton, David Joiner, et al.
  28.  
  29. Design and coding by Dan Baker, Commodore Business Machines.
  30.  
  31. The tempo handling used by this program is a bit crude and is known to have 
  32. deficiencies.  It should not be used as an example of proper tempo handling.  
  33. This program also makes extensive use of globals and other techniques which 
  34. are convenient to the program's author.  Apologies to the reader.
  35. =======================================================================*/
  36.  
  37.  
  38. /*-------------------*/
  39. /*      Includes     */
  40. /*-------------------*/
  41. /* System include files */
  42. #include <exec/types.h>
  43. #include <exec/memory.h>
  44. #include <dos/dos.h>
  45.  
  46. /* CAMD library includes */
  47. #include <midi/camd.h>
  48. #include <midi/camdbase.h>
  49. #include <midi/mididefs.h>
  50. #include <proto/camd.h>
  51.  
  52. /* RealTime library includes */
  53. #include <libraries/realtime.h>
  54. #include <proto/realtime.h>
  55.  
  56. /* System function prototypes */
  57. #include <proto/exec.h>
  58. #include <proto/dos.h>
  59. #include <proto/intuition.h>
  60.  
  61. /* Mididt specific includes */
  62. #include "debug.h"
  63. #include "register.h"
  64. #include "midiclass.h"
  65.  
  66. /* Trigger definitions */
  67. #define    STM_PAUSE        1
  68. #define    STM_PLAY        2
  69. #define    STM_REWIND        12
  70. #define    STM_FASTFORWARD        13
  71. #define    STM_STOP        14
  72. #define    STM_LOCATE        16
  73.  
  74.  
  75.  
  76. /*-------------------*/
  77. /*     Prototypes    */
  78. /*-------------------*/
  79. void kill(char *killstring);
  80. ULONG ComVarLen (UBYTE *value);
  81. UBYTE *DecodeEvent(UBYTE *,struct DecTrack *, ULONG);
  82. LONG transfer(struct DecTrack *,ULONG,LONG);
  83. ULONG changetempo(ULONG,ULONG,ULONG);
  84.  
  85.  
  86. /*---------------------*/
  87. /* S M F  Header  File */
  88. /*---------------------*/
  89. /* Four-character IDentifier builder*/
  90. #define MakeID(a,b,c,d)  ( (LONG)(a)<<24L | (LONG)(b)<<16L | (c)<<8 | (d) )
  91.  
  92. struct SMFHeader {LONG     ChunkID;  /* 4 ASCII characters */
  93.                   LONG     VarLeng;
  94.                   WORD     Format;
  95.                   UWORD    Ntrks;
  96.                   WORD     Division;
  97.                  };
  98.  
  99.  
  100. struct DecTrack { ULONG absdelta;   /* 32-bit delta */
  101.                   ULONG nexclock;   /* storage */
  102.                   UBYTE status;     /* status from file */
  103.                   UBYTE rstatus;    /* running status from track */
  104.                   UBYTE d1;         /* data byte 1 */
  105.                   UBYTE d2;         /* data byte 2 */
  106.                   ULONG absmlength; /* 32-bit absolute metalength */
  107.                   UBYTE *endmarker;
  108.                   UBYTE metatype;   /* meta event type */
  109.                   BOOL  playable;
  110.                   UBYTE tracknum;
  111.                 };
  112.  
  113.  
  114. /*------------------*/
  115. /* MIDI Header File */
  116. /*------------------*/
  117. #define MAXTRAX 64L
  118. #define TWOxMAXTRAX 128L
  119. #define MIDIBUFSIZE 512L
  120.  
  121.  
  122. /*------------------*/
  123. /*  Compiler glues  */
  124. /*------------------*/
  125. /* Compiler glue: stub functions for camd.library */
  126. struct MidiNode *CreateMidi(Tag tag, ...)
  127. {    return CreateMidiA((struct TagItem *)&tag );
  128. }
  129.  
  130. BOOL SetMidiAttrs(struct MidiNode *mi, Tag tag, ...)
  131. {    return SetMidiAttrsA(mi, (struct TagItem *)&tag );
  132. }
  133.  
  134. struct MidiLink *AddMidiLink(struct MidiNode *mi, LONG type, Tag tag, ...)
  135. {    return AddMidiLinkA(mi, type, (struct TagItem *)&tag );
  136. }
  137.  
  138.  
  139. /* Compiler glue: stub functions for realtime.library */
  140. BOOL SetPlayerAttrs(struct Player *pi, Tag tag, ...)
  141. {    return SetPlayerAttrsA(pi, (struct TagItem *)&tag );
  142. }
  143.  
  144. struct Player *CreatePlayer(Tag tag, ...)
  145. {    return CreatePlayerA( (struct TagItem *)&tag );
  146. }
  147.  
  148. #define TSHIFT  4
  149.  
  150. /*--------------*/
  151. /*   Globals    */
  152. /*--------------*/
  153. struct Library    *RealTimeBase;
  154. struct Library    *CamdBase;
  155. struct MidiDTData *mdt;
  156. struct MidiLink   *pMidiLink;
  157. struct MidiNode   *pMidiNode;
  158. struct Player     *pPlayer;
  159. UBYTE             *smfdata,*ptrack[TWOxMAXTRAX],*pData,trackct;
  160. LONG               midiSignal,smfdatasize,tempo_offs;
  161. ULONG              fillclock[2];
  162. ULONG              sizeDTrack,tfactor,initfactor,division,
  163.                    donecount,startdone;
  164. UBYTE             *pfillbuf[2],lastRSchan;
  165. BOOL               Playing;
  166.  
  167.  
  168. #define ALLNOTESOFFLEN    48
  169. UBYTE AllNotesOff[ALLNOTESOFFLEN] = {
  170. MS_Ctrl | 0,  MM_AllOff, 0,
  171. MS_Ctrl | 1,  MM_AllOff, 0,
  172. MS_Ctrl | 2,  MM_AllOff, 0,
  173. MS_Ctrl | 3,  MM_AllOff, 0,
  174. MS_Ctrl | 4,  MM_AllOff, 0,
  175. MS_Ctrl | 5,  MM_AllOff, 0,
  176. MS_Ctrl | 6,  MM_AllOff, 0,
  177. MS_Ctrl | 7,  MM_AllOff, 0,
  178. MS_Ctrl | 8,  MM_AllOff, 0,
  179. MS_Ctrl | 9,  MM_AllOff, 0,
  180. MS_Ctrl | 10, MM_AllOff, 0,
  181. MS_Ctrl | 11, MM_AllOff, 0,
  182. MS_Ctrl | 12, MM_AllOff, 0,
  183. MS_Ctrl | 13, MM_AllOff, 0,
  184. MS_Ctrl | 14, MM_AllOff, 0,
  185. MS_Ctrl | 15, MM_AllOff, 0
  186. };
  187.  
  188.  
  189.  
  190. /*-----------------------------*/
  191. /*     CODE  Starts  Here      */
  192. /*-----------------------------*/
  193.  
  194. ULONG ComVarLen (UBYTE *value)
  195. {
  196.    register ULONG newval;
  197.    register UBYTE x;
  198.  
  199.    x=0;newval=0L;
  200.    while(x<4)
  201.    {
  202.       newval <<= 7;
  203.       newval |=  *(value+x) & 0x7f;
  204.       if(*(value+x) < 0x80)x=4;
  205.       x++;
  206.    }
  207.    return(newval);
  208. }
  209.  
  210.  
  211. /*-----------*/
  212. /* Main code */
  213. /*-----------*/
  214. ClassCall void PlayMidi(void)
  215. {
  216.    struct Process    *myproc;
  217.    struct PlayMsg    *mymsg;
  218.    BYTE               oldpri;
  219.  
  220.    struct SMFHeader  *pSMFHeader;
  221.    UBYTE             *pbyte,x;
  222.    WORD               numtrack;
  223.    UWORD              countcyc;
  224.    LONG               y,z,res;
  225.    BOOL               timerr;
  226.    ULONG              masterswitch,lowclock,
  227.                       ylength[2],starttfactor,
  228.                       pause_offs,pause_start;
  229.  
  230.    UBYTE fillbuf1[MIDIBUFSIZE]; /* These buffers hold the notes translated */
  231.    UBYTE fillbuf2[MIDIBUFSIZE]; /* from the midifile file for playback          */
  232.    struct DecTrack *pDTrack[MAXTRAX];
  233.  
  234.    /*--------------------*/
  235.    /* Initialize globals */
  236.    /*--------------------*/
  237.    pMidiLink=NULL;
  238.    pMidiNode=NULL;
  239.    pPlayer=NULL;
  240.    midiSignal=-1;
  241.    donecount=0L;
  242.    pfillbuf[0]=fillbuf1;
  243.    pfillbuf[1]=fillbuf2;
  244.    fillclock[0]=0L;
  245.    fillclock[1]=0L;
  246.    lastRSchan=0xf1; /* Status of $F1 is undefined in Standard MIDI file Spec */
  247.    starttfactor= 12 << TSHIFT;
  248.    Playing = FALSE;
  249.  
  250.    /*-----------------*/
  251.    /* Get startup msg */
  252.    /*-----------------*/
  253.    myproc=(struct Process *) FindTask(NULL);
  254.    WaitPort(&myproc->pr_MsgPort);
  255.    mymsg=(struct PlayMsg *) GetMsg(&myproc->pr_MsgPort);
  256.    mdt=mymsg->mdt;
  257.    ReplyMsg(&mymsg->msg);
  258.    smfdatasize=mdt->mdt_BufferLen;
  259.    smfdata=mdt->mdt_Buffer;
  260.    D(bug("Received msg %lx on %lx\n",mymsg,myproc));
  261.  
  262.    RealTimeBase=NULL;
  263.    CamdBase=OpenLibrary("camd.library",37L);
  264.    if(!CamdBase)
  265.       kill("No camd.library");
  266.  
  267.    RealTimeBase=OpenLibrary("realtime.library",37L);
  268.    if(!RealTimeBase)
  269.       kill("No realtime.library");
  270.  
  271.    /*-----------------*/
  272.    /* Evaluate Header */
  273.    /*-----------------*/
  274.    pSMFHeader=(struct SMFHeader *)mdt->mdt_Buffer;
  275.    if ( (pSMFHeader->ChunkID != MakeID('M','T','h','d')) ||
  276.         (pSMFHeader->VarLeng != 6) )
  277.       kill("Unknown header");
  278.  
  279.    if (pSMFHeader->Format == 0 ) 
  280.       D(bug("Parsing midifile format type 0\n"));
  281.    else if (pSMFHeader->Format == 1 ) 
  282.       D(bug("Parsing midifile format type 1\n"));
  283.    else                          
  284.       kill("Unknown format type");
  285.  
  286.  
  287.    if(pSMFHeader->Ntrks >MAXTRAX )
  288.       kill("Wrong number of tracks");
  289.    else
  290.       D(bug("Midifile has %ld tracks\n",pSMFHeader->Ntrks));
  291.  
  292.  
  293.    /*--------------------*/
  294.    /* Evaluate time base */
  295.    /*--------------------*/
  296.    if (pSMFHeader->Division < 0)
  297.       kill("Unsupported time code");
  298.    else
  299.    {
  300.       D(bug("Midifile has 1/%ldth quarter notes per delta tick\n",
  301.               pSMFHeader->Division));
  302.       division=(ULONG)pSMFHeader->Division;
  303.  
  304.       /* According to "Standrd MIDI Files 1.0", July 1988, page 5 */
  305.       /* para. 4: "...time signature is assumed to be 4/4 and the */
  306.       /*           tempo 120 beats per minute."                   */
  307.       starttfactor=changetempo(500000L,starttfactor,0L); /* One quarter note every half second */
  308.    }
  309.  
  310.    /*----------------------------------------------*/
  311.    /* Set up a MidiNode and a MidiLink.  Link the  */
  312.    /* node to the default "out.0" MidiCluster .    */
  313.    /*----------------------------------------------*/
  314.    pMidiNode=CreateMidi( MIDI_Name,     "MidiDT Player",
  315.                          MIDI_MsgQueue,  0L,    /* This is a send-only   */
  316.                          MIDI_SysExSize, 4096L, /* MIDI node so no input */
  317.                          TAG_END);              /* buffers are needed.   */
  318.    if(!pMidiNode)
  319.       kill("Out of memory");
  320.  
  321.    pMidiLink=AddMidiLink( pMidiNode, MLTYPE_Sender, 
  322.                                      MLINK_Comment,  "MidiDT Link",
  323.                                      MLINK_Parse,    TRUE,
  324.                                      MLINK_Location, mdt->mdt_Cluster,
  325.                                      TAG_END);
  326.    if(!pMidiLink)
  327.       kill("Out of memory");
  328.  
  329.    /*---------------------------------------------------------------*/ 
  330.    /* Set up a Player and a Conductor to get timing information */
  331.    /*---------------------------------------------------------------*/ 
  332.    midiSignal = AllocSignal(-1L);
  333.    if(midiSignal==-1) 
  334.        kill("Out of memory");
  335.  
  336.    pPlayer=CreatePlayer(     PLAYER_Name,    "MidiDT Player",
  337.                              PLAYER_Conductor,  "MidiDT Conductor",
  338.                              PLAYER_AlarmSigTask, myproc,
  339.                              PLAYER_AlarmSigBit,midiSignal,
  340.                              TAG_END);
  341.    if(!pPlayer)
  342.        kill("Player fail");
  343.  
  344.  
  345.  for (countcyc=0; countcyc<mdt->mdt_Cycles || mdt->mdt_Repeat; countcyc++)
  346.  {
  347.    D(bug("Cycle %ld of %ld\n",countcyc+1,mdt->mdt_Cycles));
  348.  
  349.    /*----------------------*/
  350.    /* Find the MIDI tracks */
  351.    /*----------------------*/
  352.    donecount=0;
  353.    trackct=0;
  354.    pbyte=smfdata;
  355.  
  356.    while((pbyte-smfdata < smfdatasize) && (trackct < MAXTRAX))
  357.    {
  358.       if((*pbyte=='M')&&(*(pbyte+1)=='T')&&
  359.          (*(pbyte+2)=='r')&&(*(pbyte+3)=='k'))
  360.       {
  361.          /* Beginning of track */
  362.          ptrack[trackct]=pbyte+8;
  363.          /* End of track marker */
  364.          ptrack[MAXTRAX+trackct-1]=pbyte;
  365.          trackct++;
  366.          pbyte+=4;
  367.       }
  368.       else pbyte++;
  369.    }
  370.  
  371.    /* End of track marker */   
  372.    ptrack[MAXTRAX+trackct-1]=pbyte;
  373.  
  374.    if(trackct != pSMFHeader->Ntrks)
  375.       kill("Wrong number of tracks");
  376.    D(bug("There are %ld tracks in this Midifile.\n",trackct));
  377.  
  378.  
  379.    /*----------------------------------------*/
  380.    /* Set up DTrack structure for each track */
  381.    /*----------------------------------------*/
  382.    sizeDTrack=trackct*sizeof(struct DecTrack);
  383.    pData=AllocMem( sizeDTrack, MEMF_PUBLIC | MEMF_CLEAR );
  384.    if(!pData)
  385.       kill("Out of memory");
  386.  
  387.    numtrack=1;
  388.    for(x=0;x<trackct;x++)
  389.    {
  390.       pDTrack[x]=(struct DecTrack *)
  391.                  (x * sizeof(struct DecTrack) + pData);
  392.       /* add end marker */
  393.       pDTrack[x]->endmarker = ptrack[MAXTRAX+x];
  394.       pDTrack[x]->tracknum = numtrack++;
  395.    }
  396.  
  397.    /*------------------------------------------------*/  
  398.    /* Get events from track into DecTrack structures */
  399.    /*------------------------------------------------*/
  400.    y=0;
  401.    masterswitch=0L;
  402.    lowclock=0xffffffff;
  403.    tempo_offs=0;
  404.    tfactor=starttfactor;
  405.  
  406.    /* Initialize DecTrack structures */
  407.    for(x=0;x<trackct;x++)
  408.    {  
  409.       /* Takes a pointer to the delta of a raw <MTrk event>, a pointer   */
  410.       /* to a DecTrack decoding structure to store the decoded event and */ 
  411.       /* a switch that tells which of the two buffers to use.  Returns a */
  412.       /* pointer to the next raw <MTrk event> in the track or 0 if the   */
  413.       /* track is exhausted.                                             */
  414.       ptrack[x] = DecodeEvent( ptrack[x] , pDTrack[x] , masterswitch );
  415.       if(pDTrack[x]->nexclock < lowclock && ptrack[x])
  416.          /* Find the first event */
  417.          lowclock=pDTrack[x]->nexclock;
  418.    }
  419.  
  420.    /*-----------------------------------*/
  421.    /* Transfer first events to A buffer */
  422.    /*-----------------------------------*/
  423.    for(x=0;x<trackct;x++)
  424.    {
  425.       if((pDTrack[x]->nexclock==lowclock) && ptrack[x])
  426.       {
  427.          /* Transfer event to parse buffer and handle successor */
  428.          y=transfer(pDTrack[x],masterswitch,y);
  429.          z=1;
  430.          while(z==1)
  431.          {
  432.             ptrack[x]=DecodeEvent(ptrack[x],pDTrack[x],masterswitch);
  433.             /* Next delta is zero... */
  434.             if( !(pDTrack[x]->absdelta) && ptrack[x])
  435.             {
  436.                y=transfer(pDTrack[x],masterswitch,y);
  437.             }
  438.             else {z=0;}
  439.          }
  440.       }
  441.    }
  442.    ylength[masterswitch]=y;
  443.    fillclock[masterswitch]=(ULONG)(((tfactor*lowclock)+tempo_offs) >> TSHIFT);
  444.  
  445.    /*------------------------------------*/
  446.    /* Transfer second events to B buffer */
  447.    /*------------------------------------*/
  448.    y=0;
  449.    masterswitch=1L;
  450.    lowclock=0xffffffff;
  451.    for(x=0;x<trackct;x++)
  452.    {
  453.       if(pDTrack[x]->nexclock < lowclock && ptrack[x])
  454.          lowclock=pDTrack[x]->nexclock;
  455.    }
  456.  
  457.    for(x=0;x<trackct;x++)
  458.    {
  459.       if(pDTrack[x]->nexclock==lowclock && ptrack[x])
  460.       {
  461.          /* Transfer event to parse buffer and handle successor */
  462.          y=transfer(pDTrack[x],masterswitch,y);
  463.          z=1;
  464.          while(z==1)
  465.          {
  466.             ptrack[x]=DecodeEvent(ptrack[x],pDTrack[x],masterswitch);
  467.             /* Next delta is zero... */
  468.             if( !(pDTrack[x]->absdelta) && ptrack[x])
  469.             {
  470.                y=transfer(pDTrack[x],masterswitch,y);
  471.             }
  472.             else {z=0;}
  473.          }
  474.       }
  475.    }
  476.  
  477.    ylength[masterswitch]=y;
  478.    fillclock[masterswitch]=(ULONG)(((tfactor*lowclock)+tempo_offs) >> TSHIFT);
  479.  
  480.    /*-----------------------------------------------------*/
  481.    /* Priority Must Be Above Intuition and Graphics Stuff */
  482.    /*-----------------------------------------------------*/ 
  483.    oldpri=SetTaskPri(myproc,25);
  484.  
  485.    /*---------------------------------*/
  486.    /* Make sure the clock is stopped. */
  487.    /*---------------------------------*/
  488.    res = SetConductorState( pPlayer, CONDSTATE_STOPPED, 0L );
  489.    if(res!=0)
  490.        kill("Conductor fail");
  491.  
  492.    /*-------------------------------------------*/
  493.    /* Play the first batch of notes in Buffer A */
  494.    /*-------------------------------------------*/
  495.    if(ylength[masterswitch^1]!=0)
  496.       {
  497.       ParseMidi(pMidiLink,pfillbuf[masterswitch^1],
  498.                           ylength[masterswitch^1]);
  499.       }
  500.  
  501.    /*------------------------------------*/
  502.    /* and start the RealTime alarm clock */
  503.    /*------------------------------------*/
  504.    res = SetConductorState( pPlayer, CONDSTATE_RUNNING, 0L );
  505.    if(res!=0)
  506.        kill("Conductor fail");
  507.  
  508.    /*---------------------*/
  509.    /* and set the alarm.  */
  510.    /*---------------------*/
  511.    timerr = SetPlayerAttrs( pPlayer, 
  512.                             PLAYER_AlarmTime, fillclock[masterswitch],
  513.                             PLAYER_Ready, TRUE,
  514.                             TAG_END);
  515.    if(!timerr)
  516.        kill("Player fail");
  517.  
  518.    Playing = TRUE;
  519.    pause_offs=0;
  520.  
  521.    /*-----------------*/
  522.    /* MAIN EVENT LOOP */
  523.    /*-----------------*/   
  524.    while(donecount<trackct)
  525.    {
  526.       masterswitch ^= 1L;
  527.       y=0;
  528.       lowclock=0xffffffff;
  529.  
  530.       /*------------------------------------------------*/  
  531.       /* Get events from track into DecTrack structures */
  532.       /*------------------------------------------------*/
  533.       for(x=0;x<trackct;x++)
  534.       {
  535.          if((pDTrack[x]->nexclock < lowclock) && ptrack[x])
  536.             lowclock=pDTrack[x]->nexclock;
  537.       }
  538.  
  539.       /*-----------------------------------*/
  540.       /* Transfer events to current buffer */
  541.       /*-----------------------------------*/
  542.       for(x=0;x<trackct;x++)
  543.       {
  544.          if((pDTrack[x]->nexclock==lowclock) && ptrack[x])
  545.          {
  546.             /* Transfer event to parse buffer and handle successor */
  547.             y=transfer(pDTrack[x],masterswitch,y);
  548.             z=1;
  549.             while(z==1)
  550.             {
  551.                ptrack[x]=DecodeEvent(ptrack[x],pDTrack[x],masterswitch);
  552.                /* Next delta is zero... */
  553.                if( !(pDTrack[x]->absdelta) && ptrack[x] )
  554.                {
  555.                   y=transfer(pDTrack[x],masterswitch,y);
  556.                }
  557.                else {z=0;}
  558.             }
  559.          }
  560.       }
  561.  
  562.       ylength[masterswitch]=y;
  563.       fillclock[masterswitch]=(LONG)((((tfactor*lowclock)+tempo_offs)>>TSHIFT)+pause_offs);
  564.  
  565.       /*---------------------------------------------------------------*/
  566.       /* Wait() for the CAMD alarm or a CTRL-C keypress from the user. */
  567.       /*---------------------------------------------------------------*/
  568.       if (mdt->mdt_Playing==STM_PAUSE)
  569.       {
  570.          D(bug("Received PAUSE\n"));
  571.          pause_start = pPlayer->pl_MetricTime;
  572.          while( mdt->mdt_Playing==STM_PAUSE )
  573.             Delay(10);
  574.          pause_offs += pPlayer->pl_MetricTime - pause_start;
  575.          D(bug("No more PAUSE\n"));
  576.       }
  577.       if(timerr)
  578.          Wait(1L<< midiSignal | SIGBREAKF_CTRL_C);
  579.  
  580.       if (mdt->mdt_Playing==STM_STOP)
  581.       {
  582.          /* Restore Priority and Quit */
  583.          SetTaskPri(myproc,oldpri);
  584.          D(bug("Received STOP\n"));
  585.          kill(NULL);
  586.       }
  587.  
  588.       /*-------------------------------*/
  589.       /* Start the next set of events  */
  590.       /*-------------------------------*/
  591.       if(ylength[masterswitch^1]!=0)
  592.          {
  593.          ParseMidi(pMidiLink,pfillbuf[masterswitch^1],
  594.                              ylength[masterswitch^1]);
  595.          }
  596.  
  597.       /*---------------------*/
  598.       /* and set the alarm.  */
  599.       /*---------------------*/
  600.       timerr = SetPlayerAttrs( pPlayer, 
  601.                                PLAYER_AlarmTime, fillclock[masterswitch],
  602.                                PLAYER_Ready, TRUE,
  603.                                TAG_END);
  604.       if(!timerr)
  605.           kill("Player fail");
  606.    }
  607.  
  608.    /*-----------------------------------*/
  609.    /* Finish off the last set of events */
  610.    /*-----------------------------------*/
  611.    D(bug("Last events\n"));
  612.    masterswitch^=1L;
  613.  
  614.    if(timerr)
  615.       Wait(1L<< midiSignal | SIGBREAKF_CTRL_C);
  616.  
  617.  
  618.    if(ylength[masterswitch^1]!=0)
  619.       {
  620.       ParseMidi(pMidiLink,pfillbuf[masterswitch^1],
  621.                        ylength[masterswitch^1]);
  622.       }
  623.  
  624.  
  625.    /* Restore Priority */
  626.    SetTaskPri(myproc,oldpri);
  627.    FreeMem(pData,sizeDTrack);
  628.    pData=NULL;
  629.  
  630.  }
  631.  
  632.    D(bug("End of File, all OK.\n"));
  633.    kill(NULL);
  634. }
  635.  
  636.  
  637. /*------------------------------*/
  638. /* Cleanup and return resources */
  639. /*------------------------------*/
  640. void kill(char *killstring)
  641. {
  642.    struct EasyStruct myES =
  643.    {
  644.      sizeof(struct EasyStruct),
  645.      0,
  646.      "MidiDT Player",
  647.      "Fatal Error:\n%s",
  648.      "Ok",
  649.    };
  650.  
  651.    if(Playing)         ParseMidi(pMidiLink,AllNotesOff,ALLNOTESOFFLEN);
  652.    if(pPlayer)         DeletePlayer(pPlayer);
  653.    if(midiSignal != -1)FreeSignal(midiSignal);
  654.    if(pData)           FreeMem(pData,sizeDTrack);
  655.    if(pMidiLink)       RemoveMidiLink(pMidiLink);
  656.    if(pMidiNode)       DeleteMidi(pMidiNode);
  657.    if(RealTimeBase)    CloseLibrary(RealTimeBase);
  658.    if(CamdBase)        CloseLibrary(CamdBase);
  659.    if(killstring)      EasyRequest(NULL, &myES, NULL, killstring);
  660.    D(if(killstring)   {bug("Player exit: ");bug(killstring);bug(".\n");});
  661.    if(mdt->mdt_SignalTask) Signal(mdt->mdt_SignalTask, mdt->mdt_SignalBit);
  662.    mdt->mdt_PlayProc=NULL;
  663.    mdt->mdt_Playing=STM_STOP;
  664.    Exit(0);
  665. }
  666.  
  667.  
  668. /*--------------------------------------------------*/  
  669. /* Translate from raw track data to a decoded event */
  670. /*--------------------------------------------------*/  
  671. UBYTE *DecodeEvent(UBYTE *ptdata,struct DecTrack *pDTdata, ULONG deswitch)
  672. {
  673.    LONG status;
  674.    ULONG length;
  675.    BOOL skipit;
  676.    UBYTE tempbyte;
  677.  
  678.    pDTdata->absdelta = 0L;
  679.    pDTdata->playable = TRUE; /* Assume it's playble and not a meta-event */
  680.  
  681.    do
  682.    {
  683.       /* is this track all used up? */             
  684.       if( ptdata >= pDTdata->endmarker )
  685.       {
  686.          D(bug("Track %ld done\n", pDTdata->tracknum));
  687.          donecount++;
  688.          return(0L);
  689.       }
  690.       else /* there is more data to handle in the track */
  691.       {
  692.          /* Decode delta */
  693.          pDTdata->absdelta += ComVarLen(ptdata);
  694.          pDTdata->nexclock+= pDTdata->absdelta;
  695.  
  696.          /* Update pointer to event following delta */
  697.          while(*ptdata>127)
  698.             {
  699.             ptdata++;
  700.             }
  701.          ptdata++;
  702.  
  703.          if(*ptdata>127) /* Event with status ($80-$FF): decode new status */  
  704.          {
  705.             status=*ptdata;
  706.          
  707.             pDTdata->status=status;
  708.             pDTdata->rstatus=0;    /* No running status was used */
  709.      
  710.             ptdata++;
  711.             
  712.             if(status<240) /* Handle easy status $8x - $Ex */
  713.             {
  714.                skipit=FALSE;
  715.                pDTdata->d1 = *ptdata;
  716.                if(status<192 || status>223) /* $80-$BF, $E0-$EF: 2 data bytes */
  717.                {
  718.                   ptdata++;
  719.                   pDTdata->d2=*ptdata;
  720.                }
  721.                else pDTdata->d2=0;            /* $C0-$DF: 1 data byte */
  722.             }
  723.             else /* Status byte $Fx, system exclusive or meta events  */
  724.             {
  725.                skipit=TRUE;
  726.                
  727.                if(status==0xff)            /* It's a meta event ($ff) */
  728.                {
  729.                   pDTdata->metatype=*ptdata;
  730.               
  731.                   ptdata++; /* Now pointing at length byte */
  732.  
  733.                   if(pDTdata->metatype==81)
  734.                   {
  735.                      /* Tempo change event.  There are 60 milllion    */
  736.                      /* microseconds in a minute.  The lower 3 bytes  */ 
  737.                      /* pointed to by ptdata give the microseconds    */
  738.                      /* per MIDI quarter note. So, assuming a quarter */
  739.                      /* note gets the beat, this equation             */
  740.                      /*      60000000L /                              */
  741.                      /*          ( *((ULONG *)ptdata) & 0x00ffffff ) )*/
  742.                      /* gives beats per minute.                       */
  743.  
  744.                      tfactor = changetempo( *((ULONG *)ptdata) & 0x00ffffff, tfactor,
  745.                         pDTdata->nexclock - pDTdata->absdelta);
  746.  
  747.                      /* Tempo event is not playable.  This prevents the */
  748.                      /* event from being transferred to the play buffer */
  749.                      pDTdata->playable = FALSE; 
  750.  
  751.                      /* Even though this event can't be played, it     */
  752.                      /* takes some time and should not be skipped.     */
  753.                      skipit=FALSE;
  754.                   }
  755.                   length=ComVarLen(ptdata);
  756.                   pDTdata->absmlength=length;
  757.                   while(*ptdata>127)ptdata++;
  758.  
  759.                   ptdata+=length;
  760.                }
  761.                else if(status==0xf0 || status==0xf7) /* It's a sysex event */
  762.                {
  763.                      pDTdata->playable = FALSE; 
  764.                      skipit=FALSE;
  765.                   pDTdata->metatype=0xff;
  766.                   length=ComVarLen(ptdata);
  767.                   pDTdata->absmlength=length;
  768.                   while(*ptdata>127)ptdata++;
  769.                   D(bug("Sysex event %lx %lx %lx %lx %lx %lx %lx %lx\n",
  770.                        (long)ptdata[1], (long)ptdata[2], (long)ptdata[3], (long)ptdata[4], (long)ptdata[5],
  771.                        (long)ptdata[6], (long)ptdata[7], (long)ptdata[8]));
  772.                   tempbyte=ptdata[0];
  773.                   ptdata[0]=0xf0;
  774.                   PutSysEx(pMidiLink, ptdata);
  775.                   ptdata[0]=tempbyte;
  776.  
  777.                   ptdata+=length;
  778.                }
  779.                else        /* It's an unkown event type ($f1-$f6, $f8-$fe) */
  780.                {
  781.                   pDTdata->metatype=0xff;
  782.                   D(bug("Unknown event\n"));
  783.                }
  784.             }
  785.          }
  786.          else /* Event without status ($00-$7F): use running status */
  787.          {
  788.             skipit=FALSE;
  789.             /* Running status data bytes */
  790.             status=pDTdata->status;
  791.             pDTdata->rstatus=status;
  792.  
  793.             if(status==0)
  794.                kill("No initial status");
  795.  
  796.             pDTdata->d1=*ptdata;
  797.  
  798.             if(status<192 || status>223) /* $80-$BF, $E0-$EF: 2 data bytes */
  799.             {
  800.                ptdata++;
  801.                pDTdata->d2=*ptdata;
  802.             }
  803.             else pDTdata->d2=0;         /* $C0-$DF: 1 data byte */
  804.          }
  805.          ptdata++;
  806.       }
  807.    }
  808.    while(skipit);
  809.  
  810.    return(ptdata);
  811. }
  812.  
  813.  
  814. /*------------------------------------------------------------*/
  815. /* Transfer the decoded event to the fill buffer for playback */
  816. /*------------------------------------------------------------*/
  817. LONG
  818. transfer(struct DecTrack *pDT,ULONG mswitch,LONG ylen)
  819. {
  820.    ULONG y;
  821.    y=(ULONG )ylen;
  822.  
  823.    if (pDT->playable)
  824.    {
  825.       if(pDT->rstatus == lastRSchan)
  826.       { 
  827.          /* Running status so just put the 2 data bytes in buffer */
  828.          *(pfillbuf[mswitch] + y)=pDT->d1;
  829.          y++;
  830.          *(pfillbuf[mswitch] + y)=pDT->d2;
  831.       }
  832.       else 
  833.       {
  834.          /* New status so store status and data bytes */
  835.          *(pfillbuf[mswitch] + y)=pDT->status;
  836.          y++;
  837.          *(pfillbuf[mswitch] + y)=pDT->d1;
  838.          if(pDT->status<192 || pDT->status>223)
  839.          {
  840.             y++;
  841.             *(pfillbuf[mswitch] + y)=pDT->d2;
  842.          }
  843.          lastRSchan=pDT->status;     
  844.       }
  845.       y++;
  846.    }
  847.    return((LONG)y);
  848. }
  849.  
  850.  
  851. /*-------------------------------------------------------------------------*/
  852. /* Handle the Change Tempo event.   With the realtime.library, the timing  */
  853. /* quantum is fixed at .83 milliseconds (1.2kHz).  This makes handling of  */
  854. /* Playmf tempo a bit rough.  Tempo is controlled through a ULONG integer  */
  855. /* named tfactor which is used to multiply the time deltas in the Playmf   */
  856. /* file.  We can't multiply the time deltas by a fractional amount so we   */
  857. /* will shift up before dividing down for tfactor, and shift down after    */
  858. /* using the tfactor later.  This in effect gives us fractional control.   */
  859. /* To deal with the fact that tempo changes would cause us to wait for     */
  860. /* inappropriate past or future times on upcoming notes, we calculate a    */
  861. /* tempo_offs time offset (also shifted up) for use in time calculations.  */
  862. /*-------------------------------------------------------------------------*/
  863. ULONG
  864. changetempo(ULONG ctbpm, ULONG oldtfactor, ULONG eventtime)
  865. {
  866.    ULONG newtfactor,oldtime,newtime;
  867.  
  868.    /* ctbpm is the new microseconds per midi quarter note                */
  869.    /* Division is the part of a quarter note represented by a delta of 1 */
  870.    /* So ctbpm/division is the new microseconds per delta                */
  871.    /* CAMD uses 1200 ticks/sec or 833 microseconds per tick              */
  872.    /* We will compute a value which is:                                  */
  873.    /* ((microseconds per delta) << TSHIFT ) / 833                        */
  874.    /* The TSHIFT will give us some fractional control, and will be       */
  875.    /*    shifted out later when the new tfactor) is used.                */
  876.  
  877.    newtfactor = ((ctbpm << TSHIFT) / division) / 833; /* new tfactor */
  878.  
  879.    if((eventtime)&&(Playing))
  880.     {
  881.     /* We know our midi event time relative to the start of the file.
  882.      * We can calculate what CAMD time that equals at our initial tempo,
  883.      * and also at the new tempo.  We will save this difference as
  884.      * tempo_offs, and use tempo_offs to adjust all main program
  885.      * midi time -> CAMD time calculations.
  886.      * In other words, we figure out what CAMD time we would have
  887.      * been at now, if we had been playing at the new tempo all along.
  888.      * Using that information, we can adjust all upcoming MIDI
  889.      * Alarm wakeup times up or down by the amount the new tempo
  890.      * tfactor would have thrown us off.  Note that tempo_offs is
  891.      * based on values shifted up by TSHIFT, and this will be shifted
  892.      * out later in the main program time calculations.
  893.      */
  894.     oldtime = initfactor * eventtime; 
  895.     newtime = newtfactor * eventtime;
  896.     tempo_offs = oldtime - newtime;
  897.     D(bug("oldtime=%ld newtime=%ld tempo_offs = %ld\n",
  898.         oldtime>>TSHIFT,newtime>>TSHIFT,tempo_offs>>TSHIFT));
  899.     }
  900.    else
  901.     {
  902.     initfactor = newtfactor;
  903.     }
  904.    D(bug("changetempo: ctbpm=%ld newtfactor=%ld\n", ctbpm,newtfactor));
  905.    return(newtfactor);
  906. }
  907.  
  908.  
  909.