

/*
#    Sfront, a SAOL to C translator    
#    This file: Launches notes for control driver
#    Copyright (C) 1999  Regents of the University of California
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License (Version 2) as
#    published by the Free Software Foundation.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#    Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu
*/

#include "tree.h"


/*********************************************************/
/*          core routine for control parsing             */
/*********************************************************/

void makecontrolsys(void)

{

  int lc = 0;

  if (cmidi || session)
    {
      z[lc++]="unsigned char  ndata, vdata;";
      z[lc++]="unsigned short ec;";
    }
  if (csasl)
    {
      z[lc++]="unsigned char priority;";
      z[lc++]="unsigned short id;";
      z[lc++]="unsigned short label;";
      z[lc++]="unsigned int pnum;";
      z[lc++]="float * p;";
    }
  z[lc++]="float oldtime;";
  z[lc++]="struct instr_line * oldest;";
  z[lc++]="int ne, newevents, netevents;";
  z[lc++]="unsigned char cmd;";
  z[lc++]="float fval;\n";

  if (cin)
    z[lc++]="newevents = csys_newdata();";

  if (session && cmidi)
    {
      z[lc++]="netevents = nsys_newdata();";
      z[lc++]="if (netevents || (newevents & CSYS_MIDIEVENTS))";
      z[lc++]="do";
      z[lc++]=" {";
      z[lc++]="  if (netevents)";
      z[lc++]="   {";
      z[lc++]="     netevents = nsys_midievent(&cmd,&ndata,&vdata,&ec);";
      z[lc++]="     ne = netevents ? CSYS_MIDIEVENTS : ";
      z[lc++]="          (newevents & CSYS_MIDIEVENTS); ";
      z[lc++]="   }";
      z[lc++]="  else";
      z[lc++]="   {";
      z[lc++]="     ne = csys_midievent(&cmd,&ndata,&vdata,&ec,&fval);";
      z[lc++]="     if (cmd >= CSYS_MIDI_TSTART)";
      z[lc++]="       nsys_midisend(cmd, ndata, vdata, ec);";
      z[lc++]="   }";
    }
  else
    {
      if (cmidi)
	{
	  z[lc++]="if (newevents & CSYS_MIDIEVENTS)";
	  z[lc++]="do";
	  z[lc++]=" {";
	  z[lc++]="  ne = csys_midievent(&cmd,&ndata,&vdata,&ec,&fval);";
	}
      if (session)
	{
	  z[lc++]="netevents = nsys_newdata();";
	  z[lc++]="if (netevents)";
	  z[lc++]="do";
	  z[lc++]=" {";
	  z[lc++]="  ne = nsys_midievent(&cmd,&ndata,&vdata,&ec);";
	}
    }

  if (cmidi || session)
    {
      z[lc++]="  if ((ec < CSYS_MAXEXTCHAN)||((cmd&0xF0)==CSYS_MIDI_SPECIAL))";
      z[lc++]="  switch(cmd&0xF0) {";
      z[lc++]="   case CSYS_MIDI_NOTEON:";
      z[lc++]="   if ((cme_first[ec])==NULL)";
      z[lc++]="     break;";
      z[lc++]="   if (vdata != 0)";
      z[lc++]="    {";
      z[lc++]="     if (*cme_next[ec] == NULL)";
      z[lc++]="       *cme_next[ec] = *cme_first[ec] = *cme_last[ec];";
      z[lc++]="     else";
      z[lc++]="       {";
      z[lc++]="         oldest = NULL;";
      z[lc++]="         oldtime = MAXENDTIME;";
      z[lc++]="         *cme_next[ec] = *cme_first[ec];";
      z[lc++]="         while ((*cme_next[ec]) < (*cme_end[ec]))";
      z[lc++]="   	 {";
      z[lc++]="   	   if (((*cme_next[ec])->noteon == NOTUSEDYET)||";
      z[lc++]="   	       ((*cme_next[ec])->noteon == ALLDONE))";
      z[lc++]="   	     break;";
      z[lc++]="            if ((*cme_next[ec])->starttime < oldtime)";
      z[lc++]="             {";
      z[lc++]="               oldest =  (*cme_next[ec]);";
      z[lc++]="               oldtime = (*cme_next[ec])->starttime;";
      z[lc++]="             }";
      z[lc++]="   	   (*cme_next[ec])++;";
      z[lc++]="   	 }";
      z[lc++]="        if ((*cme_next[ec]) == (*cme_end[ec]))";
      z[lc++]="         {";
      z[lc++]="           *cme_next[ec] = oldest;"; 
      z[lc++]="           oldest->nstate->iline = NULL;";
      z[lc++]="         }";
      z[lc++]="         if ((*cme_next[ec]) > (*cme_last[ec]))";
      z[lc++]="   	    *cme_last[ec] = *cme_next[ec];";
      z[lc++]="       }";
      z[lc++]="     (*cme_next[ec])->starttime = scorebeats - scoremult;"; 
      z[lc++]="     (*cme_next[ec])->endtime = MAXENDTIME;";
      z[lc++]="     (*cme_next[ec])->abstime = 0.0F;"; 
      z[lc++]="     (*cme_next[ec])->time = 0.0F;"; 
      z[lc++]="     (*cme_next[ec])->sdur = -1.0F;";
      z[lc++]="     (*cme_next[ec])->released = 0;";
      z[lc++]="     (*cme_next[ec])->turnoff = 0;";
      z[lc++]="     (*cme_next[ec])->noteon = TOBEPLAYED;";
      z[lc++]="     (*cme_next[ec])->numchan = ec + CSYS_EXTCHANSTART;";
      z[lc++]="     (*cme_next[ec])->preset  = cme_preset[ec];"; 
      z[lc++]="     (*cme_next[ec])->notenum  = ndata;"; 
      z[lc++]="     (*cme_next[ec])->p[0] = ndata ;"; 
      z[lc++]="     (*cme_next[ec])->p[1] = vdata ;"; 
      z[lc++]="     break;";
      z[lc++]="    }";
      z[lc++]="   case CSYS_MIDI_NOTEOFF:"; 
      z[lc++]="    if ((cme_first[ec])==NULL)";
      z[lc++]="      break;";
      z[lc++]="    oldest = NULL;";
      z[lc++]="    oldtime = MAXENDTIME;";
      z[lc++]="    for (sysidx=*cme_first[ec];sysidx<=*cme_last[ec];sysidx++)";
      z[lc++]="      if ((sysidx->notenum == ndata) && ";
      z[lc++]="          (sysidx->numchan == ec + CSYS_EXTCHANSTART) &&";
      z[lc++]="          (sysidx->starttime < oldtime))";
      z[lc++]="       {";
      z[lc++]="         oldest = sysidx;";
      z[lc++]="         oldtime = sysidx->starttime;";
      z[lc++]="       }";
      z[lc++]="    if (oldest)"; 
      z[lc++]="       {";
      z[lc++]="          oldest->endtime = scorebeats - scoremult;"; 
      z[lc++]="          oldest->notenum += 256;"; 
      z[lc++]="       }";
      z[lc++]="    break;";
      z[lc++]="   case CSYS_MIDI_PTOUCH:";
      z[lc++]="    NG(CSYS_FRAMELEN*(ec+CSYS_EXTCHANSTART)+CSYS_TOUCHPOS+ndata)=vdata;";
      z[lc++]="   break;";
      z[lc++]="   case CSYS_MIDI_CTOUCH:";
      z[lc++]="    NG(CSYS_FRAMELEN*(ec+CSYS_EXTCHANSTART)+CSYS_CHTOUCHPOS)=vdata;";
      z[lc++]="   break;";
      z[lc++]="   case CSYS_MIDI_WHEEL:";
      z[lc++]="    NG(CSYS_FRAMELEN*(ec + CSYS_EXTCHANSTART) + CSYS_BENDPOS) = ";
      z[lc++]="                                            128*vdata + ndata;";
      z[lc++]="   break;";
      z[lc++]="   case CSYS_MIDI_CC:";
      z[lc++]="    NG(CSYS_FRAMELEN*(ec+CSYS_EXTCHANSTART)+CSYS_CCPOS+ndata)=vdata;";
      z[lc++]="    switch(ndata) {";
      z[lc++]="     case CSYS_MIDI_CC_BANKSELECT_LSB:";
      z[lc++]="      csys_banklsb = vdata;";
      z[lc++]="      csys_bank = csys_banklsb + 128*csys_bankmsb;";
      z[lc++]="      break;";
      z[lc++]="     case CSYS_MIDI_CC_BANKSELECT_MSB:";
      z[lc++]="      csys_bankmsb = vdata;";
      z[lc++]="      csys_bank = csys_banklsb + 128*csys_bankmsb;";
      z[lc++]="      break;";
      z[lc++]="     case CSYS_MIDI_CC_ALLSOUNDOFF:";

      /* Uncomment following line to make an ALLSOUNDOFF on any channel */
      /*                 kill all instrs on all channels.               */
      /*
      z[lc++]="      for (ec = 0; ec < CSYS_MAXEXTCHAN; ec++)";
      */

      z[lc++]="       if ((cme_first[ec]))";
      z[lc++]="        for (sysidx=*cme_first[ec];sysidx<=*cme_last[ec];sysidx++)";
      z[lc++]="         {";
      z[lc++]="            sysidx->noteon = ALLDONE;";
      z[lc++]="            sysidx->nstate->iline = NULL;";
      z[lc++]="         }";
      z[lc++]="      break;";
      z[lc++]="     case CSYS_MIDI_CC_ALLNOTESOFF:";

      /* Uncomment following line to make an ALLNOTESOFF on any channel */
      /*                 kill all instrs on all channels.               */
      /*
      z[lc++]="      for (ec = 0; ec < CSYS_MAXEXTCHAN; ec++)";
      */

      z[lc++]="       if ((cme_first[ec]))";
      z[lc++]="        for (sysidx=*cme_first[ec];sysidx<=*cme_last[ec];sysidx++)";
      z[lc++]="         {";
      z[lc++]="            sysidx->endtime =  scorebeats - scoremult;";
      z[lc++]="            sysidx->notenum += 256;";
      z[lc++]="         }";
      z[lc++]="      break;";
      z[lc++]="     case CSYS_MIDI_CC_RESETALLCONTROL:";
      z[lc++]="      for (i = 0; i < CSYS_MIDI_CC_ALLSOUNDOFF; i++)";
      z[lc++]="        NG(CSYS_FRAMELEN*(ec+CSYS_EXTCHANSTART)+CSYS_CCPOS+i)=0.0F;";
      z[lc++]="      NG(CSYS_FRAMELEN*(ec + CSYS_EXTCHANSTART)+";
      z[lc++]="         CSYS_MIDI_CC_CHANVOLUME_MSB) = 100.0F;";
      z[lc++]="      NG(CSYS_FRAMELEN*(ec + CSYS_EXTCHANSTART)+";
      z[lc++]="         CSYS_MIDI_CC_PAN_MSB) = 64.0F;";
      z[lc++]="      NG(CSYS_FRAMELEN*(ec + CSYS_EXTCHANSTART)+";
      z[lc++]="         CSYS_MIDI_CC_EXPRESSION_MSB) = 127.0F;";
      z[lc++]="      csys_bank = csys_banklsb = csys_bankmsb = 0;";
      z[lc++]="      break;";
      z[lc++]="     default:";
      z[lc++]="      break;";
      z[lc++]="     }";
      z[lc++]="   break;";
      z[lc++]="   case CSYS_MIDI_PROGRAM:";
      z[lc++]="    if ((CSYS_NULLPROGRAM == 0) && (ndata >= CSYS_MAXPRESETS))";
      z[lc++]="      break;";
      z[lc++]="    if ((cme_first[ec]))";
      z[lc++]="     for (sysidx=*cme_first[ec];sysidx<=*cme_last[ec];sysidx++)";
      z[lc++]="       if ((sysidx->numchan == ec + CSYS_EXTCHANSTART) &&";
      z[lc++]="          (sysidx->noteon <= PLAYING))";
      z[lc++]="        {";
      z[lc++]="           sysidx->endtime = scorebeats - scoremult;"; 
      z[lc++]="           sysidx->notenum += 256;"; 
      z[lc++]="        }";
      z[lc++]="    if ((CSYS_NULLPROGRAM == 0) || (ndata < CSYS_MAXPRESETS))";
      z[lc++]="      {";
      z[lc++]="       cme_first[ec] = cmp_first[ndata];";
      z[lc++]="       cme_last[ec] = cmp_last[ndata];";
      z[lc++]="       cme_end[ec] = cmp_end[ndata];";
      z[lc++]="       cme_next[ec] = cmp_next[ndata];";
      z[lc++]="      }";
      z[lc++]="    else";
      z[lc++]="      cme_first[ec] = cme_last[ec] = cme_end[ec] = cme_next[ec] = NULL;";
      z[lc++]="   break;";
      z[lc++]="   case CSYS_MIDI_SPECIAL:";
      z[lc++]="    if (cmd == CSYS_MIDI_NEWTEMPO)";
      z[lc++]="     {";
      z[lc++]="      if (fval <= 0.0F)";
      z[lc++]="        break;";
      z[lc++]="      kbase = kcycleidx;";
      z[lc++]="      scorebase = scorebeats;";
      z[lc++]="      tempo = fval;";
      z[lc++]="      scoremult = 1.666667e-02F*KTIME*tempo;";
      z[lc++]="      endkcycle = kbase + (int)(KRATE*(endtime-scorebase)*";
      z[lc++]="                  (60.0F/tempo));";
      z[lc++]="      break;";
      z[lc++]="     }";
      z[lc++]="    if (cmd == CSYS_MIDI_ENDTIME)";
      z[lc++]="     {";
      z[lc++]="      if (fval <= scorebeats)";
      z[lc++]="      {";
      z[lc++]="        endtime = scorebeats;";
      z[lc++]="        endkcycle = kcycleidx;";
      z[lc++]="      }";
      z[lc++]="      else";
      z[lc++]="      {";
      z[lc++]="        endtime = fval;";
      z[lc++]="        endkcycle = kbase + (int)(KRATE*(endtime-scorebase)*";
      z[lc++]="                    (60.0F/tempo));";
      z[lc++]="      }";
      z[lc++]="      break;";
      z[lc++]="     }";
      z[lc++]="    if (cmd == CSYS_MIDI_POWERUP)";
      z[lc++]="     {";
      z[lc++]="      ec &= 0xFFF0;";
      z[lc++]="      memset(&(NG(CSYS_FRAMELEN*(ec+CSYS_EXTCHANSTART))), 0,";
      z[lc++]="             sizeof(float)*CSYS_FRAMELEN*16);";
      z[lc++]="      for (i = 0; i < 16; i++)";
      z[lc++]="      {";
      z[lc++]="        NG(CSYS_FRAMELEN*(ec + CSYS_EXTCHANSTART)+";
      z[lc++]="           CSYS_MIDI_CC_CHANVOLUME_MSB) = 100.0F;";
      z[lc++]="        NG(CSYS_FRAMELEN*(ec + CSYS_EXTCHANSTART)+";
      z[lc++]="           CSYS_MIDI_CC_PAN_MSB) = 64.0F;";
      z[lc++]="        NG(CSYS_FRAMELEN*(ec + CSYS_EXTCHANSTART)+";
      z[lc++]="           CSYS_MIDI_CC_EXPRESSION_MSB) = 127.0F;";
      z[lc++]="        NG(CSYS_FRAMELEN*(ec + CSYS_EXTCHANSTART)+";
      z[lc++]="           CSYS_BENDPOS) = 8192.0F;";
      z[lc++]="        NG(CSYS_FRAMELEN*(ec + CSYS_EXTCHANSTART)+";
      z[lc++]="           CSYS_EXTPOS) = (float)ec;";
      z[lc++]="        if ((cme_first[ec]))";
      z[lc++]="         for (sysidx=*cme_first[ec];sysidx<=*cme_last[ec];sysidx++)";
      z[lc++]="          if (sysidx->numchan == (ec + CSYS_EXTCHANSTART))";
      z[lc++]="            {";
      z[lc++]="               sysidx->endtime =  scorebeats - scoremult;";
      z[lc++]="               sysidx->notenum += 256;";
      z[lc++]="            }";
      z[lc++]="        cme_first[ec] = cmp_first[i % CSYS_MAXPRESETS];";
      z[lc++]="        cme_last[ec] = cmp_last[i % CSYS_MAXPRESETS];";
      z[lc++]="        cme_end[ec] = cmp_end[i % CSYS_MAXPRESETS];";
      z[lc++]="        cme_next[ec] = cmp_next[i % CSYS_MAXPRESETS];";
      z[lc++]="        ec++;";
      z[lc++]="      }";
      z[lc++]="      break;";
      z[lc++]="     }";
      z[lc++]="   break;";
      z[lc++]="   default:";
      z[lc++]="   break;";
      z[lc++]="  }";
      z[lc++]=" } while (ne != CSYS_DONE);";

      if (session)
	z[lc++]=" nsys_endcycle();";
    }

  if (csasl)
    {
      z[lc++]="if (newevents & CSYS_SASLEVENTS)";
      z[lc++]="do";
      z[lc++]="{";
      z[lc++]="  ne = csys_saslevent(&cmd,&priority,&id,&label,&fval,&pnum,&p);";
      z[lc++]="  switch(cmd) {";
      z[lc++]="   case CSYS_SASL_ENDTIME:";
      z[lc++]="    if (fval <= scorebeats)";
      z[lc++]="    {";
      z[lc++]="      endtime = scorebeats;";
      z[lc++]="      endkcycle = kcycleidx;";
      z[lc++]="    }";
      z[lc++]="    else";
      z[lc++]="    {";
      z[lc++]="      endtime = fval;";
      z[lc++]="      endkcycle = kbase + (int)(KRATE*(endtime-scorebase)*";
      z[lc++]="                  (60.0F/tempo));";
      z[lc++]="    }";
      z[lc++]="    break;";
      z[lc++]="   case CSYS_SASL_TEMPO:";
      z[lc++]="    if (fval <= 0.0F)";
      z[lc++]="      break;";
      z[lc++]="    kbase = kcycleidx;";
      z[lc++]="    scorebase = scorebeats;";
      z[lc++]="    tempo = fval;";
      z[lc++]="    scoremult = 1.666667e-02F*KTIME*tempo;";
      z[lc++]="    endkcycle = kbase + (int)(KRATE*(endtime-scorebase)*";
      z[lc++]="                (60.0F/tempo));";
      z[lc++]="    break;";
      z[lc++]="   case CSYS_SASL_CONTROL:";
      z[lc++]="    if (id > CSYS_SASL_NOINSTR)";
      z[lc++]="      break;";
      z[lc++]="    if (maxsc == CSYS_SASL_MAXCONTROL)";
      z[lc++]="      break;";
      z[lc++]="    saslcontrol[maxsc].id = id;";
      z[lc++]="    saslcontrol[maxsc].label = label;";
      z[lc++]="    saslcontrol[maxsc].fptr = pnum;";
      z[lc++]="    saslcontrol[maxsc++].fval = fval;";
      z[lc++]="    break;";
      z[lc++]="   case CSYS_SASL_TABLE:";
      z[lc++]="    if (id > GBL_ENDTBL)";
      z[lc++]="      break;";
      z[lc++]="    sasltable[maxtb].tgen = label;";
      z[lc++]="    sasltable[maxtb].pnum = pnum;";
      z[lc++]="    sasltable[maxtb].p = NULL;";
      z[lc++]="    if (pnum)";
      z[lc++]="     {"; /* calloc uses pnum+1 for tgen_sample */
      z[lc++]="       sasltable[maxtb].p = (float *)"; 
      z[lc++]="                              calloc(pnum+1, sizeof(float));";
      z[lc++]="       while ((pnum--) > 0)";
      z[lc++]="         sasltable[maxtb].p[pnum] = p[pnum];";
      z[lc++]="     }";
      z[lc++]="    sasltable[maxtb++].index = id;";
      z[lc++]="    break;";
      z[lc++]="   case CSYS_SASL_INSTR:";
      z[lc++]="    if (id >= CSYS_MAXSASLINSTR)";
      z[lc++]="      break;";
      z[lc++]="    if (*cs_next[id] == NULL)";
      z[lc++]="      *cs_next[id] = *cs_first[id] = *cs_last[id];";
      z[lc++]="    else";
      z[lc++]="      {";
      z[lc++]="        oldest = NULL;";
      z[lc++]="        oldtime = MAXENDTIME;";
      z[lc++]="        *cs_next[id] = *cs_first[id];";
      z[lc++]="        while ((*cs_next[id]) < (*cs_end[id]))";
      z[lc++]="         {";
      z[lc++]="           if (((*cs_next[id])->noteon == NOTUSEDYET)||";
      z[lc++]="               ((*cs_next[id])->noteon == ALLDONE))";
      z[lc++]="             break;";
      z[lc++]="           if ((*cs_next[id])->starttime < oldtime)";
      z[lc++]="            {";
      z[lc++]="              oldest = (*cs_next[id]);";
      z[lc++]="              oldtime = (*cs_next[id])->starttime;";
      z[lc++]="            }";
      z[lc++]="           (*cs_next[id])++;";
      z[lc++]="         }";
      z[lc++]="        if ((*cs_next[id]) == (*cs_end[id]))";
      z[lc++]="         {";
      z[lc++]="           *cs_next[id] = oldest;"; 
      z[lc++]="           oldest->nstate->iline = NULL;";
      z[lc++]="         }";
      z[lc++]="        if ((*cs_next[id]) > (*cs_last[id]))";
      z[lc++]="         *cs_last[id] = *cs_next[id];";
      z[lc++]="      }";
      z[lc++]="    (*cs_next[id])->starttime = scorebeats - scoremult;"; 
      z[lc++]="    (*cs_next[id])->endtime = MAXENDTIME;";
      z[lc++]="    (*cs_next[id])->abstime = 0.0F;"; 
      z[lc++]="    (*cs_next[id])->time = 0.0F;"; 
      z[lc++]="    (*cs_next[id])->sdur = fval;";
      z[lc++]="    (*cs_next[id])->released = 0;";
      z[lc++]="    (*cs_next[id])->turnoff = 0;";
      z[lc++]="    (*cs_next[id])->noteon = TOBEPLAYED;";
      z[lc++]="    (*cs_next[id])->numchan = 0;";
      z[lc++]="    (*cs_next[id])->notenum = 0;";
      z[lc++]="    (*cs_next[id])->preset  = 0;"; 
      z[lc++]="    (*cs_next[id])->label  = label;";
      z[lc++]="    pnum = (pnum > MAXPFIELDS) ? MAXPFIELDS : pnum;";
      z[lc++]="    while ((pnum--) > 0)";
      z[lc++]="     (*cs_next[id])->p[pnum] = p[pnum];"; 
      z[lc++]="    break;";
      z[lc++]="   case CSYS_SASL_NOOP:";
      z[lc++]="    break;";
      z[lc++]="   default:";
      z[lc++]="    break;";
      z[lc++]="}";
      z[lc++]=" } while (ne != CSYS_DONE);";
    }
  printraw(lc);
  fprintf(outfile,"\n");

}

