home *** CD-ROM | disk | FTP | other *** search
/ Audio Version 4.94 / audioversion4.94knowledgemediaresourcelibraryoctober1994.iso / amiga / utils / exp_iv / play.c < prev    next >
C/C++ Source or Header  |  1991-05-16  |  25KB  |  642 lines

  1. /* play.c */
  2.  
  3. /* $Author: Espie $
  4.  * $Date: 91/05/16 15:05:39 $
  5.  * $Revision: 1.46 $
  6.  * $Log:    play.c,v $
  7.  * Revision 1.46  91/05/16  15:05:39  Espie
  8.  * Conditional asm, else use stub.
  9.  * 
  10.  * Revision 1.45  91/05/12  22:39:01  Espie
  11.  * Corrected a stupid bug in change_speed:
  12.  * with speed 0, I was going through the OTHER cases,
  13.  * with expected results (MUCH too fast).
  14.  *
  15.  * Revision 1.44  91/05/12  19:55:47  Espie
  16.  * Split partly to commands.
  17.  * Corrected oneshot logic, added new periods handling.
  18.  * Other minor changes.
  19.  *
  20.  * Revision 1.43  91/05/12  15:59:33  Espie
  21.  * Tried to correct the oneshot bug.
  22.  *
  23.  * Revision 1.42  91/05/11  14:58:37  Espie
  24.  * Tried to correct the ``eaten note'' problem. Not done yet.
  25.  *
  26.  * Revision 1.41  91/05/09  17:37:01  Espie
  27.  * Non standard speed modes. (Old and New).
  28.  * Hopefully a temporary kludge, with better
  29.  * loader, we could magically determine what
  30.  * each speed change means...
  31.  *
  32.  * Revision 1.40  91/05/08  15:52:12  Espie
  33.  * Apparent problems with volume latch, nothing changed,
  34.  * problems were not coming from here.
  35.  *
  36.  * Revision 1.39  91/05/07  12:13:15  Espie
  37.  * Speed or not speed ??
  38.  *
  39.  * Revision 1.38  91/05/07  02:53:30  Espie
  40.  * Corrected oneshot bug.
  41.  *
  42.  * Revision 1.37  91/05/06  15:15:35  Espie
  43.  * Changed some more stuff from public to private status.
  44.  *
  45.  * Revision 1.36  91/05/05  19:07:14  Espie
  46.  * New private fields, now we should manage all speed changes
  47.  * by ourselves.
  48.  *
  49.  * Revision 1.35  91/05/05  15:40:15  Espie
  50.  * Semi-automatic conversion. Works mostly
  51.  * (bug in run the gauntlet at measure 6).
  52.  *
  53.  * Revision 1.34  91/05/02  23:33:09  Espie
  54.  * *** empty log message ***
  55.  *
  56.  * Revision 1.33  91/05/02  01:32:31  Espie
  57.  * New automaton for the player, simpler.
  58.  *
  59.  * Revision 1.32  91/04/30  16:52:58  Espie
  60.  * Corrected speed bug: we only
  61.  * set the new speed after all channels have
  62.  * been processed.
  63.  *
  64.  * Revision 1.31  91/04/30  01:47:06  Espie
  65.  * Fixed out some minor problems: now speed 0 is recognized as an end.
  66.  * On start at a new pos, we send a ON_PATTERN message for people
  67.  * wanting to update the pattern number dumbly.
  68.  * Easier for us than for them !
  69.  *
  70.  * Revision 1.30  91/04/30  00:35:50  Espie
  71.  * Stable version III.
  72.  *
  73.  * Revision 1.29  91/04/29  15:06:49  Espie
  74.  * Moved control of start/stop actions to interrupt.c
  75.  *
  76.  * Revision 1.28  91/04/28  22:52:54  Espie
  77.  * Tranpose added.
  78.  *
  79.  * Revision 1.27  91/04/28  20:35:04  Espie
  80.  * New check for speed (finespeed adjust).
  81.  *
  82.  * Revision 1.26  91/04/27  20:48:37  Espie
  83.  * Dual speed tempo.
  84.  *
  85.  * Revision 1.25  91/04/27  16:44:27  Espie
  86.  * Optimized again.
  87.  * Changed part of the control, now all the commands are local functions.
  88.  * Tried to optimize size of parameters, but Lattice won't let me... bug, Bug, BUG !
  89.  *
  90.  * Revision 1.24  91/04/27  04:00:52  Espie
  91.  * many new optimizations, some cleanup.
  92.  * (constant folding, separation of arpeggio in 3 commands, etc).
  93.  *
  94.  * Revision 1.23  91/04/27  00:25:00  Espie
  95.  * New timing routine (works).
  96.  * Now times itself.
  97.  * First try at constant folding for cases.
  98.  * Optimize further...
  99.  *
  100.  * Revision 1.22  91/04/26  16:34:36  Espie
  101.  * Completely new timing, far from perfect yet.
  102.  * The interrupt routine is now a 3-state automaton.
  103.  * The timing relies entirely on the wait() function, which
  104.  * waits for intervals between each call. Smallest wait should
  105.  * be reparameterized.
  106.  * Should add an ``efficiency'' count: what percentage of the CPU time
  107.  * do we use ? Since nobody is able to time us, we should time ourselves.
  108.  *
  109.  * Revision 1.21  91/04/26  01:29:16  Espie
  110.  * Refixed the vibrato command once again.
  111.  * Plays right, don't touch :-(.
  112.  *
  113.  *
  114.  * Revision 1.20  91/04/25  02:05:52  Espie
  115.  * Corrected vibrato.... should work correctly.
  116.  * Added filter control (good idea ?).
  117.  *
  118.  * Revision 1.19  91/04/24  23:40:13  Espie
  119.  * Fixed the vibrato routine. This is now the correct
  120.  * depth/speed.
  121.  *
  122.  * Revision 1.18  91/04/24  15:26:07  Espie
  123.  * Fixed up small problem, which had no chance to appear before.
  124.  * The instrument_reload command does reset everything, including
  125.  * the period now, since we can multitask with other users...
  126.  *
  127.  * Revision 1.17  91/04/23  21:24:54  Espie
  128.  * Totally revised logic for the automaton.
  129.  * It is now much easier to set up anything through the interrupt.
  130.  * While it is in stop mode, the song pointers don't have to be valid.
  131.  * The oneshot setting has been thoroughly tested, it seems necessary
  132.  * to stop the audio hardware at that point (cleanup is not fast enough).
  133.  * Added the reload_instrument stuff to try to restart from a pause.
  134.  * Also, finetunes are now implemented.
  135.  * Parameters not yet reduced to minimum size, logic between note and period
  136.  * not completely alright too.
  137.  *
  138.  * Revision 1.16  91/04/21  20:04:17  Espie
  139.  * Handles arpeggio, apparently correctly.
  140.  * Has a crude ``oversampling'' mechanism.
  141.  * Does know something about notes.
  142.  * Not perfect in its handling of finetune instruments (examples ?).
  143.  *
  144.  * Revision 1.15  91/04/21  12:11:47  Espie
  145.  * Stable version, known as bunch II.
  146.  * Also features ``right'' log description.
  147.  *
  148.  * Revision 1.14  91/04/21  11:31:56  Espie
  149.  * Try out for automatic log messages
  150.  *
  151.  * Revision 1.13  91/04/21  11:27:13  Espie
  152.  * Added automatic log messages.
  153.  *
  154.  * Revision 1.12  91/04/21  11:16:17  Espie
  155.  * Simplified player.
  156.  *
  157.  * Revision 1.11  91/04/20  18:12:59  Espie
  158.  * Improved player:
  159.  * simplified calls to audio routines.
  160.  * Caught a subtle bug in the instrument number stuff.
  161.  * Caught the volume change problems.
  162.  * Seems to work great.
  163.  *
  164.  * Revision 1.10  91/04/20  03:55:31  Espie
  165.  * Cleaned up version.
  166.  * Does play mod.shadowfire correctly.
  167.  *
  168.  * Revision 1.9   91/04/20  03:07:08  Espie
  169.  * Debugged version. Portamento is now working correctly.
  170.  * Incorrect loading of instrument has been fixed:
  171.  * while portamento, frequency should not be changed, but
  172.  * volume should be anyway. Not too easy.
  173.  * (To check, change volume always, actually).
  174.  *
  175.  * Revision 1.8   91/04/19  19:46:57  Espie
  176.  * Tone portamento working better. Successfull.
  177.  *
  178.  * Revision 1.7   91/04/19  18:35:24  Espie
  179.  * Version before an experiment.
  180.  *
  181.  * Revision 1.6   91/04/19  13:20:30  Espie
  182.  * Augmented player: broken up in small functions,
  183.  * signals task for events, recognizes many events,
  184.  * but not everything quite yet...
  185.  *
  186.  * Revision 1.5   91/04/19  02:18:35  Espie
  187.  * new player, plays about 90% of my files correctly.
  188.  * Missing arpegios, volume slide and command 4, whatever that is.
  189.  *
  190.  * Revision 1.4   91/04/18  20:23:34  Espie
  191.  * No assembly stub necessary under SAS C.
  192.  *
  193.  * Revision 1.3   91/04/18  02:26:14  Espie
  194.  * bunch I.
  195.  *
  196.  * Revision 1.2   91/04/18  02:19:12  Espie
  197.  * ``Working'' simple-minded player.
  198.  *
  199.  * Revision 1.1   91/04/18  01:34:53  Espie
  200.  * Initial revision
  201.  *
  202.  */
  203.  
  204. #include <exec/types.h>
  205. #include <hardware/cia.h>
  206. #include <proto/exec.h>
  207. #include <dos/dos.h>
  208. #include <stdlib.h>
  209. #include <custom/cleanup.h>
  210. #include "song.h"
  211. #include "player.h"
  212. #include "public_play.h"
  213. #include "int_play.h"
  214. #include "proto.h"
  215. #include "periods.h"
  216. #include "lproto.h"
  217.  
  218.  
  219.  
  220. /***
  221.  *
  222.  *               The micro-timing package
  223.  *
  224.  ***/
  225.  
  226.  
  227. /* get current timer value
  228.  */
  229. UWORD gettimer(struct play *play)
  230.         {
  231.                 return *PRIVATE.latchlo | (*PRIVATE.latchhi<<8);
  232.         }
  233.  
  234. /* relatch with the correct time for an interval
  235.  * between the start of this interrupt and the next
  236.  * interrupt of value
  237.  */
  238. void relatch(struct play *play, int value)
  239.         {
  240.                 PRIVATE.current = PRIVATE.latched - gettimer(play);
  241.                 value -= PRIVATE.current;
  242.                 *PRIVATE.latchlo = value & 255;
  243.                 *PRIVATE.latchhi = value>>8;
  244.                         /* IMPORTANT: force load of latched value ! */
  245.                 *PRIVATE.control |= CIACRAF_LOAD;
  246.                 PRIVATE.latched = value;
  247.  
  248.                         /* time ourselves, while we're at it */
  249.                 PUBLIC.sleep+= PRIVATE.latched;
  250.                 PUBLIC.cpu += PRIVATE.current;
  251.         }
  252.  
  253. void rebuild_timers(struct play *play)
  254.         {
  255.                 PRIVATE.maintimer = PUBLIC.timebase/PRIVATE.finespeed;
  256.                 PRIVATE.effecttimer = PUBLIC.effectbase/PRIVATE.finespeed;
  257.                 PRIVATE.smalltimer = 600;
  258.         }
  259.  
  260. #ifdef LATTICE
  261. void __interrupt __asm do_play(register __a1 struct play *play)
  262. #else
  263. void C_do_play(struct play *play)
  264. #endif
  265.         {
  266.                 (*PRIVATE.state)(play);
  267.         }
  268.  
  269. void init_player(struct play *play)
  270.         {
  271.         int track;
  272.                 PRIVATE.state = wait_play;
  273.                 reset_player(play);
  274.                 rebuild_timers(play);
  275.                 PRIVATE.latched = PRIVATE.maintimer;
  276.                 for (track = 0; track < NUMBER_TRACKS; track++)
  277.                         {
  278.                                 PRIVATE.track[track]->pursue = do_nothing;
  279.                                 PRIVATE.track[track]->channel = track;
  280.                         }
  281.                 PRIVATE.setup[0] = setup_arpeggio;
  282.                 PRIVATE.setup[1] = setup_porta_up;
  283.                 PRIVATE.setup[2] = setup_porta_down;
  284.                 PRIVATE.setup[3] = setup_portamento;
  285.                 PRIVATE.setup[4] = setup_vibrato;
  286.                 PRIVATE.setup[5] = ignore;
  287.                 PRIVATE.setup[6] = ignore;
  288.                 PRIVATE.setup[7] = ignore;
  289.                 PRIVATE.setup[8] = ignore;
  290.                 PRIVATE.setup[9] = ignore;
  291.                 PRIVATE.setup[10]= setup_volume_slide;
  292.                 PRIVATE.setup[11]= do_fastskip;
  293.                 PRIVATE.setup[12]= do_change_volume;
  294.                 PRIVATE.setup[13]= do_skip;
  295.                 PRIVATE.setup[14]= do_change_filter;
  296.                 PRIVATE.setup[15]= do_change_speed;
  297.                 init_audio_hard(&play->private);
  298.         }
  299.  
  300. void wait_play(struct play *play)
  301.         {
  302.                 if (PUBLIC.command)
  303.                         PRIVATE.state = normal_play;
  304.                 return;
  305.         }
  306.  
  307. void normal_play(struct play *play)
  308.         {
  309.                 PRIVATE.replay = FALSE;
  310.                 PRIVATE.volume = PUBLIC.volume;
  311.                 play_next(play);
  312.                 /* setup for the new replay routine
  313.                  */
  314.                 if (PRIVATE.tempo_change)
  315.                         {
  316.                                 rebuild_timers(play);
  317.                                 PRIVATE.tempo_change = FALSE;
  318.                         }
  319.                 if (PRIVATE.replay)
  320.                         {
  321.                                 PRIVATE.state = latch_samples;
  322.                                 PRIVATE.spent = PRIVATE.latched - gettimer(play);
  323.                                 relatch(play, PRIVATE.smalltimer+PRIVATE.spent);
  324.                         }
  325.                 else
  326.                         relatch(play, PRIVATE.effecttimer);
  327.  
  328.         }
  329.  
  330. void latch_samples(struct play *play)
  331.         {
  332.                         /* dma was off, turn it back on */
  333.                 turn_on_dma(&play->private);
  334.                 PRIVATE.state = install_replay;
  335.                 relatch(play, PRIVATE.smalltimer);
  336.         }
  337.  
  338. void install_replay(struct play *play)
  339.         {
  340.         int track;
  341.                         /* setup the replay section */
  342.                 for (track = 0; track < NUMBER_TRACKS; track++)
  343.                         if (PRIVATE.track[track]->newnote)
  344.                                 set_replay(&play->private, PRIVATE.track[track]->instr,
  345.                                                 PRIVATE.track[track]->channel);
  346.                 PRIVATE.state = normal_play;
  347.                 relatch(play, PRIVATE.maintimer - 2 * PRIVATE.smalltimer
  348.                                 - PRIVATE.spent);
  349.         }
  350.  
  351.  
  352.  
  353.  
  354. /* this function should be called every time a volume is to be set,
  355.  * because the master volume changes according to the user's whim.
  356.  */
  357. int scaled_volume(int master, struct automaton *cst)
  358.         {
  359.                 return (cst->volume * master) /256;
  360.         }
  361.  
  362. void new_volume(struct priv_play *private, struct automaton *cst)
  363.         {
  364.                 change_volume(private, cst->channel,
  365.                         scaled_volume(private->volume, cst));
  366.         }
  367.  
  368. void new_period(struct priv_play *private, struct automaton *cst)
  369.         {
  370.                 change_period(private, cst->channel, cst->period);
  371.         }
  372.  
  373.         /* what to do when play has just ended */
  374.  
  375. void ended_play(struct play *play)
  376.         {
  377.                 PRIVATE.has_ended = TRUE;
  378.         }
  379.  
  380. void send_out(struct play *play)
  381.         {
  382.                 PUBLIC.position = PRIVATE.position;
  383.                 PUBLIC.pattern = PRIVATE.pattern;
  384.                 PUBLIC.speed = PRIVATE.speed;
  385.                 PUBLIC.finespeed = PRIVATE.finespeed;
  386.         }
  387.  
  388. void install_filter(struct priv_play *private)
  389.         {
  390.                 if (private->filter)
  391.                         filter_on();
  392.                 else
  393.                         filter_off();
  394.         }
  395.  
  396. void reset_player(struct play *play)
  397.         {
  398.         int track;
  399.         struct automaton *cst;
  400.                 PRIVATE.filter = FALSE;
  401.                 install_filter(&play->private);
  402.                 reset_audio();
  403.                 for (track = 0; track < NUMBER_TRACKS; track++)
  404.                         {
  405.                                 cst = PRIVATE.track[track];
  406.                                 cst->instr = PUBLIC.sample[0];
  407.                                 cst->rate = 0;
  408.                                 cst->depth = 0;
  409.                                 cst->speed = 0;
  410.                         }
  411.                                 /* dummy sample */
  412.                 PRIVATE.counter = 0;
  413.                 send_out(play);
  414.                         /* turns out to be simpler for the display */
  415.                 send(play, ON_PATTERN);
  416.                 PRIVATE.speed = 6;
  417.                 PRIVATE.finespeed = 100;
  418.                 rebuild_timers(play);
  419.         }
  420.  
  421. void play_next(struct play *play)
  422.         {
  423.         struct automaton *cst;
  424.         int track;
  425.                 if (PUBLIC.resume)
  426.                         {
  427.                                 clear_mask(&play->private);
  428.                                 install_filter(&play->private);
  429.                                 for (track = 0; track < NUMBER_TRACKS; track++)
  430.                                         {
  431.                                                 cst = PRIVATE.track[track];
  432.                                                 cst->p_table =
  433.                                                         PRIVATE.period_table[cst->instr->finetune]
  434.                                                         +PUBLIC.transpose;
  435.                                                 new_period(&play->private, cst);
  436.                                                 new_volume(&play->private, cst);
  437.                                                 set_replay(&play->private,cst->instr, cst->channel);
  438.                                         }
  439.                                 turn_on_dma(&play->private);
  440.                         }
  441.                 if (++PRIVATE.counter < PRIVATE.speed)
  442.                         {
  443.                                         /* continue_notes */
  444.                                 for (track = 0; track < NUMBER_TRACKS; track++)
  445.                                         (*PRIVATE.track[track]->pursue)(&play->private,
  446.                                                         PRIVATE.track[track]);
  447.                         }
  448.                 else
  449.                         {
  450.                                 if (PRIVATE.has_ended)
  451.                                         {
  452.                                                 send(play, ON_END);
  453.                                                 PRIVATE.has_ended = FALSE;
  454.                                                 if (PUBLIC.oneshot)
  455.                                                         {
  456.                                                                 PUBLIC.command = STOP;
  457.                                                                 PUBLIC.oneshot = FALSE;
  458.                                                         }
  459.                                         }
  460.                                 if (PUBLIC.command)
  461.                                         {
  462.                                                 switch(PUBLIC.command)
  463.                                                         {
  464.                                                         case STOP:
  465.                                                                 PRIVATE.state = wait_play;
  466.                                                                 reset_player(play);
  467.                                                                 break;
  468.                                                         case NEWPOS:
  469.                                                                 PRIVATE.pattern = PUBLIC.pattern;
  470.                                                                 PRIVATE.position = PUBLIC.position;
  471.                                                                 reset_player(play);
  472.                                                                 clear_mask(&play->private);
  473.                                                                 break;
  474.                                                         default:
  475.                                                                 break;
  476.                                                         }
  477.                                                 PUBLIC.command = NONE;
  478.                                                 send(play, ON_COMMAND);
  479.                                                 return;
  480.                                         }
  481.                                 PRIVATE.block = PUBLIC.info->pblocks[PRIVATE.pattern];
  482.                                 PRIVATE.counter = 0;
  483.                                 clear_mask(&play->private);
  484.                                 play_notes(play);
  485.                         }
  486.         }
  487.  
  488. UWORD compute_period(struct priv_play *private, struct automaton *cst)
  489.         {
  490.                 if (cst->note > FINE_PERIOD)
  491.                         return private->period_table[NUMBER_TUNING - 1]
  492.                                 [cst->note - FINE_PERIOD];
  493.                 else
  494.                         {
  495.                                 return cst->p_table[cst->note];
  496.                         }
  497.         }
  498.  
  499.  
  500. void play_notes(struct play *play)
  501.         {
  502.         struct automaton *cst;
  503.         int track;
  504.         struct priv_play *private;
  505.                 private = &play->private;
  506.                 private->fastskip = -1;
  507.                 private->skip = -1;
  508.                 private->newspeed = -1;
  509.                 for (track = 0; track < NUMBER_TRACKS; track++)
  510.                         {
  511.                                 cst = private->track[track];
  512.                                 private->e = &private->block->e[track][PRIVATE.position];
  513.                                         /* We DO reload the volume each time we change the sample */
  514.                                 if (private->e->sample_number != 0)
  515.                                         {
  516.                                                 cst->instr = PUBLIC.sample[private->e->sample_number];
  517.                                                 cst->volume = cst->instr->volume;
  518.                                                 cst->p_table = private->period_table[cst->instr->finetune]
  519.                                                                 +PUBLIC.transpose;
  520.                                                 if (cst->instr->finetune)
  521.                                                         send(play, ON_BLIP);
  522.                                                 new_volume(private, cst);
  523.                                         }
  524.                                         /* default next command, unless
  525.                                          * there is something more interesting to do
  526.                                          */
  527.                                 cst->pursue = do_nothing;
  528.                                         /* there is a new note unless we don't have any period,
  529.                                          * or this is the SPECIAL PORTAMENTO command
  530.                                          */
  531.                                 if (cst->newnote = (private->e->note != NO_NOTE &&
  532.                                         private->setup[private->e->effect] != setup_portamento))
  533.                                         {
  534.                                                 cst->note = private->e->note;
  535.                                                 cst->period = compute_period(private, cst);
  536.                                                 set_note(private, cst->instr, cst->channel,
  537.                                                         cst->period);
  538.                                                 cst->offset = 0;
  539.                                                 private->replay = TRUE;
  540.                                         }
  541.                                 (*private->setup[private->e->effect])(private, cst);
  542.                         }
  543.                 if (private->newspeed != -1)
  544.                         change_speed(play);
  545.                 if (private->skip!=-1)
  546.                         {
  547.                                 private->position = private->skip;
  548.                                 private->pattern++;
  549.                                 if (private->pattern >= PUBLIC.info->length)
  550.                                         {
  551.                                                 private->pattern = 0;
  552.                                                 ended_play(play);
  553.                                         }
  554.                                 send(play, ON_PATTERN);
  555.                         }
  556.                 else
  557.                         {
  558.                                 if (private->fastskip != -1)
  559.                                         {
  560.                                                 private->position = 0;
  561.                                                 if (private->fastskip < private->pattern)
  562.                                                         ended_play(play);
  563.                                                 private->pattern = private->fastskip;
  564.                                                 send(play, ON_PATTERN);
  565.                                         }
  566.                                 else
  567.                                         advance_position(play);
  568.                         }
  569.                 PUBLIC.pattern = private->pattern;
  570.                 PUBLIC.position = private->position;
  571.         }
  572.  
  573. #define STD 0
  574. #define OLD 1
  575. #define NEW 2
  576.  
  577. void change_speed(struct play *play)
  578.         {
  579.                 if (PRIVATE.newspeed == 0)
  580.                         {
  581.                                 switch(PUBLIC.mode)
  582.                                         {
  583.                                         case NEW:
  584.                                                 PRIVATE.speed = 6;
  585.                                                 PRIVATE.finespeed = 100;
  586.                                                 rebuild_timers(play);
  587.                                                 PRIVATE.fastskip = 0;
  588.                                                 break;
  589.                                         case STD:
  590.                                                 ended_play(play);
  591.                                                 break;
  592.                                         case OLD:
  593.                                                 break;
  594.                                         }
  595.                         }
  596.                 else
  597.                         {
  598.                                 if (PRIVATE.newspeed >= 32 && PUBLIC.mode != OLD)
  599.                                         {
  600.                                                 PRIVATE.finespeed = PRIVATE.newspeed-31;
  601.                                                 if (PUBLIC.mode == STD)
  602.                                                         PRIVATE.speed = 6;
  603.                                                 rebuild_timers(play);
  604.                                         }
  605.                                 else
  606.                                         {
  607.                                                 PRIVATE.speed = PRIVATE.newspeed;
  608.                                                 if (PRIVATE.finespeed != 100 && PUBLIC.mode != NEW)
  609.                                                         {
  610.                                                                 PRIVATE.finespeed = 100;
  611.                                                                 rebuild_timers(play);
  612.                                                         }
  613.                                         }
  614.                         }
  615.                 send_out(play);
  616.                 send(play, ON_SPEED_CHANGE);
  617.         }
  618.  
  619. void send(struct play *play, ULONG event)
  620.         {
  621.                 if (PUBLIC.on_signal & event && PUBLIC.task && PUBLIC.signal != 0)
  622.                         {
  623.                                 Signal(PUBLIC.task, PUBLIC.signal);
  624.                         }
  625.                 PUBLIC.signaled |= event;
  626.         }
  627.  
  628. void advance_position(struct play *play)
  629.         {
  630.                 PRIVATE.position++;
  631.                 if (PRIVATE.position < BLOCK_LENGTH)
  632.                         return;
  633.                 PRIVATE.position = 0;
  634.                 PRIVATE.pattern++;
  635.                 send(play, ON_PATTERN);
  636.                 if (PRIVATE.pattern >= PUBLIC.info->length)
  637.                         {
  638.                                 PRIVATE.pattern = 0;
  639.                                 ended_play(play);
  640.                         }
  641.         }
  642.