home *** CD-ROM | disk | FTP | other *** search
/ PC Loisirs 18 / cd.iso / sharewar / mikm202 / source / mplayer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-09-18  |  26.6 KB  |  1,296 lines

  1. #include <stdlib.h>
  2. #include "mtypes.h"
  3. #include "munitrk.h"
  4. #include "mdriver.h"
  5. #include "mloader.h"
  6. #include "mplayer.h"
  7.  
  8.  
  9. UNIMOD *pf;            // <- this modfile is being played
  10. UWORD reppos;            // patternloop position
  11. UWORD repcnt;            // times to loop
  12. UWORD vbtick;            // tick counter
  13. UWORD patbrk;            // position where to start a new pattern
  14. UBYTE patdly;            // patterndelay counter
  15. UBYTE patdly2;            // patterndelay counter
  16. UWORD numrow;            // number of rows on current pattern
  17. WORD  posjmp;            /*     flag to indicate a position jump is needed...
  18.                             changed since 1.00: now also indicates the
  19.                             direction the position has to jump to:
  20.  
  21.                             0: Don't do anything
  22.                             1: Jump back 1 position
  23.                             2: Restart on current position
  24.                             3: Jump forward 1 position
  25.                         */
  26. int   forbid;            // forbidflag
  27.  
  28.  
  29. /*
  30.     Set forbid to 1 when you want to modify any of the mp_sngpos, mp_patpos etc.
  31.     variables and clear it when you're done. This prevents getting strange
  32.     results due to intermediate interrupts.
  33. */
  34.  
  35.  
  36. AUDTMP mp_audio[32];    // max 32 channels
  37. UBYTE  mp_bpm;            // beats-per-minute speed
  38. UWORD  mp_patpos;        // current row number (0-255)
  39. WORD   mp_sngpos;        // current song position
  40. UWORD  mp_sngspd;        // current songspeed
  41. UWORD  mp_channel;        // channel it's working on
  42. BOOL   mp_extspd=1;        // extended speed flag, default enabled
  43. BOOL   mp_panning=1;    // panning flag, default enabled
  44. BOOL   mp_loop=0;        // loop module ?
  45. UBYTE  mp_volume=100;    // song volume (0-100)
  46. AUDTMP *a;                // current AUDTMP it's working on
  47.  
  48.  
  49. UWORD mytab[12]={
  50.     1712*16,1616*16,1524*16,1440*16,1356*16,1280*16,
  51.     1208*16,1140*16,1076*16,1016*16,960*16,907*16
  52. };
  53.  
  54. static UBYTE VibratoTable[32]={
  55.     0,24,49,74,97,120,141,161,
  56.     180,197,212,224,235,244,250,253,
  57.     255,253,250,244,235,224,212,197,
  58.     180,161,141,120,97,74,49,24
  59. };
  60.  
  61.  
  62. // linear periods to frequency translation table:
  63.  
  64. UWORD lintab[768]={
  65. 16726,16741,16756,16771,16786,16801,16816,16832,16847,16862,16877,16892,16908,16923,16938,16953,
  66. 16969,16984,16999,17015,17030,17046,17061,17076,17092,17107,17123,17138,17154,17169,17185,17200,
  67. 17216,17231,17247,17262,17278,17293,17309,17325,17340,17356,17372,17387,17403,17419,17435,17450,
  68. 17466,17482,17498,17513,17529,17545,17561,17577,17593,17608,17624,17640,17656,17672,17688,17704,
  69. 17720,17736,17752,17768,17784,17800,17816,17832,17848,17865,17881,17897,17913,17929,17945,17962,
  70. 17978,17994,18010,18027,18043,18059,18075,18092,18108,18124,18141,18157,18174,18190,18206,18223,
  71. 18239,18256,18272,18289,18305,18322,18338,18355,18372,18388,18405,18421,18438,18455,18471,18488,
  72. 18505,18521,18538,18555,18572,18588,18605,18622,18639,18656,18672,18689,18706,18723,18740,18757,
  73. 18774,18791,18808,18825,18842,18859,18876,18893,18910,18927,18944,18961,18978,18995,19013,19030,
  74. 19047,19064,19081,19099,19116,19133,19150,19168,19185,19202,19220,19237,19254,19272,19289,19306,
  75. 19324,19341,19359,19376,19394,19411,19429,19446,19464,19482,19499,19517,19534,19552,19570,19587,
  76. 19605,19623,19640,19658,19676,19694,19711,19729,19747,19765,19783,19801,19819,19836,19854,19872,
  77. 19890,19908,19926,19944,19962,19980,19998,20016,20034,20052,20071,20089,20107,20125,20143,20161,
  78. 20179,20198,20216,20234,20252,20271,20289,20307,20326,20344,20362,20381,20399,20418,20436,20455,
  79. 20473,20492,20510,20529,20547,20566,20584,20603,20621,20640,20659,20677,20696,20715,20733,20752,
  80. 20771,20790,20808,20827,20846,20865,20884,20902,20921,20940,20959,20978,20997,21016,21035,21054,
  81. 21073,21092,21111,21130,21149,21168,21187,21206,21226,21245,21264,21283,21302,21322,21341,21360,
  82. 21379,21399,21418,21437,21457,21476,21496,21515,21534,21554,21573,21593,21612,21632,21651,21671,
  83. 21690,21710,21730,21749,21769,21789,21808,21828,21848,21867,21887,21907,21927,21946,21966,21986,
  84. 22006,22026,22046,22066,22086,22105,22125,22145,22165,22185,22205,22226,22246,22266,22286,22306,
  85. 22326,22346,22366,22387,22407,22427,22447,22468,22488,22508,22528,22549,22569,22590,22610,22630,
  86. 22651,22671,22692,22712,22733,22753,22774,22794,22815,22836,22856,22877,22897,22918,22939,22960,
  87. 22980,23001,23022,23043,23063,23084,23105,23126,23147,23168,23189,23210,23230,23251,23272,23293,
  88. 23315,23336,23357,23378,23399,23420,23441,23462,23483,23505,23526,23547,23568,23590,23611,23632,
  89. 23654,23675,23696,23718,23739,23761,23782,23804,23825,23847,23868,23890,23911,23933,23954,23976,
  90. 23998,24019,24041,24063,24084,24106,24128,24150,24172,24193,24215,24237,24259,24281,24303,24325,
  91. 24347,24369,24391,24413,24435,24457,24479,24501,24523,24545,24567,24590,24612,24634,24656,24679,
  92. 24701,24723,24746,24768,24790,24813,24835,24857,24880,24902,24925,24947,24970,24992,25015,25038,
  93. 25060,25083,25105,25128,25151,25174,25196,25219,25242,25265,25287,25310,25333,25356,25379,25402,
  94. 25425,25448,25471,25494,25517,25540,25563,25586,25609,25632,25655,25678,25702,25725,25748,25771,
  95. 25795,25818,25841,25864,25888,25911,25935,25958,25981,26005,26028,26052,26075,26099,26123,26146,
  96. 26170,26193,26217,26241,26264,26288,26312,26336,26359,26383,26407,26431,26455,26479,26502,26526,
  97. 26550,26574,26598,26622,26646,26670,26695,26719,26743,26767,26791,26815,26839,26864,26888,26912,
  98. 26937,26961,26985,27010,27034,27058,27083,27107,27132,27156,27181,27205,27230,27254,27279,27304,
  99. 27328,27353,27378,27402,27427,27452,27477,27502,27526,27551,27576,27601,27626,27651,27676,27701,
  100. 27726,27751,27776,27801,27826,27851,27876,27902,27927,27952,27977,28003,28028,28053,28078,28104,
  101. 28129,28155,28180,28205,28231,28256,28282,28307,28333,28359,28384,28410,28435,28461,28487,28513,
  102. 28538,28564,28590,28616,28642,28667,28693,28719,28745,28771,28797,28823,28849,28875,28901,28927,
  103. 28953,28980,29006,29032,29058,29084,29111,29137,29163,29190,29216,29242,29269,29295,29322,29348,
  104. 29375,29401,29428,29454,29481,29507,29534,29561,29587,29614,29641,29668,29694,29721,29748,29775,
  105. 29802,29829,29856,29883,29910,29937,29964,29991,30018,30045,30072,30099,30126,30154,30181,30208,
  106. 30235,30263,30290,30317,30345,30372,30400,30427,30454,30482,30509,30537,30565,30592,30620,30647,
  107. 30675,30703,30731,30758,30786,30814,30842,30870,30897,30925,30953,30981,31009,31037,31065,31093,
  108. 31121,31149,31178,31206,31234,31262,31290,31319,31347,31375,31403,31432,31460,31489,31517,31546,
  109. 31574,31602,31631,31660,31688,31717,31745,31774,31803,31832,31860,31889,31918,31947,31975,32004,
  110. 32033,32062,32091,32120,32149,32178,32207,32236,32265,32295,32324,32353,32382,32411,32441,32470,
  111. 32499,32529,32558,32587,32617,32646,32676,32705,32735,32764,32794,32823,32853,32883,32912,32942,
  112. 32972,33002,33031,33061,33091,33121,33151,33181,33211,33241,33271,33301,33331,33361,33391,33421
  113. };
  114.  
  115.  
  116.  
  117.  
  118. #define LOGFAC 2*16
  119.  
  120. UWORD logtab[]={
  121.     LOGFAC*907,LOGFAC*900,LOGFAC*894,LOGFAC*887,LOGFAC*881,LOGFAC*875,LOGFAC*868,LOGFAC*862,
  122.     LOGFAC*856,LOGFAC*850,LOGFAC*844,LOGFAC*838,LOGFAC*832,LOGFAC*826,LOGFAC*820,LOGFAC*814,
  123.     LOGFAC*808,LOGFAC*802,LOGFAC*796,LOGFAC*791,LOGFAC*785,LOGFAC*779,LOGFAC*774,LOGFAC*768,
  124.     LOGFAC*762,LOGFAC*757,LOGFAC*752,LOGFAC*746,LOGFAC*741,LOGFAC*736,LOGFAC*730,LOGFAC*725,
  125.     LOGFAC*720,LOGFAC*715,LOGFAC*709,LOGFAC*704,LOGFAC*699,LOGFAC*694,LOGFAC*689,LOGFAC*684,
  126.     LOGFAC*678,LOGFAC*675,LOGFAC*670,LOGFAC*665,LOGFAC*660,LOGFAC*655,LOGFAC*651,LOGFAC*646,
  127.     LOGFAC*640,LOGFAC*636,LOGFAC*632,LOGFAC*628,LOGFAC*623,LOGFAC*619,LOGFAC*614,LOGFAC*610,
  128.     LOGFAC*604,LOGFAC*601,LOGFAC*597,LOGFAC*592,LOGFAC*588,LOGFAC*584,LOGFAC*580,LOGFAC*575,
  129.     LOGFAC*570,LOGFAC*567,LOGFAC*563,LOGFAC*559,LOGFAC*555,LOGFAC*551,LOGFAC*547,LOGFAC*543,
  130.     LOGFAC*538,LOGFAC*535,LOGFAC*532,LOGFAC*528,LOGFAC*524,LOGFAC*520,LOGFAC*516,LOGFAC*513,
  131.     LOGFAC*508,LOGFAC*505,LOGFAC*502,LOGFAC*498,LOGFAC*494,LOGFAC*491,LOGFAC*487,LOGFAC*484,
  132.     LOGFAC*480,LOGFAC*477,LOGFAC*474,LOGFAC*470,LOGFAC*467,LOGFAC*463,LOGFAC*460,LOGFAC*457,
  133.     LOGFAC*453,LOGFAC*450,LOGFAC*447,LOGFAC*443,LOGFAC*440,LOGFAC*437,LOGFAC*434,LOGFAC*431
  134. };
  135.  
  136.  
  137. WORD Interpolate(WORD p,WORD p1,WORD p2,WORD v1,WORD v2)
  138. {
  139.     WORD dp,dv,di;
  140.  
  141.     if(p1==p2) return v1;
  142.  
  143.     dv=v2-v1;
  144.     dp=p2-p1;
  145.     di=p-p1;
  146.  
  147.     return v1 + ((LONG)(di*dv) / dp);
  148. }
  149.  
  150.  
  151. UWORD getlinearperiod(UBYTE note,UWORD fine)
  152. {
  153.     return((10L*12*16*4)-((UWORD)note*16*4)-(fine/2)+64);
  154. }
  155.  
  156.  
  157. UWORD getlogperiod(UBYTE note,UWORD fine)
  158. {
  159.     UBYTE n,o;
  160.     UWORD p1,p2,i;
  161.  
  162.     n=note%12;
  163.     o=note/12;
  164.     i=(n<<3)+(fine>>4);            // n*8 + fine/16
  165.  
  166.     p1=logtab[i];
  167.     p2=logtab[i+1];
  168.  
  169.     return(Interpolate(fine/16,0,15,p1,p2)>>o);
  170. }
  171.  
  172.  
  173. UWORD getoldperiod(UBYTE note,UWORD c2spd)
  174. {
  175.     UBYTE n,o;
  176.     ULONG period;
  177.  
  178.     if(!c2spd) return 4242;        // <- prevent divide overflow.. (42 eheh)
  179.  
  180.     n=note%12;
  181.     o=note/12;
  182.     period=((8363L*mytab[n]) >> o )/c2spd;
  183.     return period;
  184. }
  185.  
  186.  
  187.  
  188. UWORD GetPeriod(UBYTE note,UWORD c2spd)
  189. {
  190.     if(pf->flags&UF_XMPERIODS){
  191.         return (pf->flags&UF_LINEAR) ? getlinearperiod(note,c2spd) : getlogperiod(note,c2spd);
  192.     }
  193.     return(getoldperiod(note,c2spd));
  194. }
  195.  
  196.  
  197.  
  198. void DoEEffects(UBYTE dat)
  199. {
  200.     UBYTE nib;
  201.  
  202.     nib=dat&0xf;
  203.  
  204.     switch(dat>>4){
  205.  
  206.         case 0x0:    // filter toggle, not supported
  207.                 break;
  208.  
  209.         case 0x1:    // fineslide up
  210.                 if(!vbtick) a->tmpperiod-=(nib<<2);
  211.                 break;
  212.  
  213.         case 0x2:    // fineslide dn
  214.                 if(!vbtick) a->tmpperiod+=(nib<<2);
  215.                 break;
  216.  
  217.         case 0x3:    // glissando ctrl
  218.                 a->glissando=nib;
  219.                 break;
  220.  
  221.         case 0x4:    // set vibrato waveform
  222.                 a->wavecontrol&=0xf0;
  223.                 a->wavecontrol|=nib;
  224.                 break;
  225.  
  226.         case 0x5:    // set finetune
  227. //                a->c2spd=finetune[nib];
  228. //                a->tmpperiod=GetPeriod(a->note,pf->samples[a->sample].transpose,a->c2spd);
  229.                 break;
  230.  
  231.         case 0x6:    // set patternloop
  232.  
  233.                 if(vbtick) break;
  234.  
  235.                 /* hmm.. this one is a real kludge. But now it
  236.                    works. */
  237.  
  238.                 if(nib){        // set reppos or repcnt ?
  239.  
  240.                     /* set repcnt, so check if repcnt already is set,
  241.                        which means we are already looping */
  242.  
  243.                     if(repcnt>0)
  244.                         repcnt--;        // already looping, decrease counter
  245.                     else
  246.                         repcnt=nib;        // not yet looping, so set repcnt
  247.  
  248.                     if(repcnt)            // jump to reppos if repcnt>0
  249.                         mp_patpos=reppos;
  250.                 }
  251.                 else{
  252.                     reppos=mp_patpos-1;    // set reppos
  253.                 }
  254.                 break;
  255.  
  256.  
  257.         case 0x7:    // set tremolo waveform
  258.                 a->wavecontrol&=0x0f;
  259.                 a->wavecontrol|=nib<<4;
  260.                 break;
  261.  
  262.         case 0x8:    // not used
  263.                 if(mp_panning) a->panning=nib<<4;
  264.                 break;
  265.  
  266.         case 0x9:    // retrig note
  267.  
  268.                 /* only retrigger if
  269.                    data nibble > 0 */
  270.  
  271.                 if(nib>0){
  272.                     if(a->retrig==0){
  273.  
  274.                         /* when retrig counter reaches 0,
  275.                            reset counter and restart the sample */
  276.  
  277.                         a->kick=1;
  278.                         a->retrig=nib;
  279.                     }
  280.                     a->retrig--; // countdown
  281.                 }
  282.                 break;
  283.  
  284.         case 0xa:    // fine volume slide up
  285.                 if(vbtick) break;
  286.  
  287.                 a->tmpvolume+=nib;
  288.                 if(a->tmpvolume>64) a->tmpvolume=64;
  289.                 break;
  290.  
  291.         case 0xb:    // fine volume slide dn
  292.                 if(vbtick) break;
  293.  
  294.                 a->tmpvolume-=nib;
  295.                 if(a->tmpvolume<0) a->tmpvolume=0;
  296.                 break;
  297.  
  298.         case 0xc:    // cut note
  299.  
  300.                 /* When vbtick reaches the cut-note value,
  301.                    turn the volume to zero ( Just like
  302.                    on the amiga) */
  303.  
  304.                 if(vbtick>=nib){
  305.                     a->tmpvolume=0;            // just turn the volume down
  306.                 }
  307.                 break;
  308.  
  309.         case 0xd:    // note delay
  310.  
  311.                 /* delay the start of the
  312.                    sample until vbtick==nib */
  313.  
  314.                 if(vbtick==nib){
  315.                     a->kick=1;
  316.                 }
  317.                 else a->kick=0;
  318.                 break;
  319.  
  320.         case 0xe:    // pattern delay
  321.                 if(vbtick) break;
  322.                 if(!patdly2) patdly=nib+1;                // only once (when vbtick=0)
  323.                 break;
  324.  
  325.         case 0xf:    // invert loop, not supported
  326.                 break;
  327.     }
  328. }
  329.  
  330.  
  331. void DoVibrato(void)
  332. {
  333.     UBYTE q;
  334.     UWORD temp;
  335.  
  336.     q=(a->vibpos>>2)&0x1f;
  337.  
  338.     switch(a->wavecontrol&3){
  339.  
  340.         case 0:    // sine
  341.             temp=VibratoTable[q];
  342.             break;
  343.  
  344.         case 1:    // ramp down
  345.             q<<=3;
  346.             if(a->vibpos<0) q=255-q;
  347.             temp=q;
  348.             break;
  349.  
  350.         case 2:    // square wave
  351.             temp=255;
  352.             break;
  353.     }
  354.  
  355.     temp*=a->vibdepth;
  356.     temp>>=7;
  357.     temp<<=2;
  358.  
  359.     if(a->vibpos>=0)
  360.         a->period=a->tmpperiod+temp;
  361.     else
  362.         a->period=a->tmpperiod-temp;
  363.  
  364.     if(vbtick) a->vibpos+=a->vibspd;    // do not update when vbtick==0
  365. }
  366.  
  367.  
  368.  
  369. void DoTremolo(void)
  370. {
  371.     UBYTE q;
  372.     UWORD temp;
  373.  
  374.     q=(a->trmpos>>2)&0x1f;
  375.  
  376.     switch((a->wavecontrol>>4)&3){
  377.  
  378.         case 0:    // sine
  379.             temp=VibratoTable[q];
  380.             break;
  381.  
  382.         case 1:    // ramp down
  383.             q<<=3;
  384.             if(a->trmpos<0)    q=255-q;
  385.             temp=q;
  386.             break;
  387.  
  388.         case 2:    // square wave
  389.             temp=255;
  390.             break;
  391.     }
  392.  
  393.     temp*=a->trmdepth;
  394.     temp>>=6;
  395.  
  396.     if(a->trmpos>=0){
  397.         a->volume=a->tmpvolume+temp;
  398.         if(a->volume>64) a->volume=64;
  399.     }
  400.     else{
  401.         a->volume=a->tmpvolume-temp;
  402.         if(a->volume<0) a->volume=0;
  403.     }
  404.  
  405.     if(vbtick) a->trmpos+=a->trmspd;    // do not update when vbtick==0
  406. }
  407.  
  408.  
  409. void DoVolSlide(UBYTE dat)
  410. {
  411.     if(!vbtick) return;        // do not update when vbtick==0
  412.  
  413.     a->tmpvolume+=dat>>4;            // volume slide
  414.     a->tmpvolume-=dat&0xf;
  415.     if(a->tmpvolume<0) a->tmpvolume=0;
  416.     if(a->tmpvolume>64) a->tmpvolume=64;
  417. }
  418.  
  419.  
  420.  
  421. void DoS3MVolSlide(UBYTE inf)
  422. {
  423.     UBYTE lo,hi;
  424.  
  425.     if(inf){
  426.         a->s3mvolslide=inf;
  427.     }
  428.     inf=a->s3mvolslide;
  429.  
  430.     lo=inf&0xf;
  431.     hi=inf>>4;
  432.  
  433.     if(hi==0){
  434.         a->tmpvolume-=lo;
  435.     }
  436.     else if(lo==0){
  437.         a->tmpvolume+=hi;
  438.     }
  439.     else if(hi==0xf){
  440.         if(!vbtick) a->tmpvolume-=lo;
  441.     }
  442.     else if(lo==0xf){
  443.         if(!vbtick) a->tmpvolume+=hi;
  444.     }
  445.  
  446.     if(a->tmpvolume<0) a->tmpvolume=0;
  447.     if(a->tmpvolume>64) a->tmpvolume=64;
  448. }
  449.  
  450.  
  451.  
  452. void DoXMVolSlide(UBYTE inf)
  453. {
  454.     UBYTE lo,hi;
  455.  
  456.     if(inf){
  457.         a->s3mvolslide=inf;
  458.     }
  459.     inf=a->s3mvolslide;
  460.  
  461.     if(!vbtick) return;
  462.  
  463.     lo=inf&0xf;
  464.     hi=inf>>4;
  465.  
  466.     if(hi==0)
  467.         a->tmpvolume-=lo;
  468.     else
  469.         a->tmpvolume+=hi;
  470.  
  471.     if(a->tmpvolume<0) a->tmpvolume=0;
  472.     if(a->tmpvolume>64) a->tmpvolume=64;
  473. }
  474.  
  475.  
  476. void DoXMPanSlide(UBYTE inf)
  477. {
  478.     UBYTE lo,hi;
  479.     WORD pan;
  480.  
  481.  
  482.     if(inf!=0) a->pansspd=inf;
  483.     else inf=a->pansspd;
  484.  
  485.     if(!vbtick) return;
  486.  
  487.     lo=inf&0xf;
  488.     hi=inf>>4;
  489.  
  490.     // slide right has absolute priority:
  491.  
  492.     if(hi) lo=0;
  493.  
  494.     pan=a->panning;
  495.  
  496.     pan-=lo;
  497.     pan+=hi;
  498.  
  499.     if(pan<0) pan=0;
  500.     if(pan>255) pan=255;
  501.  
  502.     a->panning=pan;
  503. }
  504.  
  505.  
  506.  
  507. void DoS3MSlideDn(UBYTE inf)
  508. {
  509.     UBYTE hi,lo;
  510.  
  511.     if(inf!=0) a->slidespeed=inf;
  512.     else inf=a->slidespeed;
  513.  
  514.     hi=inf>>4;
  515.     lo=inf&0xf;
  516.  
  517.     if(hi==0xf){
  518.         if(!vbtick) a->tmpperiod+=(UWORD)lo<<2;
  519.     }
  520.     else if(hi==0xe){
  521.         if(!vbtick) a->tmpperiod+=lo;
  522.     }
  523.     else{
  524.         if(vbtick) a->tmpperiod+=(UWORD)inf<<2;
  525.     }
  526. }
  527.  
  528.  
  529.  
  530. void DoS3MSlideUp(UBYTE inf)
  531. {
  532.     UBYTE hi,lo;
  533.  
  534.     if(inf!=0) a->slidespeed=inf;
  535.     else inf=a->slidespeed;
  536.  
  537.     hi=inf>>4;
  538.     lo=inf&0xf;
  539.  
  540.     if(hi==0xf){
  541.         if(!vbtick) a->tmpperiod-=(UWORD)lo<<2;
  542.     }
  543.     else if(hi==0xe){
  544.         if(!vbtick) a->tmpperiod-=lo;
  545.     }
  546.     else{
  547.         if(vbtick) a->tmpperiod-=(UWORD)inf<<2;
  548.     }
  549. }
  550.  
  551.  
  552.  
  553. void DoS3MTremor(UBYTE inf)
  554. {
  555.     UBYTE on,off;
  556.  
  557.     on=(inf>>4)+1;
  558.     off=(inf&0xf)+1;
  559.  
  560.     a->s3mtremor%=(on+off);
  561.     a->volume=(a->s3mtremor < on ) ? a->tmpvolume:0;
  562.     a->s3mtremor++;
  563. }
  564.  
  565.  
  566.  
  567. void DoS3MRetrig(UBYTE inf)
  568. {
  569.     UBYTE hi,lo;
  570.  
  571.     hi=inf>>4;
  572.     lo=inf&0xf;
  573.  
  574.     if(lo){
  575.         a->s3mrtgslide=hi;
  576.         a->s3mrtgspeed=lo;
  577.     }
  578.  
  579.     if(hi){
  580.         a->s3mrtgslide=hi;
  581.     }
  582.  
  583.     /* only retrigger if
  584.        lo nibble > 0 */
  585.  
  586.     if(a->s3mrtgspeed>0){
  587.         if(a->retrig==0){
  588.  
  589.             /* when retrig counter reaches 0,
  590.                reset counter and restart the sample */
  591.  
  592.             a->kick=1;
  593.             a->retrig=a->s3mrtgspeed;
  594.  
  595.             if(vbtick){            // don't slide on first retrig
  596.                 switch(a->s3mrtgslide){
  597.  
  598.                     case 1:
  599.                     case 2:
  600.                     case 3:
  601.                     case 4:
  602.                     case 5:
  603.                         a->tmpvolume-=(1<<(a->s3mrtgslide-1));
  604.                         break;
  605.  
  606.                     case 6:
  607.                         a->tmpvolume=(2*a->tmpvolume)/3;
  608.                         break;
  609.  
  610.                     case 7:
  611.                         a->tmpvolume=a->tmpvolume>>1;
  612.                         break;
  613.  
  614.                     case 9:
  615.                     case 0xa:
  616.                     case 0xb:
  617.                     case 0xc:
  618.                     case 0xd:
  619.                         a->tmpvolume+=(1<<(a->s3mrtgslide-9));
  620.                         break;
  621.  
  622.                     case 0xe:
  623.                         a->tmpvolume=(3*a->tmpvolume)/2;
  624.                         break;
  625.  
  626.                     case 0xf:
  627.                         a->tmpvolume=a->tmpvolume<<1;
  628.                         break;
  629.                 }
  630.                 if(a->tmpvolume<0) a->tmpvolume=0;
  631.                 if(a->tmpvolume>64) a->tmpvolume=64;
  632.             }
  633.         }
  634.         a->retrig--; // countdown
  635.     }
  636. }
  637.  
  638.  
  639. void DoS3MSpeed(UBYTE speed)
  640. {
  641.     if(vbtick || patdly2) return;
  642.  
  643.     if(speed){            // <- v0.44 bugfix
  644.         mp_sngspd=speed;
  645.         vbtick=0;
  646.     }
  647. }
  648.  
  649.  
  650. void DoS3MTempo(UBYTE tempo)
  651. {
  652.     if(vbtick || patdly2) return;
  653.     mp_bpm=tempo;
  654. }
  655.  
  656.  
  657. void DoToneSlide(void)
  658. {
  659.     int dist,t;
  660.  
  661.     if(!vbtick){
  662.         a->tmpperiod=a->period;
  663.         return;
  664.     }
  665.  
  666.     /* We have to slide a->period towards a->wantedperiod, so
  667.        compute the difference between those two values */
  668.  
  669.     dist=a->period-a->wantedperiod;
  670.  
  671.     if( dist==0 ||                   // if they are equal
  672.         a->portspeed>abs(dist) ){    // or if portamentospeed is too big
  673.  
  674.         a->period=a->wantedperiod;    // make tmpperiod equal tperiod
  675.     }
  676.     else if(dist>0){                // dist>0 ?
  677.         a->period-=a->portspeed;    // then slide up
  678.     }
  679.     else
  680.         a->period+=a->portspeed;    // dist<0 -> slide down
  681.  
  682. /*    if(a->glissando){
  683.  
  684.          If glissando is on, find the nearest
  685.            halfnote to a->tmpperiod
  686.  
  687.         for(t=0;t<60;t++){
  688.             if(a->tmpperiod>=npertab[a->finetune][t]) break;
  689.         }
  690.  
  691.         a->period=npertab[a->finetune][t];
  692.     }
  693.     else
  694. */
  695.     a->tmpperiod=a->period;
  696. }
  697.  
  698.  
  699. void DoPTEffect0(UBYTE dat)
  700. {
  701.     UBYTE note;
  702.  
  703.     note=a->note;
  704.  
  705.     if(dat!=0){
  706.         switch(vbtick%3){
  707.             case 1:
  708.                 note+=(dat>>4); break;
  709.             case 2:
  710.                 note+=(dat&0xf); break;
  711.         }
  712.         a->period=GetPeriod(note+a->transpose,a->c2spd);
  713.         a->ownper=1;
  714.     }
  715. }
  716.  
  717.  
  718. void PlayNote(void)
  719. {
  720.     INSTRUMENT *i;
  721.     SAMPLE *s;
  722.     UWORD period;
  723.     UBYTE inst,c;
  724.     UBYTE note;
  725.  
  726.     if(a->row==NULL) return;
  727.  
  728.     UniSetRow(a->row);
  729.  
  730.     while(c=UniGetByte()){
  731.  
  732.         switch(c){
  733.  
  734.             case UNI_NOTE:
  735.                 note=UniGetByte();
  736.  
  737.                 if(note==96){            // key off ?
  738.                     a->keyon=0;
  739.                     if(!(a->i->volflg & EF_ON)){
  740.                         a->tmpvolume=0;
  741.                     }
  742.                 }
  743.                 else{
  744.                     a->note=note;
  745.  
  746.                     period=GetPeriod(note+a->transpose,a->c2spd);
  747.  
  748.                     a->wantedperiod=period;
  749.                     a->tmpperiod=period;
  750.  
  751.                     a->kick=1;
  752.                     a->start=0;
  753.  
  754.                     // retrig tremolo and vibrato waves ?
  755.  
  756.                     if(!(a->wavecontrol&0x80)) a->trmpos=0;
  757.                     if(!(a->wavecontrol&0x08)) a->vibpos=0;
  758.                 }
  759.                 break;
  760.  
  761.             case UNI_INSTRUMENT:
  762.                 inst=UniGetByte();
  763.                 if(inst>=pf->numins) break;        // <- safety valve
  764.  
  765.                 a->sample=inst;
  766.  
  767.                 i=&pf->instruments[inst];
  768.                 a->i=i;
  769.  
  770.                 s=&i->samples[i->samplenumber[a->note]];
  771.                 a->s=s;
  772.  
  773.                 // channel or instrument determined panning ?
  774.  
  775.                 if(s->flags& SF_OWNPAN){
  776.                     a->panning=s->panning;
  777.                 }
  778.                 else{
  779.                     a->panning=pf->panning[mp_channel];
  780.                 }
  781.  
  782.                 a->transpose=s->transpose;
  783.                 a->handle=s->handle;
  784.                 a->tmpvolume=s->volume;
  785.                 a->volume=s->volume;
  786.                 a->c2spd=s->c2spd;
  787.                 a->retrig=0;
  788.                 a->s3mtremor=0;
  789.  
  790.                 period=GetPeriod(a->note+a->transpose,a->c2spd);
  791.  
  792.                 a->wantedperiod=period;
  793.                 a->tmpperiod=period;
  794.                 break;
  795.  
  796.             default:
  797.                 UniSkipOpcode(c);
  798.                 break;
  799.         }
  800.     }
  801. }
  802.  
  803.  
  804.  
  805.  
  806. void PlayEffects(void)
  807. {
  808.     UBYTE c,dat;
  809.  
  810.     if(a->row==NULL) return;
  811.  
  812.     UniSetRow(a->row);
  813.  
  814.     a->ownper=0;
  815.     a->ownvol=0;
  816.  
  817.     while(c=UniGetByte()){
  818.  
  819.         switch(c){
  820.  
  821.             case UNI_NOTE:
  822.             case UNI_INSTRUMENT:
  823.                 UniSkipOpcode(c);
  824.                 break;
  825.  
  826.             case UNI_PTEFFECT0:
  827.                 DoPTEffect0(UniGetByte());
  828.                 break;
  829.  
  830.             case UNI_PTEFFECT1:
  831.                 dat=UniGetByte();
  832.                 if(dat!=0) a->slidespeed=(UWORD)dat<<2;
  833.                 if(vbtick) a->tmpperiod-=a->slidespeed;
  834.                 break;
  835.  
  836.             case UNI_PTEFFECT2:
  837.                 dat=UniGetByte();
  838.                 if(dat!=0) a->slidespeed=(UWORD)dat<<2;
  839.                 if(vbtick) a->tmpperiod+=a->slidespeed;
  840.                 break;
  841.  
  842.             case UNI_PTEFFECT3:
  843.                 dat=UniGetByte();
  844.                 a->kick=0;
  845.                 if(dat!=0){
  846.                     a->portspeed=dat;
  847.                     a->portspeed<<=2;
  848.                 }
  849.                 DoToneSlide();
  850.                 a->ownper=1;
  851.                 break;
  852.  
  853.             case UNI_PTEFFECT4:
  854.                 dat=UniGetByte();
  855.                 if(dat&0x0f) a->vibdepth=dat&0xf;
  856.                 if(dat&0xf0) a->vibspd=(dat&0xf0)>>2;
  857.                 DoVibrato();
  858.                 a->ownper=1;
  859.                 break;
  860.  
  861.             case UNI_PTEFFECT5:
  862.                 dat=UniGetByte();
  863.                 a->kick=0;
  864.                 DoToneSlide();
  865.                 DoVolSlide(dat);
  866.                 a->ownper=1;
  867.                 break;
  868.  
  869.             case UNI_PTEFFECT6:
  870.                 dat=UniGetByte();
  871.                 DoVibrato();
  872.                 DoVolSlide(dat);
  873.                 a->ownper=1;
  874.                 break;
  875.  
  876.             case UNI_PTEFFECT7:
  877.                 dat=UniGetByte();
  878.                 if(dat&0x0f) a->trmdepth=dat&0xf;
  879.                 if(dat&0xf0) a->trmspd=(dat&0xf0)>>2;
  880.                 DoTremolo();
  881.                 a->ownvol=1;
  882.                 break;
  883.  
  884.             case UNI_PTEFFECT8:
  885.                 dat=UniGetByte();
  886.                 if(mp_panning) a->panning=dat;
  887.                 break;
  888.  
  889.             case UNI_PTEFFECT9:
  890.                 dat=UniGetByte();
  891.                 if(dat) a->soffset=(UWORD)dat<<8;    // <- 0.43 fix..
  892.                 a->start=a->soffset;
  893.                 if(a->start>a->s->length) a->start=a->s->length;
  894.                 break;
  895.  
  896.             case UNI_PTEFFECTA:
  897.                 DoVolSlide(UniGetByte());
  898.                 break;
  899.  
  900.             case UNI_PTEFFECTB:
  901.                 dat=UniGetByte();
  902.                 if(patdly2) break;
  903.                 patbrk=0;
  904.                 mp_sngpos=dat-1;
  905.                 posjmp=3;
  906.                 break;
  907.  
  908.             case UNI_PTEFFECTC:
  909.                 dat=UniGetByte();
  910.                 if(vbtick) break;
  911.                 if(dat>64) dat=64;
  912.                 a->tmpvolume=dat;
  913.                 break;
  914.  
  915.             case UNI_PTEFFECTD:
  916.                 dat=UniGetByte();
  917.                 if(patdly2) break;
  918.                 {
  919.                     int hi=(dat&0xf0)>>4;
  920.                     int    lo=(dat&0xf);
  921.                     patbrk=(hi*10)+lo;
  922.                 }
  923.                 if(patbrk>64) patbrk=64;    // <- v0.42 fix
  924.                 posjmp=3;
  925.                 break;
  926.  
  927.             case UNI_PTEFFECTE:
  928.                 DoEEffects(UniGetByte());
  929.                 break;
  930.  
  931.             case UNI_PTEFFECTF:
  932.                 dat=UniGetByte();
  933.  
  934.                 if(vbtick || patdly2) break;
  935.  
  936.                 if(mp_extspd && dat>=0x20){
  937.                     mp_bpm=dat;
  938.                 }
  939.                 else{
  940.                     if(dat){            // <- v0.44 bugfix
  941.                         mp_sngspd=dat;
  942.                         vbtick=0;
  943.                     }
  944.                 }
  945.                 break;
  946.  
  947.             case UNI_S3MEFFECTD:
  948.                 DoS3MVolSlide(UniGetByte());
  949.                 break;
  950.  
  951.             case UNI_S3MEFFECTE:
  952.                 DoS3MSlideDn(UniGetByte());
  953.                 break;
  954.  
  955.             case UNI_S3MEFFECTF:
  956.                 DoS3MSlideUp(UniGetByte());
  957.                 break;
  958.  
  959.             case UNI_S3MEFFECTI:
  960.                 DoS3MTremor(UniGetByte());
  961.                 a->ownvol=1;
  962.                 break;
  963.  
  964.             case UNI_S3MEFFECTQ:
  965.                 DoS3MRetrig(UniGetByte());
  966.                 break;
  967.  
  968.             case UNI_S3MEFFECTA:
  969.                 DoS3MSpeed(UniGetByte());
  970.                 break;
  971.  
  972.             case UNI_S3MEFFECTT:
  973.                 DoS3MTempo(UniGetByte());
  974.                 break;
  975.  
  976.             case UNI_XMEFFECTA:
  977.                 DoXMVolSlide(UniGetByte());
  978.                 break;
  979.  
  980.             case UNI_XMEFFECTP:
  981.                 DoXMPanSlide(UniGetByte());
  982.                 break;
  983.  
  984.             default:
  985.                 UniSkipOpcode(c);
  986.                 break;
  987.         }
  988.     }
  989.  
  990.     if(!a->ownper){
  991.         a->period=a->tmpperiod;
  992.     }
  993.  
  994.     if(!a->ownvol){
  995.         a->volume=a->tmpvolume;
  996.     }
  997. }
  998.  
  999.  
  1000.  
  1001.  
  1002. WORD InterpolateEnv(WORD p,ENVPT *a,ENVPT *b)
  1003. {
  1004.     return(Interpolate(p,a->pos,b->pos,a->val,b->val));
  1005. }
  1006.  
  1007.  
  1008. WORD DoPan(WORD envpan,WORD pan)
  1009. {
  1010.     return(pan + (((envpan-128)*(128-abs(pan-128)))/128));
  1011. }
  1012.  
  1013. WORD DoVol(ULONG a,WORD b,WORD c)
  1014. {
  1015.     a*=b;
  1016.     a*=c;
  1017.  
  1018.     return(a>>23);
  1019. }
  1020.  
  1021.  
  1022. void StartEnvelope(ENVPR *t,UBYTE flg,UBYTE pts,UBYTE sus,UBYTE beg,UBYTE end,ENVPT *p)
  1023. {
  1024.     t->flg=flg;
  1025.     t->pts=pts;
  1026.     t->sus=sus;
  1027.     t->beg=beg;
  1028.     t->end=end;
  1029.     t->env=p;
  1030.     t->p=0;
  1031.     t->a=0;
  1032.     t->b=1;
  1033. }
  1034.  
  1035.  
  1036.  
  1037. WORD ProcessEnvelope(ENVPR *t,WORD v,UBYTE keyon)
  1038. {
  1039.     if(t->flg & EF_ON){
  1040.  
  1041.         // panning active? -> copy variables
  1042.  
  1043.         UBYTE a,b;
  1044.         UWORD p;
  1045.  
  1046.         a=t->a;
  1047.         b=t->b;
  1048.         p=t->p;
  1049.  
  1050.         // compute the envelope value between points a and b
  1051.  
  1052.         v=InterpolateEnv(p,&t->env[a],&t->env[b]);
  1053.  
  1054.         /* Should we sustain? (sustain flag on, key-on, point a is the sustain
  1055.            point, and the pointer is exactly on point a) */
  1056.  
  1057.         if((t->flg & EF_SUSTAIN) && keyon && a==t->sus && p==t->env[a].pos){
  1058.             // do nothing
  1059.         }
  1060.         else{
  1061.             // don't sustain, so increase pointer.
  1062.  
  1063.             p++;
  1064.  
  1065.             // pointer reached point b?
  1066.  
  1067.             if(p >= t->env[b].pos){
  1068.  
  1069.                 // shift points a and b
  1070.  
  1071.                 a=b; b++;
  1072.  
  1073.                 if(t->flg & EF_LOOP){
  1074.                     if(b > t->end){
  1075.                         a=t->beg;
  1076.                         b=a+1;
  1077.                         p=t->env[a].pos;
  1078.                     }
  1079.                 }
  1080.                 else{
  1081.                     if(b >= t->pts){
  1082.                         b--;
  1083.                         p--;
  1084.                     }
  1085.                 }
  1086.             }
  1087.         }
  1088.         t->a=a;
  1089.         t->b=b;
  1090.         t->p=p;
  1091.     }
  1092.     return v;
  1093. }
  1094.  
  1095. /*
  1096. long GetFreq2(long period)
  1097. {
  1098.     float frequency;
  1099.  
  1100.     frequency=8363.0*pow(2,((6*12*16*4.0)-period)/(12*16*4.0));
  1101.     return(floor(frequency));
  1102. }
  1103. */
  1104.  
  1105. long GetFreq2(long period)
  1106. {
  1107.     int okt;
  1108.     long frequency;
  1109.     period=7680-period;
  1110.     okt=period/768;
  1111.     frequency=lintab[period%768];
  1112.     frequency<<=2;
  1113.     return(frequency>>(7-okt));
  1114. }
  1115.  
  1116. void MP_HandleTick(void)
  1117. {
  1118.     int z,t,tr;
  1119.  
  1120.     if(forbid) return;    // don't go any further when forbid is true
  1121.  
  1122.     if(MP_Ready()) return;
  1123.  
  1124.     if(++vbtick>=mp_sngspd){
  1125.  
  1126.         mp_patpos++;
  1127.         vbtick=0;
  1128.  
  1129.         if(patdly){
  1130.             patdly2=patdly;
  1131.             patdly=0;
  1132.         }
  1133.  
  1134.         if(patdly2){
  1135.  
  1136.             // patterndelay active
  1137.  
  1138.             if(--patdly2){
  1139.                 mp_patpos--;    // so turn back mp_patpos by 1
  1140.             }
  1141.         }
  1142.  
  1143.         /* Do we have to get a new patternpointer ?
  1144.            (when mp_patpos reaches 64 or when
  1145.            a patternbreak is active) */
  1146.  
  1147.         if( mp_patpos == numrow ) posjmp=3;
  1148.  
  1149.  
  1150.         if( posjmp ){
  1151.             mp_patpos=patbrk;
  1152.             mp_sngpos+=(posjmp-2);
  1153.             patbrk=posjmp=0;
  1154.             if(mp_sngpos>=pf->numpos){
  1155.                 if(!mp_loop) return;
  1156.                 mp_sngpos=0;
  1157.             }
  1158.             if(mp_sngpos<0) mp_sngpos=pf->numpos-1;
  1159.         }
  1160.  
  1161.  
  1162.         if(!patdly2){
  1163.  
  1164.             for(t=0;t<pf->numchn;t++){
  1165.  
  1166.                 tr=pf->patterns[(pf->positions[mp_sngpos]*pf->numchn)+t];
  1167.                 numrow=pf->pattrows[pf->positions[mp_sngpos]];
  1168.  
  1169.                 mp_channel=t;
  1170.                 a=&mp_audio[t];
  1171.                 a->row=(tr<pf->numtrk) ? UniFindRow(pf->tracks[tr],mp_patpos) : NULL;
  1172.  
  1173.                 PlayNote();
  1174.             }
  1175.         }
  1176.     }
  1177.  
  1178.     // Update effects
  1179.  
  1180.     for(t=0;t<pf->numchn;t++){
  1181.         mp_channel=t;
  1182.         a=&mp_audio[t];
  1183.         PlayEffects();
  1184.     }
  1185.  
  1186.     for(t=0;t<pf->numchn;t++){
  1187.         INSTRUMENT *i;
  1188.         SAMPLE *s;
  1189.         WORD envpan,envvol;
  1190.  
  1191.         a=&mp_audio[t];
  1192.         i=a->i;
  1193.         s=a->s;
  1194.  
  1195.         if(a->period<40) a->period=40;
  1196.         if(a->period>8000) a->period=8000;
  1197.  
  1198.         if(a->kick){
  1199.             MD_VoicePlay(t,a->handle,a->start,s->length,s->loopstart,s->loopend,s->flags);
  1200.             a->kick=0;
  1201.             a->keyon=1;
  1202.  
  1203.             a->fadevol=32767;
  1204.  
  1205.             StartEnvelope(&a->venv,i->volflg,i->volpts,i->volsus,i->volbeg,i->volend,i->volenv);
  1206.             StartEnvelope(&a->penv,i->panflg,i->panpts,i->pansus,i->panbeg,i->panend,i->panenv);
  1207.         }
  1208.  
  1209.         envvol=ProcessEnvelope(&a->venv,256,a->keyon);
  1210.         envpan=ProcessEnvelope(&a->penv,128,a->keyon);
  1211.  
  1212.         MD_VoiceSetVolume(t,(DoVol(a->fadevol,envvol,a->volume)*mp_volume)/100);
  1213.  
  1214.         if(s->flags& SF_OWNPAN){
  1215.             MD_VoiceSetPanning(t,DoPan(envpan,a->panning));
  1216.         }
  1217.         else{
  1218.             MD_VoiceSetPanning(t,a->panning);
  1219.         }
  1220.  
  1221.         if(pf->flags&UF_LINEAR)
  1222.             MD_VoiceSetFrequency(t,GetFreq2(a->period));
  1223.         else
  1224.             MD_VoiceSetFrequency(t,(3579546UL<<2)/a->period);
  1225.  
  1226.         /*  if key-off, start substracting
  1227.             fadeoutspeed from fadevol: */
  1228.  
  1229.         if(!a->keyon){
  1230.             a->fadevol-=i->volfade;
  1231.             if(a->fadevol<0) a->fadevol=0;
  1232.         }
  1233.     }
  1234. }
  1235.  
  1236.  
  1237.  
  1238. void MP_Init(UNIMOD *m)
  1239. {
  1240.     int t;
  1241.  
  1242.     pf=m;
  1243.     reppos=0;
  1244.     repcnt=0;
  1245.     mp_sngpos=0;
  1246.     mp_sngspd=m->initspeed;
  1247.  
  1248.     vbtick=mp_sngspd;
  1249.     patdly=0;
  1250.     patdly2=0;
  1251.     mp_bpm=m->inittempo;
  1252.  
  1253.     forbid=0;
  1254.     mp_patpos=0;
  1255.     posjmp=2;        // <- make sure the player fetches the first note
  1256.     patbrk=0;
  1257.  
  1258.     /* Make sure the player doesn't start with garbage: */
  1259.  
  1260.     for(t=0;t<pf->numchn;t++){
  1261.         mp_audio[t].kick=0;
  1262.         mp_audio[t].tmpvolume=0;
  1263.         mp_audio[t].retrig=0;
  1264.         mp_audio[t].wavecontrol=0;
  1265.         mp_audio[t].glissando=0;
  1266.         mp_audio[t].soffset=0;
  1267.     }
  1268. }
  1269.  
  1270.  
  1271.  
  1272. int MP_Ready(void)
  1273. {
  1274.     return(mp_sngpos>=pf->numpos);
  1275. }
  1276.  
  1277.  
  1278. void MP_NextPosition(void)
  1279. {
  1280.     forbid=1;
  1281.     posjmp=3;
  1282.     patbrk=0;
  1283.     vbtick=mp_sngspd;
  1284.     forbid=0;
  1285. }
  1286.  
  1287.  
  1288. void MP_PrevPosition(void)
  1289. {
  1290.     forbid=1;
  1291.     posjmp=1;
  1292.     patbrk=0;
  1293.     vbtick=mp_sngspd;
  1294.     forbid=0;
  1295. }
  1296.