home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / far100.zip / TRAK.C < prev    next >
C/C++ Source or Header  |  1994-08-06  |  17KB  |  577 lines

  1. /* Farandole Composer v1.00 (c)'94 by Daniel Potter */
  2. /* This is the module used for playing/tracking songs. May you blow your nose
  3.    many times over it. This module has been changed slightly since release
  4.    but the changes are only cosmetic so don't worry about it. */
  5.  
  6. #define _PORT_DEFS
  7. #include "defaults.h"
  8. #include "dos.h"
  9. #include "far.h"
  10. #include "math.h"
  11. #include "kb.h"
  12. #include "gus.h"
  13.  
  14. volatile word OverFlow=0,OCount=0,PlayOrder=0;
  15.          int  mTempo[16];
  16. volatile long PitchWheel[16]={0},DestPitch[16]={0},Increment[16]={0},PresPitch[16]={0};
  17. volatile int  VolWheel[16]={0},DestVol[16]={0},VIncrement[16]={0},PresVol[16]={0};
  18. volatile long RetLeft[16]={0},RetSpc[16]={0},CurSpc[16]={0},RetSmp[16]={0},RetVol[16]={0xF};
  19. volatile int  OfftCnt[16]={0},RetCnt[16]={0};
  20. volatile int  VibOn[16]={0};
  21. volatile int  VibPtr[16]={0},VibInc[16]={0};
  22. volatile int  CurVols[16]={15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15};
  23.          int  SinTable[16][128]={0};
  24. volatile int  CurFreqs[16]={0};
  25. volatile int  VibAmp=4;
  26. volatile Flag near TempoType=1;
  27. volatile int  PlayTempo=4,TempoBend=0;
  28. volatile int  CurChSmp[16]={0};
  29. volatile int  Bars[16]={0};
  30. volatile byte GrabBuf[64]={0};
  31.  
  32. extern   Flag BarsOff;
  33.          word fs;
  34. extern word Freqs[];
  35. extern int fsize;
  36.  
  37. // This used to be a routine to do real volume bars. it was too slow.. have
  38. // at it.
  39. void GetBarData(int ch) {
  40.   int  q,s;
  41.   long ChPos;
  42.   int  div;
  43.  
  44. /*  ChPos=VoicePos(ch)-4;
  45.   U_DumpDRAMToMemory(GrabBuf,ChPos>>16,ChPos&0xFFFF,8);
  46.   for (q=0,div=0;q<8;q++) div+=GrabBuf[q];
  47.   Bars[ch]=(long)abs(div)*32/((long)128*8);
  48. //  Bars[ch]=(long)Bars[ch]*0xEFFF/VolTab[(CurVols[ch]*4)+VolWheel[ch]];
  49.   if (Bars[ch]<0) Bars[ch]=0;
  50.   if (Bars[ch]>31) Bars[ch]=31; */
  51.   Bars[ch]=0;
  52. }
  53.  
  54. void ChSpeed(dword divisor) {
  55.   byte om;
  56.  
  57.   om=inportb(0x21);
  58.   disable();
  59.   outp(0x43,0x34);
  60.   outp(0x40,divisor&0xFF);
  61.   outp(0x40,divisor>>8);
  62.   outp(0x43,0x90);
  63.   outp(0x61,inportb(0x61)|3);
  64.   outp(0x21,om);
  65.   enable();
  66. }
  67.  
  68. void UpdateTempo(int tps) {
  69.   dword eax,di,cx;
  70.  
  71.   switch(TempoType) {
  72.     case 0:
  73.       eax=(dword)((long)tps*32)>>2;
  74.       if (!eax) return;
  75.       eax=1197255/eax;
  76.       OCount=32; OverFlow=32;
  77.       break;
  78.     case 1:
  79.       if (!tps) return;
  80.       eax=1197255/tps;
  81.       cx=0; di=0;
  82.       while (eax>0xFFFF) {
  83.         eax>>=1;
  84.         di++; cx++;
  85.       }
  86.       if (cx>=2) di++;
  87.       di+=3;
  88.       OverFlow=di; OCount=di;
  89.       break;
  90.   }
  91.   ChSpeed(eax);
  92. }
  93.  
  94. void UdTempo() {
  95.   if (TempoType)
  96.     UpdateTempo(mTempo[PlayTempo]+TempoBend);
  97.   else
  98.     UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
  99.   return;
  100. }
  101.  
  102. void CalcTempo() {
  103.   word q;
  104.   double t,f=1,y,amp;
  105.  
  106.   mTempo[0]=256;
  107.   for (q=1;q<16;q++) mTempo[q]=128/q;
  108.  
  109.   for (amp=0;amp<16;amp++)
  110.     for (t=0;t<1;t+=(1.0/128)) {
  111.       y=sin(2*3.1415*f*t)*amp;
  112.       SinTable[amp][t*128]=y;
  113.     }
  114. }
  115.  
  116. #pragma option -r-
  117. void UpdateTops();
  118. void interrupt (*OldInt8)();
  119. void interrupt Int8() {
  120.   word c,ov,m,q;
  121.   long fp,sp,t,ch;
  122.   byte fekt;
  123.  
  124. //  outportb(0x20,0x20);
  125.   if (!TempoType) {
  126.     if ((OCount%8)) goto oo;
  127.   }
  128.   for (ch=0;ch<16;ch++) {
  129.     if (!(OCount%8)) {
  130. /*      if (Bars[ch]<(PlayTempo)) Bars[ch]=0;
  131.       if (Bars[ch]) Bars[ch]-=PlayTempo; */
  132.       GetBarData(ch);
  133.       UpdateBars();
  134.     }
  135.     if (VibOn[ch]) {
  136.       VibPtr[ch]+=VibInc[ch];              // Update vibrato table cntr
  137.       if (VibPtr[ch]>=128)                 // Reset counter
  138.         VibPtr[ch]=0;
  139.       if (!Increment[ch])                  // Note port doing it for us?
  140.         SetFreq(ch,CurFreqs[ch]+PitchWheel[ch]+SinTable[VibAmp][VibPtr[ch]]);
  141.     }
  142.     if (Increment[ch]) {                   // Deal with note port
  143.       t=(CurFreqs[ch]+PitchWheel[ch]);
  144.       if (Increment[ch]<0) {
  145.         if (t<=DestPitch[ch]) {
  146.           Increment[ch]=0;
  147.           PresPitch[ch]=0;
  148.           CurFreqs[ch]=DestPitch[ch];
  149.           DestPitch[ch]=0;
  150.         }
  151.         else
  152.           PresPitch[ch]+=Increment[ch];
  153.       }
  154.       else {
  155.         if (t>=DestPitch[ch]) {
  156.           Increment[ch]=0;
  157.           PresPitch[ch]=0;
  158.           CurFreqs[ch]=DestPitch[ch];
  159.           DestPitch[ch]=0;
  160.         }
  161.         else
  162.           PresPitch[ch]+=Increment[ch];
  163.       }
  164.     }
  165.     PitchWheel[ch]=PresPitch[ch]/256;
  166.     SetFreq(ch,CurFreqs[ch]+PitchWheel[ch]+SinTable[VibAmp][VibPtr[ch]]);
  167.  
  168.     if (VIncrement[ch]) {                   // Deal with vol port
  169.       t=(CurVols[ch]*4)+VolWheel[ch];
  170.       if (VIncrement[ch]<0) {
  171.         if (t<=DestVol[ch]) {
  172.           VIncrement[ch]=0;
  173.           PresVol[ch]=0;
  174.           CurVols[ch]=DestVol[ch]/4;
  175.           DestVol[ch]=0;
  176.         }
  177.         else
  178.           PresVol[ch]+=VIncrement[ch];
  179.       }
  180.       else {
  181.         if (t>=DestVol[ch]) {
  182.           VIncrement[ch]=0;
  183.           PresVol[ch]=0;
  184.           CurVols[ch]=DestVol[ch]/4;
  185.           DestPitch[ch]=0;
  186.         }
  187.         else
  188.           PresVol[ch]+=VIncrement[ch];
  189.       }
  190.       VolWheel[ch]=PresVol[ch];
  191.       if ( ((CurVols[ch]*4)+VolWheel[ch])< 0) {
  192.         VIncrement[ch]=0;
  193.         PresVol[ch]=0;
  194.         CurVols[ch]=DestVol[ch]/4;
  195.         DestVol[ch]=0;
  196.         SetVol(ch,VolTab[0]);
  197.       }
  198.       else
  199.         SetVol(ch,VolTab[(CurVols[ch]*4)+VolWheel[ch]]);
  200.  
  201.     }
  202.  
  203.     if (RetLeft[ch] && ChanOn[ch]) {               // Deal with retrigger
  204.       CurSpc[ch]+=2;
  205.       if (CurSpc[ch]>=RetSpc[ch]) {
  206.         if (!OfftCnt[ch]) goto DoNote1;            // No note offset (retrig)
  207.         if (OfftCnt[ch]==RetCnt[ch]) goto DoNote1; // Time for output of note
  208.         goto NoNote1;
  209.         DoNote1:
  210.           q=RetSmp[ch];
  211.           m=Sample[q].LoopMode;
  212.           CurVols[ch]=RetVol[ch]-1;
  213.           CurChSmp[ch]=q;
  214.           if (m&(1<<2))
  215.             PlaySample(Sample[q].Seg/2,
  216.                        Sample[q].Off/2,
  217.                        Sample[q].Rep/2,
  218.                        Sample[q].RepEnd/2,
  219.                        ch,m);
  220.           else
  221.             PlaySample(Sample[q].Seg,
  222.                        Sample[q].Off,
  223.                        Sample[q].Rep,
  224.                        Sample[q].RepEnd,
  225.                        ch,m);
  226.           SetVol(ch,VolTab[(CurVols[ch]*4)+VolWheel[ch]]);
  227.           RetLeft[ch]--;
  228.           CurSpc[ch]=0;
  229.         NoNote1:
  230.           RetCnt[ch]++;
  231.       }
  232.     }
  233.   }
  234.  
  235. oo:
  236.   if (OCount--) {
  237.     outportb(0x20,0x20);
  238.     return;
  239.   }
  240.   OCount=OverFlow;
  241.  
  242.   ov=CurVoice;
  243.   for (c=0;c<16;c++) {
  244.     CurVoice=c;
  245.     OfftCnt[CurVoice]=0; RetCnt[CurVoice]=0; RetLeft[CurVoice]=0;
  246. //    if (Bars[CurVoice]<(PlayTempo*2)) Bars[CurVoice]=0;
  247. //    if (Bars[CurVoice]) Bars[CurVoice]-=PlayTempo*2;
  248.     fekt=Pattern[CurSpot+3]&0xF0;
  249.     if (Pattern[CurSpot] && ChanOn[CurVoice] && fekt!=0x30) {
  250.       q=Pattern[CurSpot+1];
  251.       m=Sample[q].LoopMode;
  252.       if (Sample[Pattern[CurSpot+1]].SType&1) m|=(1<<2);
  253.       CurFreqs[CurVoice]=Freqs[Pattern[CurSpot]-1];
  254.       SetFreq(CurVoice,CurFreqs[CurVoice]);
  255.       CurChSmp[CurVoice]=q;
  256.       if (m&(1<<2))
  257.         PlaySample(Sample[q].Seg/2,
  258.                    Sample[q].Off/2,
  259.                    Sample[q].Rep/2,
  260.                    Sample[q].RepEnd/2,
  261.                    CurVoice,m);
  262.       else
  263.         PlaySample(Sample[q].Seg,
  264.                    Sample[q].Off,
  265.                    Sample[q].Rep,
  266.                    Sample[q].RepEnd,
  267.                    CurVoice,m);
  268.       PresPitch[CurVoice]=0;
  269.       DestPitch[CurVoice]=0; Increment[CurVoice]=0;
  270. //      Bars[CurVoice]=(Pattern[CurSpot+2]*fs)/16;
  271.     }
  272.     SetBalance(CurVoice,CurBalance[CurVoice]);
  273.     if (Pattern[CurSpot+2] && ChanOn[CurVoice] && fekt!=0xa0) {
  274.       PresVol[CurVoice]=0; VolWheel[CurVoice]=0;
  275.       DestVol[CurVoice]=0; VIncrement[CurVoice]=0;
  276.  
  277.       CurVols[CurVoice]=(Pattern[CurSpot+2]-1);
  278.       SetVol(CurVoice,VolTab[(CurVols[CurVoice]*4)]);
  279. //      Bars[CurVoice]=(Pattern[CurSpot+2]*fs)/16;
  280.     }
  281.     if (Pattern[CurSpot+3]) {
  282.       switch(Pattern[CurSpot+3]&0xF0) {
  283.         case 0xf0:  // Modify tempo
  284.           CurTempo=Pattern[CurSpot+3]&0xF;
  285.           PlayTempo=CurTempo;
  286.           if (TempoType)
  287.             UpdateTempo(mTempo[PlayTempo]+TempoBend);
  288.           else
  289.             UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
  290.           break;
  291.         case 0xe0:  // Fine tempo up/cancel
  292.           if (Pattern[CurSpot+3]&0xF) {
  293.             TempoBend+=Pattern[CurSpot+3]&0xF;
  294.             if ((TempoBend+mTempo[PlayTempo])>=100)
  295.               TempoBend=100;
  296.           }
  297.           else
  298.             TempoBend=0;
  299.           if (TempoType)
  300.             UpdateTempo(mTempo[PlayTempo]+TempoBend);
  301.           else
  302.             UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
  303.           break;
  304.         case 0xd0:  // Fine tempo down/cancel
  305.           if (Pattern[CurSpot+3]&0xF) {
  306.             TempoBend-=Pattern[CurSpot+3]&0xF;
  307.             if ((TempoBend+mTempo[PlayTempo])<=0)
  308.               TempoBend=0;
  309.           }
  310.           else
  311.             TempoBend=0;
  312.           if (TempoType)
  313.             UpdateTempo(mTempo[PlayTempo]+TempoBend);
  314.           else
  315.             UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
  316.           break;
  317.         case 0xb0:  // Set Balance
  318.           CurBalance[CurVoice]=Pattern[CurSpot+3]&0xF;
  319.           SetBalance(CurVoice,CurBalance[CurVoice]);
  320.           if (Tracking)
  321.             UpdatePanning();
  322.           break;
  323.         case 0x10:  // raise pitch
  324.           PresPitch[CurVoice]+=((Pattern[CurSpot+3]&0xF)*4)*256;
  325.           PitchWheel[CurVoice]=PresPitch[CurVoice]/256;
  326.           DestPitch[CurVoice]=0; Increment[CurVoice]=0;
  327.           SetFreq(ch,CurFreqs[ch]+PitchWheel[ch]+SinTable[VibAmp][VibPtr[ch]]);
  328.           break;
  329.         case 0x20:  // lower pitch
  330.           PresPitch[CurVoice]-=((Pattern[CurSpot+3]&0xF)*4)*256;
  331.           PitchWheel[CurVoice]=PresPitch[CurVoice]/256;
  332.           DestPitch[CurVoice]=0; Increment[CurVoice]=0;
  333.           SetFreq(ch,CurFreqs[ch]+PitchWheel[ch]+SinTable[VibAmp][VibPtr[ch]]);
  334.           break;
  335.         case 0x30:  // Port to note
  336.           if (Pattern[CurSpot]) {
  337.             t=0;
  338.             fp=CurFreqs[CurVoice]+PitchWheel[CurVoice];
  339.             sp=Freqs[Pattern[CurSpot]-1];
  340.             DestPitch[CurVoice]=sp;
  341.             if (fp>sp) {t=sp;sp=fp;fp=t;}
  342.             if (Pattern[CurSpot+3]&0xF)
  343.               Increment[CurVoice]=((sp-fp)*256)/((Pattern[CurSpot+3]&0xF)*
  344.                 (mTempo[PlayTempo]+TempoBend));
  345.             else
  346.               Increment[CurVoice]=((sp-fp)*256)/(1*
  347.                 (mTempo[PlayTempo]+TempoBend));
  348.             Increment[CurVoice]*=8;
  349.             if (t) Increment[CurVoice]=-Increment[CurVoice];
  350.           }
  351.           break;
  352.         case 0xC0:  // Note Offset
  353.           OfftCnt[CurVoice]=Pattern[CurSpot+3]&0xF;
  354.           if (Pattern[CurSpot]) {
  355.             RetLeft[CurVoice]=0xE;
  356.             if (TempoType)
  357.               RetSpc[CurVoice]=((mTempo[PlayTempo]+TempoBend)/(RetLeft[CurVoice]+1))/4;
  358.             else
  359.               RetSpc[CurVoice]=((mTempo[PlayTempo]+TempoBend)/(RetLeft[CurVoice]+1))/2;
  360.             RetSmp[CurVoice]=Pattern[CurSpot+1];
  361.             RetVol[CurVoice]=Pattern[CurSpot+2];
  362.             CurSpc[CurVoice]=0;
  363.           }
  364.           break;
  365.         case 0x40:  // Retrigger
  366.           if (Pattern[CurSpot]) {
  367.             RetLeft[CurVoice]=(Pattern[CurSpot+3]&0xF)-1;
  368.             if (TempoType)
  369.               RetSpc[CurVoice]=((mTempo[PlayTempo]+TempoBend)/(RetLeft[CurVoice]+1))/4;
  370.             else
  371.               RetSpc[CurVoice]=((mTempo[PlayTempo]+TempoBend)/(RetLeft[CurVoice]+1))/2;
  372.             RetSmp[CurVoice]=Pattern[CurSpot+1];
  373.             RetVol[CurVoice]=Pattern[CurSpot+2];
  374.             CurSpc[CurVoice]=0;
  375.           }
  376.           break;
  377.         case 0x50:  // Set vibrato amplitude
  378.           VibAmp=Pattern[CurSpot+3]&0xF;
  379.           break;
  380.         case 0x60:  // Vibrato Control
  381.           if (!VibOn[CurVoice]) {
  382.             VibOn[CurVoice]=1;
  383.             VibInc[CurVoice]=(Pattern[CurSpot+3]&0xF)*6;
  384.             VibPtr[CurVoice]=0;
  385.           }
  386.           else
  387.             VibInc[CurVoice]=(Pattern[CurSpot+3]&0xF)*6;
  388.           break;
  389.         case 0x90:  // Sustained vibrato control
  390.           if (Pattern[CurSpot+3]&0xF) {   // On
  391.             if (!VibOn[CurVoice]) {
  392.               VibOn[CurVoice]=2;
  393.               VibInc[CurVoice]=(Pattern[CurSpot+3]&0xF)*6;
  394.               VibPtr[CurVoice]=0;
  395.             }
  396.             else
  397.               VibInc[CurVoice]=(Pattern[CurSpot+3]&0xF)*6;
  398.           }
  399.           else {                          // Off
  400.             VibPtr[CurVoice]=0;
  401.             VibInc[CurVoice]=0;
  402.             VibOn[CurVoice]=FALSE;
  403.           }
  404.           break;
  405.         case 0x70:  // VolSldUp
  406.           q=Pattern[CurSpot+3]&0xF;
  407.           CurVols[CurVoice]+=q;
  408.           if (CurVols[CurVoice]>0xF) CurVols[CurVoice]=0xF;
  409.           SetVol(CurVoice,VolTab[(CurVols[CurVoice]*4)+VolWheel[CurVoice]]);
  410. //          Bars[CurVoice]=((CurVols[CurVoice]+1)*fs)/16;
  411.           break;
  412.         case 0x80:  // VolSldDn
  413.           q=Pattern[CurSpot+3]&0xF;
  414.           CurVols[CurVoice]-=q;
  415.           if (CurVols[CurVoice]<0) CurVols[CurVoice]=0;
  416.           SetVol(CurVoice,VolTab[(CurVols[CurVoice]*4)+VolWheel[CurVoice]]);
  417. //          Bars[CurVoice]=((CurVols[CurVoice]+1)*fs)/16;
  418.           break;
  419.         case 0xA0:  // Port to Vol
  420.           if (Pattern[CurSpot+2]) {
  421.             t=0;
  422.             fp=(CurVols[CurVoice]*4)+VolWheel[CurVoice];
  423.             sp=(Pattern[CurSpot+2]*4)-1;
  424.             DestVol[CurVoice]=sp;
  425.             if (fp>sp) {t=sp;sp=fp;fp=t;}
  426.             if (Pattern[CurSpot+3]&0xF)
  427.               VIncrement[CurVoice]=((sp-fp)*16)/((Pattern[CurSpot+3]&0xF)*
  428.                 (mTempo[PlayTempo]+TempoBend));
  429.             else
  430.               VIncrement[CurVoice]=((sp-fp)*16)/(1*
  431.                 (mTempo[PlayTempo]+TempoBend));
  432.             if (t) VIncrement[CurVoice]=-VIncrement[CurVoice];
  433.           }
  434.           break;
  435.         case 0x00: // Global funct
  436.           switch(Pattern[CurSpot+3]&0xF) {
  437.             case 1: // Ramp off
  438.             case 2: // Ramp on
  439.               VolRamps=(Pattern[CurSpot+3]&0xF)-1;
  440.               break;
  441.             case 3:
  442.               q=CurChSmp[CurVoice];
  443.               SetLoops(Sample[q].Seg,Sample[q].Off,Sample[q].Len,
  444.                 Sample[q].LoopMode&0xf7,CurVoice);
  445.               break;
  446.             case 4: // 669 tempos
  447.             case 5: // far tempos
  448.               TempoType=(Pattern[CurSpot+3]&0xF)-4;
  449.               if (TempoType)
  450.                 UpdateTempo(mTempo[PlayTempo]+TempoBend);
  451.               else
  452.                 UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
  453.               break;
  454.           }
  455.           break;
  456.       }
  457.     }
  458.     if (VibOn[CurVoice]==1 && (Pattern[CurSpot+3]&0xF0)!=0x60) {
  459.       VibPtr[CurVoice]=0;
  460.       VibInc[CurVoice]=0;
  461.       VibOn[CurVoice]=FALSE;
  462.     }
  463. /*    if (Bars[CurVoice]>=fs) Bars[CurVoice]=fs-1;
  464.     if (Bars[CurVoice]<1) Bars[CurVoice]=1; */
  465.   }
  466.   CurVoice=ov;
  467.   if (CurRow<=BreakLoc) {
  468.     if (CurRow-CurTop==31) {
  469.       if (Tracking) {
  470.         CurRow++;
  471.         CurTop=CurRow;
  472.         TrakUpdate=TRUE;
  473.       }
  474.       else
  475.         CurRow++;
  476.     }
  477.     else
  478.       if (Tracking) {
  479.         MoveCurs(CurVoice,CurRow+1);
  480.         UDBars=TRUE;;
  481.       }
  482.       else
  483.         CurRow++;
  484.   }
  485.   else {
  486.     if (PatLock) {
  487.       if (Tracking) {
  488.         TrakUpdate=TRUE;
  489.         CurRow=0; CurTop=0;
  490.       }
  491.       else
  492.         CurRow=0;
  493.     }
  494.     else {
  495.       PutAwayPat(CurPattern);
  496.       if (Order[CurOrder+1]==0xFF)
  497.         CurOrder=LoopTo;
  498.       else
  499.         CurOrder++;
  500.       CurPattern=Order[CurOrder];
  501.       GetPat(CurPattern);
  502.       if (Tracking) {
  503.         CurTop=0;
  504.         CurRow=0;
  505.         TrakUpdate=TRUE;
  506.       }
  507.       else
  508.         CurRow=0;
  509.     }
  510.   }
  511.  
  512.   outportb(0x20,0x20);
  513. }
  514.  
  515. #pragma option -r
  516.  
  517. void StopMusic() {
  518.   word q;
  519.  
  520.   if (Playing) {
  521.     ChSpeed(0);
  522.     setvect(8,OldInt8);
  523.     if (Tracking) UpdateChans();
  524.     KillBars();
  525.   }
  526.   for (q=0;q<16;q++) StopSample(q);
  527.   Playing=NO;
  528. }
  529.  
  530. void ResetChannel(int ch) {
  531.   PlaySample(0,32,0,0,ch,0);
  532. }
  533.  
  534. void StartMusic() {
  535.   word q;
  536.  
  537.   fs=fsize*4;
  538.   StopMusic();
  539.   KillBars();
  540.  
  541.   memset(GrabBuf,0,64);
  542.   U_DumpSampleToDRAM(GrabBuf,0,0,64);
  543.   for (q=0;q<16;q++) SetBalance(q,CurBalance[q]);
  544.   for (q=0;q<16;q++) ResetChannel(q);
  545.  
  546.   memset(PitchWheel,0,sizeof(PitchWheel));
  547.   memset(VibOn,0,sizeof(VibOn));
  548.   memset(VibPtr,0,sizeof(VibPtr));
  549.   memset(VibInc,0,sizeof(VibInc));
  550.   memset(RetLeft,0,sizeof(RetLeft));
  551.   PlayTempo=CurTempo;
  552.   UpdateChans();
  553.   UpdateOrder();
  554.   OldInt8=getvect(8);
  555.   setvect(8,Int8);
  556.   if (TempoType)
  557.     UpdateTempo(mTempo[PlayTempo]+TempoBend);
  558.   else
  559.     UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
  560.   OCount=OverFlow;
  561.   Playing=YES;
  562.  
  563.   if (!Tracking) {
  564.     DrawF(0,42,11,9," Playing song.. Press any key except D to stop playback - Press D to shell to DOS                                                   ");
  565.     do {
  566.       GetCh();
  567.       if (LKHit=='D') {
  568.         DosShell();
  569.         LKHit='D';
  570.       }
  571.     } while (LKHit=='D');
  572.     StopMusic();
  573.     UpdateStat();
  574.     UpdateChans();
  575.   }
  576. }
  577.