/*********************************************************/
/*          SASL control command for control driver      */
/*********************************************************/


void makesaslcontrolsys(void)

{

  int lc = 0;

  z[lc++]="while ((maxsc--) > 0)";
  z[lc++]=" {";
  z[lc++]="   if (saslcontrol[maxsc].id == CSYS_SASL_NOINSTR)";
  z[lc++]="     {";
  z[lc++]="       if (saslcontrol[maxsc].fptr < GBL_ENDVAR)";
  z[lc++]="        NG(saslcontrol[maxsc].fptr) = saslcontrol[maxsc].fval;";
  z[lc++]="      }";
  z[lc++]="    else";
  z[lc++]="     {";
  z[lc++]="       for (sysidx= *cs_first[saslcontrol[maxsc].id];";
  z[lc++]="            sysidx<= *cs_last[saslcontrol[maxsc].id];sysidx++)";
  z[lc++]="         if ((sysidx->label == saslcontrol[maxsc].label)&&";
  z[lc++]="             (sysidx->noteon == PLAYING))";
  z[lc++]="           sysidx->nstate->v[saslcontrol[maxsc].fptr].f";
  z[lc++]="                                = saslcontrol[maxsc].fval;";

  /* extra loops needed for other sources of labelled instrs */

  if (allsasl->numlabels && allsasl->instrroot)
    {
      z[lc++]="";
      z[lc++]="    if ((saslcontrol[maxsc].label < CSYS_LABELNUM) &&";
      z[lc++]="         css_first[saslcontrol[maxsc].id])";
      z[lc++]="      for (sysidx= *css_first[saslcontrol[maxsc].id];";
      z[lc++]="           sysidx<= *css_last[saslcontrol[maxsc].id];sysidx++)";
      z[lc++]="        if ((sysidx->label == saslcontrol[maxsc].label)&&";
      z[lc++]="            (sysidx->noteon == PLAYING))";
      z[lc++]="          sysidx->nstate->v[saslcontrol[maxsc].fptr].f";
      z[lc++]="                             = saslcontrol[maxsc].fval;";
    }


  if (abssasl->numlabels && abssasl->instrroot)
    {
      z[lc++]="";
      z[lc++]="    if ((saslcontrol[maxsc].label < CSYS_LABELNUM) &&";
      z[lc++]="         csa_first[saslcontrol[maxsc].id])";
      z[lc++]="      for (sysidx= *csa_first[saslcontrol[maxsc].id];";
      z[lc++]="           sysidx<= *csa_last[saslcontrol[maxsc].id];sysidx++)";
      z[lc++]="        if ((sysidx->label == saslcontrol[maxsc].label)&&";
      z[lc++]="            (sysidx->noteon == PLAYING))";
      z[lc++]="          sysidx->nstate->v[saslcontrol[maxsc].fptr].f";
      z[lc++]="                             = saslcontrol[maxsc].fval;";

    }


  z[lc++]="     }";
  z[lc++]=" }";
  z[lc++]="maxsc = 0;";

  printraw(lc);
  fprintf(outfile,"\n");

}


