home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Amiga / Applications / Musique / PlayMF_VU.lha / Fireworks / Source / linear.c < prev    next >
C/C++ Source or Header  |  1998-03-31  |  9KB  |  363 lines

  1.  
  2. /*-------------------------------------------------*/
  3. /* fireworks.c - graphical MIDI note visualisation */
  4. /*          « 1998 by Christian Buchner            */
  5. /*-------------------------------------------------*/
  6.  
  7. #include "fireworks.h"
  8. #include "fireworks_protos.h"
  9.  
  10. #include "linear_protos.h"
  11.  
  12. extern UBYTE randomarray33[256];
  13.  
  14. /*-----------------------------------*/
  15. /* Linear fireworks (straight lines) */
  16. /*-----------------------------------*/
  17.  
  18. struct LinData
  19. {
  20.     struct Globals *glob;
  21.     struct Prefs *pref;
  22.     
  23.     ULONG curtime;
  24.     
  25.     WORD centx, centy;
  26.     WORD divx, divy;
  27.     
  28.     struct MinList CrackerList;
  29.     
  30.     WORD fxtab[128], fytab[128];
  31. };
  32.  
  33. #define SCALE 1024
  34.  
  35. /* the firecrackers */
  36.  
  37. struct LinearCracker
  38. {
  39.     struct Node        cr_node;
  40.     UBYTE            cr_chn;            /* 0 - 15  */
  41.     UBYTE            cr_note;        /* 0 - 127 */
  42.     UBYTE            cr_vel;            /* 0 - 127 */
  43.     
  44.     LONG            cr_starttime;        /* time stamp of note on */
  45.     LONG            cr_stoptime;        /* time stamp of note off */
  46.     UWORD            cr_savedlifetime;    /* lifetime when ray hit border */
  47.     
  48.     WORD            cr_fx;            /* -SCALE to SCALE equals -1 to -1 */
  49.     WORD            cr_fy;            /* -SCALE to SCALE equals -1 to -1 */
  50.     
  51.     WORD            cr_sparkx;        /* for painting sparks */
  52.     WORD            cr_sparky;
  53. };
  54.  
  55. APTR Lin_InitFireworks(struct Globals *glob, struct Prefs *pref)
  56. {
  57.     struct LinData *ld = NULL;
  58.     UWORD i;
  59.     
  60.     if (ld = AllocVec(sizeof(struct LinData), MEMF_ANY|MEMF_CLEAR))
  61.     {
  62.         ld->glob = glob;
  63.         ld->pref = pref;
  64.         
  65.         NewList((struct List*)&ld->CrackerList);
  66.         
  67.         /* pre-calculate angles of all possible 128 notes */
  68.         for (i = 0 ; i < 128 ; i++)
  69.         {
  70.             float angle = PI - (float)i/127 * PI;
  71.             
  72.             ld->fxtab[i] = SCALE * cos(angle);
  73.             ld->fytab[i] = SCALE * sin(angle);
  74.         }
  75.         
  76.         Lin_RethinkWindow((APTR)ld);
  77.         
  78.         GetTimeDelta();            /* initialize delta counter */
  79.         ld->curtime = 0;        /* start at time counter 0 */
  80.     }
  81.     
  82.     return((APTR)ld);
  83. }
  84.  
  85. void Lin_RethinkWindow(APTR data)
  86. {
  87.     struct LinData *ld = (struct LinData*) data;
  88.     struct Globals *glob = ld->glob;
  89.     
  90.     /* Calculate ray scaling factors */
  91.     ld->divx  = SCALE * MAXCOORD / (glob->ww);
  92.     ld->divy  = SCALE * MAXCOORD / (glob->wh);
  93.     ld->centx = CENTER_X * (glob->ww) / MAXCOORD;
  94.     ld->centy = CENTER_Y * (glob->wh) / MAXCOORD;
  95. }
  96.  
  97. void Lin_TimePassed(APTR data)
  98. {
  99.     struct LinData *ld = (struct LinData*) data;
  100.     
  101.     ld->curtime += GetTimeDelta();
  102. }
  103.  
  104. BOOL Lin_IsIdle(APTR data)
  105. {
  106.     struct LinData *ld = (struct LinData*) data;
  107.     
  108.     if (IsListEmpty((struct List*)&ld->CrackerList))
  109.         return(TRUE);
  110.     else
  111.         return(FALSE);
  112. }
  113.  
  114. void Lin_DrawFireworks(APTR data, UWORD Mask)
  115. {
  116.     struct LinData *ld = (struct LinData*) data;
  117.     struct LinearCracker *cr, *ncr;
  118.     struct Globals *glob = ld->glob;
  119.     struct Prefs *pref = ld->pref;
  120.     
  121.     UWORD lifetime;
  122.     UWORD deathtime;
  123.     WORD sx1, sy1;
  124.     WORD sx2, sy2;
  125.     LONG lastpen = -1, newpen;
  126.     
  127.     struct Layer *SaveLayer = glob->PaintRP.Layer;
  128.         
  129.     for ( cr = (struct LinearCracker*) ld->CrackerList.mlh_Head ;
  130.           ncr = (struct LinearCracker*) cr->cr_node.ln_Succ ;
  131.           cr = ncr )
  132.     {
  133.         /* get the ray's lifetime information */
  134.         
  135.         if (cr->cr_savedlifetime == 0xffff)
  136.             if ((ld->curtime - cr->cr_starttime) < 0x10000)
  137.                 lifetime = (UWORD)(ld->curtime - cr->cr_starttime);
  138.             else
  139.                 lifetime = 0xffff;
  140.         else
  141.             lifetime = cr->cr_savedlifetime;
  142.         
  143.         /* calculate ray starting points */
  144.         sx1 = ld->centx + cr->cr_fx *  lifetime / ld->divx;
  145.         sy1 = ld->centy - cr->cr_fy *  lifetime / ld->divy;
  146.         
  147.         if (cr->cr_savedlifetime == 0xffff)
  148.         {
  149.             if ((sx1 >= glob->ww) || (sy1 >= glob->wh) || (sx1 < 0) || (sy1 < 0))
  150.             {
  151.                 /* Start of ray hit window borders */
  152.                 /* save the time this happened to prevent */
  153.                 /* the ray from growing longer than */
  154.                 /* graphic's clipping can handle safely */
  155.                 cr->cr_savedlifetime = lifetime;
  156.             }
  157.         }
  158.         
  159.         /* has ray already been stopped by a note off? */
  160.         if (cr->cr_stoptime == -1)
  161.         {
  162.             /* no, still emmitting from the centre */
  163.             sx2 = ld->centx;
  164.             sy2 = ld->centy;
  165.             deathtime = 0;
  166.         }
  167.         else
  168.         {
  169.             /* get the time when the note off occured */
  170.             if ((ld->curtime - cr->cr_stoptime) < 0x10000)
  171.                 deathtime = (UWORD)(ld->curtime - cr->cr_stoptime);
  172.             else
  173.                 deathtime = 0xffff;
  174.             
  175.             /* is the ray just a dot? */
  176.             if (lifetime == deathtime)
  177.             {
  178.                 sx2 = sx1;
  179.                 sy2 = sy1;
  180.             }
  181.             else
  182.             {
  183.                 /* calculate ray ending points */
  184.                 sy2 = ld->centy - cr->cr_fy * deathtime / ld->divy;
  185.                 sx2 = ld->centx + cr->cr_fx * deathtime / ld->divx;
  186.             }
  187.         }
  188.         
  189.         /* see if the ray has disappeared or exceeded */
  190.         /* its maximum time since the note was released */
  191.         if ((sx2 >= glob->ww) || (sy2 >= glob->wh) || (sx2 < 0) || (sy2 < 0) ||
  192.             deathtime  == 0xffff )
  193.         {
  194.             Remove((struct Node*)cr);
  195.             FreePooled(glob->NotePool,cr,sizeof(struct LinearCracker));
  196.         }
  197.         else
  198.         {
  199.             /* display this channel ? */
  200.             if ((1<<cr->cr_chn) & Mask)
  201.             {
  202.                 /* change pen if necessary */
  203.                 newpen = glob->PenArray[Channelpens+cr->cr_chn];
  204.                 if (lastpen != newpen)
  205.                 {
  206.                     SetAPen(&glob->PaintRP, newpen);
  207.                     lastpen = newpen;
  208.                 }
  209.                 
  210.                 /* draw the ray */
  211.                 Move(&glob->PaintRP, sx1, sy1);
  212.                 Draw(&glob->PaintRP, sx2, sy2);
  213.                 
  214.                 if (pref->Flags & PREFF_DOUBLE)
  215.                 {
  216.                     WORD dx, dy;
  217.                     dx = sx2 - sx1; if (dx<0) dx=-dx;
  218.                     dy = sy2 - sy1; if (dy<0) dy=-dy;
  219.                     
  220.                     if (dy >= dx)
  221.                     {
  222.                         Move(&glob->PaintRP, sx1+1, sy1);
  223.                         Draw(&glob->PaintRP, sx2+1, sy2);
  224.                     }
  225.                     else
  226.                     {
  227.                         Move(&glob->PaintRP, sx1, sy1+1);
  228.                         Draw(&glob->PaintRP, sx2, sy2+1);
  229.                     }
  230.                 }
  231.                 if (pref->Flags & PREFF_SPARKS)
  232.                 {
  233.                     cr->cr_sparkx = sx1;
  234.                     cr->cr_sparky = sy1;
  235.                 }
  236.             }
  237.         }
  238.     }
  239.     
  240.     if (pref->Flags & PREFF_SPARKS)
  241.     {
  242.         SetAPen(&glob->PaintRP, glob->PenArray[Sparkpen]);
  243.         
  244.         for ( cr = (struct LinearCracker*) ld->CrackerList.mlh_Head ;
  245.               ncr = (struct LinearCracker*) cr->cr_node.ln_Succ ;
  246.               cr = ncr )
  247.         {
  248.             /* display this channel ? */
  249.             if ((1<<cr->cr_chn) & Mask)
  250.             {
  251.                 if (cr->cr_savedlifetime == 0xffff)
  252.                 {
  253.                     UWORD margin = (pref->Flags & PREFF_DOUBLE) ? 2 : 1;
  254.                     UBYTE rnd = (ld->curtime>>6) + cr->cr_starttime + cr->cr_note;
  255.                     
  256.                     if (randomarray33[rnd])
  257.                     {
  258.                         sx1 = cr->cr_sparkx;
  259.                         sy1 = cr->cr_sparky;
  260.                         
  261.                         if ((sx1 >= margin) && (sy1 >= margin) &&
  262.                             (sx1 < (glob->ww - margin)) &&
  263.                             (sy1 < (glob->wh - margin)) )
  264.                             glob->PaintRP.Layer = NULL;
  265.                         else
  266.                             glob->PaintRP.Layer = SaveLayer;
  267.                         
  268.                         RectFill(&glob->PaintRP, sx1-margin, sy1-margin, sx1+margin, sy1+margin);
  269.                     }
  270.                 }
  271.             }
  272.         }
  273.     }
  274.     
  275.     glob->PaintRP.Layer = SaveLayer;
  276. }
  277.  
  278. void Lin_NoteOn(APTR data, UBYTE chn, UBYTE note, UBYTE vel, LONG reltime)
  279. {
  280.     struct LinData *ld = (struct LinData*) data;
  281.     struct Globals *glob = ld->glob;
  282.     struct Prefs *pref = ld->pref;
  283.     struct LinearCracker *cr;
  284.     
  285.     if (cr = AllocPooled(glob->NotePool, sizeof(struct LinearCracker)))
  286.     {
  287.         cr->cr_node.ln_Pri = chn;
  288.         
  289.         cr->cr_chn  = chn;
  290.         cr->cr_note = note;
  291.         cr->cr_vel  = vel;
  292.         
  293.         cr->cr_starttime = ld->curtime - reltime;
  294.         cr->cr_stoptime  = -1;
  295.         cr->cr_savedlifetime = 0xffff;
  296.         
  297.         cr->cr_fx = ld->fxtab[note] * cr->cr_vel / 127 * pref->Sensitivity / 100;
  298.         cr->cr_fy = ld->fytab[note] * cr->cr_vel / 127 * pref->Sensitivity / 100;
  299.         
  300.         /* sorted by channel num to speed up painting */
  301.         Enqueue((struct List*)&ld->CrackerList, (struct Node*)cr);
  302.     }
  303. }
  304.  
  305. void Lin_NoteOff(APTR data, UBYTE chn, UBYTE note, LONG reltime)
  306. {
  307.     struct LinData *ld = (struct LinData*) data;
  308.     struct LinearCracker *cr, *ncr;
  309.     
  310.     for ( cr = (struct LinearCracker*) ld->CrackerList.mlh_Head ;
  311.           ncr = (struct LinearCracker*) cr->cr_node.ln_Succ ;
  312.           cr = ncr )
  313.     {
  314.         if ( (cr->cr_chn  == chn ) &&
  315.              (cr->cr_note == note) &&
  316.              (cr->cr_stoptime == -1) )
  317.         {
  318.             cr->cr_stoptime = ld->curtime - reltime;
  319.             break;
  320.         }
  321.     }
  322. }
  323.  
  324. void Lin_ReleaseNotes(APTR data, LONG reltime)
  325. {
  326.     struct LinData *ld = (struct LinData*) data;
  327.     struct LinearCracker *cr, *ncr;
  328.     
  329.     for ( cr = (struct LinearCracker*) ld->CrackerList.mlh_Head ;
  330.           ncr = (struct LinearCracker*) cr->cr_node.ln_Succ ;
  331.           cr = ncr )
  332.     {
  333.         if (cr->cr_stoptime == -1) cr->cr_stoptime = ld->curtime - reltime;
  334.     }
  335. }
  336.  
  337. void Lin_FreeNoteData(APTR data)
  338. {
  339.     struct LinData *ld = (struct LinData*) data;
  340.     struct Globals *glob = ld->glob;
  341.     struct LinearCracker *cr, *ncr;
  342.     
  343.     for ( cr = (struct LinearCracker*) ld->CrackerList.mlh_Head ;
  344.           ncr = (struct LinearCracker*) cr->cr_node.ln_Succ ;
  345.           cr = ncr )
  346.     {
  347.         Remove((struct Node*)cr);
  348.         FreePooled(glob->NotePool,cr,sizeof(struct LinearCracker));
  349.     }
  350. }
  351.  
  352. void Lin_ExitFireworks(APTR data)
  353. {
  354.     struct LinData *ld = (struct LinData*) data;
  355.     
  356.     if (ld)
  357.     {
  358.         Lin_FreeNoteData(data);
  359.         
  360.         FreeVec(ld);
  361.     }
  362. }
  363.