]> 4ch.mooo.com Git - 16.git/blob - 16/adplug/adplug/src/protrack.cpp
renamed: 16/adplug/adplug-2.2.1/.DS_Store -> 16/adplug/adplug/.DS_Store
[16.git] / 16 / adplug / adplug / src / protrack.cpp
1 /*
2  * Adplug - Replayer for many OPL2/OPL3 audio file formats.
3  * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp@gmx.net>, et al.
4  * 
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  * 
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  * 
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * protrack.cpp - Generic Protracker Player
20  *
21  * NOTES:
22  * This is a generic Protracker-based formats player. It offers all Protracker
23  * features, plus a good set of extensions to be compatible to other Protracker
24  * derivatives. It is derived from the former SA2 player. If you got a
25  * Protracker-like format, this is most certainly the player you want to use.
26  */
27
28 #include <cstring>
29 #include "protrack.h"
30 #include "debug.h"
31
32 #define SPECIALARPLEN   256     // Standard length of special arpeggio lists
33 #define JUMPMARKER      0x80    // Orderlist jump marker
34
35 // SA2 compatible adlib note table
36 const unsigned short CmodPlayer::sa2_notetable[12] =
37   {340,363,385,408,432,458,485,514,544,577,611,647};
38
39 // SA2 compatible vibrato rate table
40 const unsigned char CmodPlayer::vibratotab[32] =
41   {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1};
42
43 /*** public methods *************************************/
44
45 CmodPlayer::CmodPlayer(Copl *newopl)
46   : CPlayer(newopl), inst(0), order(0), arplist(0), arpcmd(0), initspeed(6),
47     nop(0), activechan(0xffffffff), flags(Standard), curchip(opl->getchip()),
48     nrows(0), npats(0), nchans(0)
49 {
50   realloc_order(128);
51   realloc_patterns(64, 64, 9);
52   realloc_instruments(250);
53   init_notetable(sa2_notetable);
54 }
55
56 CmodPlayer::~CmodPlayer()
57 {
58   dealloc();
59 }
60
61 bool CmodPlayer::update()
62 {
63   unsigned char         pattbreak=0, donote, pattnr, chan, oplchan, info1,
64     info2, info, pattern_delay;
65   unsigned short        track;
66   unsigned long         row;
67
68   if(!speed)            // song full stop
69     return !songend;
70
71   // effect handling (timer dependant)
72   for(chan = 0; chan < nchans; chan++) {
73     oplchan = set_opl_chip(chan);
74
75     if(arplist && arpcmd && inst[channel[chan].inst].arpstart) {        // special arpeggio
76       if(channel[chan].arpspdcnt)
77         channel[chan].arpspdcnt--;
78       else
79         if(arpcmd[channel[chan].arppos] != 255) {
80           switch(arpcmd[channel[chan].arppos]) {
81           case 252: channel[chan].vol1 = arplist[channel[chan].arppos]; // set volume
82             if(channel[chan].vol1 > 63) // ?????
83               channel[chan].vol1 = 63;
84             channel[chan].vol2 = channel[chan].vol1;
85             setvolume(chan);
86             break;
87           case 253: channel[chan].key = 0; setfreq(chan); break;        // release sustaining note
88           case 254: channel[chan].arppos = arplist[channel[chan].arppos]; break; // arpeggio loop
89           default: if(arpcmd[channel[chan].arppos]) {
90             if(arpcmd[channel[chan].arppos] / 10)
91               opl->write(0xe3 + op_table[oplchan], arpcmd[channel[chan].arppos] / 10 - 1);
92             if(arpcmd[channel[chan].arppos] % 10)
93               opl->write(0xe0 + op_table[oplchan], (arpcmd[channel[chan].arppos] % 10) - 1);
94             if(arpcmd[channel[chan].arppos] < 10)       // ?????
95               opl->write(0xe0 + op_table[oplchan], arpcmd[channel[chan].arppos] - 1);
96           }
97           }
98           if(arpcmd[channel[chan].arppos] != 252) {
99             if(arplist[channel[chan].arppos] <= 96)
100               setnote(chan,channel[chan].note + arplist[channel[chan].arppos]);
101             if(arplist[channel[chan].arppos] >= 100)
102               setnote(chan,arplist[channel[chan].arppos] - 100);
103           } else
104             setnote(chan,channel[chan].note);
105           setfreq(chan);
106           if(arpcmd[channel[chan].arppos] != 255)
107             channel[chan].arppos++;
108           channel[chan].arpspdcnt = inst[channel[chan].inst].arpspeed - 1;
109         }
110     }
111
112     info1 = channel[chan].info1;
113     info2 = channel[chan].info2;
114     if(flags & Decimal)
115       info = channel[chan].info1 * 10 + channel[chan].info2;
116     else
117       info = (channel[chan].info1 << 4) + channel[chan].info2;
118     switch(channel[chan].fx) {
119     case 0:     if(info) {      // arpeggio
120       if(channel[chan].trigger < 2)
121         channel[chan].trigger++;
122       else
123         channel[chan].trigger = 0;
124       switch(channel[chan].trigger) {
125       case 0: setnote(chan,channel[chan].note); break;
126       case 1: setnote(chan,channel[chan].note + info1); break;
127       case 2: setnote(chan,channel[chan].note + info2);
128       }
129       setfreq(chan);
130     }
131       break;
132     case 1: slide_up(chan,info); setfreq(chan); break;  // slide up
133     case 2: slide_down(chan,info); setfreq(chan); break;        // slide down
134     case 3: tone_portamento(chan,channel[chan].portainfo); break;       // tone portamento
135     case 4: vibrato(chan,channel[chan].vibinfo1,channel[chan].vibinfo2); break; // vibrato
136     case 5:     // tone portamento & volume slide
137     case 6: if(channel[chan].fx == 5)           // vibrato & volume slide
138       tone_portamento(chan,channel[chan].portainfo);
139     else
140       vibrato(chan,channel[chan].vibinfo1,channel[chan].vibinfo2);
141     case 10: if(del % 4)        // SA2 volume slide
142       break;
143       if(info1)
144         vol_up(chan,info1);
145       else
146         vol_down(chan,info2);
147       setvolume(chan);
148       break;
149     case 14: if(info1 == 3)     // retrig note
150       if(!(del % (info2+1)))
151         playnote(chan);
152       break;
153     case 16: if(del % 4)        // AMD volume slide
154       break;
155       if(info1)
156         vol_up_alt(chan,info1);
157       else
158         vol_down_alt(chan,info2);
159       setvolume(chan);
160       break;
161     case 20:                    // RAD volume slide
162       if(info < 50)
163         vol_down_alt(chan,info);
164       else
165         vol_up_alt(chan,info - 50);
166       setvolume(chan);
167       break;
168     case 26:                    // volume slide
169       if(info1)
170         vol_up(chan,info1);
171       else
172         vol_down(chan,info2);
173       setvolume(chan);
174       break;
175     case 28:
176       if (info1) {
177         slide_up(chan,1); channel[chan].info1--;
178       }
179       if (info2) {
180         slide_down(chan,1); channel[chan].info2--;
181       }
182       setfreq(chan);
183       break;
184     }
185   }
186
187   if(del) {             // speed compensation
188     del--;
189     return !songend;
190   }
191
192   // arrangement handling
193   if(!resolve_order()) return !songend;
194   pattnr = order[ord];
195
196   if(!rw) AdPlug_LogWrite("\nCmodPlayer::update(): Pattern: %d, Order: %d\n", pattnr, ord);
197   AdPlug_LogWrite("CmodPlayer::update():%3d|", rw);
198
199   // play row
200   pattern_delay = 0;
201   row = rw;
202   for(chan = 0; chan < nchans; chan++) {
203     oplchan = set_opl_chip(chan);
204
205     if(!(activechan >> (31 - chan)) & 1) {      // channel active?
206       AdPlug_LogWrite("N/A|");
207       continue;
208     }
209     if(!(track = trackord[pattnr][chan])) {     // resolve track
210       AdPlug_LogWrite("------------|");
211       continue;
212     } else
213       track--;
214
215     AdPlug_LogWrite("%3d%3d%2X%2X%2X|", tracks[track][row].note,
216                     tracks[track][row].inst, tracks[track][row].command,
217                     tracks[track][row].param1, tracks[track][row].param2);
218
219     donote = 0;
220     if(tracks[track][row].inst) {
221       channel[chan].inst = tracks[track][row].inst - 1;
222       if (!(flags & Faust)) {
223         channel[chan].vol1 = 63 - (inst[channel[chan].inst].data[10] & 63);
224         channel[chan].vol2 = 63 - (inst[channel[chan].inst].data[9] & 63);
225         setvolume(chan);
226       }
227     }
228
229     if(tracks[track][row].note && tracks[track][row].command != 3) {    // no tone portamento
230       channel[chan].note = tracks[track][row].note;
231       setnote(chan,tracks[track][row].note);
232       channel[chan].nextfreq = channel[chan].freq;
233       channel[chan].nextoct = channel[chan].oct;
234       channel[chan].arppos = inst[channel[chan].inst].arpstart;
235       channel[chan].arpspdcnt = 0;
236       if(tracks[track][row].note != 127)        // handle key off
237         donote = 1;
238     }
239     channel[chan].fx = tracks[track][row].command;
240     channel[chan].info1 = tracks[track][row].param1;
241     channel[chan].info2 = tracks[track][row].param2;
242
243     if(donote)
244       playnote(chan);
245
246     // command handling (row dependant)
247     info1 = channel[chan].info1;
248     info2 = channel[chan].info2;
249     if(flags & Decimal)
250       info = channel[chan].info1 * 10 + channel[chan].info2;
251     else
252       info = (channel[chan].info1 << 4) + channel[chan].info2;
253     switch(channel[chan].fx) {
254     case 3: // tone portamento
255       if(tracks[track][row].note) {
256         if(tracks[track][row].note < 13)
257           channel[chan].nextfreq = notetable[tracks[track][row].note - 1];
258         else
259           if(tracks[track][row].note % 12 > 0)
260             channel[chan].nextfreq = notetable[(tracks[track][row].note % 12) - 1];
261           else
262             channel[chan].nextfreq = notetable[11];
263         channel[chan].nextoct = (tracks[track][row].note - 1) / 12;
264         if(tracks[track][row].note == 127) {    // handle key off
265           channel[chan].nextfreq = channel[chan].freq;
266           channel[chan].nextoct = channel[chan].oct;
267         }
268       }
269       if(info)  // remember vars
270         channel[chan].portainfo = info;
271       break;
272
273     case 4: // vibrato (remember vars)
274       if(info) {
275         channel[chan].vibinfo1 = info1;
276         channel[chan].vibinfo2 = info2;
277       }
278       break;
279
280     case 7: tempo = info; break;        // set tempo
281
282     case 8: channel[chan].key = 0; setfreq(chan); break;        // release sustaining note
283
284     case 9: // set carrier/modulator volume
285       if(info1)
286         channel[chan].vol1 = info1 * 7;
287       else
288         channel[chan].vol2 = info2 * 7;
289       setvolume(chan);
290       break;
291
292     case 11: // position jump
293       pattbreak = 1; rw = 0; if(info < ord) songend = 1; ord = info; break;
294
295     case 12: // set volume
296       channel[chan].vol1 = info;
297       channel[chan].vol2 = info;
298       if(channel[chan].vol1 > 63)
299         channel[chan].vol1 = 63;
300       if(channel[chan].vol2 > 63)
301         channel[chan].vol2 = 63;
302       setvolume(chan);
303       break;
304
305     case 13: // pattern break
306       if(!pattbreak) { pattbreak = 1; rw = info; ord++; } break;
307
308     case 14: // extended command
309       switch(info1) {
310       case 0: // define cell-tremolo
311         if(info2)
312           regbd |= 128;
313         else
314           regbd &= 127;
315         opl->write(0xbd,regbd);
316         break;
317
318       case 1: // define cell-vibrato
319         if(info2)
320           regbd |= 64;
321         else
322           regbd &= 191;
323         opl->write(0xbd,regbd);
324         break;
325
326       case 4: // increase volume fine
327         vol_up_alt(chan,info2);
328         setvolume(chan);
329         break;
330
331       case 5: // decrease volume fine
332         vol_down_alt(chan,info2);
333         setvolume(chan);
334         break;
335
336       case 6: // manual slide up
337         slide_up(chan,info2);
338         setfreq(chan);
339         break;
340
341       case 7: // manual slide down
342         slide_down(chan,info2);
343         setfreq(chan);
344         break;
345
346       case 8: // pattern delay (rows)
347         pattern_delay = info2 * speed;
348         break;
349       }
350       break;
351
352     case 15: // SA2 set speed
353       if(info <= 0x1f)
354         speed = info;
355       if(info >= 0x32)
356         tempo = info;
357       if(!info)
358         songend = 1;
359       break;
360
361     case 17: // alternate set volume
362       channel[chan].vol1 = info;
363       if(channel[chan].vol1 > 63)
364         channel[chan].vol1 = 63;
365       if(inst[channel[chan].inst].data[0] & 1) {
366         channel[chan].vol2 = info;
367         if(channel[chan].vol2 > 63)
368           channel[chan].vol2 = 63;
369       }
370
371       setvolume(chan);
372       break;
373
374     case 18: // AMD set speed
375       if(info <= 31 && info > 0)
376         speed = info;
377       if(info > 31 || !info)
378         tempo = info;
379       break;
380
381     case 19: // RAD/A2M set speed
382       speed = (info ? info : info + 1);
383       break;
384
385     case 21: // set modulator volume
386       if(info <= 63)
387         channel[chan].vol2 = info;
388       else
389         channel[chan].vol2 = 63;
390       setvolume(chan);
391       break;
392
393     case 22: // set carrier volume
394       if(info <= 63)
395         channel[chan].vol1 = info;
396       else
397         channel[chan].vol1 = 63;
398       setvolume(chan);
399       break;
400
401     case 23: // fine frequency slide up
402       slide_up(chan,info);
403       setfreq(chan);
404       break;
405
406     case 24: // fine frequency slide down
407       slide_down(chan,info);
408       setfreq(chan);
409       break;
410
411     case 25: // set carrier/modulator waveform
412       if(info1 != 0x0f)
413         opl->write(0xe3 + op_table[oplchan],info1);
414       if(info2 != 0x0f)
415         opl->write(0xe0 + op_table[oplchan],info2);
416       break;
417
418     case 27: // set chip tremolo/vibrato
419       if(info1)
420         regbd |= 128;
421       else
422         regbd &= 127;
423       if(info2)
424         regbd |= 64;
425       else
426         regbd &= 191;
427       opl->write(0xbd,regbd);
428       break;
429
430     case 29: // pattern delay (frames)
431       pattern_delay = info;
432       break;
433     }
434   }
435
436   // speed compensation
437   del = speed - 1 + pattern_delay;
438
439   if(!pattbreak) {      // next row (only if no manual advance)
440     rw++;
441     if(rw >= nrows) {
442       rw = 0;
443       ord++;
444     }
445   }
446
447   resolve_order();      // so we can report songend right away
448   AdPlug_LogWrite("\n");
449   return !songend;
450 }
451
452 unsigned char CmodPlayer::set_opl_chip(unsigned char chan)
453   /*
454    * Sets OPL chip according to channel number. Channels 0-8 are on first chip,
455    * channels 9-17 are on second chip. Returns corresponding OPL channel
456    * number.
457    */
458 {
459   int newchip = chan < 9 ? 0 : 1;
460
461   if(newchip != curchip) {
462     opl->setchip(newchip);
463     curchip = newchip;
464   }
465
466   return chan % 9;
467 }
468
469 bool CmodPlayer::resolve_order()
470   /*
471    * Resolves current orderlist entry, checking for jumps and loops.
472    *
473    * Returns true on correct processing, false if immediate recursive loop
474    * has been detected.
475    */
476 {
477   if(ord < length) {
478     while(order[ord] >= JUMPMARKER) {   // jump to order
479       unsigned long neword = order[ord] - JUMPMARKER;
480
481       if(neword <= ord) songend = 1;
482       if(neword == ord) return false;
483       ord = neword;
484     }
485   } else {
486     songend = 1;
487     ord = restartpos;
488   }
489
490   return true;
491 }
492
493 void CmodPlayer::rewind(int subsong)
494 {
495   unsigned long i;
496
497   // Reset playing variables
498   songend = del = ord = rw = regbd = 0;
499   tempo = bpm; speed = initspeed;
500
501   // Reset channel data
502   memset(channel,0,sizeof(Channel)*nchans);
503
504   // Compute number of patterns, if needed
505   if(!nop)
506     for(i=0;i<length;i++)
507       nop = (order[i] > nop ? order[i] : nop);
508
509   opl->init();          // Reset OPL chip
510   opl->write(1, 32);    // Go to ym3812 mode
511
512   // Enable OPL3 extensions if flagged
513   if(flags & Opl3) {
514     opl->setchip(1);
515     opl->write(1, 32);
516     opl->write(5, 1);
517     opl->setchip(0);
518   }
519
520   // Enable tremolo/vibrato depth if flagged
521   if(flags & Tremolo) regbd |= 128;
522   if(flags & Vibrato) regbd |= 64;
523   if(regbd) opl->write(0xbd, regbd);
524 }
525
526 float CmodPlayer::getrefresh()
527 {
528   return (float) (tempo / 2.5);
529 }
530
531 void CmodPlayer::init_trackord()
532 {
533   unsigned long i;
534
535   for(i=0;i<npats*nchans;i++)
536     trackord[i / nchans][i % nchans] = i + 1;
537 }
538
539 bool CmodPlayer::init_specialarp()
540 {
541   arplist = new unsigned char[SPECIALARPLEN];
542   arpcmd = new unsigned char[SPECIALARPLEN];
543
544   return true;
545 }
546
547 void CmodPlayer::init_notetable(const unsigned short *newnotetable)
548 {
549   memcpy(notetable, newnotetable, 12 * 2);
550 }
551
552 bool CmodPlayer::realloc_order(unsigned long len)
553 {
554   if(order) delete [] order;
555   order = new unsigned char[len];
556   return true;
557 }
558
559 bool CmodPlayer::realloc_patterns(unsigned long pats, unsigned long rows, unsigned long chans)
560 {
561   unsigned long i;
562
563   dealloc_patterns();
564
565   // set new number of tracks, rows and channels
566   npats = pats; nrows = rows; nchans = chans;
567
568   // alloc new patterns
569   tracks = new Tracks *[pats * chans];
570   for(i=0;i<pats*chans;i++) tracks[i] = new Tracks[rows];
571   trackord = new unsigned short *[pats];
572   for(i=0;i<pats;i++) trackord[i] = new unsigned short[chans];
573   channel = new Channel[chans];
574
575   // initialize new patterns
576   for(i=0;i<pats*chans;i++) memset(tracks[i],0,sizeof(Tracks)*rows);
577   for(i=0;i<pats;i++) memset(trackord[i],0,chans*2);
578
579   return true;
580 }
581
582 void CmodPlayer::dealloc_patterns()
583 {
584   unsigned long i;
585
586   // dealloc everything previously allocated
587   if(npats && nrows && nchans) {
588     for(i=0;i<npats*nchans;i++) delete [] tracks[i];
589     delete [] tracks;
590     for(i=0;i<npats;i++) delete [] trackord[i];
591     delete [] trackord;
592     delete [] channel;
593   }
594 }
595
596 bool CmodPlayer::realloc_instruments(unsigned long len)
597 {
598   // dealloc previous instance, if any
599   if(inst) delete [] inst;
600
601   inst = new Instrument[len];
602   memset(inst,0,sizeof(Instrument)*len);        // reset instruments
603   return true;
604 }
605
606 void CmodPlayer::dealloc()
607 {
608   if(inst) delete [] inst;
609   if(order) delete [] order;
610   if(arplist) delete [] arplist;
611   if(arpcmd) delete [] arpcmd;
612   dealloc_patterns();
613 }
614
615 /*** private methods *************************************/
616
617 void CmodPlayer::setvolume(unsigned char chan)
618 {
619   unsigned char oplchan = set_opl_chip(chan);
620
621   if(flags & Faust)
622     setvolume_alt(chan);
623   else {
624     opl->write(0x40 + op_table[oplchan], 63-channel[chan].vol2 + (inst[channel[chan].inst].data[9] & 192));
625     opl->write(0x43 + op_table[oplchan], 63-channel[chan].vol1 + (inst[channel[chan].inst].data[10] & 192));
626   }
627 }
628
629 void CmodPlayer::setvolume_alt(unsigned char chan)
630 {
631   unsigned char oplchan = set_opl_chip(chan);
632   unsigned char ivol2 = inst[channel[chan].inst].data[9] & 63;
633   unsigned char ivol1 = inst[channel[chan].inst].data[10] & 63;
634
635   opl->write(0x40 + op_table[oplchan], (((63 - (channel[chan].vol2 & 63)) + ivol2) >> 1) + (inst[channel[chan].inst].data[9] & 192));
636   opl->write(0x43 + op_table[oplchan], (((63 - (channel[chan].vol1 & 63)) + ivol1) >> 1) + (inst[channel[chan].inst].data[10] & 192));
637 }
638
639 void CmodPlayer::setfreq(unsigned char chan)
640 {
641   unsigned char oplchan = set_opl_chip(chan);
642
643   opl->write(0xa0 + oplchan, channel[chan].freq & 255);
644   if(channel[chan].key)
645     opl->write(0xb0 + oplchan, ((channel[chan].freq & 768) >> 8) + (channel[chan].oct << 2) | 32);
646   else
647     opl->write(0xb0 + oplchan, ((channel[chan].freq & 768) >> 8) + (channel[chan].oct << 2));
648 }
649
650 void CmodPlayer::playnote(unsigned char chan)
651 {
652   unsigned char oplchan = set_opl_chip(chan);
653   unsigned char op = op_table[oplchan], insnr = channel[chan].inst;
654
655   if(!(flags & NoKeyOn))
656     opl->write(0xb0 + oplchan, 0);      // stop old note
657
658   // set instrument data
659   opl->write(0x20 + op, inst[insnr].data[1]);
660   opl->write(0x23 + op, inst[insnr].data[2]);
661   opl->write(0x60 + op, inst[insnr].data[3]);
662   opl->write(0x63 + op, inst[insnr].data[4]);
663   opl->write(0x80 + op, inst[insnr].data[5]);
664   opl->write(0x83 + op, inst[insnr].data[6]);
665   opl->write(0xe0 + op, inst[insnr].data[7]);
666   opl->write(0xe3 + op, inst[insnr].data[8]);
667   opl->write(0xc0 + oplchan, inst[insnr].data[0]);
668   opl->write(0xbd, inst[insnr].misc);   // set misc. register
669
670   // set frequency, volume & play
671   channel[chan].key = 1;
672   setfreq(chan);
673
674   if (flags & Faust) {
675     channel[chan].vol2 = 63;
676     channel[chan].vol1 = 63;
677   }
678   setvolume(chan);
679 }
680
681 void CmodPlayer::setnote(unsigned char chan, int note)
682 {
683   if(note > 96) {
684     if(note == 127) {   // key off
685       channel[chan].key = 0;
686       setfreq(chan);
687       return;
688     } else
689       note = 96;
690   }
691
692   if(note < 13)
693     channel[chan].freq = notetable[note - 1];
694   else
695     if(note % 12 > 0)
696       channel[chan].freq = notetable[(note % 12) - 1];
697     else
698       channel[chan].freq = notetable[11];
699   channel[chan].oct = (note - 1) / 12;
700   channel[chan].freq += inst[channel[chan].inst].slide; // apply pre-slide
701 }
702
703 void CmodPlayer::slide_down(unsigned char chan, int amount)
704 {
705   channel[chan].freq -= amount;
706   if(channel[chan].freq <= 342) {
707     if(channel[chan].oct) {
708       channel[chan].oct--;
709       channel[chan].freq <<= 1;
710     } else
711       channel[chan].freq = 342;
712   }
713 }
714
715 void CmodPlayer::slide_up(unsigned char chan, int amount)
716 {
717   channel[chan].freq += amount;
718   if(channel[chan].freq >= 686) {
719     if(channel[chan].oct < 7) {
720       channel[chan].oct++;
721       channel[chan].freq >>= 1;
722     } else
723       channel[chan].freq = 686;
724   }
725 }
726
727 void CmodPlayer::tone_portamento(unsigned char chan, unsigned char info)
728 {
729   if(channel[chan].freq + (channel[chan].oct << 10) < channel[chan].nextfreq +
730      (channel[chan].nextoct << 10)) {
731     slide_up(chan,info);
732     if(channel[chan].freq + (channel[chan].oct << 10) > channel[chan].nextfreq +
733        (channel[chan].nextoct << 10)) {
734       channel[chan].freq = channel[chan].nextfreq;
735       channel[chan].oct = channel[chan].nextoct;
736     }
737   }
738   if(channel[chan].freq + (channel[chan].oct << 10) > channel[chan].nextfreq +
739      (channel[chan].nextoct << 10)) {
740     slide_down(chan,info);
741     if(channel[chan].freq + (channel[chan].oct << 10) < channel[chan].nextfreq +
742        (channel[chan].nextoct << 10)) {
743       channel[chan].freq = channel[chan].nextfreq;
744       channel[chan].oct = channel[chan].nextoct;
745     }
746   }
747   setfreq(chan);
748 }
749
750 void CmodPlayer::vibrato(unsigned char chan, unsigned char speed, unsigned char depth)
751 {
752   int i;
753
754   if(!speed || !depth)
755     return;
756
757   if(depth > 14)
758     depth = 14;
759
760   for(i=0;i<speed;i++) {
761     channel[chan].trigger++;
762     while(channel[chan].trigger >= 64)
763       channel[chan].trigger -= 64;
764     if(channel[chan].trigger >= 16 && channel[chan].trigger < 48)
765       slide_down(chan,vibratotab[channel[chan].trigger - 16] / (16-depth));
766     if(channel[chan].trigger < 16)
767       slide_up(chan,vibratotab[channel[chan].trigger + 16] / (16-depth));
768     if(channel[chan].trigger >= 48)
769       slide_up(chan,vibratotab[channel[chan].trigger - 48] / (16-depth));
770   }
771   setfreq(chan);
772 }
773
774 void CmodPlayer::vol_up(unsigned char chan, int amount)
775 {
776   if(channel[chan].vol1 + amount < 63)
777     channel[chan].vol1 += amount;
778   else
779     channel[chan].vol1 = 63;
780
781   if(channel[chan].vol2 + amount < 63)
782     channel[chan].vol2 += amount;
783   else
784     channel[chan].vol2 = 63;
785 }
786
787 void CmodPlayer::vol_down(unsigned char chan, int amount)
788 {
789   if(channel[chan].vol1 - amount > 0)
790     channel[chan].vol1 -= amount;
791   else
792     channel[chan].vol1 = 0;
793
794   if(channel[chan].vol2 - amount > 0)
795     channel[chan].vol2 -= amount;
796   else
797     channel[chan].vol2 = 0;
798 }
799
800 void CmodPlayer::vol_up_alt(unsigned char chan, int amount)
801 {
802   if(channel[chan].vol1 + amount < 63)
803     channel[chan].vol1 += amount;
804   else
805     channel[chan].vol1 = 63;
806   if(inst[channel[chan].inst].data[0] & 1) {
807     if(channel[chan].vol2 + amount < 63)
808       channel[chan].vol2 += amount;
809     else
810       channel[chan].vol2 = 63;
811   }
812 }
813
814 void CmodPlayer::vol_down_alt(unsigned char chan, int amount)
815 {
816   if(channel[chan].vol1 - amount > 0)
817     channel[chan].vol1 -= amount;
818   else
819     channel[chan].vol1 = 0;
820   if(inst[channel[chan].inst].data[0] & 1) {
821     if(channel[chan].vol2 - amount > 0)
822       channel[chan].vol2 -= amount;
823     else
824       channel[chan].vol2 = 0;
825   }
826 }