/*********************************************************/
/*         cross-control command for control driver      */
/*********************************************************/

void makesaslcrosscontrol(char * prefix)

{

  fprintf(outfile,"         for (i = 0; i < CSYS_MAXSASLINSTR; i++)\n");
  fprintf(outfile,"           for (sysidx= *cs_first[i];sysidx<= *cs_last[i];sysidx++)\n");
  fprintf(outfile,"             if ((sysidx->label == %scontrolidx->label)&&\n", prefix);
  fprintf(outfile,"                 (sysidx->noteon == PLAYING))\n");
  fprintf(outfile,"               sysidx->nstate->v[%scontrolidx->imptr].f\n",prefix);
  fprintf(outfile,"                                     = %scontrolidx->imval;\n",prefix);

}

/*********************************************************/
/*          SASL table command for control driver        */
/*********************************************************/


void makesasltablesys(void)

{

  int lc = 0;

  z[lc++]="while ((maxtb--) > 0)";
  z[lc++]=" {";
  z[lc++]="   switch (sasltable[maxtb].tgen) {";                 
  z[lc++]="    case CSYS_SASL_TGEN_SAMPLE:";
  z[lc++]="     tgen_sample(&(gtables[sasltable[maxtb].index]),";
  z[lc++]="                 sasltable[maxtb].pnum, sasltable[maxtb].p);";
  z[lc++]="     break;";
  z[lc++]="    case CSYS_SASL_TGEN_DATA:";
  z[lc++]="     tgen_data(&(gtables[sasltable[maxtb].index]),";
  z[lc++]="                 sasltable[maxtb].pnum, sasltable[maxtb].p);";
  z[lc++]="     break;";
  z[lc++]="    case CSYS_SASL_TGEN_RANDOM:";
  z[lc++]="     tgen_random(&(gtables[sasltable[maxtb].index]),";
  z[lc++]="                 sasltable[maxtb].pnum, sasltable[maxtb].p);";
  z[lc++]="     break;";
  z[lc++]="    case CSYS_SASL_TGEN_STEP:";
  z[lc++]="     tgen_step(&(gtables[sasltable[maxtb].index]),";
  z[lc++]="                 sasltable[maxtb].pnum, sasltable[maxtb].p);";
  z[lc++]="     break;";
  z[lc++]="    case CSYS_SASL_TGEN_LINESEG:";
  z[lc++]="     tgen_lineseg(&(gtables[sasltable[maxtb].index]),";
  z[lc++]="                 sasltable[maxtb].pnum, sasltable[maxtb].p);";
  z[lc++]="     break;";
  z[lc++]="    case CSYS_SASL_TGEN_EXPSEG:";
  z[lc++]="     tgen_expseg(&(gtables[sasltable[maxtb].index]),";
  z[lc++]="                 sasltable[maxtb].pnum, sasltable[maxtb].p);";
  z[lc++]="     break;";
  z[lc++]="    case CSYS_SASL_TGEN_CUBICSEG:";
  z[lc++]="     tgen_cubicseg(&(gtables[sasltable[maxtb].index]),";
  z[lc++]="                 sasltable[maxtb].pnum, sasltable[maxtb].p);";
  z[lc++]="     break;";
  z[lc++]="    case CSYS_SASL_TGEN_POLYNOMIAL:";
  z[lc++]="     tgen_polynomial(&(gtables[sasltable[maxtb].index]),";
  z[lc++]="                 sasltable[maxtb].pnum, sasltable[maxtb].p);";
  z[lc++]="     break;";
  z[lc++]="    case CSYS_SASL_TGEN_SPLINE:"; 
  z[lc++]="     tgen_spline(&(gtables[sasltable[maxtb].index]),";
  z[lc++]="                 sasltable[maxtb].pnum, sasltable[maxtb].p);";
  z[lc++]="     break;";
  z[lc++]="    case CSYS_SASL_TGEN_WINDOW  :";   
  z[lc++]="     tgen_window(&(gtables[sasltable[maxtb].index]),";
  z[lc++]="                 sasltable[maxtb].pnum, sasltable[maxtb].p);";
  z[lc++]="     break;";
  z[lc++]="    case CSYS_SASL_TGEN_HARM :";  
  z[lc++]="     tgen_harm(&(gtables[sasltable[maxtb].index]),";
  z[lc++]="                 sasltable[maxtb].pnum, sasltable[maxtb].p);";
  z[lc++]="     break;";
  z[lc++]="    case CSYS_SASL_TGEN_HARM_PHASE:"; 
  z[lc++]="     tgen_harm_phase(&(gtables[sasltable[maxtb].index]),";
  z[lc++]="                 sasltable[maxtb].pnum, sasltable[maxtb].p);";
  z[lc++]="     break;";
  z[lc++]="    case CSYS_SASL_TGEN_PERIODIC:";
  z[lc++]="     tgen_periodic(&(gtables[sasltable[maxtb].index]),";
  z[lc++]="                 sasltable[maxtb].pnum, sasltable[maxtb].p);";
  z[lc++]="     break;";
  z[lc++]="    case CSYS_SASL_TGEN_BUZZ :"; 
  z[lc++]="     tgen_buzz(&(gtables[sasltable[maxtb].index]),";
  z[lc++]="                 sasltable[maxtb].pnum, sasltable[maxtb].p);";
  z[lc++]="     break;";
  z[lc++]="    case CSYS_SASL_TGEN_CONCAT:";
  z[lc++]="     tgen_concat_global(&(gtables[sasltable[maxtb].index]),";
  z[lc++]="                 sasltable[maxtb].pnum, sasltable[maxtb].p);";
  z[lc++]="     break;";
  z[lc++]="    case CSYS_SASL_TGEN_EMPTY :";
  z[lc++]="     tgen_empty(&(gtables[sasltable[maxtb].index]),";
  z[lc++]="                 sasltable[maxtb].pnum, sasltable[maxtb].p);";
  z[lc++]="     break;";
  z[lc++]="    case CSYS_SASL_TGEN_DESTROY:";
  z[lc++]="     tgen_destroy(&(gtables[sasltable[maxtb].index]),";
  z[lc++]="                 sasltable[maxtb].pnum, sasltable[maxtb].p);";
  z[lc++]="     break;";
  z[lc++]="     }";
  z[lc++]=" }";
  z[lc++]="maxtb = 0;";

  printraw(lc);
  fprintf(outfile,"\n");

}

